Add list search, compact business cards, registration approval queue, and Montime branding.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-23 18:13:24 +03:30
co-authored by Cursor
parent be26c6d89a
commit 5629213449
15 changed files with 519 additions and 67 deletions
+29 -27
View File
@@ -1,6 +1,32 @@
<template>
<article class="overflow-hidden rounded-2xl border border-border bg-surface-2 transition hover:border-brand-500/40 hover:shadow-md">
<div class="relative aspect-[16/10] bg-surface-3">
<article
class="flex items-center gap-3 rounded-xl border border-border bg-surface-2 p-2.5 transition hover:border-brand-500/40 hover:shadow-sm"
>
<div class="min-w-0 flex-1">
<div class="flex items-start justify-between gap-2">
<div class="min-w-0 flex-1">
<h3 class="truncate text-sm font-semibold text-text">{{ business.title }}</h3>
<p v-if="business.category" class="mt-0.5 truncate text-xs text-muted">
{{ business.category.title }}
</p>
<p v-if="ownerText" class="mt-0.5 truncate text-xs text-muted">{{ ownerText }}</p>
</div>
<AppBadge
class="shrink-0 !px-1.5 !py-0.5 text-[10px]"
:tone="business.isActive ? 'success' : 'warning'"
>
{{ activeLabel(business.isActive) }}
</AppBadge>
</div>
<div v-if="$slots.actions" class="mt-2 flex flex-wrap gap-1">
<slot name="actions" />
</div>
</div>
<div
class="relative h-14 w-14 shrink-0 overflow-hidden rounded-lg bg-surface-3 sm:h-16 sm:w-16"
>
<img
v-if="cover"
:src="cover"
@@ -10,28 +36,10 @@
/>
<div
v-else
class="flex h-full w-full items-center justify-center text-4xl text-muted/50"
class="flex h-full w-full items-center justify-center text-xl text-muted/50"
>
🏪
</div>
<AppBadge
class="absolute left-2 top-2"
:tone="business.isActive ? 'success' : 'warning'"
>
{{ activeLabel(business.isActive) }}
</AppBadge>
</div>
<div class="p-3">
<h3 class="truncate font-semibold text-text">{{ business.title }}</h3>
<p v-if="business.category" class="mt-0.5 truncate text-xs text-muted">
{{ business.category.title }}
</p>
<p v-if="ownerText" class="mt-1 truncate text-xs text-muted">{{ ownerText }}</p>
<div v-if="$slots.actions" class="mt-3 grid gap-1" :class="actionGridClass">
<slot name="actions" />
</div>
</div>
</article>
</template>
@@ -46,13 +54,7 @@ import { businessCoverUrl } from '@/utils/media';
const props = defineProps<{
business: Business;
ownerText?: string | null;
actionCols?: number;
}>();
const cover = computed(() => businessCoverUrl(props.business.images));
const actionGridClass = computed(() => {
const cols = props.actionCols ?? 3;
return cols === 2 ? 'grid-cols-2' : 'grid-cols-3';
});
</script>
+29
View File
@@ -0,0 +1,29 @@
<template>
<AppInput
:id="id"
v-model="model"
type="search"
:label="label"
:placeholder="placeholder"
autocomplete="off"
enterkeyhint="search"
/>
</template>
<script setup lang="ts">
import AppInput from '@/components/ui/AppInput.vue';
const model = defineModel<string>({ default: '' });
withDefaults(
defineProps<{
id?: string;
label?: string;
placeholder?: string;
}>(),
{
id: 'search',
placeholder: 'جستجو…',
},
);
</script>