add mange qr-codes
Deploy frontend / frontend (push) Successful in 57s

This commit is contained in:
2024-12-03 00:17:47 +02:00
parent 2f4ae28cce
commit 5c7cb6f8db
8 changed files with 140 additions and 11 deletions
+1
View File
@@ -28,6 +28,7 @@ declare module 'vue' {
InputText: typeof import('primevue/inputtext')['default']
ManagePlacementInstructions: typeof import('./src/components/manage/ManagePlacementInstructions.vue')['default']
ProgressSpinner: typeof import('primevue/progressspinner')['default']
QRCodeCard: typeof import('./src/components/manage/QRCodeCard.vue')['default']
QueryRender: typeof import('./src/components/QueryRender.vue')['default']
RadioButton: typeof import('primevue/radiobutton')['default']
ReadContactInfo: typeof import('./src/components/read/ReadContactInfo.vue')['default']
+3 -1
View File
@@ -2,7 +2,9 @@
"name": "НаСвязи",
"short_name": "НаСвязи",
"categories": ["communication", "utilities", "social", "productivity"],
"start_url": "/",
"id": "https://hereconnect.condev.ru",
"start_url": "https://hereconnect.condev.ru/manage/dashboard",
"scope": "https://hereconnect.condev.ru/",
"icons": [
{
"src": "/android-chrome-192x192.png",
+15 -5
View File
@@ -5,16 +5,26 @@ type Props = {
query: UseQueryReturnType<R, E>
}
const slots = defineSlots<{
default?: (slotBindings: { data: R }) => void
error?: (slotBindings: { error: E; reload: typeof refetch }) => void
loading?: () => void
}>()
const { query } = defineProps<Props>()
const { data, error, refetch, isSuccess, isError, isLoading } = query
</script>
<template>
<slot v-if="isSuccess" name="default" :data="data! as R" />
<slot v-else-if="isLoading" name="loading"><p class="text-gray-500">Загрузка данных...</p></slot>
<slot v-else-if="isError" name="error" :error="error as E" :reload="refetch">
Ошибка загрузки данных:
{{ error && typeof error === 'object' && 'message' in error ? error.message : error }}
<slot v-if="isSuccess" name="default" :data="data!" />
<slot v-else-if="isLoading" name="loading">
<p class="text-gray-500" v-if="!slots.loading">Загрузка данных...</p>
</slot>
<slot v-else-if="isError" name="error" :error="error!" :reload="refetch">
<template v-if="!slots.error">
Ошибка загрузки данных:
{{ error && typeof error === 'object' && 'message' in error ? error.message : error }}
</template>
</slot>
</template>
@@ -0,0 +1,46 @@
<template>
<RouterLink :to="`/manage/qr/${qrCode.uri}`" class="p-4 rounded-lg bg-white shadow-md">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center">
<i :class="['pi', iconClass, 'text-gray-500', 'mr-2']" />
<h2 class="text-lg font-semibold">{{ qrCode.name }}</h2>
</div>
<!-- <Button-->
<!-- label="Настроить"-->
<!-- :to="`/manage/${qrCode.uri}/settings`"-->
<!-- as="router-link"-->
<!-- class="p-button-outlined p-button-sm"-->
<!-- />-->
</div>
<div class="text-gray-500">Создано: {{ formatedCreatedAt }}</div>
</RouterLink>
</template>
<script setup lang="ts">
import { computed, defineProps } from 'vue'
import type { QRCodeDocument } from '@hereconnect/types'
const props = defineProps<{
qrCode: QRCodeDocument
}>()
const iconClass = computed(() => {
const icons: Record<string, string> = {
car: 'pi-car',
pet: 'pi-paw',
door: 'pi-door-closed',
store: 'pi-shop',
restaurant_table: 'pi-utensils',
other: 'pi-question-circle',
}
return icons[props.qrCode.placement] || 'pi-question-circle'
})
const formatDate = (date: string) => {
// Форматирование даты
const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric' }
return new Date(date).toLocaleDateString(['ru-RU'], options)
}
const formatedCreatedAt = computed(() => formatDate(props.qrCode.created_at))
</script>
+1
View File
@@ -3,6 +3,7 @@ export const ROUTE_NAMES = {
CREATE: 'create',
MANAGE_QR_CODE_READY: 'manage-qr-code-ready',
MANAGE_QR_CODE_CHAT: 'manage-qr-code-chat',
MANAGE_DASHBOARD: 'manage-dashboard',
READ_QR_CODE: 'read-qr-code',
DONATE: 'donate',
PUBLIC_CHAT: 'public-chat',
+9 -3
View File
@@ -14,13 +14,19 @@ const routes = [
component: () => import('@/views/CreateView.vue'),
},
{
path: '/manage/:qr_code_uri/ready',
path: '/manage/dashboard',
name: ROUTE_NAMES.MANAGE_DASHBOARD,
component: () => import('@/views/ManageDashboardView.vue'),
props: true,
},
{
path: '/manage/qr/:qr_code_uri/ready',
name: ROUTE_NAMES.MANAGE_QR_CODE_READY,
component: () => import('@/views/ManageQRCodeReadyView.vue'),
props: true,
},
{
path: '/manage/:qr_code_uri/chat/:chat',
path: '/manage/qr/:qr_code_uri/chat/:chat',
name: ROUTE_NAMES.MANAGE_QR_CODE_CHAT,
component: () => import('@/views/ManageQRCodeChatView.vue'),
props: true,
@@ -37,7 +43,7 @@ const routes = [
component: () => import('@/views/DonateView.vue'),
},
{
path: '/chat/:qr_code_uri/:chat',
path: '/read/:qr_code_uri/chat/:chat',
name: ROUTE_NAMES.PUBLIC_CHAT,
component: () => import('@/views/PublicChatView.vue'),
props: true,
@@ -0,0 +1,63 @@
<template>
<div class="p-6">
<h1 class="text-2xl font-bold mb-4 text-center">Управление QR-кодами</h1>
<QueryRender :query="query">
<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-sm"
/>
</div>
</div>
<div v-else class="text-center text-gray-500">
<p>Нет созданных 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="text-center text-red-500">
<p>Произошла ошибка при загрузке данных. Пожалуйста, попробуйте позже.</p>
<Button label="Повторить попытку" class="p-button mt-4" @click="reload()" />
</div>
</template>
<template #loading>
<div class="text-center text-gray-500">
<p>Загрузка QR-кодов...</p>
<ProgressSpinner styleClass="mt-4" />
</div>
</template>
</QueryRender>
</div>
</template>
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query'
import { qrCodeDbLocal } from '@/api/dbs'
const query = useQuery({
queryKey: ['qrCodes'],
queryFn: async () => {
return qrCodeDbLocal.allDocs({
include_docs: true,
startkey: 'qr_code:',
endkey: 'qr_code:\uffff',
})
},
})
</script>
@@ -121,7 +121,7 @@ const start = async () => {
requireInteraction: true,
timestamp,
data: {
url: `/manage/${msgDoc.qr_code_uri}/chat/${msgDoc.chat}#message-${msgDoc.created_at}`,
url: `/manage/qr/${msgDoc.qr_code_uri}/chat/${msgDoc.chat}#message-${msgDoc.created_at}`,
payload: { tag },
},
} as const;
@@ -200,7 +200,7 @@ const start = async () => {
requireInteraction: true,
timestamp,
data: {
url: `/chat/${msgDoc.qr_code_uri}/${msgDoc.chat}#message-${msgDoc.created_at}`,
url: `/read/qr/${msgDoc.qr_code_uri}/chat/${msgDoc.chat}#msg-${msgDoc.created_at}`,
payload: { tag },
},
} as const;