improve
Deploy app frontend / app frontend (push) Successful in 1m36s

This commit is contained in:
2024-12-06 14:42:03 +02:00
parent 9c69812258
commit 2a1ab52235
9 changed files with 202 additions and 128 deletions
+3
View File
@@ -28,6 +28,9 @@ declare module 'vue' {
ExamplesSection: typeof import('./src/components/TheWelcome/ExamplesSection.vue')['default'] ExamplesSection: typeof import('./src/components/TheWelcome/ExamplesSection.vue')['default']
InputText: typeof import('primevue/inputtext')['default'] InputText: typeof import('primevue/inputtext')['default']
LinkCopyButton: typeof import('./src/components/link/LinkCopyButton.vue')['default'] LinkCopyButton: typeof import('./src/components/link/LinkCopyButton.vue')['default']
LinkMono: typeof import('./src/components/link/LinkMono.vue')['default']
LinkQrCode: typeof import('./src/components/link/LinkQrCode.vue')['default']
LinkQRCode: typeof import('./src/components/link/LinkQRCode.vue')['default']
LinkShareButton: typeof import('./src/components/link/LinkShareButton.vue')['default'] LinkShareButton: typeof import('./src/components/link/LinkShareButton.vue')['default']
LinkShareTelegramButton: typeof import('./src/components/link/LinkShareTelegramButton.vue')['default'] LinkShareTelegramButton: typeof import('./src/components/link/LinkShareTelegramButton.vue')['default']
ManagePlacementInstructions: typeof import('./src/components/manage/ManagePlacementInstructions.vue')['default'] ManagePlacementInstructions: typeof import('./src/components/manage/ManagePlacementInstructions.vue')['default']
+3 -1
View File
@@ -19,7 +19,9 @@ const { data, error, refetch, isSuccess, isError, isLoading } = query
<template> <template>
<slot v-if="isSuccess" name="default" :data="data!" /> <slot v-if="isSuccess" name="default" :data="data!" />
<slot v-else-if="isLoading" name="loading"> <slot v-else-if="isLoading" name="loading">
<p class="text-gray-500" v-if="!slots.loading">Загрузка данных...</p> <div class="text-center text-gray-500" v-if="!slots.loading">
<ProgressSpinner styleClass="mt-4" />
</div>
</slot> </slot>
<slot v-else-if="isError" name="error" :error="error!" :reload="refetch"> <slot v-else-if="isError" name="error" :error="error!" :reload="refetch">
<template v-if="!slots.error"> <template v-if="!slots.error">
@@ -0,0 +1,12 @@
<template>
<a
:href="url"
class="font-mono text-nowrap text-sm text-gray-600 underline underline-offset-4 hover:text-gray-800 hover:no-underline"
target="_blank"
>{{ url }}</a
>
</template>
<script setup lang="ts">
defineProps<{ url: string }>()
</script>
@@ -10,7 +10,7 @@
rel="noopener noreferrer" rel="noopener noreferrer"
icon="pi pi-telegram" icon="pi pi-telegram"
title="Поделиться ссылкой в Telegram" title="Поделиться ссылкой в Telegram"
label="отправить ссылку в Telegram" label="Отправить ссылку в Telegram"
/> />
</template> </template>
+1
View File
@@ -5,6 +5,7 @@ export const ROUTE_NAMES = {
MANAGE_QR_CODE_READY: 'manage-qr-code-ready', MANAGE_QR_CODE_READY: 'manage-qr-code-ready',
MANAGE_QR_CODE_CHAT: 'manage-qr-code-chat', MANAGE_QR_CODE_CHAT: 'manage-qr-code-chat',
MANAGE_DASHBOARD: 'manage-dashboard', MANAGE_DASHBOARD: 'manage-dashboard',
MANAGE_DASHBOARD_QR: 'manage-dashboard-qr',
READ_QR_CODE: 'read-qr-code', READ_QR_CODE: 'read-qr-code',
DONATE: 'donate', DONATE: 'donate',
PUBLIC_CHAT: 'public-chat', PUBLIC_CHAT: 'public-chat',
+6
View File
@@ -25,6 +25,12 @@ const routes = [
component: () => import('@/views/ManageDashboardView.vue'), component: () => import('@/views/ManageDashboardView.vue'),
props: true, props: true,
}, },
{
path: '/manage/qr',
name: ROUTE_NAMES.MANAGE_DASHBOARD_QR,
component: () => import('@/views/ManageDashboardView.vue'),
props: true,
},
{ {
path: '/manage/qr/:qr_code_uri', path: '/manage/qr/:qr_code_uri',
name: ROUTE_NAMES.MANAGE_QR_CODE, name: ROUTE_NAMES.MANAGE_QR_CODE,
+69 -42
View File
@@ -1,48 +1,75 @@
<template> <template>
<div class="p-6"> <MetaHead>
<h1 class="text-2xl font-bold mb-4 text-center">Управление QR-кодами</h1> <title>Ваши QR-коды НаСвязи</title>
<QueryRender :query="query"> <meta
<template #default="{ data }"> name="description"
<div v-if="data.rows.length > 0" class="flex flex-col gap-5"> content="Просматривайте и управляйте сообщениями, отправленными через ваш QR-код. Полная конфиденциальность и удобный интерфейс чата"
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> />
<QRCodeCard v-for="{ doc: qrCode } in data.rows" :key="qrCode!.uri" :qrCode="qrCode!" /> </MetaHead>
</div>
<div class="text-center">
<Button
icon="pi pi-qrcode"
label="Создать QR‑код"
to="/create"
as="router-link"
class="p-button-outlined p-button-sm"
/>
</div>
</div>
<div v-else class="text-center text-gray-500">
<p class="mb-6">Нет созданных QR-кодов. Вы можете создать их прямо сейчас!</p>
<Button
icon="pi pi-qrcode"
label="Создать QR‑код"
to="/create"
as="router-link"
class="p-button-lg"
/>
</div>
</template>
<template #error="{ reload }"> <div class="flex flex-col min-h-full">
<div class="text-center text-red-500"> <main class="flex-grow flex justify-center py-6 px-4 md:px-6">
<p>Произошла ошибка при загрузке данных. Пожалуйста, попробуйте позже.</p> <div>
<Button label="Повторить попытку" class="p-button mt-4" @click="reload()" /> <h1 class="text-2xl font-bold mb-4 text-center lg:text-left">Управление QR-кодами</h1>
</div> <QueryRender :query="query">
</template> <template #default="{ data }">
<div v-if="data.rows.length > 0" class="flex flex-col gap-5">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<QRCodeCard
v-for="{ doc: qrCode } in data.rows"
:key="qrCode!.uri"
:qrCode="qrCode!"
/>
</div>
<div class="text-center">
<Button
icon="pi pi-qrcode"
label="Создать QR‑код"
to="/create"
as="router-link"
class="p-button-outlined p-button-sm"
/>
</div>
</div>
<div v-else class="text-center text-gray-500">
<p class="mb-6">Нет созданных QR-кодов. Вы можете создать их прямо сейчас!</p>
<Button
icon="pi pi-qrcode"
label="Создать QR‑код"
to="/create"
as="router-link"
class="p-button-lg"
/>
</div>
</template>
<template #loading> <template #error="{ reload }">
<div class="text-center text-gray-500"> <div class="text-center text-red-500">
<p>Загрузка QR-кодов...</p> <p>Произошла ошибка при загрузке данных. Пожалуйста, попробуйте позже.</p>
<ProgressSpinner styleClass="mt-4" /> <Button label="Повторить попытку" class="p-button mt-4" @click="reload()" />
</div> </div>
</template> </template>
</QueryRender>
<template #loading>
<div class="text-center text-gray-500">
<p>Загрузка QR-кодов...</p>
<ProgressSpinner styleClass="mt-4" />
</div>
</template>
</QueryRender>
</div>
</main>
<footer class="bg-gray-100 text-center py-4 border-t text-sm text-gray-700">
<p>
Нужен еще один?
<a href="/create" class="underline">Создайте QRкод</a>.
</p>
<p class="mt-1">
Сделайте НаСвязи удобнее. Будем рады вашей&nbsp;<a href="/donate" class="underline"
>поддержке</a
>.
</p>
</footer>
</div> </div>
</template> </template>
@@ -16,9 +16,12 @@
}" }"
> >
<section class="max-w-prose w-full flex flex-col gap-1"> <section class="max-w-prose w-full flex flex-col gap-1">
<p v-if="svgQueryIsLoading || qrCodeQueryIsLoading" class="text-gray-500 mt-4"> <div
Загрузка... v-if="svgQueryIsLoading || qrCodeQueryIsLoading"
</p> class="text-gray-500 mt-4 text-center"
>
<ProgressSpinner styleClass="mt-4" />
</div>
<p v-else-if="svgQueryIsError" class="text-red-500 mt-4"> <p v-else-if="svgQueryIsError" class="text-red-500 mt-4">
Ошибка генерации QRкода: {{ svgQueryError?.message }} Ошибка генерации QRкода: {{ svgQueryError?.message }}
</p> </p>
@@ -62,16 +65,7 @@
<div v-if="qrCodeDoc && qrCodeDoc.url" class="text-center mt-6 text-sm"> <div v-if="qrCodeDoc && qrCodeDoc.url" class="text-center mt-6 text-sm">
<div> <div>
Ссылка в QR-коде: Ссылка в QR-коде:
<span class="text-nowrap"> <LinkQRCode :url="qrCodeDoc.url" />
<a
class="font-mono text-sm text-gray-600 underline underline-offset-4 hover:text-gray-800 hover:no-underline"
:href="qrCodeDoc.url"
target="_blank"
rel="noopener noreferrer"
>
{{ qrCodeDoc.url }}
</a>
</span>
</div> </div>
<div class="flex gap-2 justify-center mt-2"> <div class="flex gap-2 justify-center mt-2">
<LinkCopyButton :url="qrCodeDoc.url" /> <LinkCopyButton :url="qrCodeDoc.url" />
+100 -71
View File
@@ -1,75 +1,105 @@
<template> <template>
<div class="p-6"> <div class="flex flex-col min-h-full">
<h1 class="text-2xl font-bold mb-4 text-center lg:text-left">Управление QR-кодом</h1> <main class="flex-grow flex justify-center py-6 px-4 md:px-6">
<QueryRender :query="qrCodeQuery" #default="{ data: qrCodeDoc }"> <div>
<div class="bg-white p-6 rounded-lg shadow-md mb-6"> <h1 class="text-2xl font-bold mb-4 text-center lg:text-left">Управление QR-кодом</h1>
<div class="flex items-center justify-between mb-4"> <QueryRender :query="qrCodeQuery">
<div class="flex items-center"> <template #default="{ data: qrCodeDoc }">
<QRCodePlacementIcon :placement="qrCodeDoc.placement" /> <MetaHead>
<h2 class="text-xl font-semibold">{{ qrCodeDoc.name }}</h2> <title>{{ qrCodeDoc.name }}: управление QR-кодом НаСвязи</title>
</div> <meta
<div class="flex gap-2"> name="description"
<Button content="Просматривайте и управляйте сообщениями, отправленными через ваш QR-код. Полная конфиденциальность и удобный интерфейс чата"
icon="pi pi-cog" />
label="Настроить" </MetaHead>
:to="`/manage/qr/${qrCodeDoc.uri}/settings`" <div class="bg-white p-6 rounded-lg shadow-md mb-6">
as="router-link" <div class="flex items-center justify-between mb-4">
severity="secondary" <div class="flex items-center">
size="small" <QRCodePlacementIcon :placement="qrCodeDoc.placement" />
outlined <h2 class="text-xl font-semibold">{{ qrCodeDoc.name }}</h2>
/> </div>
<Button <div class="flex gap-2">
icon="pi pi-qrcode" <!-- <Button-->
label="QR-код и инструкции" <!-- icon="pi pi-cog"-->
:to="`/manage/qr/${qrCodeDoc.uri}/ready`" <!-- label="Настроить"-->
as="router-link" <!-- :to="`/manage/qr/${qrCodeDoc.uri}/settings`"-->
severity="secondary" <!-- as="router-link"-->
size="small" <!-- severity="secondary"-->
outlined <!-- size="small"-->
/> <!-- outlined-->
</div> <!-- />-->
</div> <Button
<div class="mb-4 flex gap-2 items-baseline"> icon="pi pi-qrcode"
<strong>Ссылка: </strong> label="QR-код и инструкции"
<a :href="qrCodeDoc.url" class="text-blue-500" target="_blank">{{ qrCodeDoc.url }}</a> :to="`/manage/qr/${qrCodeDoc.uri}/ready`"
<LinkCopyButton :url="qrCodeDoc.url" /> as="router-link"
<LinkShareTelegramButton severity="secondary"
:shareUrl="qrCodeDoc.url" size="small"
shareText="Используйте эту ссылку НаСвязи!" outlined
/> />
</div> </div>
<div> </div>
<p><strong>Создано:</strong> {{ formatDate(qrCodeDoc.created_at) }}</p> <div class="mb-4 flex gap-2 items-baseline flex-wrap">
<!-- <p><strong>Количество сканирований:</strong> {{ qrCodeDoc.scanCount }}</p>--> <strong>Ссылка: </strong>
<!-- <p><strong>Последнее сканирование:</strong> {{ formatDate(qrCodeDoc.lastScan) }}</p>--> <LinkQRCode :url="qrCodeDoc.url" />
</div> <div class="flex gap-2 items-baseline flex-wrap">
</div> <LinkCopyButton :url="qrCodeDoc.url" />
</QueryRender> <LinkShareTelegramButton
:shareUrl="qrCodeDoc.url"
shareText="Используйте эту ссылку НаСвязи!"
/>
</div>
</div>
<div>
<p>
<strong>Создано: </strong>
<span class="text-nowrap">{{ formatDate(qrCodeDoc.created_at) }}</span>
</p>
<!-- <p><strong>Количество сканирований:</strong> {{ qrCodeDoc.scanCount }}</p>-->
<!-- <p><strong>Последнее сканирование:</strong> {{ formatDate(qrCodeDoc.lastScan) }}</p>-->
</div>
</div>
</template>
</QueryRender>
<!-- <div class="bg-white p-6 rounded-lg shadow-md mb-6">--> <!-- <div class="bg-white p-6 rounded-lg shadow-md mb-6">-->
<!-- <h2 class="text-xl font-bold mb-4">Чаты</h2>--> <!-- <h2 class="text-xl font-bold mb-4">Чаты</h2>-->
<!-- <div v-if="chats.length > 0" class="grid grid-cols-1 gap-4">--> <!-- <div v-if="chats.length > 0" class="grid grid-cols-1 gap-4">-->
<!-- <div v-for="chat in chats" :key="chat._id" class="p-4 rounded-lg bg-white shadow-md">--> <!-- <div v-for="chat in chats" :key="chat._id" class="p-4 rounded-lg bg-white shadow-md">-->
<!-- <div class="flex items-center justify-between">--> <!-- <div class="flex items-center justify-between">-->
<!-- <div>--> <!-- <div>-->
<!-- <p class="text-lg font-semibold">Чат #{{ chat._id }}</p>--> <!-- <p class="text-lg font-semibold">Чат #{{ chat._id }}</p>-->
<!-- <p class="text-gray-500">--> <!-- <p class="text-gray-500">-->
<!-- Последнее сообщение: {{ formatDate(chat.lastMessageDate) }}--> <!-- Последнее сообщение: {{ formatDate(chat.lastMessageDate) }}-->
<!-- </p>--> <!-- </p>-->
<!-- </div>--> <!-- </div>-->
<!-- <Button--> <!-- <Button-->
<!-- label="Открыть"--> <!-- label="Открыть"-->
<!-- :to="`/manage/qr/${qrCodeDoc.uri}/chat/${chat._id}`"--> <!-- :to="`/manage/qr/${qrCodeDoc.uri}/chat/${chat._id}`"-->
<!-- as="router-link"--> <!-- as="router-link"-->
<!-- class="p-button-outlined p-button-sm"--> <!-- class="p-button-outlined p-button-sm"-->
<!-- />--> <!-- />-->
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
<!-- <div v-else class="text-center text-gray-500">--> <!-- <div v-else class="text-center text-gray-500">-->
<!-- <p>Нет активных чатов для этого QR-кода.</p>--> <!-- <p>Нет активных чатов для этого QR-кода.</p>-->
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
</div>
</main>
<footer class="bg-gray-100 text-center py-4 border-t text-sm text-gray-700">
<p>
Нужен еще один?
<a href="/create" class="underline">Создайте QRкод</a>.
</p>
<p class="mt-1">
Сделайте НаСвязи удобнее. Будем рады вашей&nbsp;<a href="/donate" class="underline"
>поддержке</a
>.
</p>
</footer>
</div> </div>
</template> </template>
@@ -77,7 +107,6 @@
import { computed } from 'vue' import { computed } from 'vue'
import type { QRCodeDocument } from '@hereconnect/types' import type { QRCodeDocument } from '@hereconnect/types'
import { getQrCodeDocument } from '@/api/qrCode' import { getQrCodeDocument } from '@/api/qrCode'
import CopyLinkButton from '@/components/CopyLinkButton.vue'
const props = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>() const props = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>()