support dark theme closes #25
Deploy service message-delivery-method-web-push / service message-delivery-method-web-push (push) Successful in 1m17s
Deploy db-migrations / db-migrations (push) Successful in 38s
Deploy app frontend / app frontend (push) Successful in 2m14s

This commit is contained in:
2024-12-08 11:06:31 +02:00
parent 0d40aaf2da
commit ab86a3b8e1
34 changed files with 689 additions and 261 deletions
+1
View File
@@ -48,6 +48,7 @@ declare module 'vue' {
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
TabBar: typeof import('./src/components/layout/TabBar.vue')['default'] TabBar: typeof import('./src/components/layout/TabBar.vue')['default']
TabMenuItem: typeof import('./src/components/layout/TabMenuItem.vue')['default'] TabMenuItem: typeof import('./src/components/layout/TabMenuItem.vue')['default']
Textarea: typeof import('primevue/textarea')['default']
TheWelcome: typeof import('./src/components/TheWelcome/TheWelcome.vue')['default'] TheWelcome: typeof import('./src/components/TheWelcome/TheWelcome.vue')['default']
} }
} }
+1
View File
@@ -63,6 +63,7 @@
"postcss": "^8.4.49", "postcss": "^8.4.49",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"rollup-plugin-manifest-json": "^1.7.0", "rollup-plugin-manifest-json": "^1.7.0",
"sass-embedded": "^1.82.0",
"tailwindcss": "^3.4.14", "tailwindcss": "^3.4.14",
"tailwindcss-safe-area": "^0.6.0", "tailwindcss-safe-area": "^0.6.0",
"typescript": "~5.6.3", "typescript": "~5.6.3",
+16
View File
@@ -29,6 +29,22 @@ registerServiceWorker()
// }) // })
// }) // })
// .catch(console.error) // .catch(console.error)
// import { usePrefersColorSchemeStore } from '@/stores/usePrefersColorSchemeStore'
// import { watch } from 'vue'
// const { isDarkMode } = usePrefersColorSchemeStore()
//
// watch(
// () => isDarkMode,
// () => {
// if (isDarkMode) {
// document.documentElement.classList.add('dark')
// } else {
// document.documentElement.classList.remove('dark')
// }
// },
// { immediate: true },
// )
</script> </script>
<template> <template>
+9 -4
View File
@@ -1,12 +1,17 @@
<template> <template>
<RouterLink :to="route" class="p-4 rounded-lg bg-white shadow-md"> <RouterLink
:to="route"
class="p-4 rounded-lg bg-white dark:bg-gray-800 shadow-md text-gray-800 dark:text-gray-300"
>
<div class="flex items-center justify-between mb-2" v-if="qrCodeDoc"> <div class="flex items-center justify-between mb-2" v-if="qrCodeDoc">
<div class="flex items-center"> <div class="flex items-center gap-2">
<QRCodePlacementIcon :placement="qrCodeDoc.placement" /> <QRCodePlacementIcon :placement="qrCodeDoc.placement" />
<h2 class="text-lg font-semibold">{{ qrCodeDoc.name }}</h2> <h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">
{{ qrCodeDoc.name }}
</h2>
</div> </div>
</div> </div>
<div class="text-gray-500"> <div class="text-gray-500 dark:text-gray-400">
<span class="text-nowrap">{{ formatedCreatedAt }}</span> <span class="text-nowrap">{{ formatedCreatedAt }}</span>
</div> </div>
</RouterLink> </RouterLink>
@@ -6,44 +6,53 @@
</div> </div>
<Checkbox v-else v-model="enabled" inputId="webPush" name="delivery" binary /> <Checkbox v-else v-model="enabled" inputId="webPush" name="delivery" binary />
<label for="webPush">Прислать уведомление, когда придет ответ</label> <label for="webPush" class="text-gray-800 dark:text-gray-300">
Прислать уведомление, когда придет ответ
</label>
</div> </div>
<!-- Инструкции для iOS --> <!-- Инструкции для iOS -->
<div <div
v-if="showRequireStandaloneInstructionsForIOS" v-if="showRequireStandaloneInstructionsForIOS"
class="bg-yellow-100 text-yellow-800 p-4 rounded my-4" class="bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-300 p-4 rounded my-4"
> >
<p class="mb-2">Чтобы включить уведомления, добавьте это приложение на главный экран:</p> <p class="mb-2 dark:text-yellow-200">
Чтобы включить уведомления, добавьте это приложение на главный экран:
</p>
<ul class="list-disc pl-5"> <ul class="list-disc pl-5">
<li class="mb-1"> <li class="mb-1 dark:text-yellow-200">
Нажмите Нажмите
<strong class="font-semibold"> <strong class="font-semibold">
"<img "<img
src="@/assets/icons/apple-share.svg?url" src="@/assets/icons/apple-share.svg?url"
alt="Поделиться" alt="Поделиться"
class="h-7 -mt-2 inline-block" class="h-7 -mt-2 inline-block dark:filter dark:invert"
/>" />"
</strong> </strong>
внизу экрана внизу экрана
</li> </li>
<li class="mb-1"> <li class="mb-1 dark:text-yellow-200">
Выберите Выберите
<strong class="inline-flex items-baseline font-semibold"> <strong class="inline-flex items-baseline font-semibold">
<span class="me-1">"На экран «Домой»</span> <span class="me-1">"На экран «Домой»</span>
<img <img
src="@/assets/icons/apple-system-plus.svg?url" src="@/assets/icons/apple-system-plus.svg?url"
alt="" alt=""
class="h-4 inline-block self-center" class="h-4 inline-block self-center dark:filter dark:invert"
/>" />
"
</strong> </strong>
</li> </li>
<li>Откройте приложение с главного экрана и повторите попытку.</li> <li class="dark:text-yellow-200">
Откройте приложение с главного экрана и повторите попытку.
</li>
</ul> </ul>
</div> </div>
<!-- Ошибка разрешений --> <!-- Ошибка разрешений -->
<p v-else-if="isError" class="text-red-500 mb-2">{{ error?.message || error }}<br /></p> <p v-else-if="isError" class="text-red-500 dark:text-red-400 mb-2">
{{ error?.message || error }}<br />
</p>
</div> </div>
</template> </template>
@@ -240,6 +249,6 @@ watch(
) )
const showRequireStandaloneInstructionsForIOS = computed( const showRequireStandaloneInstructionsForIOS = computed(
() => isError.value && isIOS.value && !isStandalone.value && enabled.value, () => true, //isError.value && isIOS.value && !isStandalone.value && enabled.value,
) )
</script> </script>
@@ -1,5 +1,5 @@
<template> <template>
<div class="max-w-screen-sm mx-auto px-4 md:px-0 font-sans text-gray-800"> <div class="max-w-screen-sm mx-auto px-4 md:px-0 font-sans text-gray-800 dark:text-gray-100">
<!-- Hero Section --> <!-- Hero Section -->
<section class="text-center py-12"> <section class="text-center py-12">
<div class="flex flex-col md:flex-row items-center gap-8"> <div class="flex flex-col md:flex-row items-center gap-8">
@@ -14,7 +14,7 @@
</RouterLink> </RouterLink>
<div> <div>
<h1 class="text-3xl font-bold">Создайте уникальный QRкод для связи</h1> <h1 class="text-3xl font-bold">Создайте уникальный QRкод для связи</h1>
<p class="mt-2 text-lg text-gray-600 text-justify"> <p class="mt-2 text-lg text-gray-600 dark:text-gray-400 text-justify">
Люди смогут отправлять вам сообщения, сканируя этот QRкод, без необходимости раскрывать Люди смогут отправлять вам сообщения, сканируя этот QRкод, без необходимости раскрывать
ваши контактные данные. ваши контактные данные.
</p> </p>
@@ -29,12 +29,12 @@
</div> </div>
</section> </section>
<hr /> <hr class="dark:border-gray-700" />
<!-- Where to Use Section --> <!-- Where to Use Section -->
<section id="setup" class="py-8 text-center"> <section id="setup" class="py-8 text-center">
<h2 class="text-2xl font-semibold">Где использовать?</h2> <h2 class="text-2xl font-semibold">Где использовать?</h2>
<p class="mt-2 text-lg text-gray-600 text-justify"> <p class="mt-2 text-lg text-gray-600 dark:text-gray-400 text-justify">
QRкод можно будет разместить на вашем автомобиле, на входной двери или на ошейнике вашего QRкод можно будет разместить на вашем автомобиле, на входной двери или на ошейнике вашего
питомца это позволит окружающим легко связаться с вами в случае необходимости, при этом питомца это позволит окружающим легко связаться с вами в случае необходимости, при этом
ваши контактные данные останутся конфиденциальными. ваши контактные данные останутся конфиденциальными.
@@ -46,7 +46,7 @@
<!-- Simple Setup Section --> <!-- Simple Setup Section -->
<section id="settings" class="py-8 text-center"> <section id="settings" class="py-8 text-center">
<h2 class="text-2xl font-semibold">Легкость настройки</h2> <h2 class="text-2xl font-semibold">Легкость настройки</h2>
<p class="mt-2 text-lg text-gray-600 text-justify"> <p class="mt-2 text-lg text-gray-600 dark:text-gray-400 text-justify">
Создайте QRкод, выберите доступные действия и начните использовать. Создайте QRкод, выберите доступные действия и начните использовать.
</p> </p>
<div class="flex justify-center mt-6"> <div class="flex justify-center mt-6">
@@ -61,7 +61,7 @@
</section> </section>
<!-- Footer --> <!-- Footer -->
<footer class="py-4 border-t text-center"> <footer class="py-4 border-t text-center dark:border-gray-700">
<p>НаСвязи © 2024</p> <p>НаСвязи © 2024</p>
</footer> </footer>
</div> </div>
@@ -5,10 +5,15 @@
<InputText <InputText
id="newMessage" id="newMessage"
v-model="newMessage" v-model="newMessage"
class="flex-1" class="flex-1 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700"
placeholder="Напишите сообщение" placeholder="Напишите сообщение"
/> />
<Button type="submit" icon="pi pi-send" class="p-button-md" :disabled="!newMessage.trim()" /> <Button
type="submit"
icon="pi pi-send"
class="p-button-md dark:bg-primary-600 dark:hover:bg-primary-700"
:disabled="!newMessage.trim()"
/>
</form> </form>
<ChatSubscribeWebPush :qr_code_uri :chat :user_chat_role="userRole" /> <ChatSubscribeWebPush :qr_code_uri :chat :user_chat_role="userRole" />
@@ -12,8 +12,10 @@
<Card <Card
class="p-card-sm" class="p-card-sm"
:class="{ :class="{
'bg-blue-50 border-blue-300 text-blue-500': message.from === userRole, 'bg-blue-50 dark:bg-blue-900 border-blue-300 dark:border-blue-700 text-blue-500 dark:text-blue-200':
'bg-gray-50 border-gray-300 text-gray-700': message.from !== userRole, message.from === userRole,
'bg-gray-50 dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300':
message.from !== userRole,
}" }"
> >
<template #content> <template #content>
@@ -1,12 +1,18 @@
<template> <template>
<section> <section>
<h2 class="text-xl font-semibold mb-4">Выберите доступные действия</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4">Укажите, какие действия будут доступны для сканирующих QRкод.</p> Выберите доступные действия
<p class="text-sm text-gray-500 mb-6">Вы сможете изменить эти настройки позже.</p> </h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
Укажите, какие действия будут доступны для сканирующих QRкод.
</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
Вы сможете изменить эти настройки позже.
</p>
<div class="flex flex-col gap-3 mb-4"> <div class="flex flex-col gap-3 mb-4">
<div v-for="(label, action) in actionsOptions" :key="action" class="flex items-center gap-2"> <div v-for="(label, action) in actionsOptions" :key="action" class="flex items-center gap-2">
<Checkbox v-model="model" :inputId="action" :value="action" @change="next" /> <Checkbox v-model="model" :inputId="action" :value="action" @change="next" />
<label :for="action">{{ label }}</label> <label :for="action" class="text-gray-700 dark:text-gray-300">{{ label }}</label>
</div> </div>
</div> </div>
</section> </section>
@@ -1,7 +1,9 @@
<template> <template>
<section> <section>
<h2 class="text-xl font-semibold mb-4">Куда отправлять сообщения?</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4">Выберите, как вы хотите получать сообщения.</p> Куда отправлять сообщения?
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">Выберите, как вы хотите получать сообщения.</p>
<CreateMessageDeliveryOptions> <CreateMessageDeliveryOptions>
<template #telegram="{ label, method }"> <template #telegram="{ label, method }">
<CreateMessageDeliveryOptionTelegram <CreateMessageDeliveryOptionTelegram
@@ -9,6 +11,7 @@
:method :method
v-model="localModel" v-model="localModel"
@change="onChange" @change="onChange"
class="text-gray-700 dark:text-gray-300"
/> />
</template> </template>
<template #webPush="{ label, method }"> <template #webPush="{ label, method }">
@@ -17,10 +20,17 @@
:method :method
v-model="localModel" v-model="localModel"
@change="onChange" @change="onChange"
class="text-gray-700 dark:text-gray-300"
/> />
</template> </template>
<template #default="{ label, method }"> <template #default="{ label, method }">
<CreateMessageDeliveryOption :label :method v-model="localModel" @change="onChange" /> <CreateMessageDeliveryOption
:label
:method
v-model="localModel"
@change="onChange"
class="text-gray-700 dark:text-gray-300"
/>
</template> </template>
</CreateMessageDeliveryOptions> </CreateMessageDeliveryOptions>
</section> </section>
@@ -2,7 +2,7 @@
<CreateMessageDeliveryOption :label :method v-model="model" /> <CreateMessageDeliveryOption :label :method v-model="model" />
<!-- Сообщение о недоступности --> <!-- Сообщение о недоступности -->
<p v-if="telegramNotice" class="text-red-500 mb-2"> <p v-if="telegramNotice" class="text-red-500 dark:text-red-400 my-2 outline outline-1 py-2 px-4">
Отправка в Telegram пока в разработке.<br /> Отправка в Telegram пока в разработке.<br />
Этот способ отправки сообщений можно будет выбрать позже. Этот способ отправки сообщений можно будет выбрать позже.
</p> </p>
@@ -4,11 +4,13 @@
<!-- Инструкции для iOS --> <!-- Инструкции для iOS -->
<div <div
v-if="showRequireStandaloneInstructionsForIOS" v-if="showRequireStandaloneInstructionsForIOS"
class="bg-yellow-100 text-yellow-800 p-4 rounded my-4" class="bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-300 p-4 rounded my-4"
> >
<p class="mb-2">Чтобы включить уведомления, добавьте это приложение на главный экран:</p> <p class="mb-2 dark:text-yellow-200">
Чтобы включить уведомления, добавьте это приложение на главный экран:
</p>
<ul class="list-disc pl-5"> <ul class="list-disc pl-5">
<li class="mb-1"> <li class="mb-1 dark:text-yellow-200">
Нажмите Нажмите
<strong class="font-semibold"> <strong class="font-semibold">
"<img "<img
@@ -19,7 +21,7 @@
</strong> </strong>
внизу экрана внизу экрана
</li> </li>
<li class="mb-1"> <li class="mb-1 dark:text-yellow-200">
Выберите Выберите
<strong class="inline-flex items-baseline font-semibold"> <strong class="inline-flex items-baseline font-semibold">
<span class="me-1">"На экран «Домой»</span> <span class="me-1">"На экран «Домой»</span>
@@ -30,14 +32,16 @@
/>" />"
</strong> </strong>
</li> </li>
<li>Откройте приложение с главного экрана и повторите попытку.</li> <li class="dark:text-yellow-200">
Откройте приложение с главного экрана и повторите попытку.
</li>
</ul> </ul>
</div> </div>
<!-- Ошибка разрешений --> <!-- Ошибка разрешений -->
<p v-else-if="isError && model === method" class="text-red-500 mb-2"> <p v-else-if="isError && model === method" class="text-red-500 dark:text-red-400 mb-2">
{{ error }}.<br /> {{ error }}.<br />
<button @click="retry()" class="text-blue-500 underline">Повторить</button> <button @click="retry()" class="text-blue-500 dark:text-blue-400 underline">Повторить</button>
</p> </p>
</template> </template>
@@ -1,7 +1,11 @@
<template> <template>
<section> <section>
<h2 class="text-xl font-semibold mb-4">Где вы хотите разместить QRкод?</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4">Этот выбор поможет настроить QRкод с подходящими действиями.</p> Где вы хотите разместить QRкод?
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
Этот выбор поможет настроить QRкод с подходящими действиями.
</p>
<div class="flex flex-col gap-3 mb-4"> <div class="flex flex-col gap-3 mb-4">
<div v-for="{ label, type } in qrCodePlacements" :key="type" class="flex items-center gap-2"> <div v-for="{ label, type } in qrCodePlacements" :key="type" class="flex items-center gap-2">
<RadioButton <RadioButton
@@ -11,7 +15,7 @@
:value="type" :value="type"
@change="$emit('nextStep')" @change="$emit('nextStep')"
/> />
<label :for="type">{{ label }}</label> <label :for="type" class="text-gray-700 dark:text-gray-300">{{ label }}</label>
</div> </div>
</div> </div>
</section> </section>
@@ -1,18 +1,26 @@
<template> <template>
<section> <section>
<h2 class="text-xl font-semibold mb-4">Сообщения для отправки</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4"> Сообщения для отправки
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
После считывания QRкода можно будет выбрать одно из этих сообщений или написать своё. После считывания QRкода можно будет выбрать одно из этих сообщений или написать своё.
</p> </p>
<p class="text-sm text-gray-500 mb-6">Вы сможете изменить эти сообщения позже.</p> <p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
Вы сможете изменить эти сообщения позже.
</p>
<!-- Список сообщений --> <!-- Список сообщений -->
<div class="flex flex-col gap-2 mb-4"> <div class="flex flex-col gap-2 mb-4">
<div v-for="(message, index) in messages" :key="index" class="flex gap-2" ref="messagesRef"> <div v-for="(message, index) in messages" :key="index" class="flex gap-2" ref="messagesRef">
<InputText v-model="messages[index]" class="flex-1" placeholder="Введите сообщение" /> <InputText
v-model="messages[index]"
class="flex-1 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700"
placeholder="Введите сообщение"
/>
<Button <Button
icon="pi pi-trash" icon="pi pi-trash"
class="p-button-danger p-button-text" variant="text"
@click="removeMessage(index)" @click="removeMessage(index)"
title="Удалить сообщение" title="Удалить сообщение"
/> />
@@ -23,7 +31,7 @@
<Button <Button
label="Добавить сообщение" label="Добавить сообщение"
icon="pi pi-plus" icon="pi pi-plus"
class="p-button-sm p-button-outlined mb-4" class="p-button-sm p-button-outlined mb-4 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-300"
@click="addMessage" @click="addMessage"
/> />
</section> </section>
@@ -1,17 +1,28 @@
<template> <template>
<section> <section>
<h2 class="text-xl font-semibold mb-4">Введите название для вашего QRкода</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4">Название поможет вам организовать ваши QRкоды.</p> Введите название для вашего QRкода
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
Название поможет вам организовать ваши QRкоды.
</p>
<form @submit.prevent="emit('nextStep')"> <form @submit.prevent="emit('nextStep')">
<label for="name" class="block text-gray-700 font-semibold mb-2">Название</label> <label for="name" class="block text-gray-700 dark:text-gray-300 font-semibold mb-2">
<InputText id="name" v-model="name" class="w-full" placeholder="Введите название" /> Название
<p v-if="!name" class="text-red-500 text-sm mt-1">Название обязательно.</p> </label>
<InputText
id="name"
v-model="name"
class="w-full dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700"
placeholder="Введите название"
/>
<p v-if="!name" class="text-red-500 dark:text-red-400 text-sm mt-1">Название обязательно</p>
<Button <Button
type="submit" type="submit"
:label="buttonLabel" :label="buttonLabel"
class="p-button-md mt-4 mb-4" class="p-button-md mt-4 mb-4 dark:border-orange-500 dark:hover:border-orange-600 dark:text-gray-300"
:loading="isPending" :loading="isPending"
:disabled="!name || isPending" :disabled="!name || isPending"
/> />
@@ -1,9 +1,9 @@
<template> <template>
<div <div
class="sticky bottom-0 bg-white shadow-md py-safe-or-4 sm:border-b sm:order-first sm:justify-center touch-none" class="sticky bottom-0 bg-white dark:bg-gray-800 shadow-md dark:shadow-lg py-safe-or-4 sm:border-b dark:sm:border-gray-700 sm:order-first sm:justify-center touch-none"
> >
<div <div
class="flex justify-around sm:justify-between sm:gap-8 sm:px-4 sm:flex-row sm:bg-white sm:max-w-prose mx-auto" class="flex justify-around sm:justify-between sm:gap-8 sm:px-4 sm:flex-row sm:bg-white dark:sm:bg-gray-800 sm:max-w-prose mx-auto"
> >
<TabMenuItem <TabMenuItem
v-for="{ route, label, icon, unreadCount } in tabs" v-for="{ route, label, icon, unreadCount } in tabs"
@@ -12,6 +12,7 @@
:icon :icon
:to="{ name: route }" :to="{ name: route }"
:unreadCount :unreadCount
class="dark:text-gray-300 dark:hover:text-gray-100"
/> />
</div> </div>
</div> </div>
@@ -6,16 +6,26 @@
@click="navigate" @click="navigate"
class="flex flex-col items-center w-full sm:flex-row sm:items-center sm:w-auto gap-1 relative" class="flex flex-col items-center w-full sm:flex-row sm:items-center sm:w-auto gap-1 relative"
> >
<i :class="['pi', `pi-${icon}`, 'text-2xl sm:mr-2', isActive && 'text-primary-700']"></i> <i
:class="[
'pi',
`pi-${icon}`,
'text-2xl sm:mr-2',
isActive ? 'text-primary-700 dark:text-primary-300' : 'text-gray-700 dark:text-gray-300',
]"
></i>
<span <span
class="text-xs font-medium sm:text-base text-center" class="text-xs font-medium sm:text-base text-center"
:class="{ 'text-primary-700': isActive, 'text-gray-700': !isActive }" :class="{
'text-primary-700 dark:text-primary-300': isActive,
'text-gray-700 dark:text-gray-300': !isActive,
}"
> >
{{ label }} {{ label }}
</span> </span>
<span <span
v-if="unreadCount && unreadCount > 0" v-if="unreadCount && unreadCount > 0"
class="absolute top-0 -right-2.5 bg-red-500 text-white text-xs rounded-full px-1" class="absolute top-0 -right-2.5 bg-red-500 dark:bg-red-600 text-white text-xs rounded-full px-1"
> >
{{ unreadCount }} {{ unreadCount }}
</span> </span>
@@ -1,12 +1,24 @@
<template> <template>
<a <a
:href="url" :href="url"
class="font-mono text-nowrap text-sm text-gray-600 underline underline-offset-4 hover:text-gray-800 hover:no-underline" class="font-mono text-nowrap text-sm hover:no-underline"
target="_blank" target="_blank"
>{{ url }}</a v-text="url"
> />
</template> </template>
<style scoped lang="scss">
a {
color: var(--p-surface-500); // Очень нейтральный цвет для менее акцентной ссылки
text-decoration: none;
&:hover {
color: var(--p-surface-700); // Немного более насыщенный цвет при наведении
text-decoration: none;
}
}
</style>
<script setup lang="ts"> <script setup lang="ts">
defineProps<{ url: string }>() defineProps<{ url: string }>()
</script> </script>
@@ -1,11 +1,13 @@
<template> <template>
<div class="max-w-3xl mx-auto py-6 px-4 md:px-6"> <div class="max-w-3xl mx-auto py-6 px-4 md:px-6">
<div v-if="isLoading" class="text-gray-500">Загрузка инструкции...</div> <div v-if="isLoading" class="text-gray-500 dark:text-gray-400">Загрузка инструкции...</div>
<div v-else-if="data" class="markdown"> <div v-else-if="data" class="markdown dark:text-gray-300">
<VueMarkdownIt :source="data" /> <VueMarkdownIt :source="data" />
</div> </div>
<p v-else-if="isError" class="text-red-500">Ошибка загрузки инструкции.</p> <p v-else-if="isError" class="text-red-500 dark:text-red-400">Ошибка загрузки инструкции.</p>
<p v-else class="text-gray-500">Инструкция для этого типа размещения отсутствует.</p> <p v-else class="text-gray-500 dark:text-gray-400">
Инструкция для этого типа размещения отсутствует.
</p>
</div> </div>
</template> </template>
@@ -35,102 +37,97 @@ const { isLoading, isError, data } = useQuery({
}) })
</script> </script>
<style scoped> <style scoped lang="scss">
.markdown { .markdown {
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
line-height: 1.7; line-height: 1.7;
color: #333; color: var(--p-text-color);
}
.markdown ::v-deep(h1) { & ::v-deep(h1) {
font-size: 2rem; font-size: 2rem;
margin-bottom: 1rem; margin-bottom: 1rem;
color: #111827; color: var(--p-primary-color);
font-weight: 700; font-weight: 700;
} }
.markdown ::v-deep(h2) { & ::v-deep(h2) {
font-size: 1.75rem; font-size: 1.75rem;
margin-top: 1.5rem; margin-top: 1.5rem;
margin-bottom: 1rem; margin-bottom: 1rem;
color: #1f2937; color: var(--p-secondary-color);
font-weight: 600; font-weight: 600;
} }
.markdown ::v-deep(h3) { & ::v-deep(h3) {
font-size: 1.5rem; font-size: 1.5rem;
margin-top: 1.25rem; margin-top: 1.25rem;
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
color: #374151; color: var(--p-secondary-light-color);
font-weight: 500; font-weight: 500;
} }
.markdown ::v-deep(p) { & ::v-deep(p) {
margin-bottom: 1rem; margin-bottom: 1rem;
color: #4b5563; color: var(--p-text-secondary-color);
} }
.markdown ::v-deep(ul) { & ::v-deep(ul),
list-style: disc; & ::v-deep(ol) {
margin-left: 1.5rem; margin-left: 1.5rem;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.markdown ::v-deep(ol) { & ::v-deep(li) {
list-style: decimal;
margin-left: 1.5rem;
margin-bottom: 1rem;
}
.markdown ::v-deep(li) {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.markdown ::v-deep(a) { & ::v-deep(a) {
color: #2563eb; color: var(--p-link-color);
text-decoration: underline; text-decoration: underline;
} }
.markdown ::v-deep(blockquote) { & ::v-deep(blockquote) {
border-left: 4px solid #d1d5db; border-left: 4px solid var(--p-border-color);
padding-left: 1rem; padding-left: 1rem;
color: #6b7280; color: var(--p-text-secondary-color);
margin: 1rem 0; margin: 1rem 0;
font-style: italic; font-style: italic;
} }
.markdown ::v-deep(code) { & ::v-deep(code) {
background-color: #f3f4f6; background-color: var(--p-surface-50);
border-radius: 4px; border-radius: 4px;
padding: 0.2rem 0.4rem; padding: 0.2rem 0.4rem;
font-family: 'Courier New', Courier, monospace; font-family: 'Courier New', Courier, monospace;
color: #1f2937; color: var(--p-text-color);
} }
.markdown ::v-deep(pre) { & ::v-deep(pre) {
background-color: #f9fafb; background-color: var(--p-surface-100);
padding: 1rem; padding: 1rem;
border-radius: 8px; border-radius: 8px;
overflow-x: auto; overflow-x: auto;
color: #111827; color: var(--p-text-color);
font-family: 'Courier New', Courier, monospace; font-family: 'Courier New', Courier, monospace;
} }
.markdown ::v-deep(table) { & ::v-deep(table) {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.markdown ::v-deep(th), & ::v-deep(th),
.markdown ::v-deep(td) { & ::v-deep(td) {
border: 1px solid #d1d5db; border: 1px solid var(--p-border-color);
padding: 0.5rem; padding: 0.5rem;
} }
.markdown ::v-deep(th) { & ::v-deep(th) {
background-color: #f9fafb; background-color: var(--p-surface-200);
font-weight: 600; font-weight: 600;
text-align: left; text-align: left;
color: var(--p-text-color);
}
} }
</style> </style>
@@ -1,18 +1,17 @@
<template> <template>
<RouterLink :to="`/manage/qr/${qrCode.uri}`" class="p-4 rounded-lg bg-white shadow-md"> <RouterLink
:to="`/manage/qr/${qrCode.uri}`"
class="p-4 rounded-lg bg-white dark:bg-gray-800 shadow-md text-gray-800 dark:text-gray-300"
>
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<div class="flex items-center"> <div class="flex items-center gap-2">
<QRCodePlacementIcon :placement="qrCode.placement" /> <QRCodePlacementIcon :placement="qrCode.placement" />
<h2 class="text-lg font-semibold">{{ qrCode.name }}</h2> <h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">
{{ qrCode.name }}
</h2>
</div> </div>
<!-- <Button-->
<!-- label="Настроить"-->
<!-- :to="`/manage/${qrCode.uri}/settings`"-->
<!-- as="router-link"-->
<!-- class="p-button-outlined p-button-sm"-->
<!-- />-->
</div> </div>
<div class="text-gray-500"> <div class="text-gray-500 dark:text-gray-400">
Создан: <span class="text-nowrap">{{ formatedCreatedAt }}</span> Создан: <span class="text-nowrap">{{ formatedCreatedAt }}</span>
</div> </div>
</RouterLink> </RouterLink>
@@ -1,5 +1,5 @@
<template> <template>
<i :class="['pi', iconClass, 'text-gray-500', 'mr-2']" /> <i :class="['pi', iconClass, 'text-gray-500', 'dark:text-gray-300', 'mr-2']" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@@ -1,7 +1,9 @@
<template> <template>
<section class="max-w-prose w-full text-center"> <section class="max-w-prose w-full text-center">
<!-- Контактная информация --> <!-- Контактная информация -->
<div class="flex items-start bg-gray-100 border rounded-lg p-4"> <div
class="flex items-start bg-gray-100 dark:bg-gray-800 border dark:border-gray-700 rounded-lg p-4"
>
<!-- Аватарка Gravatar --> <!-- Аватарка Gravatar -->
<div v-if="contactInfo.email" class="flex-shrink-0 mr-4"> <div v-if="contactInfo.email" class="flex-shrink-0 mr-4">
<img <img
@@ -14,18 +16,23 @@
<!-- Контакты --> <!-- Контакты -->
<div class="text-left flex-grow"> <div class="text-left flex-grow">
<p v-if="contactInfo.name" class="text-lg font-semibold">{{ contactInfo.name }}</p> <p v-if="contactInfo.name" class="text-lg font-semibold text-gray-900 dark:text-gray-100">
{{ contactInfo.name }}
</p>
<p v-if="contactInfo.phone" class="text-gray-700"> <p v-if="contactInfo.phone" class="text-gray-700 dark:text-gray-300">
Телефон: Телефон:
<a :href="`tel:${formattedPhone}`" class="underline text-blue-600"> <a :href="`tel:${formattedPhone}`" class="underline text-blue-600 dark:text-blue-400">
{{ contactInfo.phone }} {{ contactInfo.phone }}
</a> </a>
</p> </p>
<p v-if="contactInfo.email" class="text-gray-700"> <p v-if="contactInfo.email" class="text-gray-700 dark:text-gray-300">
Email: Email:
<a :href="`mailto:${contactInfo.email}`" class="underline text-blue-600"> <a
:href="`mailto:${contactInfo.email}`"
class="underline text-blue-600 dark:text-blue-400"
>
{{ contactInfo.email }} {{ contactInfo.email }}
</a> </a>
</p> </p>
@@ -40,8 +47,12 @@
</div> </div>
</div> </div>
<p v-if="success" class="text-green-500 mt-4">Контакт успешно добавлен в адресную книгу!</p> <p v-if="success" class="text-green-500 dark:text-green-400 mt-4">
<p v-if="error" class="text-red-500 mt-4">Ошибка добавления контакта: {{ error }}</p> Контакт успешно добавлен в адресную книгу!
</p>
<p v-if="error" class="text-red-500 dark:text-red-400 mt-4">
Ошибка добавления контакта: {{ error }}
</p>
</section> </section>
</template> </template>
@@ -1,6 +1,9 @@
<template> <template>
<section class="max-w-prose w-full"> <section class="max-w-prose w-full">
<p class="text-gray-600 mb-4 text-center" v-if="doc.predefinedMessages?.length"> <p
class="text-gray-600 dark:text-gray-400 mb-4 text-center"
v-if="doc.predefinedMessages?.length"
>
Выберите сообщение из списка или напишите своё: Выберите сообщение из списка или напишите своё:
</p> </p>
@@ -10,7 +13,7 @@
<Button <Button
v-for="(message, index) in doc.predefinedMessages" v-for="(message, index) in doc.predefinedMessages"
:key="index" :key="index"
class="p-button-outlined w-full text-left" class="w-full p-button-outlined text-left dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700"
:disabled="loading" :disabled="loading"
@click="sendPresetMessage(message)" @click="sendPresetMessage(message)"
> >
@@ -24,20 +27,22 @@
<InputText <InputText
id="customMessage" id="customMessage"
v-model="customMessage" v-model="customMessage"
class="flex-1" class="flex-1 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700"
placeholder="Напишите сообщение" placeholder="Напишите сообщение"
:disabled="loading" :disabled="loading"
/> />
<Button <Button
type="submit" type="submit"
icon="pi pi-send" icon="pi pi-send"
class="p-button-md" class="p-button-md dark:bg-primary-600 dark:hover:bg-primary-700"
:disabled="!customMessage.trim() || loading" :disabled="!customMessage.trim() || loading"
/> />
</form> </form>
<p v-if="success" class="text-green-500 mt-4 text-center">Сообщение отправлено!</p> <p v-if="success" class="text-green-500 dark:text-green-400 mt-4 text-center">
<p v-if="error" class="text-red-500 mt-4 text-center">Ошибка: {{ error }}</p> Сообщение отправлено!
</p>
<p v-if="error" class="text-red-500 dark:text-red-400 mt-4 text-center">Ошибка: {{ error }}</p>
</section> </section>
</template> </template>
+10 -2
View File
@@ -2,6 +2,7 @@
<div <div
class="grid h-full sm:grid-rows-[auto_1fr_auto] grid-rows-[1fr_auto_auto] overflow-hidden touch-none" class="grid h-full sm:grid-rows-[auto_1fr_auto] grid-rows-[1fr_auto_auto] overflow-hidden touch-none"
> >
<!-- Content Section -->
<div <div
class="flex overflow-hidden overflow-y-auto pb-safe-or-4 sm:pt-safe px-4 overscroll-contain touch-manipulation" class="flex overflow-hidden overflow-y-auto pb-safe-or-4 sm:pt-safe px-4 overscroll-contain touch-manipulation"
ref="contentScrollContainer" ref="contentScrollContainer"
@@ -11,20 +12,27 @@
</div> </div>
</div> </div>
<!-- Footer Section -->
<slot name="footer"> <slot name="footer">
<footer <footer
v-if="!slots.footer" v-if="!slots.footer"
class="bg-gray-100 text-center py-1.5 border-t text-xs sm:text-base text-gray-700 sm:order-last sm:pb-safe-or-1.5" class="bg-gray-100 dark:bg-gray-800 text-center py-1.5 border-t dark:border-gray-700 text-xs sm:text-base text-gray-700 dark:text-gray-300 sm:order-last sm:pb-safe-or-1.5"
> >
<span class="text-nowrap">Сделайте НаСвязи удобнее.</span> <span class="text-nowrap">Сделайте НаСвязи удобнее.</span>
<span> </span> <span> </span>
<span class="text-nowrap"> <span class="text-nowrap">
Будем рады Будем рады
<a href="/donate" class="underline underline-offset-2">вашей поддержке</a> <a
href="/donate"
class="underline underline-offset-2 text-primary-600 dark:text-primary-400"
>
вашей поддержке
</a>
</span> </span>
</footer> </footer>
</slot> </slot>
<!-- TabBar -->
<TabBar /> <TabBar />
</div> </div>
</template> </template>
+3 -22
View File
@@ -6,29 +6,10 @@ import { VueQueryPlugin, type VueQueryPluginOptions } from '@tanstack/vue-query'
import PouchDB from '@/api/PouchDB' import PouchDB from '@/api/PouchDB'
import PrimeVue from 'primevue/config' import PrimeVue from 'primevue/config'
import { definePreset } from '@primevue/themes' import { PrimeVueHereConnectPreset } from './themes/PrimeVueHereConnectPreset'
import Aura from '@primevue/themes/aura'
import './style.css' import './style.css'
import 'primeicons/primeicons.css' import 'primeicons/primeicons.css'
const MyPreset = definePreset(Aura, {
semantic: {
primary: {
50: '{rose.50}',
100: '{rose.100}',
200: '{rose.200}',
300: '{rose.300}',
400: '{rose.400}',
500: '{rose.500}',
600: '{rose.600}',
700: '{rose.700}',
800: '{rose.800}',
900: '{rose.900}',
950: '{rose.950}',
},
},
})
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
@@ -55,9 +36,9 @@ app.use(VueQueryPlugin, vueQueryPluginOptions)
app.use(router) app.use(router)
app.use(PrimeVue, { app.use(PrimeVue, {
theme: { theme: {
preset: MyPreset, preset: PrimeVueHereConnectPreset,
options: { options: {
darkModeSelector: false, darkModeSelector: 'system',
}, },
}, },
}) })
@@ -0,0 +1,13 @@
import { ref, watch } from 'vue'
import { defineStore } from 'pinia'
export const usePrefersColorSchemeStore = defineStore('prefersColorScheme', () => {
const prefersColorSchemeDarkMatchMedia = window.matchMedia('(prefers-color-scheme: dark)')
const isDarkMode = ref<boolean>(prefersColorSchemeDarkMatchMedia.matches)
prefersColorSchemeDarkMatchMedia.addEventListener('change', (e) => {
isDarkMode.value = e.matches
})
return { isDarkMode }
})
@@ -0,0 +1,45 @@
import { definePreset } from '@primevue/themes'
import Aura from '@primevue/themes/aura'
export const PrimeVueHereConnectPreset = definePreset(Aura, {
semantic: {
colorScheme: {
light: {
primary: {
50: '{rose.50}',
100: '{rose.100}',
200: '{rose.200}',
300: '{rose.300}',
400: '{rose.400}',
500: '{rose.500}',
600: '{rose.600}',
700: '{rose.700}',
800: '{rose.800}',
900: '{rose.900}',
950: '{rose.950}',
},
highlight: {
background: '{rose.100}',
focusBackground: '{rose.200}',
color: '#000000',
focusColor: '#000000',
},
},
dark: {
primary: {
50: '{orange.50}',
100: '{orange.100}',
200: '{orange.200}',
300: '{orange.300}',
400: '{orange.400}',
500: '{orange.500}',
600: '{orange.600}',
700: '{yellow.700}',
800: '{orange.800}',
900: '{orange.900}',
950: '{orange.950}',
},
},
},
},
})
+3 -1
View File
@@ -39,7 +39,9 @@
</template> </template>
</CreateSectionManager> </CreateSectionManager>
<p v-if="isError" class="text-red-500 mt-4">Ошибка создания QRкода: {{ error }}</p> <p v-if="isError" class="text-red-500 dark:text-red-400 mt-4">
Ошибка создания QRкода: {{ error }}
</p>
<div class="h-[30dvh] md:h-[10dvh] overflow-hidden"></div> <div class="h-[30dvh] md:h-[10dvh] overflow-hidden"></div>
</LayoutWithTabs> </LayoutWithTabs>
+12 -31
View File
@@ -1,7 +1,9 @@
<template> <template>
<LayoutWithTabs> <LayoutWithTabs>
<template #footer> <template #footer>
<footer class="py-4 border-t text-center text-sm hidden sm:block"> <footer
class="py-4 border-t text-center text-sm hidden sm:block border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400"
>
<p>НаСвязи © 2024</p> <p>НаСвязи © 2024</p>
</footer> </footer>
</template> </template>
@@ -12,8 +14,10 @@
</MetaHead> </MetaHead>
<section class="max-w-2xl mx-auto py-8 px-4 text-center"> <section class="max-w-2xl mx-auto py-8 px-4 text-center">
<h1 class="text-2xl font-bold mb-4">Поддержите развитие НаСвязи</h1> <h1 class="text-2xl font-bold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-6"> Поддержите развитие НаСвязи
</h1>
<p class="text-gray-600 dark:text-gray-400 mb-6">
Мы делаем всё, чтобы НаСвязи оставался удобным и полезным. Вы можете помочь нам, поддержав Мы делаем всё, чтобы НаСвязи оставался удобным и полезным. Вы можете помочь нам, поддержав
проект на Бусти. проект на Бусти.
</p> </p>
@@ -24,7 +28,7 @@
href="https://boosty.to/hereconnect/donate" href="https://boosty.to/hereconnect/donate"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="inline-block bg-orange-500 text-white font-semibold py-3 px-6 rounded-lg shadow hover:bg-orange-600 transition duration-300" class="inline-block bg-orange-500 text-white font-semibold py-3 px-6 rounded-lg shadow hover:bg-orange-600 transition duration-300 dark:hover:bg-orange-700"
> >
Поддержать через Бусти Поддержать через Бусти
</a> </a>
@@ -32,8 +36,10 @@
<!-- Рассказать друзьям --> <!-- Рассказать друзьям -->
<div class="mb-8"> <div class="mb-8">
<h2 class="text-xl font-semibold mb-4">Рассказать друзьям</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4">Поделитесь ссылкой на НаСвязи:</p> Рассказать друзьям
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">Поделитесь ссылкой на НаСвязи:</p>
<div class="flex justify-center gap-6"> <div class="flex justify-center gap-6">
<!-- Telegram --> <!-- Telegram -->
<a <a
@@ -56,31 +62,6 @@
</a> </a>
</div> </div>
</div> </div>
<!-- Обратная связь -->
<!-- <div>-->
<!-- <h2 class="text-xl font-semibold mb-4">Оставить отзыв или идею</h2>-->
<!-- <p class="text-gray-600 mb-4">Мы рады любым предложениям и обратной связи.</p>-->
<!-- <form @submit.prevent="sendFeedback">-->
<!-- <div class="mb-4">-->
<!-- <InputText v-model="email" class="w-full" placeholder="Ваш email" />-->
<!-- </div>-->
<!-- <div class="mb-4">-->
<!-- <Textarea-->
<!-- v-model="message"-->
<!-- rows="4"-->
<!-- class="w-full"-->
<!-- placeholder="Ваше сообщение"-->
<!-- ></Textarea>-->
<!-- </div>-->
<!-- <Button-->
<!-- label="Отправить"-->
<!-- class="p-button-md"-->
<!-- :disabled="!email.trim() || !message.trim()"-->
<!-- />-->
<!-- </form>-->
<!-- <p v-if="success" class="text-green-500 mt-4">Спасибо за ваше сообщение!</p>-->
<!-- </div>-->
</section> </section>
</LayoutWithTabs> </LayoutWithTabs>
</template> </template>
+5 -3
View File
@@ -19,10 +19,12 @@
<!-- Уведомление, если гость отправил только одно сообщение --> <!-- Уведомление, если гость отправил только одно сообщение -->
<div <div
v-if="count === 1 && lastMessage && lastMessage.from === 'guest'" v-if="count === 1 && lastMessage && lastMessage.from === 'guest'"
class="flex flex-col items-center justify-center text-center bg-gray-50 border border-gray-200 rounded-lg shadow-md p-6 my-6" class="flex flex-col items-center justify-center text-center bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-md p-6 my-6"
> >
<p class="text-gray-700 font-medium text-lg">Ваше сообщение отправлено.</p> <p class="text-gray-700 dark:text-gray-200 font-medium text-lg">
<p class="text-gray-600 mt-2"> Ваше сообщение отправлено.
</p>
<p class="text-gray-600 dark:text-gray-400 mt-2">
Вы можете написать ещё одно сообщение или подождать ответа. Вы можете написать ещё одно сообщение или подождать ответа.
</p> </p>
</div> </div>
+9 -3
View File
@@ -22,15 +22,21 @@
</section> </section>
</main> </main>
<footer class="bg-gray-100 text-center py-4 border-t text-sm text-gray-700"> <footer
class="bg-gray-100 dark:bg-gray-800 text-center py-4 border-t dark:border-gray-700 text-sm text-gray-700 dark:text-gray-300"
>
<p> <p>
Нужен такой же? Нужен такой же?
<a href="/create" class="underline underline-offset-2">Создайте свой QRкод</a>. <a
href="/create"
class="underline underline-offset-2 text-primary-600 dark:text-primary-400"
>Создайте свой QRкод</a
>.
</p> </p>
<p class="mt-1"> <p class="mt-1">
Сделайте НаСвязи удобнее. Будем рады вашей&nbsp;<a Сделайте НаСвязи удобнее. Будем рады вашей&nbsp;<a
href="/donate" href="/donate"
class="underline underline-offset-2" class="underline underline-offset-2 text-primary-600 dark:text-primary-400"
>поддержке</a >поддержке</a
>. >.
</p> </p>
@@ -18,24 +18,28 @@
<section class="max-w-prose w-full flex flex-col gap-1"> <section class="max-w-prose w-full flex flex-col gap-1">
<div <div
v-if="svgQueryIsLoading || qrCodeQueryIsLoading" v-if="svgQueryIsLoading || qrCodeQueryIsLoading"
class="text-gray-500 mt-4 text-center" class="text-gray-500 dark:text-gray-400 mt-4 text-center"
> >
<ProgressSpinner styleClass="mt-4" /> <ProgressSpinner styleClass="mt-4" />
</div> </div>
<p v-else-if="svgQueryIsError" class="text-red-500 mt-4 text-center"> <p v-else-if="svgQueryIsError" class="text-red-500 dark:text-red-400 mt-4 text-center">
Ошибка генерации QRкода: {{ svgQueryError?.message }} Ошибка генерации QRкода: {{ svgQueryError?.message }}
</p> </p>
<p v-else-if="qrCodeQueryIsError" class="text-red-500 mt-4 text-center"> <p v-else-if="qrCodeQueryIsError" class="text-red-500 dark:text-red-400 mt-4 text-center">
Ошибка загрузки данных QRкода: {{ qrCodeQueryError!.message }} Ошибка загрузки данных QRкода: {{ qrCodeQueryError!.message }}
</p> </p>
<template v-else> <template v-else>
<h2 class="text-xl font-semibold mb-4">Ваш QRкод готов</h2> <h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 mb-4"> Ваш QRкод готов
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-4">
Сохраните его и ознакомьтесь с инструкциями по размещению. Сохраните его и ознакомьтесь с инструкциями по размещению.
</p> </p>
<!-- Рендер QRкода --> <!-- Рендер QRкода -->
<div class="border p-4 bg-white rounded-lg mb-6"> <div class="border dark:border-gray-700 p-4 bg-white rounded-lg mb-6">
<!-- dark:bg-gray-800 -->
<img v-if="!svgQueryIsLoading && svgQueryData" :src="svgQueryData" alt="QR‑код" /> <img v-if="!svgQueryIsLoading && svgQueryData" :src="svgQueryData" alt="QR‑код" />
</div> </div>
@@ -47,7 +51,7 @@
<Button <Button
label="Скачать SVG" label="Скачать SVG"
icon="pi pi-download" icon="pi pi-download"
class="p-button-sm" class="p-button-sm dark:border-orange-500 dark:hover:border-orange-600 dark:text-gray-300"
:href="svgQueryData" :href="svgQueryData"
:download="`${sanitizedFileName}.svg`" :download="`${sanitizedFileName}.svg`"
as="a" as="a"
+12 -1
View File
@@ -6,7 +6,18 @@ import tailwindcssSafeArea from 'tailwindcss-safe-area'
export default { export default {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: { theme: {
extend: {}, extend: {
colors: {
// primary: {
// 400: '#FFA726', // Светлый акцентный цвет для темной темы
// 600: '#FB8C00', // Основной акцентный цвет для светлой темы
// },
// orange: {
// 600: '#FB923C',
// 700: '#F97316',
// },
},
},
}, },
plugins: [tailwindScrollbar, tailwindcssPrimeUI, tailwindcssSafeArea], plugins: [tailwindScrollbar, tailwindcssPrimeUI, tailwindcssSafeArea],
} }
+276 -18
View File
@@ -143,6 +143,9 @@ importers:
rollup-plugin-manifest-json: rollup-plugin-manifest-json:
specifier: ^1.7.0 specifier: ^1.7.0
version: 1.7.0 version: 1.7.0
sass-embedded:
specifier: ^1.82.0
version: 1.82.0
tailwindcss: tailwindcss:
specifier: ^3.4.14 specifier: ^3.4.14
version: 3.4.15 version: 3.4.15
@@ -163,7 +166,7 @@ importers:
version: 0.27.5(vue@3.5.13) version: 0.27.5(vue@3.5.13)
vite: vite:
specifier: ^5.4.10 specifier: ^5.4.10
version: 5.4.11(@types/node@20.17.9) version: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
vite-plugin-mock-data: vite-plugin-mock-data:
specifier: ^4.0.6 specifier: ^4.0.6
version: 4.0.6 version: 4.0.6
@@ -172,7 +175,7 @@ importers:
version: 7.6.7(vite@5.4.11)(vue@3.5.13) version: 7.6.7(vite@5.4.11)(vue@3.5.13)
vitest: vitest:
specifier: ^2.1.4 specifier: ^2.1.4
version: 2.1.6(@types/node@20.17.9)(jsdom@25.0.1) version: 2.1.6(@types/node@20.17.9)(jsdom@25.0.1)(sass-embedded@1.82.0)
vue-tsc: vue-tsc:
specifier: ^2.1.10 specifier: ^2.1.10
version: 2.1.10(typescript@5.6.3) version: 2.1.10(typescript@5.6.3)
@@ -717,6 +720,10 @@ packages:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
dev: true dev: true
/@bufbuild/protobuf@2.2.2:
resolution: {integrity: sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==}
dev: true
/@esbuild/aix-ppc64@0.21.5: /@esbuild/aix-ppc64@0.21.5:
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -2049,7 +2056,7 @@ packages:
vite: ^5.0.0 || ^6.0.0 vite: ^5.0.0 || ^6.0.0
vue: ^3.2.25 vue: ^3.2.25
dependencies: dependencies:
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
vue: 3.5.13(typescript@5.6.3) vue: 3.5.13(typescript@5.6.3)
dev: true dev: true
@@ -2069,7 +2076,7 @@ packages:
'@typescript-eslint/utils': 8.16.0(eslint@9.15.0)(typescript@5.6.3) '@typescript-eslint/utils': 8.16.0(eslint@9.15.0)(typescript@5.6.3)
eslint: 9.15.0 eslint: 9.15.0
typescript: 5.6.3 typescript: 5.6.3
vitest: 2.1.6(@types/node@20.17.9)(jsdom@25.0.1) vitest: 2.1.6(@types/node@20.17.9)(jsdom@25.0.1)(sass-embedded@1.82.0)
dev: true dev: true
/@vitest/expect@0.34.6: /@vitest/expect@0.34.6:
@@ -2103,7 +2110,7 @@ packages:
'@vitest/spy': 2.1.6 '@vitest/spy': 2.1.6
estree-walker: 3.0.3 estree-walker: 3.0.3
magic-string: 0.30.14 magic-string: 0.30.14
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
dev: true dev: true
/@vitest/pretty-format@2.1.6: /@vitest/pretty-format@2.1.6:
@@ -2684,6 +2691,10 @@ packages:
node-int64: 0.4.0 node-int64: 0.4.0
dev: true dev: true
/buffer-builder@0.2.0:
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
dev: true
/buffer-equal-constant-time@1.0.1: /buffer-equal-constant-time@1.0.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
dev: false dev: false
@@ -2833,6 +2844,10 @@ packages:
/color-name@1.1.4: /color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
/colorjs.io@0.5.2:
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
dev: true
/combined-stream@1.0.8: /combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@@ -3959,6 +3974,10 @@ packages:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
dev: false dev: false
/immutable@5.0.3:
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
dev: true
/import-fresh@3.3.0: /import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -5808,6 +5827,12 @@ packages:
dependencies: dependencies:
queue-microtask: 1.2.3 queue-microtask: 1.2.3
/rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
dependencies:
tslib: 2.8.1
dev: true
/safe-buffer@5.2.1: /safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false dev: false
@@ -5821,6 +5846,222 @@ packages:
/safer-buffer@2.1.2: /safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
/sass-embedded-android-arm64@1.82.0:
resolution: {integrity: sha512-bldHMs02QQWXsgHUZRgolNnZdMjN6XHvmUYoRkzmFq7lsvtLU6SJg2S1Wa9IZJs9jRWdTmOgA6YibSf3pROyFQ==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/sass-embedded-android-arm@1.82.0:
resolution: {integrity: sha512-ttGMvWnA/5TYdZTjr5fWHDbb9nZgKipHKCc9zZQRF5HjUydOYWKNqmAJHQtbFWaq35kd5qn6yiE73IJN6eJ6wA==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/sass-embedded-android-ia32@1.82.0:
resolution: {integrity: sha512-FUJOnxw8IYKuYuxxiOkk6QXle8/yQFtKjnuSAJuZ5ZpLVMcSZzLc3SWOtuEXYx5iSAfJCO075o2ZoG/pPrJ9aw==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [android]
requiresBuild: true
dev: true
optional: true
/sass-embedded-android-riscv64@1.82.0:
resolution: {integrity: sha512-rd+vc+sxJxNnbhaubiIJmnb1b3FvC9wxCIq8spstopbO7o1uufvBBDeRoFSJaN+7oNhamzjlYGdu6aQoQNs3+A==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [android]
requiresBuild: true
dev: true
optional: true
/sass-embedded-android-x64@1.82.0:
resolution: {integrity: sha512-EVlybGTgJ8wNLyWj8RUatPXSnmIcvCsx3EfsRfBfhGihLbn4NNpavYO9QsvZzI2XWbJqHLBCd+CvkTcDw/TaSQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/sass-embedded-darwin-arm64@1.82.0:
resolution: {integrity: sha512-LvdJPojjKlNGYOB0nSUR/ZtMDuAF4puspHlwK42aA/qK292bfSkMUKZPPapB2aSRwccc/ieBq5fI7n/WHrOCVw==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/sass-embedded-darwin-x64@1.82.0:
resolution: {integrity: sha512-6LfnD6YmG1aBfd3ReqMOJDb6Pg2Z/hmlJB7nU+Lb3E+hCNjAZAgeUHQxU/Pm1eIqJJTU/h4ib5QP0Pt9O8yVnw==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-arm64@1.82.0:
resolution: {integrity: sha512-590/y0HJr/JiyxaqgR7Xf9P20BIhJ+zhB/afAnVuZe/4lEfCpTyM5xMe2+sKLsqtrVyzs9Zm/M4S4ASUOPCggA==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-arm@1.82.0:
resolution: {integrity: sha512-ozjdC5rWzyi5Vo300I4tVZzneXOTQUiaxOr7DjtN26HuFaGAGCGmvThh2BRV4RvySg++5H9rdFu+VgyUQ5iukw==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-ia32@1.82.0:
resolution: {integrity: sha512-hpc4acZ3UTjjJ3Q/GUXqQOCSml6AFKaku0HMawra9bKyRmOpxn8V5hqgXeOWVjK2oQzCmCnJvwKoQUP+S/SIYQ==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-musl-arm64@1.82.0:
resolution: {integrity: sha512-bc2MUSMv/jabnNGEyKP2jQAYZoEzTT/c633W6QoeSEWETGCuTNjaHvWWE6qSI6/UfRg1EpuV1LQA2jPMzZfv/w==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-musl-arm@1.82.0:
resolution: {integrity: sha512-R5PQmY/I+GSoMtfLo8GgHkvF/q6x6y8VNM7yu/Ac1mJj86n48VFi29W1HfY2496+Q6cpAq7toobDj7YfldIdVA==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-musl-ia32@1.82.0:
resolution: {integrity: sha512-ZQKCFKm5TBcJ19UG6uUQmIKfVCJIWMb7e1a93lGeujSb9gyKF5Fb6MN3tuExoT7iFK8zU0Z9iyHqh93F58lcCw==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-musl-riscv64@1.82.0:
resolution: {integrity: sha512-5meSU8BHFeaT09RWfkuUrikRlC+WZcYb9To7MpfV1d9nlD7CZ2xydPExK+mj3DqRuQvTbvhMPcr7f+pHlgHINQ==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-musl-x64@1.82.0:
resolution: {integrity: sha512-ASLAMfjWv7YEPBvEOVlb3zzHq8l4Y9Eh4x3m7B1dNauGVbO11Yng5cPCX/XbwGVf30BtE75pwqvV7oXxBtN15w==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-riscv64@1.82.0:
resolution: {integrity: sha512-qWvRDXCXH3GzD8OcP0ntd8gBTK3kZyUeyXmxQDZyEtMAM4STC2Tn7+5+2JYYHlppzqWnZPFBNESvpKeOtHaBBw==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-linux-x64@1.82.0:
resolution: {integrity: sha512-AmRaHqShztwfep+M4NagdGaY7fTyWGSOM3k4Z/dd7q4nZclXbALLqNJtKx8xOM7A41LHYJ9zDpIBVRkrh0PzTA==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/sass-embedded-win32-arm64@1.82.0:
resolution: {integrity: sha512-zL9JDQZHXHSGAZe5DqSrR86wMHbm9QPziU4/3hoIG+99StuS74CuV42+hw/+FXXBkXMWbjKWsyF/HZt+I/wJuw==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/sass-embedded-win32-ia32@1.82.0:
resolution: {integrity: sha512-xE+AzLquCkFPnnpo0NHjQdLRIhG1bVs42xIKx42aUbVLYKkBDvbBGpw6EtTscRMyvcjoOqGH5saRvSFComUQcw==}
engines: {node: '>=14.0.0'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/sass-embedded-win32-x64@1.82.0:
resolution: {integrity: sha512-cEgfOQG5womOzzk16ReTv2dxPq5BG16LgLUold/LH9IZH86u4E/MN7Fspf4RWeEJ2EcLdew9QYSC2YWs1l98dQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/sass-embedded@1.82.0:
resolution: {integrity: sha512-v13sRVVZtWAQLpAGTz5D8hy+oyNKRHao5tKVc/P6AMqSP+jDM8X6GkEpL0jfbu3MaN2/hAQsd4Qx14GG1u0prQ==}
engines: {node: '>=16.0.0'}
hasBin: true
dependencies:
'@bufbuild/protobuf': 2.2.2
buffer-builder: 0.2.0
colorjs.io: 0.5.2
immutable: 5.0.3
rxjs: 7.8.1
supports-color: 8.1.1
sync-child-process: 1.0.2
varint: 6.0.0
optionalDependencies:
sass-embedded-android-arm: 1.82.0
sass-embedded-android-arm64: 1.82.0
sass-embedded-android-ia32: 1.82.0
sass-embedded-android-riscv64: 1.82.0
sass-embedded-android-x64: 1.82.0
sass-embedded-darwin-arm64: 1.82.0
sass-embedded-darwin-x64: 1.82.0
sass-embedded-linux-arm: 1.82.0
sass-embedded-linux-arm64: 1.82.0
sass-embedded-linux-ia32: 1.82.0
sass-embedded-linux-musl-arm: 1.82.0
sass-embedded-linux-musl-arm64: 1.82.0
sass-embedded-linux-musl-ia32: 1.82.0
sass-embedded-linux-musl-riscv64: 1.82.0
sass-embedded-linux-musl-x64: 1.82.0
sass-embedded-linux-riscv64: 1.82.0
sass-embedded-linux-x64: 1.82.0
sass-embedded-win32-arm64: 1.82.0
sass-embedded-win32-ia32: 1.82.0
sass-embedded-win32-x64: 1.82.0
dev: true
/saxes@6.0.0: /saxes@6.0.0:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'} engines: {node: '>=v12.22.7'}
@@ -6092,6 +6333,18 @@ packages:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
dev: true dev: true
/sync-child-process@1.0.2:
resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==}
engines: {node: '>=16.0.0'}
dependencies:
sync-message-port: 1.1.3
dev: true
/sync-message-port@1.1.3:
resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==}
engines: {node: '>=16.0.0'}
dev: true
/synckit@0.9.2: /synckit@0.9.2:
resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
@@ -6494,7 +6747,7 @@ packages:
git-url-parse: 15.0.0 git-url-parse: 15.0.0
simple-git: 3.27.0 simple-git: 3.27.0
unplugin: 1.16.0 unplugin: 1.16.0
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@@ -6577,12 +6830,16 @@ packages:
convert-source-map: 2.0.0 convert-source-map: 2.0.0
dev: true dev: true
/varint@6.0.0:
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
dev: true
/vite-hot-client@0.2.4(vite@5.4.11): /vite-hot-client@0.2.4(vite@5.4.11):
resolution: {integrity: sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==} resolution: {integrity: sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==}
peerDependencies: peerDependencies:
vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0
dependencies: dependencies:
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
dev: true dev: true
/vite-node@0.34.6(@types/node@20.17.9): /vite-node@0.34.6(@types/node@20.17.9):
@@ -6595,7 +6852,7 @@ packages:
mlly: 1.7.3 mlly: 1.7.3
pathe: 1.1.2 pathe: 1.1.2
picocolors: 1.1.1 picocolors: 1.1.1
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- less - less
@@ -6608,7 +6865,7 @@ packages:
- terser - terser
dev: true dev: true
/vite-node@2.1.6(@types/node@20.17.9): /vite-node@2.1.6(@types/node@20.17.9)(sass-embedded@1.82.0):
resolution: {integrity: sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==} resolution: {integrity: sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true hasBin: true
@@ -6617,7 +6874,7 @@ packages:
debug: 4.3.7 debug: 4.3.7
es-module-lexer: 1.5.4 es-module-lexer: 1.5.4
pathe: 1.1.2 pathe: 1.1.2
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- less - less
@@ -6649,7 +6906,7 @@ packages:
perfect-debounce: 1.0.0 perfect-debounce: 1.0.0
picocolors: 1.1.1 picocolors: 1.1.1
sirv: 3.0.0 sirv: 3.0.0
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
- supports-color - supports-color
@@ -6675,7 +6932,7 @@ packages:
'@vue/devtools-shared': 7.6.7 '@vue/devtools-shared': 7.6.7
execa: 9.5.1 execa: 9.5.1
sirv: 3.0.0 sirv: 3.0.0
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
vite-plugin-inspect: 0.8.8(vite@5.4.11) vite-plugin-inspect: 0.8.8(vite@5.4.11)
vite-plugin-vue-inspector: 5.3.1(vite@5.4.11) vite-plugin-vue-inspector: 5.3.1(vite@5.4.11)
transitivePeerDependencies: transitivePeerDependencies:
@@ -6699,12 +6956,12 @@ packages:
'@vue/compiler-dom': 3.5.13 '@vue/compiler-dom': 3.5.13
kolorist: 1.8.0 kolorist: 1.8.0
magic-string: 0.30.14 magic-string: 0.30.14
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/vite@5.4.11(@types/node@20.17.9): /vite@5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0):
resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true hasBin: true
@@ -6739,6 +6996,7 @@ packages:
esbuild: 0.21.5 esbuild: 0.21.5
postcss: 8.4.49 postcss: 8.4.49
rollup: 4.27.4 rollup: 4.27.4
sass-embedded: 1.82.0
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
dev: true dev: true
@@ -6795,7 +7053,7 @@ packages:
strip-literal: 1.3.0 strip-literal: 1.3.0
tinybench: 2.9.0 tinybench: 2.9.0
tinypool: 0.7.0 tinypool: 0.7.0
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
vite-node: 0.34.6(@types/node@20.17.9) vite-node: 0.34.6(@types/node@20.17.9)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
transitivePeerDependencies: transitivePeerDependencies:
@@ -6809,7 +7067,7 @@ packages:
- terser - terser
dev: true dev: true
/vitest@2.1.6(@types/node@20.17.9)(jsdom@25.0.1): /vitest@2.1.6(@types/node@20.17.9)(jsdom@25.0.1)(sass-embedded@1.82.0):
resolution: {integrity: sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==} resolution: {integrity: sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true hasBin: true
@@ -6853,8 +7111,8 @@ packages:
tinyexec: 0.3.1 tinyexec: 0.3.1
tinypool: 1.0.2 tinypool: 1.0.2
tinyrainbow: 1.2.0 tinyrainbow: 1.2.0
vite: 5.4.11(@types/node@20.17.9) vite: 5.4.11(@types/node@20.17.9)(sass-embedded@1.82.0)
vite-node: 2.1.6(@types/node@20.17.9) vite-node: 2.1.6(@types/node@20.17.9)(sass-embedded@1.82.0)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
transitivePeerDependencies: transitivePeerDependencies:
- less - less