Apply aqua daisyUI theme and refactor login primitives
This commit is contained in:
@@ -4,7 +4,7 @@ const isLoginPage = computed(() => route.path === '/login');
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="lk-shell">
|
<div class="lk-shell" data-theme="aqua">
|
||||||
<AppHeader v-if="!isLoginPage" />
|
<AppHeader v-if="!isLoginPage" />
|
||||||
<main class="mx-auto w-full max-w-7xl p-4 md:p-6 lg:p-8">
|
<main class="mx-auto w-full max-w-7xl p-4 md:p-6 lg:p-8">
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ const requestCodeMutation = useMutation(RequestLoginCodeDocument);
|
|||||||
const verifyCodeMutation = useMutation(VerifyLoginCodeDocument);
|
const verifyCodeMutation = useMutation(VerifyLoginCodeDocument);
|
||||||
const consumeLoginTokenMutation = useMutation(ConsumeLoginTokenDocument);
|
const consumeLoginTokenMutation = useMutation(ConsumeLoginTokenDocument);
|
||||||
|
|
||||||
const channelHint = computed(() => {
|
|
||||||
return 'Email адрес';
|
|
||||||
});
|
|
||||||
|
|
||||||
const telegramBotUrl = computed(() => config.public.telegramBotUrl || '');
|
const telegramBotUrl = computed(() => config.public.telegramBotUrl || '');
|
||||||
const maxBotUrl = computed(() => config.public.maxBotUrl || '');
|
const maxBotUrl = computed(() => config.public.maxBotUrl || '');
|
||||||
const selectedBotUrl = computed(() =>
|
const selectedBotUrl = computed(() =>
|
||||||
@@ -137,51 +133,43 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="mx-auto flex min-h-[calc(100vh-4rem)] w-full max-w-3xl items-center py-8">
|
<section class="mx-auto flex min-h-[calc(100vh-4rem)] w-full max-w-3xl items-center py-8">
|
||||||
<div class="surface-card w-full rounded-[34px] p-5 md:p-8">
|
<div class="card w-full border border-base-300 bg-base-100 shadow-xl">
|
||||||
<div class="mb-5 text-center">
|
<div class="card-body p-5 md:p-8">
|
||||||
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Вход в личный кабинет</h1>
|
<div class="mb-4 text-center">
|
||||||
<p class="mt-1 text-sm text-[#28543f]/80">
|
<h1 class="text-3xl font-extrabold">Вход в личный кабинет</h1>
|
||||||
|
<p class="mt-1 text-sm text-base-content/70">
|
||||||
Email вход по коду. Telegram/Max вход через бота и временный токен.
|
Email вход по коду. Telegram/Max вход через бота и временный токен.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mx-auto mb-5 flex w-full max-w-xl flex-wrap items-center justify-center gap-2">
|
<div class="mb-5 flex justify-center">
|
||||||
<button
|
<div class="join">
|
||||||
class="glass-capsule rounded-full px-4 py-2 text-sm font-semibold text-[#123824] transition hover:scale-[1.01]"
|
<button class="btn join-item" :class="{ 'btn-primary': channel === 'EMAIL' }" @click="channel = 'EMAIL'">
|
||||||
:class="{ 'bg-[#139957] text-white': channel === 'EMAIL' }"
|
|
||||||
@click="channel = 'EMAIL'"
|
|
||||||
>
|
|
||||||
Email
|
Email
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button class="btn join-item" :class="{ 'btn-primary': channel === 'TELEGRAM' }" @click="channel = 'TELEGRAM'">
|
||||||
class="glass-capsule rounded-full px-4 py-2 text-sm font-semibold text-[#123824] transition hover:scale-[1.01]"
|
|
||||||
:class="{ 'bg-[#139957] text-white': channel === 'TELEGRAM' }"
|
|
||||||
@click="channel = 'TELEGRAM'"
|
|
||||||
>
|
|
||||||
Telegram
|
Telegram
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button class="btn join-item" :class="{ 'btn-primary': channel === 'MAX' }" @click="channel = 'MAX'">
|
||||||
class="glass-capsule rounded-full px-4 py-2 text-sm font-semibold text-[#123824] transition hover:scale-[1.01]"
|
|
||||||
:class="{ 'bg-[#139957] text-white': channel === 'MAX' }"
|
|
||||||
@click="channel = 'MAX'"
|
|
||||||
>
|
|
||||||
Max
|
Max
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="channel === 'EMAIL' && step === 'request'" class="space-y-3">
|
<div v-if="channel === 'EMAIL' && step === 'request'" class="space-y-4">
|
||||||
<label class="form-control">
|
<fieldset class="fieldset rounded-box border border-base-300 bg-base-200/40 p-4">
|
||||||
<span class="label-text font-semibold text-[#194631]">{{ channelHint }}</span>
|
<legend class="fieldset-legend text-sm font-semibold">Email адрес</legend>
|
||||||
|
<label class="label pb-1">На этот адрес отправим код</label>
|
||||||
<input
|
<input
|
||||||
v-model="destination"
|
v-model="destination"
|
||||||
type="text"
|
type="email"
|
||||||
class="input input-bordered border-[#d0e8d8] bg-white/80"
|
class="input input-bordered w-full"
|
||||||
:placeholder="channelHint"
|
placeholder="name@company.com"
|
||||||
>
|
>
|
||||||
</label>
|
</fieldset>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn w-full border-0 bg-[#139957] text-white hover:bg-[#0d854a]"
|
class="btn btn-primary w-full"
|
||||||
:disabled="requestCodeMutation.loading.value"
|
:disabled="requestCodeMutation.loading.value"
|
||||||
@click="requestCode"
|
@click="requestCode"
|
||||||
>
|
>
|
||||||
@@ -189,25 +177,26 @@ onMounted(async () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="channel === 'EMAIL'" class="space-y-3">
|
<div v-else-if="channel === 'EMAIL'" class="space-y-4">
|
||||||
<div class="rounded-xl border border-[#d6ebde] bg-white/75 p-3 text-sm text-[#214735]">
|
<div class="alert alert-info">
|
||||||
Код отправлен на <span class="font-bold">{{ maskedDestination }}</span>.
|
Код отправлен на <span class="font-bold">{{ maskedDestination }}</span>.
|
||||||
Действителен до: <span class="font-bold">{{ expiresAt }}</span>.
|
Действителен до: <span class="font-bold">{{ expiresAt }}</span>.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="form-control">
|
<fieldset class="fieldset rounded-box border border-base-300 bg-base-200/40 p-4">
|
||||||
<span class="label-text font-semibold text-[#194631]">Код подтверждения</span>
|
<legend class="fieldset-legend text-sm font-semibold">Код подтверждения</legend>
|
||||||
|
<label class="label pb-1">Введите 6-значный код</label>
|
||||||
<input
|
<input
|
||||||
v-model="code"
|
v-model="code"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="6"
|
maxlength="6"
|
||||||
class="input input-bordered border-[#d0e8d8] bg-white/80"
|
class="input input-bordered w-full"
|
||||||
placeholder="123456"
|
placeholder="123456"
|
||||||
>
|
>
|
||||||
</label>
|
</fieldset>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn w-full border-0 bg-[#139957] text-white hover:bg-[#0d854a]"
|
class="btn btn-primary w-full"
|
||||||
:disabled="verifyCodeMutation.loading.value"
|
:disabled="verifyCodeMutation.loading.value"
|
||||||
@click="verifyCode"
|
@click="verifyCode"
|
||||||
>
|
>
|
||||||
@@ -220,49 +209,51 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="space-y-4">
|
<div v-else class="space-y-4">
|
||||||
<div class="rounded-xl border border-[#d6ebde] bg-white/75 p-3 text-sm text-[#214735]">
|
<div class="alert alert-info">
|
||||||
Откройте {{ channel === 'TELEGRAM' ? 'Telegram' : 'Max' }}-бота, отправьте команду
|
Откройте {{ channel === 'TELEGRAM' ? 'Telegram' : 'Max' }}-бота, отправьте команду
|
||||||
<span class="font-bold">{{ startCommand }}</span>, затем передайте боту свой <code>user_id</code>.
|
<span class="font-bold">{{ startCommand }}</span>, затем передайте боту свой <code>user_id</code>.
|
||||||
Бот пришлёт кнопку входа в кабинет с временным токеном.
|
Бот пришлёт кнопку входа в кабинет с временным токеном.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="form-control">
|
<fieldset class="fieldset rounded-box border border-base-300 bg-base-200/40 p-4">
|
||||||
<span class="label-text font-semibold text-[#194631]">Ваш user_id (для команды /start)</span>
|
<legend class="fieldset-legend text-sm font-semibold">Ваш user_id</legend>
|
||||||
|
<label class="label pb-1">Для команды /start в боте</label>
|
||||||
<input
|
<input
|
||||||
v-model="userIdForBot"
|
v-model="userIdForBot"
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-bordered border-[#d0e8d8] bg-white/80"
|
class="input input-bordered w-full"
|
||||||
placeholder="например: cm5abc123xyz"
|
placeholder="например: cm5abc123xyz"
|
||||||
>
|
>
|
||||||
</label>
|
</fieldset>
|
||||||
|
|
||||||
<div class="grid gap-2 sm:grid-cols-2">
|
<div class="grid gap-2 sm:grid-cols-2">
|
||||||
<button class="btn btn-outline border-[#139957] text-[#0d854a]" @click="copyStartCommand">
|
<button class="btn btn-outline" @click="copyStartCommand">
|
||||||
Скопировать команду
|
Скопировать команду
|
||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
:href="selectedBotUrl || undefined"
|
:href="selectedBotUrl || undefined"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="btn border-0 bg-[#139957] text-white hover:bg-[#0d854a]"
|
class="btn btn-primary"
|
||||||
:class="{ 'btn-disabled pointer-events-none': !selectedBotUrl }"
|
:class="{ 'btn-disabled pointer-events-none': !selectedBotUrl }"
|
||||||
>
|
>
|
||||||
Открыть бота
|
Открыть бота
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p v-if="!selectedBotUrl" class="text-xs text-[#b42318]">
|
<p v-if="!selectedBotUrl" class="text-xs text-error">
|
||||||
Ссылка на {{ channel === 'TELEGRAM' ? 'Telegram' : 'Max' }}-бота не настроена в env.
|
Ссылка на {{ channel === 'TELEGRAM' ? 'Telegram' : 'Max' }}-бота не настроена в env.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="feedback"
|
v-if="feedback"
|
||||||
class="alert mt-4"
|
class="alert mt-2"
|
||||||
:class="feedbackTone === 'success' ? 'alert-success' : 'alert-error'"
|
:class="feedbackTone === 'success' ? 'alert-success' : 'alert-error'"
|
||||||
>
|
>
|
||||||
{{ feedback }}
|
{{ feedback }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -12,6 +12,43 @@ export default {
|
|||||||
},
|
},
|
||||||
plugins: [daisyui],
|
plugins: [daisyui],
|
||||||
daisyui: {
|
daisyui: {
|
||||||
themes: ['light', 'corporate'],
|
themes: [
|
||||||
|
{
|
||||||
|
aqua: {
|
||||||
|
'color-scheme': 'light',
|
||||||
|
'base-100': 'oklch(98% 0.002 247.839)',
|
||||||
|
'base-200': 'oklch(96% 0.003 264.542)',
|
||||||
|
'base-300': 'oklch(92% 0.006 264.531)',
|
||||||
|
'base-content': 'oklch(21% 0.034 264.665)',
|
||||||
|
primary: 'oklch(84% 0.238 128.85)',
|
||||||
|
'primary-content': 'oklch(27% 0.072 132.109)',
|
||||||
|
secondary: 'oklch(71% 0.202 349.761)',
|
||||||
|
'secondary-content': 'oklch(28% 0.109 3.907)',
|
||||||
|
accent: 'oklch(67% 0.182 276.935)',
|
||||||
|
'accent-content': 'oklch(25% 0.09 281.288)',
|
||||||
|
neutral: 'oklch(13% 0.028 261.692)',
|
||||||
|
'neutral-content': 'oklch(98% 0.002 247.839)',
|
||||||
|
info: 'oklch(68% 0.169 237.323)',
|
||||||
|
'info-content': 'oklch(97% 0.013 236.62)',
|
||||||
|
success: 'oklch(76% 0.233 130.85)',
|
||||||
|
'success-content': 'oklch(98% 0.031 120.757)',
|
||||||
|
warning: 'oklch(70% 0.213 47.604)',
|
||||||
|
'warning-content': 'oklch(98% 0.016 73.684)',
|
||||||
|
error: 'oklch(65% 0.241 354.308)',
|
||||||
|
'error-content': 'oklch(97% 0.014 343.198)',
|
||||||
|
'--radius-selector': '2rem',
|
||||||
|
'--radius-field': '2rem',
|
||||||
|
'--radius-box': '2rem',
|
||||||
|
'--size-selector': '0.3125rem',
|
||||||
|
'--size-field': '0.3125rem',
|
||||||
|
'--border': '0.5px',
|
||||||
|
'--depth': '0',
|
||||||
|
'--noise': '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'light',
|
||||||
|
'corporate',
|
||||||
|
],
|
||||||
|
darkTheme: 'aqua',
|
||||||
},
|
},
|
||||||
} satisfies Config;
|
} satisfies Config;
|
||||||
|
|||||||
Reference in New Issue
Block a user