@burdenoff/microfe-proserviceworld 2026.626.2 → 2026.706.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/index.js +2 -3
  2. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  3. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  4. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  5. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  6. package/dist/proserviceworld/ProServiceWorldRoot.js +92 -136
  7. package/dist/proserviceworld/ProServiceWorldRoot.js.map +1 -1
  8. package/dist/proserviceworld/ProServiceWorldRoutes.js +18 -26
  9. package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
  10. package/dist/proserviceworld/components/ui.js +273 -0
  11. package/dist/proserviceworld/components/ui.js.map +1 -0
  12. package/dist/proserviceworld/hooks/useFiles.js +45 -0
  13. package/dist/proserviceworld/hooks/useFiles.js.map +1 -0
  14. package/dist/proserviceworld/hooks/useProServiceWorldApi.js +416 -0
  15. package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -0
  16. package/dist/proserviceworld/index.js +0 -1
  17. package/dist/proserviceworld/pages/AnalyticsPage.js +163 -475
  18. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  19. package/dist/proserviceworld/pages/ClientDetailPage.js +238 -0
  20. package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -0
  21. package/dist/proserviceworld/pages/ClientsPage.js +295 -0
  22. package/dist/proserviceworld/pages/ClientsPage.js.map +1 -0
  23. package/dist/proserviceworld/pages/CompliancePage.js +307 -0
  24. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -0
  25. package/dist/proserviceworld/pages/ConflictsPage.js +234 -0
  26. package/dist/proserviceworld/pages/ConflictsPage.js.map +1 -0
  27. package/dist/proserviceworld/pages/DashboardPage.js +179 -632
  28. package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
  29. package/dist/proserviceworld/pages/DocumentsPage.js +235 -539
  30. package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
  31. package/dist/proserviceworld/pages/EngagementDetailPage.js +444 -0
  32. package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -0
  33. package/dist/proserviceworld/pages/EngagementsPage.js +256 -0
  34. package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -0
  35. package/dist/proserviceworld/pages/InvoicesPage.js +303 -0
  36. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -0
  37. package/dist/proserviceworld/pages/MattersPage.js +275 -0
  38. package/dist/proserviceworld/pages/MattersPage.js.map +1 -0
  39. package/dist/proserviceworld/pages/PracticeAreasPage.js +176 -0
  40. package/dist/proserviceworld/pages/PracticeAreasPage.js.map +1 -0
  41. package/dist/proserviceworld/pages/TimePage.js +310 -0
  42. package/dist/proserviceworld/pages/TimePage.js.map +1 -0
  43. package/dist/proserviceworld/utils/cn.js +10 -0
  44. package/dist/proserviceworld/utils/cn.js.map +1 -0
  45. package/dist/proserviceworld/utils/nav.js +11 -0
  46. package/dist/proserviceworld/utils/nav.js.map +1 -0
  47. package/package.json +3 -2
  48. package/dist/proserviceworld/pages/AdminReportsPage.js +0 -579
  49. package/dist/proserviceworld/pages/AdminReportsPage.js.map +0 -1
  50. package/dist/proserviceworld/pages/AdminUsersPage.js +0 -468
  51. package/dist/proserviceworld/pages/AdminUsersPage.js.map +0 -1
  52. package/dist/proserviceworld/pages/BookingsPage.js +0 -446
  53. package/dist/proserviceworld/pages/BookingsPage.js.map +0 -1
  54. package/dist/proserviceworld/pages/MessagesPage.js +0 -238
  55. package/dist/proserviceworld/pages/MessagesPage.js.map +0 -1
  56. package/dist/proserviceworld/pages/PaymentsPage.js +0 -537
  57. package/dist/proserviceworld/pages/PaymentsPage.js.map +0 -1
  58. package/dist/proserviceworld/pages/ProjectsPage.js +0 -627
  59. package/dist/proserviceworld/pages/ProjectsPage.js.map +0 -1
  60. package/dist/proserviceworld/pages/ProviderDetailPage.js +0 -538
  61. package/dist/proserviceworld/pages/ProviderDetailPage.js.map +0 -1
  62. package/dist/proserviceworld/pages/ProvidersPage.js +0 -347
  63. package/dist/proserviceworld/pages/ProvidersPage.js.map +0 -1
  64. package/dist/proserviceworld/pages/ReviewsPage.js +0 -356
  65. package/dist/proserviceworld/pages/ReviewsPage.js.map +0 -1
  66. package/dist/proserviceworld/pages/ServiceDetailsPage.js +0 -631
  67. package/dist/proserviceworld/pages/ServiceDetailsPage.js.map +0 -1
  68. package/dist/proserviceworld/pages/ServicesPage.js +0 -344
  69. package/dist/proserviceworld/pages/ServicesPage.js.map +0 -1
  70. package/dist/proserviceworld/pages/VerificationPage.js +0 -370
  71. package/dist/proserviceworld/pages/VerificationPage.js.map +0 -1
  72. package/dist/proserviceworld/store/proserviceworldStore.js +0 -2490
  73. package/dist/proserviceworld/store/proserviceworldStore.js.map +0 -1
  74. package/dist/proserviceworld/utils/i18n.js +0 -15
  75. package/dist/proserviceworld/utils/i18n.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServiceDetailsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/ServiceDetailsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n EmphasisPanel,\n ShowMore,\n CTAOverflowMenu,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeft,\n Star,\n Clock,\n CheckCircle2,\n ChevronDown,\n ChevronUp,\n Package,\n FileText,\n ClipboardList,\n Tag,\n Shield,\n Calendar,\n DollarSign,\n User,\n MessageSquare,\n BookOpen,\n} from 'lucide-react';\nimport { useProServiceWorldStore } from '../store/proserviceworldStore';\n\ntype Tab = 'packages' | 'deliverables' | 'requirements' | 'faq';\n\nexport function ServiceDetailsPage() {\n const { services, providers } = useProServiceWorldStore();\n const [selectedServiceId, setSelectedServiceId] = useState(services[0]?.id ?? '');\n const [activeTab, setActiveTab] = useState<Tab>('packages');\n const [expandedFaq, setExpandedFaq] = useState<string | null>(null);\n const [showBookingModal, setShowBookingModal] = useState(false);\n const [selectedPackageId, setSelectedPackageId] = useState<string | null>(null);\n\n const service = services.find((s) => s.id === selectedServiceId) ?? services[0];\n const provider = service ? providers.find((p) => p.id === service.providerId) : null;\n\n if (!service) {\n return (\n <div className=\"p-6 bg-bg-canvas min-h-screen\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No services available\"\n description=\"There are no services to display yet. Once services are published they will appear here with full package and provider details.\"\n />\n </div>\n );\n }\n\n const tabs: { key: Tab; label: string; icon: typeof Package }[] = [\n { key: 'packages', label: 'Packages', icon: Package },\n { key: 'deliverables', label: 'Deliverables', icon: FileText },\n { key: 'requirements', label: 'Requirements', icon: ClipboardList },\n { key: 'faq', label: 'FAQ', icon: BookOpen },\n ];\n\n const pricingLabel =\n service.pricing.type === 'hourly'\n ? `$${service.pricing.hourlyRate}/hr`\n : service.pricing.type === 'fixed'\n ? `$${service.pricing.basePrice.toLocaleString()} fixed`\n : `From $${service.pricing.basePrice.toLocaleString()}`;\n\n return (\n <div className=\"space-y-6 p-6 bg-bg-canvas min-h-screen\">\n {/* Breadcrumb + Service selector */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setSelectedServiceId(services[0]?.id ?? '')}\n >\n <ArrowLeft className=\"mr-2 h-4 w-4\" /> Services\n </Button>\n <span className=\"text-text-secondary\">/</span>\n <select\n aria-label=\"Select service\"\n className=\"rounded border border-border-seam bg-bg-surface px-2 py-1 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n value={selectedServiceId}\n onChange={(e) => setSelectedServiceId(e.target.value)}\n >\n {services.map((s) => (\n <option key={s.id} value={s.id}>\n {s.title}\n </option>\n ))}\n </select>\n </div>\n <Button size=\"sm\" onClick={() => setShowBookingModal(true)}>\n <Calendar className=\"mr-2 h-4 w-4\" /> Book This Service\n </Button>\n </div>\n\n <PagePurpose icon={<Package className=\"h-4 w-4\" />}>\n Everything you need to decide on this service. Compare packages and pricing, see exactly\n what you will receive and what is required from you, read the FAQ, and review the provider\n behind it — then book the package that fits your project.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"proserviceworld-service-details\"\n steps={[\n {\n id: 'packages',\n label: 'Compare packages',\n description: 'Review tiers, features, and pricing to pick the right fit.',\n icon: <Package className=\"h-4 w-4\" />,\n onClick: () => setActiveTab('packages'),\n },\n {\n id: 'requirements',\n label: 'Check what is required',\n description: 'See the deliverables and what the provider needs from you.',\n icon: <ClipboardList className=\"h-4 w-4\" />,\n onClick: () => setActiveTab('requirements'),\n },\n {\n id: 'book',\n label: 'Book this service',\n description: 'Select a package and confirm your booking.',\n icon: <Calendar className=\"h-4 w-4\" />,\n onClick: () => setShowBookingModal(true),\n },\n ]}\n />\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Main content — 2 columns */}\n <div className=\"space-y-6 lg:col-span-2\">\n {/* Service header — the single emphasised zone */}\n <EmphasisPanel className=\"relative overflow-hidden\">\n <div className=\"flex flex-wrap items-start justify-between gap-4\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n {service.featured && <Badge>Featured</Badge>}\n <Badge variant=\"secondary\">{service.category.replace(/_/g, ' ')}</Badge>\n <Badge variant=\"outline\">{service.subcategory}</Badge>\n </div>\n <h1 className=\"text-2xl font-bold tracking-tight\">{service.title}</h1>\n <p className=\"max-w-2xl text-text-secondary\">{service.description}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-2xl font-bold text-accent-blue tabular-nums\">{pricingLabel}</p>\n <p className=\"text-xs text-text-secondary\">{service.pricing.type} pricing</p>\n </div>\n </div>\n\n {/* Stats row */}\n <div className=\"mt-6 flex flex-wrap gap-6 border-t border-border-seam pt-4\">\n <div className=\"flex items-center gap-2\">\n <Star className=\"h-4 w-4 text-status-warning-text\" />\n <span className=\"text-sm font-medium tabular-nums\">{service.rating}</span>\n <span className=\"text-xs text-text-secondary\">\n ({service.providerReviews} reviews)\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n <span className=\"text-sm tabular-nums\">{service.duration.typical} days typical</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n <span className=\"text-sm tabular-nums\">{service.totalBookings} bookings</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <Calendar className=\"h-4 w-4 text-text-secondary\" />\n <span className=\"text-sm tabular-nums\">\n {service.duration.min}-{service.duration.max} days range\n </span>\n </div>\n </div>\n\n {/* Tags */}\n {service.tags.length > 0 && (\n <div className=\"mt-4 flex flex-wrap items-center gap-2\">\n <Tag className=\"h-4 w-4 text-text-secondary\" />\n {service.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n </EmphasisPanel>\n\n {/* Tabs */}\n <div className=\"flex gap-1 border-b border-border-seam\">\n {tabs.map(({ key, label, icon: Icon }) => (\n <button\n key={key}\n onClick={() => setActiveTab(key)}\n aria-pressed={activeTab === key}\n className={`flex items-center gap-2 border-b-2 px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n activeTab === key\n ? 'border-accent-blue text-accent-blue'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n }`}\n >\n <Icon className=\"h-4 w-4\" />\n {label}\n </button>\n ))}\n </div>\n\n {/* Tab content */}\n {activeTab === 'packages' && (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {service.packages.map((pkg) => (\n <GlassCard\n key={pkg.id}\n treatment={pkg.popular ? 'glass' : 'plain'}\n glow={pkg.popular}\n className={`relative border-border-seam ${\n selectedPackageId === pkg.id ? 'ring-1 ring-accent-blue' : ''\n }`}\n >\n {pkg.popular && (\n <div className=\"absolute -top-3 left-1/2 -translate-x-1/2\">\n <Badge className=\"bg-accent-blue text-action-primary-text\">Most Popular</Badge>\n </div>\n )}\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"text-lg\">{pkg.name}</CardTitle>\n <p className=\"text-sm text-text-secondary\">{pkg.description}</p>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <span className=\"text-3xl font-bold tabular-nums\">\n ${pkg.price.toLocaleString()}\n </span>\n <span className=\"text-sm text-text-secondary\"> / {pkg.duration} days</span>\n </div>\n <ul className=\"space-y-2\">\n {pkg.features.map((feature, i) => (\n <li key={i} className=\"flex items-start gap-2 text-sm\">\n <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-status-success-text\" />\n {feature}\n </li>\n ))}\n </ul>\n <Button\n className=\"w-full\"\n variant={pkg.popular ? 'default' : 'outline'}\n onClick={() => {\n setSelectedPackageId(pkg.id);\n setShowBookingModal(true);\n }}\n >\n Select Package\n </Button>\n </CardContent>\n </GlassCard>\n ))}\n </div>\n )}\n\n {activeTab === 'deliverables' && (\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">What You&apos;ll Receive</CardTitle>\n </CardHeader>\n <CardContent>\n <ShowMore collapsedHeight={180}>\n <ul className=\"grid gap-3 sm:grid-cols-2\">\n {service.deliverables.map((item, i) => (\n <li\n key={i}\n className=\"flex items-center gap-3 rounded-lg border border-border-seam p-3\"\n >\n <FileText className=\"h-5 w-5 text-accent-blue\" />\n <span className=\"text-sm font-medium\">{item}</span>\n </li>\n ))}\n </ul>\n </ShowMore>\n </CardContent>\n </Card>\n )}\n\n {activeTab === 'requirements' && (\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">What We Need From You</CardTitle>\n </CardHeader>\n <CardContent>\n <ShowMore collapsedHeight={180}>\n <ul className=\"space-y-3\">\n {service.requirements.map((item, i) => (\n <li\n key={i}\n className=\"flex items-start gap-3 rounded-lg border border-border-seam p-3\"\n >\n <ClipboardList className=\"mt-0.5 h-5 w-5 text-status-warning-text\" />\n <span className=\"text-sm\">{item}</span>\n </li>\n ))}\n </ul>\n </ShowMore>\n </CardContent>\n </Card>\n )}\n\n {activeTab === 'faq' && (\n <div className=\"space-y-3\">\n {service.faq.length === 0 ? (\n <Card className=\"border-border-seam\">\n <CardContent className=\"py-6\">\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No FAQ items yet\"\n description=\"This service does not have any frequently asked questions yet. Message the provider if you have a question before booking.\"\n />\n </CardContent>\n </Card>\n ) : (\n service.faq.map((item) => (\n <Card key={item.id} className=\"border-border-seam\">\n <button\n className=\"flex w-full items-center justify-between p-4 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n aria-expanded={expandedFaq === item.id}\n onClick={() => setExpandedFaq(expandedFaq === item.id ? null : item.id)}\n >\n <span className=\"font-medium\">{item.question}</span>\n {expandedFaq === item.id ? (\n <ChevronUp className=\"h-4 w-4 text-text-secondary\" />\n ) : (\n <ChevronDown className=\"h-4 w-4 text-text-secondary\" />\n )}\n </button>\n {expandedFaq === item.id && (\n <CardContent className=\"border-t border-border-seam pt-4\">\n <p className=\"text-sm text-text-secondary\">{item.answer}</p>\n </CardContent>\n )}\n </Card>\n ))\n )}\n </div>\n )}\n </div>\n\n {/* Provider sidebar */}\n <div className=\"space-y-4\">\n {provider && (\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Service Provider</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-accent-soft text-text-primary font-semibold\">\n {provider.name.charAt(0)}\n </div>\n <div>\n <p className=\"font-medium\">{provider.name}</p>\n <p className=\"text-sm text-text-secondary\">{provider.businessName}</p>\n </div>\n </div>\n\n {provider.verified && (\n <div className=\"flex items-center gap-2 rounded-lg bg-status-success-bg-subtle p-2\">\n <Shield className=\"h-4 w-4 text-status-success-text\" />\n <span className=\"text-sm font-medium text-status-success-text\">\n Verified Provider\n </span>\n </div>\n )}\n\n <div className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Rating</span>\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-4 w-4 text-status-warning-text\" />\n <span className=\"font-medium tabular-nums\">{provider.rating}</span>\n <span className=\"text-text-secondary tabular-nums\">\n ({provider.totalReviews})\n </span>\n </div>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Completion Rate</span>\n <span className=\"font-medium tabular-nums\">{provider.completionRate}%</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Response Time</span>\n <span className=\"font-medium tabular-nums\">{provider.responseTime}h avg</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Experience</span>\n <span className=\"font-medium tabular-nums\">\n {provider.yearsExperience} years\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Projects Done</span>\n <span className=\"font-medium tabular-nums\">{provider.projectsCompleted}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Hourly Rate</span>\n <span className=\"font-medium tabular-nums\">${provider.hourlyRate}/hr</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Location</span>\n <span className=\"font-medium\">{provider.location}</span>\n </div>\n </div>\n\n <div className=\"space-y-2 border-t border-border-seam pt-3\">\n <p className=\"text-xs font-medium text-text-secondary\">Certifications</p>\n <div className=\"flex flex-wrap gap-1\">\n {provider.certifications.map((cert) => (\n <Badge key={cert} variant=\"secondary\" className=\"text-xs\">\n {cert}\n </Badge>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2 border-t border-border-seam pt-3\">\n <p className=\"text-xs font-medium text-text-secondary\">Languages</p>\n <div className=\"flex flex-wrap gap-1\">\n {provider.languages.map((lang) => (\n <Badge key={lang} variant=\"outline\" className=\"text-xs\">\n {lang}\n </Badge>\n ))}\n </div>\n </div>\n\n <div className=\"flex gap-2 border-t border-border-seam pt-3\">\n <Button className=\"flex-1\" size=\"sm\" variant=\"outline\">\n <User className=\"mr-2 h-4 w-4\" /> View Profile\n </Button>\n <Button className=\"flex-1\" size=\"sm\" variant=\"outline\">\n <MessageSquare className=\"mr-2 h-4 w-4\" /> Message\n </Button>\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Quick booking card */}\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Quick Book</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">Starting from</span>\n <span className=\"text-lg font-bold text-accent-blue tabular-nums\">\n ${service.pricing.basePrice.toLocaleString()}\n </span>\n </div>\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Clock className=\"h-4 w-4\" />\n <span>Typical duration: {service.duration.typical} days</span>\n </div>\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <DollarSign className=\"h-4 w-4\" />\n <span>{service.pricing.type} pricing model</span>\n </div>\n <Button className=\"w-full\" onClick={() => setShowBookingModal(true)}>\n <Calendar className=\"mr-2 h-4 w-4\" /> Book Now\n </Button>\n </CardContent>\n </GlassCard>\n </div>\n </div>\n\n {/* Booking Modal */}\n {showBookingModal && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay\">\n <GlassCard treatment=\"glass\" className=\"w-full max-w-lg mx-4 border-border-seam\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>Book Service</CardTitle>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setShowBookingModal(false)}>\n Close\n </Button>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <p className=\"font-medium\">{service.title}</p>\n <p className=\"text-sm text-text-secondary\">by {service.providerName}</p>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-sm font-medium\">Select Package</p>\n {service.packages.map((pkg) => (\n <button\n key={pkg.id}\n onClick={() => setSelectedPackageId(pkg.id)}\n aria-pressed={selectedPackageId === pkg.id}\n className={`w-full rounded-lg border p-3 text-left transition-shadow focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n selectedPackageId === pkg.id\n ? 'border-accent-blue bg-accent-blue-subtle'\n : 'border-border-seam hover:shadow-pop'\n }`}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-medium\">{pkg.name}</span>\n <span className=\"font-bold tabular-nums\">${pkg.price.toLocaleString()}</span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n {pkg.description} - {pkg.duration} days\n </p>\n </button>\n ))}\n </div>\n\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n className=\"flex-1\"\n onClick={() => setShowBookingModal(false)}\n >\n Cancel\n </Button>\n <Button className=\"flex-1\" disabled={!selectedPackageId}>\n Confirm Booking\n </Button>\n </div>\n </CardContent>\n </GlassCard>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,344 +0,0 @@
1
- import { useProServiceWorldStore as e } from "../store/proserviceworldStore.js";
2
- import { tWithFallback as t } from "../utils/i18n.js";
3
- import { useMemo as n, useState as r } from "react";
4
- import { Clock as i, Compass as a, Grid as o, List as s, Search as c, Star as l, Tag as u } from "lucide-react";
5
- import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell";
6
- import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
7
- import { AuroraBackground as h, Badge as g, Button as _, GlassCard as v, GradientText as y, IllustratedEmptyState as b, Input as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
8
- //#region src/proserviceworld/pages/ServicesPage.tsx
9
- var C = {
10
- accounting_bookkeeping: {
11
- key: "proserviceworld.shared.categories.accountingBookkeeping",
12
- fallback: "Accounting & Bookkeeping"
13
- },
14
- business_consulting: {
15
- key: "proserviceworld.shared.categories.businessConsulting",
16
- fallback: "Business Consulting"
17
- },
18
- creative_design: {
19
- key: "proserviceworld.shared.categories.creativeDesign",
20
- fallback: "Creative & Design"
21
- },
22
- education_training: {
23
- key: "proserviceworld.shared.categories.educationTraining",
24
- fallback: "Education & Training"
25
- },
26
- financial_services: {
27
- key: "proserviceworld.shared.categories.financialServices",
28
- fallback: "Financial Services"
29
- },
30
- healthcare: {
31
- key: "proserviceworld.shared.categories.healthcare",
32
- fallback: "Healthcare"
33
- },
34
- human_resources: {
35
- key: "proserviceworld.shared.categories.humanResources",
36
- fallback: "Human Resources"
37
- },
38
- insurance: {
39
- key: "proserviceworld.shared.categories.insurance",
40
- fallback: "Insurance"
41
- },
42
- it_technology: {
43
- key: "proserviceworld.shared.categories.itTechnology",
44
- fallback: "IT & Technology"
45
- },
46
- legal_services: {
47
- key: "proserviceworld.shared.categories.legalServices",
48
- fallback: "Legal Services"
49
- },
50
- marketing_advertising: {
51
- key: "proserviceworld.shared.categories.marketingAdvertising",
52
- fallback: "Marketing & Advertising"
53
- },
54
- real_estate: {
55
- key: "proserviceworld.shared.categories.realEstate",
56
- fallback: "Real Estate"
57
- }
58
- };
59
- function w() {
60
- let { t: w } = d(), E = (e, n, r) => t(w, e, n, r), { services: D } = e(), [O, k] = r(""), [A, j] = r(""), [M, N] = r("grid"), [P, F] = r(1), I = n(() => {
61
- let e = [...D];
62
- if (O) {
63
- let t = O.toLowerCase();
64
- e = e.filter((e) => e.title.toLowerCase().includes(t) || e.description.toLowerCase().includes(t) || e.tags.some((e) => e.toLowerCase().includes(t)));
65
- }
66
- return A && (e = e.filter((e) => e.category === A)), e;
67
- }, [
68
- D,
69
- O,
70
- A
71
- ]), L = Math.ceil(I.length / 12), R = I.slice((P - 1) * 12, P * 12), z = O ? E("proserviceworld.services.subtitleWithQuery", "{{count}} services found for \"{{query}}\"", {
72
- count: I.length,
73
- query: O
74
- }) : E("proserviceworld.services.subtitle", "{{count}} services found", { count: I.length }), B = (e) => {
75
- let t = C[e];
76
- return E(t.key, t.fallback);
77
- };
78
- return /* @__PURE__ */ m("div", {
79
- className: "space-y-6 p-6 bg-bg-canvas min-h-screen",
80
- children: [
81
- /* @__PURE__ */ m("div", {
82
- className: "relative overflow-hidden rounded-card -mx-2 px-2 pt-1 flex flex-col md:flex-row md:items-center md:justify-between gap-4",
83
- children: [
84
- /* @__PURE__ */ p(h, { intensity: "subtle" }),
85
- /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h1", {
86
- className: "text-2xl font-semibold tracking-tight",
87
- children: /* @__PURE__ */ p(y, { children: E("proserviceworld.services.title", "Services") })
88
- }), /* @__PURE__ */ p("p", {
89
- className: "text-sm text-text-secondary",
90
- children: z
91
- })] }),
92
- /* @__PURE__ */ m("div", {
93
- className: "flex items-center gap-2 mt-4 md:mt-0",
94
- children: [/* @__PURE__ */ p(_, {
95
- variant: M === "grid" ? "default" : "outline",
96
- size: "sm",
97
- onClick: () => N("grid"),
98
- children: /* @__PURE__ */ p(o, { className: "h-4 w-4" })
99
- }), /* @__PURE__ */ p(_, {
100
- variant: M === "list" ? "default" : "outline",
101
- size: "sm",
102
- onClick: () => N("list"),
103
- children: /* @__PURE__ */ p(s, { className: "h-4 w-4" })
104
- })]
105
- })
106
- ]
107
- }),
108
- /* @__PURE__ */ p(S, {
109
- icon: /* @__PURE__ */ p(a, { className: "h-4 w-4" }),
110
- children: E("proserviceworld.services.purpose", "Discover professional services from vetted providers. Search and filter by category to compare offerings, pricing, and ratings — then open a service to review packages and book the right fit for your project.")
111
- }),
112
- /* @__PURE__ */ m("div", {
113
- className: "flex flex-col sm:flex-row gap-4",
114
- children: [/* @__PURE__ */ m("div", {
115
- className: "flex-1 relative",
116
- children: [/* @__PURE__ */ p(c, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ p(x, {
117
- placeholder: E("proserviceworld.services.search.placeholder", "Search services..."),
118
- value: O,
119
- onChange: (e) => {
120
- k(e.target.value), F(1);
121
- },
122
- className: "pl-10"
123
- })]
124
- }), /* @__PURE__ */ m("select", {
125
- value: A,
126
- onChange: (e) => {
127
- j(e.target.value), F(1);
128
- },
129
- className: "px-4 py-2 border border-border-seam rounded-md bg-bg-surface text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
130
- children: [
131
- /* @__PURE__ */ p("option", {
132
- value: "",
133
- children: E("proserviceworld.shared.filters.allCategories", "All Categories")
134
- }),
135
- /* @__PURE__ */ p("option", {
136
- value: "financial_services",
137
- children: B("financial_services")
138
- }),
139
- /* @__PURE__ */ p("option", {
140
- value: "legal_services",
141
- children: B("legal_services")
142
- }),
143
- /* @__PURE__ */ p("option", {
144
- value: "marketing_advertising",
145
- children: B("marketing_advertising")
146
- }),
147
- /* @__PURE__ */ p("option", {
148
- value: "it_technology",
149
- children: B("it_technology")
150
- }),
151
- /* @__PURE__ */ p("option", {
152
- value: "human_resources",
153
- children: B("human_resources")
154
- }),
155
- /* @__PURE__ */ p("option", {
156
- value: "accounting_bookkeeping",
157
- children: B("accounting_bookkeeping")
158
- }),
159
- /* @__PURE__ */ p("option", {
160
- value: "creative_design",
161
- children: B("creative_design")
162
- }),
163
- /* @__PURE__ */ p("option", {
164
- value: "education_training",
165
- children: B("education_training")
166
- })
167
- ]
168
- })]
169
- }),
170
- R.length > 0 ? /* @__PURE__ */ p("div", {
171
- className: M === "grid" ? "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" : "space-y-4",
172
- children: R.map((e) => /* @__PURE__ */ p(v, {
173
- treatment: "glass",
174
- glow: e.featured,
175
- className: "border-border-seam p-0 transition-shadow hover:shadow-pop",
176
- children: /* @__PURE__ */ p("div", {
177
- className: M === "grid" ? "p-6" : "p-4 flex items-center gap-6",
178
- children: M === "grid" ? /* @__PURE__ */ m(f, { children: [
179
- /* @__PURE__ */ m("div", {
180
- className: "flex items-center justify-between mb-3",
181
- children: [/* @__PURE__ */ p(g, {
182
- variant: "outline",
183
- className: "text-xs capitalize",
184
- children: B(e.category)
185
- }), e.featured && /* @__PURE__ */ p(g, { children: E("proserviceworld.services.badges.featured", "Featured") })]
186
- }),
187
- /* @__PURE__ */ p("h3", {
188
- className: "font-semibold mb-2",
189
- children: e.title
190
- }),
191
- /* @__PURE__ */ p("p", {
192
- className: "text-sm text-text-secondary mb-3 line-clamp-2",
193
- children: e.description
194
- }),
195
- /* @__PURE__ */ m("div", {
196
- className: "flex items-center gap-2 mb-3 text-sm",
197
- children: [
198
- /* @__PURE__ */ p("div", {
199
- className: "h-6 w-6 rounded-full bg-bg-sunken flex items-center justify-center text-xs",
200
- children: e.providerName.charAt(0)
201
- }),
202
- /* @__PURE__ */ p("span", {
203
- className: "text-text-secondary",
204
- children: e.providerName
205
- }),
206
- e.providerVerified && /* @__PURE__ */ p(T, {})
207
- ]
208
- }),
209
- /* @__PURE__ */ m("div", {
210
- className: "flex items-center justify-between text-sm",
211
- children: [/* @__PURE__ */ m("div", {
212
- className: "flex items-center",
213
- children: [
214
- /* @__PURE__ */ p(l, { className: "h-4 w-4 text-status-warning-text fill-current mr-1" }),
215
- /* @__PURE__ */ p("span", {
216
- className: "tabular-nums",
217
- children: e.providerRating.toFixed(1)
218
- }),
219
- /* @__PURE__ */ m("span", {
220
- className: "text-text-secondary ml-1 tabular-nums",
221
- children: [
222
- "(",
223
- e.providerReviews,
224
- ")"
225
- ]
226
- })
227
- ]
228
- }), /* @__PURE__ */ p("span", {
229
- className: "font-medium tabular-nums",
230
- children: E("proserviceworld.services.card.pricing.from", "From ${{amount}}", { amount: e.pricing.basePrice.toLocaleString() })
231
- })]
232
- }),
233
- /* @__PURE__ */ p("div", {
234
- className: "flex flex-wrap gap-1 mt-3",
235
- children: e.tags.slice(0, 3).map((e) => /* @__PURE__ */ p("span", {
236
- className: "inline-block px-2 py-0.5 bg-bg-sunken text-xs rounded",
237
- children: e
238
- }, e))
239
- }),
240
- /* @__PURE__ */ m("div", {
241
- className: "flex items-center gap-4 mt-3 pt-3 border-t border-border-seam text-xs text-text-secondary",
242
- children: [/* @__PURE__ */ m("span", {
243
- className: "flex items-center",
244
- children: [/* @__PURE__ */ p(i, { className: "h-3 w-3 mr-1" }), E("proserviceworld.services.card.meta.days", "{{count}} days", { count: e.duration.typical })]
245
- }), /* @__PURE__ */ m("span", {
246
- className: "flex items-center",
247
- children: [/* @__PURE__ */ p(u, { className: "h-3 w-3 mr-1" }), E("proserviceworld.services.card.meta.bookings", "{{count}} bookings", { count: e.totalBookings })]
248
- })]
249
- })
250
- ] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("div", {
251
- className: "flex-1 min-w-0",
252
- children: [
253
- /* @__PURE__ */ m("div", {
254
- className: "flex items-center gap-2 mb-1",
255
- children: [/* @__PURE__ */ p("h3", {
256
- className: "font-semibold",
257
- children: e.title
258
- }), e.featured && /* @__PURE__ */ p(g, {
259
- className: "text-xs",
260
- children: E("proserviceworld.services.badges.featured", "Featured")
261
- })]
262
- }),
263
- /* @__PURE__ */ p("p", {
264
- className: "text-sm text-text-secondary mb-2 line-clamp-1",
265
- children: e.description
266
- }),
267
- /* @__PURE__ */ m("div", {
268
- className: "flex items-center gap-3 text-sm text-text-secondary",
269
- children: [
270
- /* @__PURE__ */ p("span", { children: e.providerName }),
271
- /* @__PURE__ */ m("span", {
272
- className: "flex items-center",
273
- children: [/* @__PURE__ */ p(l, { className: "h-3 w-3 text-status-warning-text fill-current mr-0.5" }), /* @__PURE__ */ p("span", {
274
- className: "tabular-nums",
275
- children: e.providerRating.toFixed(1)
276
- })]
277
- }),
278
- /* @__PURE__ */ p("span", {
279
- className: "capitalize",
280
- children: B(e.category)
281
- })
282
- ]
283
- })
284
- ]
285
- }), /* @__PURE__ */ m("div", {
286
- className: "text-right shrink-0",
287
- children: [/* @__PURE__ */ p("div", {
288
- className: "font-medium",
289
- children: E("proserviceworld.services.card.pricing.from", "From ${{amount}}", { amount: e.pricing.basePrice.toLocaleString() })
290
- }), /* @__PURE__ */ p("div", {
291
- className: "text-sm text-text-secondary",
292
- children: E("proserviceworld.services.card.meta.days", "{{count}} days", { count: e.duration.typical })
293
- })]
294
- })] })
295
- })
296
- }, e.id))
297
- }) : /* @__PURE__ */ p(b, {
298
- illustration: "empty-search",
299
- title: E("proserviceworld.services.empty.title", "No services found"),
300
- description: E("proserviceworld.shared.empty.adjustFilters", "Try adjusting your search criteria or filters.")
301
- }),
302
- L > 1 && /* @__PURE__ */ m("div", {
303
- className: "flex justify-center gap-2",
304
- children: [
305
- /* @__PURE__ */ p(_, {
306
- variant: "outline",
307
- disabled: P === 1,
308
- onClick: () => F((e) => e - 1),
309
- children: E("proserviceworld.shared.pagination.previous", "Previous")
310
- }),
311
- /* @__PURE__ */ p("span", {
312
- className: "flex items-center px-4 text-sm",
313
- children: E("proserviceworld.shared.pagination.pageInfo", "Page {{page}} of {{total}}", {
314
- page: P,
315
- total: L
316
- })
317
- }),
318
- /* @__PURE__ */ p(_, {
319
- variant: "outline",
320
- disabled: P >= L,
321
- onClick: () => F((e) => e + 1),
322
- children: E("proserviceworld.shared.pagination.next", "Next")
323
- })
324
- ]
325
- })
326
- ]
327
- });
328
- }
329
- function T() {
330
- return /* @__PURE__ */ p("svg", {
331
- className: "h-4 w-4 text-accent-blue",
332
- viewBox: "0 0 20 20",
333
- fill: "currentColor",
334
- children: /* @__PURE__ */ p("path", {
335
- fillRule: "evenodd",
336
- d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
337
- clipRule: "evenodd"
338
- })
339
- });
340
- }
341
- //#endregion
342
- export { w as ServicesPage };
343
-
344
- //# sourceMappingURL=ServicesPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServicesPage.js","names":[],"sources":["../../../src/proserviceworld/pages/ServicesPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n Card,\n CardContent,\n Button,\n Badge,\n Input,\n GlassCard,\n AuroraBackground,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Search, Grid, List, Star, Clock, Tag, Compass } from 'lucide-react';\nimport { useProServiceWorldStore } from '../store/proserviceworldStore';\nimport type { ServiceCategory } from '../types';\nimport { tWithFallback } from '../utils/i18n';\n\nconst serviceCategoryLabels: Record<ServiceCategory, { key: string; fallback: string }> = {\n accounting_bookkeeping: {\n key: 'proserviceworld.shared.categories.accountingBookkeeping',\n fallback: 'Accounting & Bookkeeping',\n },\n business_consulting: {\n key: 'proserviceworld.shared.categories.businessConsulting',\n fallback: 'Business Consulting',\n },\n creative_design: {\n key: 'proserviceworld.shared.categories.creativeDesign',\n fallback: 'Creative & Design',\n },\n education_training: {\n key: 'proserviceworld.shared.categories.educationTraining',\n fallback: 'Education & Training',\n },\n financial_services: {\n key: 'proserviceworld.shared.categories.financialServices',\n fallback: 'Financial Services',\n },\n healthcare: { key: 'proserviceworld.shared.categories.healthcare', fallback: 'Healthcare' },\n human_resources: {\n key: 'proserviceworld.shared.categories.humanResources',\n fallback: 'Human Resources',\n },\n insurance: { key: 'proserviceworld.shared.categories.insurance', fallback: 'Insurance' },\n it_technology: {\n key: 'proserviceworld.shared.categories.itTechnology',\n fallback: 'IT & Technology',\n },\n legal_services: {\n key: 'proserviceworld.shared.categories.legalServices',\n fallback: 'Legal Services',\n },\n marketing_advertising: {\n key: 'proserviceworld.shared.categories.marketingAdvertising',\n fallback: 'Marketing & Advertising',\n },\n real_estate: { key: 'proserviceworld.shared.categories.realEstate', fallback: 'Real Estate' },\n};\n\nexport function ServicesPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>): string =>\n tWithFallback(t, key, fallback, params);\n const { services } = useProServiceWorldStore();\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedCategory, setSelectedCategory] = useState<ServiceCategory | ''>('');\n const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');\n const [currentPage, setCurrentPage] = useState(1);\n const perPage = 12;\n\n const filtered = useMemo(() => {\n let result = [...services];\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n result = result.filter(\n (s) =>\n s.title.toLowerCase().includes(q) ||\n s.description.toLowerCase().includes(q) ||\n s.tags.some((t) => t.toLowerCase().includes(q))\n );\n }\n if (selectedCategory) result = result.filter((s) => s.category === selectedCategory);\n return result;\n }, [services, searchQuery, selectedCategory]);\n\n const totalPages = Math.ceil(filtered.length / perPage);\n const paged = filtered.slice((currentPage - 1) * perPage, currentPage * perPage);\n const subtitle = searchQuery\n ? tr('proserviceworld.services.subtitleWithQuery', '{{count}} services found for \"{{query}}\"', {\n count: filtered.length,\n query: searchQuery,\n })\n : tr('proserviceworld.services.subtitle', '{{count}} services found', {\n count: filtered.length,\n });\n const categoryLabel = (category: ServiceCategory): string => {\n const entry = serviceCategoryLabels[category];\n return tr(entry.key, entry.fallback);\n };\n\n return (\n <div className=\"space-y-6 p-6 bg-bg-canvas min-h-screen\">\n <div className=\"relative overflow-hidden rounded-card -mx-2 px-2 pt-1 flex flex-col md:flex-row md:items-center md:justify-between gap-4\">\n <AuroraBackground intensity=\"subtle\" />\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n <GradientText>{tr('proserviceworld.services.title', 'Services')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{subtitle}</p>\n </div>\n <div className=\"flex items-center gap-2 mt-4 md:mt-0\">\n <Button\n variant={viewMode === 'grid' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setViewMode('grid')}\n >\n <Grid className=\"h-4 w-4\" />\n </Button>\n <Button\n variant={viewMode === 'list' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setViewMode('list')}\n >\n <List className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n <PagePurpose icon={<Compass className=\"h-4 w-4\" />}>\n {tr(\n 'proserviceworld.services.purpose',\n 'Discover professional services from vetted providers. Search and filter by category to compare offerings, pricing, and ratings — then open a service to review packages and book the right fit for your project.'\n )}\n </PagePurpose>\n\n <div className=\"flex flex-col sm:flex-row gap-4\">\n <div className=\"flex-1 relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder={tr('proserviceworld.services.search.placeholder', 'Search services...')}\n value={searchQuery}\n onChange={(e) => {\n setSearchQuery(e.target.value);\n setCurrentPage(1);\n }}\n className=\"pl-10\"\n />\n </div>\n <select\n value={selectedCategory}\n onChange={(e) => {\n setSelectedCategory(e.target.value as ServiceCategory | '');\n setCurrentPage(1);\n }}\n className=\"px-4 py-2 border border-border-seam rounded-md bg-bg-surface text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <option value=\"\">\n {tr('proserviceworld.shared.filters.allCategories', 'All Categories')}\n </option>\n <option value=\"financial_services\">{categoryLabel('financial_services')}</option>\n <option value=\"legal_services\">{categoryLabel('legal_services')}</option>\n <option value=\"marketing_advertising\">{categoryLabel('marketing_advertising')}</option>\n <option value=\"it_technology\">{categoryLabel('it_technology')}</option>\n <option value=\"human_resources\">{categoryLabel('human_resources')}</option>\n <option value=\"accounting_bookkeeping\">{categoryLabel('accounting_bookkeeping')}</option>\n <option value=\"creative_design\">{categoryLabel('creative_design')}</option>\n <option value=\"education_training\">{categoryLabel('education_training')}</option>\n </select>\n </div>\n\n {paged.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6'\n : 'space-y-4'\n }\n >\n {paged.map((service) => (\n <GlassCard\n key={service.id}\n treatment=\"glass\"\n glow={service.featured}\n className=\"border-border-seam p-0 transition-shadow hover:shadow-pop\"\n >\n <div className={viewMode === 'grid' ? 'p-6' : 'p-4 flex items-center gap-6'}>\n {viewMode === 'grid' ? (\n <>\n <div className=\"flex items-center justify-between mb-3\">\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {categoryLabel(service.category)}\n </Badge>\n {service.featured && (\n <Badge>{tr('proserviceworld.services.badges.featured', 'Featured')}</Badge>\n )}\n </div>\n <h3 className=\"font-semibold mb-2\">{service.title}</h3>\n <p className=\"text-sm text-text-secondary mb-3 line-clamp-2\">\n {service.description}\n </p>\n <div className=\"flex items-center gap-2 mb-3 text-sm\">\n <div className=\"h-6 w-6 rounded-full bg-bg-sunken flex items-center justify-center text-xs\">\n {service.providerName.charAt(0)}\n </div>\n <span className=\"text-text-secondary\">{service.providerName}</span>\n {service.providerVerified && <CheckMark />}\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <div className=\"flex items-center\">\n <Star className=\"h-4 w-4 text-status-warning-text fill-current mr-1\" />\n <span className=\"tabular-nums\">{service.providerRating.toFixed(1)}</span>\n <span className=\"text-text-secondary ml-1 tabular-nums\">\n ({service.providerReviews})\n </span>\n </div>\n <span className=\"font-medium tabular-nums\">\n {tr('proserviceworld.services.card.pricing.from', 'From ${{amount}}', {\n amount: service.pricing.basePrice.toLocaleString(),\n })}\n </span>\n </div>\n <div className=\"flex flex-wrap gap-1 mt-3\">\n {service.tags.slice(0, 3).map((t) => (\n <span key={t} className=\"inline-block px-2 py-0.5 bg-bg-sunken text-xs rounded\">\n {t}\n </span>\n ))}\n </div>\n <div className=\"flex items-center gap-4 mt-3 pt-3 border-t border-border-seam text-xs text-text-secondary\">\n <span className=\"flex items-center\">\n <Clock className=\"h-3 w-3 mr-1\" />\n {tr('proserviceworld.services.card.meta.days', '{{count}} days', {\n count: service.duration.typical,\n })}\n </span>\n <span className=\"flex items-center\">\n <Tag className=\"h-3 w-3 mr-1\" />\n {tr('proserviceworld.services.card.meta.bookings', '{{count}} bookings', {\n count: service.totalBookings,\n })}\n </span>\n </div>\n </>\n ) : (\n <>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <h3 className=\"font-semibold\">{service.title}</h3>\n {service.featured && (\n <Badge className=\"text-xs\">\n {tr('proserviceworld.services.badges.featured', 'Featured')}\n </Badge>\n )}\n </div>\n <p className=\"text-sm text-text-secondary mb-2 line-clamp-1\">\n {service.description}\n </p>\n <div className=\"flex items-center gap-3 text-sm text-text-secondary\">\n <span>{service.providerName}</span>\n <span className=\"flex items-center\">\n <Star className=\"h-3 w-3 text-status-warning-text fill-current mr-0.5\" />\n <span className=\"tabular-nums\">{service.providerRating.toFixed(1)}</span>\n </span>\n <span className=\"capitalize\">{categoryLabel(service.category)}</span>\n </div>\n </div>\n <div className=\"text-right shrink-0\">\n <div className=\"font-medium\">\n {tr('proserviceworld.services.card.pricing.from', 'From ${{amount}}', {\n amount: service.pricing.basePrice.toLocaleString(),\n })}\n </div>\n <div className=\"text-sm text-text-secondary\">\n {tr('proserviceworld.services.card.meta.days', '{{count}} days', {\n count: service.duration.typical,\n })}\n </div>\n </div>\n </>\n )}\n </div>\n </GlassCard>\n ))}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title={tr('proserviceworld.services.empty.title', 'No services found')}\n description={tr(\n 'proserviceworld.shared.empty.adjustFilters',\n 'Try adjusting your search criteria or filters.'\n )}\n />\n )}\n\n {totalPages > 1 && (\n <div className=\"flex justify-center gap-2\">\n <Button\n variant=\"outline\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage((p) => p - 1)}\n >\n {tr('proserviceworld.shared.pagination.previous', 'Previous')}\n </Button>\n <span className=\"flex items-center px-4 text-sm\">\n {tr('proserviceworld.shared.pagination.pageInfo', 'Page {{page}} of {{total}}', {\n page: currentPage,\n total: totalPages,\n })}\n </span>\n <Button\n variant=\"outline\"\n disabled={currentPage >= totalPages}\n onClick={() => setCurrentPage((p) => p + 1)}\n >\n {tr('proserviceworld.shared.pagination.next', 'Next')}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nfunction CheckMark() {\n return (\n <svg className=\"h-4 w-4 text-accent-blue\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n"],"mappings":"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"}