From d1a471199bce2508368b34a3f97f1692ffb66ca0 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sat, 13 Jun 2026 10:19:31 +0330 Subject: [PATCH] edit business owner --- src/api/types.ts | 7 +- src/components/booking/DesktopBookingFlow.vue | 10 +- src/components/home/HomeDiscoveryContent.vue | 21 +- src/components/home/HomeHeroSection.vue | 8 + src/components/home/HomeServiceCard.vue | 40 +- src/components/home/HomeServicesSection.vue | 25 +- src/components/landing/DesktopLandingPage.vue | 26 +- src/components/shell/SiteFooter.vue | 8 +- src/composables/useAppNav.ts | 12 - src/composables/useOwnedBusiness.ts | 52 ++ src/layouts/DesktopLoginLayout.vue | 96 +- src/layouts/WebAppLayout.vue | 7 +- src/router/index.ts | 9 + src/utils/service-pricing.ts | 234 ++++- src/views/app/AppBusinessDetailView.vue | 28 +- src/views/app/AppHomeView.vue | 28 +- src/views/app/AppOwnerView.vue | 877 ++++++++++++++++-- 17 files changed, 1268 insertions(+), 220 deletions(-) create mode 100644 src/composables/useOwnedBusiness.ts diff --git a/src/api/types.ts b/src/api/types.ts index 65f0e9f..e3852f6 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -22,6 +22,7 @@ export type Business = { slug: string; description?: string | null; address?: string | null; + contactPhone?: string | null; phone?: string | null; isActive: boolean; categoryId: string; @@ -39,6 +40,7 @@ export type UpdateBusinessPayload = { subtitle?: string | null; description?: string | null; address?: string | null; + contactPhone?: string | null; phone?: string | null; isActive?: boolean; concurrentCapacity?: number; @@ -122,14 +124,17 @@ export type CreateBusinessRegistrationPayload = { phone?: string; }; +export type BusinessServiceRequestStatus = 'pending' | 'approved' | 'rejected'; + export type BusinessServiceRequest = { id: string; businessId: string; - status: string; + status: BusinessServiceRequestStatus; title: string; description?: string | null; price: string; durationMinutes?: number | null; + adminNote?: string | null; createdAt: string; }; diff --git a/src/components/booking/DesktopBookingFlow.vue b/src/components/booking/DesktopBookingFlow.vue index c619033..b6fd21a 100644 --- a/src/components/booking/DesktopBookingFlow.vue +++ b/src/components/booking/DesktopBookingFlow.vue @@ -289,8 +289,10 @@ const classStepRequired = computed( () => Boolean(props.business.serviceClassesEnabled) && serviceClasses.value.length > 0, ); +const classesEnabled = computed(() => Boolean(props.business.serviceClassesEnabled)); + const perClass = computed( - () => Boolean(props.business.serviceClassesEnabled) && Boolean(selectedClassId.value), + () => classesEnabled.value && Boolean(selectedClassId.value), ); const selectedServices = computed(() => @@ -347,7 +349,7 @@ const summaryItems = computed(() => ), durationLabel: serviceDurationLabel( service, - perClass.value, + classesEnabled.value, serviceClasses.value, selectedClassId.value || undefined, ), @@ -440,7 +442,7 @@ const canProceed = computed(() => { function durationFor(service: BusinessService) { return serviceDurationLabel( service, - perClass.value, + classesEnabled.value, serviceClasses.value, selectedClassId.value || undefined, ); @@ -449,7 +451,7 @@ function durationFor(service: BusinessService) { function priceFor(service: BusinessService) { return servicePriceLabel( service, - perClass.value, + classesEnabled.value, serviceClasses.value, selectedClassId.value || undefined, ); diff --git a/src/components/home/HomeDiscoveryContent.vue b/src/components/home/HomeDiscoveryContent.vue index a1e40cc..aa6b3ab 100644 --- a/src/components/home/HomeDiscoveryContent.vue +++ b/src/components/home/HomeDiscoveryContent.vue @@ -33,6 +33,8 @@ import { ApiError } from '@/api/client'; import type { Business, BusinessCategory } from '@/api/types'; import HomeBusinessList from '@/components/home/HomeBusinessList.vue'; import HomeSearchAndFilter from '@/components/home/HomeSearchAndFilter.vue'; +import { useOwnedBusiness } from '@/composables/useOwnedBusiness'; +import { useAuthStore } from '@/stores/auth'; const props = withDefaults( defineProps<{ @@ -41,6 +43,9 @@ const props = withDefaults( { listVariant: 'compact' }, ); +const auth = useAuthStore(); +const { ensureLoaded, isOwnBusiness } = useOwnedBusiness(); + const categories = ref([]); const businesses = ref([]); const selectedCategoryId = ref(null); @@ -58,10 +63,16 @@ const showSearch = computed(() => businesses.value.length > 1); const filteredBusinesses = computed(() => { const q = searchQuery.value.trim().toLowerCase(); - if (!q) { - return businesses.value; + let items = businesses.value; + + if (auth.isBusinessOwner) { + items = items.filter((business) => !isOwnBusiness(business.id)); } - return businesses.value.filter((b) => { + + if (!q) { + return items; + } + return items.filter((b) => { const haystack = [b.title, b.description, b.address] .filter(Boolean) .join(' ') @@ -107,6 +118,10 @@ watch(selectedCategoryId, () => { }); onMounted(async () => { + if (auth.isLoggedIn) { + await auth.loadUser(); + await ensureLoaded(); + } await loadCategories(); await loadBusinesses(); }); diff --git a/src/components/home/HomeHeroSection.vue b/src/components/home/HomeHeroSection.vue index 3fe48a6..8095cf2 100644 --- a/src/components/home/HomeHeroSection.vue +++ b/src/components/home/HomeHeroSection.vue @@ -39,6 +39,7 @@
@@ -50,11 +50,15 @@ import HomeServiceCard from '@/components/home/HomeServiceCard.vue'; import ServiceGridSkeleton from '@/components/ui/ServiceGridSkeleton.vue'; import type { LandingServiceItem } from '@/types/landing'; -const props = defineProps<{ - items: LandingServiceItem[]; - loading: boolean; - error: string; -}>(); +const props = withDefaults( + defineProps<{ + items: LandingServiceItem[]; + loading: boolean; + error: string; + bookingEnabled?: boolean; + }>(), + { bookingEnabled: true }, +); const gridClass = computed(() => { const count = props.items.length; @@ -64,13 +68,8 @@ const gridClass = computed(() => { return 'lg:grid-cols-2'; }); -const featuredIndex = computed(() => { - const len = props.items.length; - if (!len) return 0; - return Math.min(2, len - 1); -}); - function serviceLink(item: LandingServiceItem) { + if (!props.bookingEnabled) return '#services'; return { name: 'app-business-detail', params: { id: item.businessId }, diff --git a/src/components/landing/DesktopLandingPage.vue b/src/components/landing/DesktopLandingPage.vue index 6c2fd3e..d285a12 100644 --- a/src/components/landing/DesktopLandingPage.vue +++ b/src/components/landing/DesktopLandingPage.vue @@ -1,11 +1,16 @@