From 4f3d461dcf0bec397a486863e06a2251403e4b79 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sun, 24 May 2026 15:58:52 +0330 Subject: [PATCH] Add optional slug field to business registration form Co-authored-by: Cursor --- src/api/types.ts | 1 + src/utils/slug.ts | 21 ++++++++++++++++++ src/views/app/AppRegisterBusinessView.vue | 26 ++++++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/utils/slug.ts diff --git a/src/api/types.ts b/src/api/types.ts index c02b29d..12ef004 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -50,6 +50,7 @@ export type BusinessRegistrationRequest = { export type CreateBusinessRegistrationPayload = { title: string; categoryId: string; + slug?: string; description?: string; contactPhone?: string; address?: string; diff --git a/src/utils/slug.ts b/src/utils/slug.ts new file mode 100644 index 0000000..a3a4f71 --- /dev/null +++ b/src/utils/slug.ts @@ -0,0 +1,21 @@ +/** Simple slug for API (latin, hyphen-separated). */ +export function slugify(value: string): string { + return value + .trim() + .toLowerCase() + .replace(/\s+/g, '-') + .replace(/[^a-z0-9-]/g, '') + .replace(/-+/g, '-') + .replace(/^-|-$/g, ''); +} + +const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/; + +export function isValidSlug(slug: string): boolean { + return SLUG_PATTERN.test(slug); +} + +export function optionalSlug(value: string): string | undefined { + const trimmed = value.trim(); + return trimmed || undefined; +} diff --git a/src/views/app/AppRegisterBusinessView.vue b/src/views/app/AppRegisterBusinessView.vue index a5919dd..07f55f8 100644 --- a/src/views/app/AppRegisterBusinessView.vue +++ b/src/views/app/AppRegisterBusinessView.vue @@ -37,7 +37,16 @@
- + + +
@@ -93,6 +102,7 @@ import AppButton from '@/components/ui/AppButton.vue'; import AppInput from '@/components/ui/AppInput.vue'; import WebAppLayout from '@/layouts/WebAppLayout.vue'; import { useAuthStore } from '@/stores/auth'; +import { isValidSlug, optionalSlug, slugify } from '@/utils/slug'; const router = useRouter(); const auth = useAuthStore(); @@ -100,11 +110,13 @@ const auth = useAuthStore(); const loading = ref(true); const saving = ref(false); const error = ref(''); +const slugTouched = ref(false); const categories = ref([]); const requests = ref([]); const form = ref({ title: '', + slug: '', categoryId: '', description: '', contactPhone: '', @@ -148,17 +160,29 @@ onMounted(async () => { } }); +function maybeSlug() { + if (!slugTouched.value && !form.value.slug.trim()) { + form.value.slug = slugify(form.value.title); + } +} + async function onSubmit() { if (!form.value.title.trim() || !form.value.categoryId) { error.value = 'نام و دسته را وارد کنید.'; return; } + const slug = optionalSlug(form.value.slug); + if (slug && !isValidSlug(slug)) { + error.value = 'اسلاگ فقط حروف کوچک انگلیسی و خط تیره باشد.'; + return; + } saving.value = true; error.value = ''; try { await submitBusinessRegistration({ title: form.value.title.trim(), categoryId: form.value.categoryId, + ...(slug ? { slug } : {}), description: form.value.description.trim() || undefined, contactPhone: form.value.contactPhone.trim() || undefined, address: form.value.address.trim() || undefined,