@burdenoff/microfe-proserviceworld 2026.703.1 → 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 +1 -1
  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":"ProjectsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/ProjectsPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Input,\n GlassCard,\n AuroraBackground,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n NextSteps,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Search,\n Plus,\n Calendar,\n DollarSign,\n Users,\n CheckCircle2,\n Clock,\n AlertTriangle,\n Target,\n Tag,\n ChevronRight,\n BarChart3,\n Flag,\n} from 'lucide-react';\nimport { useProServiceWorldStore } from '../store/proserviceworldStore';\nimport type { ProjectStatus, Priority } from '../types';\n\ntype DetailTab = 'overview' | 'timeline' | 'milestones' | 'team';\n\nconst statusConfig: Record<ProjectStatus, { label: string; color: string; dot: string }> = {\n planning: { label: 'Planning', color: 'text-status-warning-text', dot: 'bg-status-warning-text' },\n active: { label: 'Active', color: 'text-accent-blue', dot: 'bg-accent-blue' },\n on_hold: { label: 'On Hold', color: 'text-status-warning-text', dot: 'bg-status-warning-text' },\n completed: {\n label: 'Completed',\n color: 'text-status-success-text',\n dot: 'bg-status-success-text',\n },\n cancelled: { label: 'Cancelled', color: 'text-status-error-text', dot: 'bg-status-error-text' },\n};\n\nconst priorityConfig: Record<\n Priority,\n { label: string; variant: 'default' | 'secondary' | 'outline' | 'destructive' }\n> = {\n low: { label: 'Low', variant: 'outline' },\n medium: { label: 'Medium', variant: 'secondary' },\n high: { label: 'High', variant: 'default' },\n critical: { label: 'Critical', variant: 'destructive' },\n};\n\nconst milestoneStatusDot: Record<string, string> = {\n completed: 'bg-status-success-text',\n in_progress: 'bg-accent-blue',\n pending: 'bg-bg-sunken',\n overdue: 'bg-status-error-text',\n};\n\nconst milestoneStatusColor: Record<string, string> = {\n completed: 'text-status-success-text',\n in_progress: 'text-accent-blue',\n pending: 'text-text-secondary',\n overdue: 'text-status-error-text',\n};\n\nexport function ProjectsPage() {\n const { projects } = useProServiceWorldStore();\n const [searchQuery, setSearchQuery] = useState('');\n const [statusFilter, setStatusFilter] = useState<ProjectStatus | 'all'>('all');\n const [selectedProjectId, setSelectedProjectId] = useState<string>(projects[0]?.id ?? '');\n const [detailTab, setDetailTab] = useState<DetailTab>('overview');\n\n const filteredProjects = useMemo(() => {\n let result = [...projects];\n if (statusFilter !== 'all') result = result.filter((p) => p.status === statusFilter);\n if (searchQuery.trim()) {\n const q = searchQuery.toLowerCase();\n result = result.filter(\n (p) => p.title.toLowerCase().includes(q) || p.category.toLowerCase().includes(q)\n );\n }\n return result;\n }, [projects, statusFilter, searchQuery]);\n\n const selectedProject = projects.find((p) => p.id === selectedProjectId);\n\n const detailTabs: { key: DetailTab; label: string }[] = [\n { key: 'overview', label: 'Overview' },\n { key: 'timeline', label: 'Timeline' },\n { key: 'milestones', label: 'Milestones' },\n { key: 'team', label: 'Team' },\n ];\n\n return (\n <div className=\"space-y-6 p-6 bg-bg-canvas min-h-screen\">\n {/* Hero header — the ONE aurora backdrop for this page. */}\n <div className=\"relative overflow-hidden rounded-card -mx-2 px-2 pt-1\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n <GradientText>Projects</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Track progress and manage your professional service projects.\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" /> New Project\n </Button>\n </div>\n </div>\n\n <PagePurpose icon={<Target className=\"h-4 w-4\" />}>\n Run your engagements from kickoff to delivery. Pick a project to see its budget, progress,\n milestones, timeline, and team in one place — so you always know what is on track, what is\n at risk, and what is due next.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"proserviceworld-projects\"\n steps={[\n {\n id: 'timeline',\n label: 'Walk the timeline',\n description: 'See milestones in chronological order to gauge momentum.',\n icon: <Calendar className=\"h-4 w-4\" />,\n onClick: () => setDetailTab('timeline'),\n },\n {\n id: 'milestones',\n label: 'Drill into milestones',\n description: 'Review deliverables, dependencies, and due dates.',\n icon: <Flag className=\"h-4 w-4\" />,\n onClick: () => setDetailTab('milestones'),\n },\n {\n id: 'team',\n label: 'Check the team',\n description: 'See who is assigned and their roles.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => setDetailTab('team'),\n },\n ]}\n />\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Project sidebar */}\n <div className=\"space-y-4\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search projects...\"\n aria-label=\"Search projects\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"pl-10\"\n />\n </div>\n\n <div className=\"flex flex-wrap gap-1\">\n {(['all', 'active', 'planning', 'completed', 'on_hold', 'cancelled'] as const).map(\n (status) => (\n <button\n key={status}\n onClick={() => setStatusFilter(status)}\n aria-pressed={statusFilter === status}\n className={`rounded px-2 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${\n statusFilter === status\n ? 'bg-accent-blue text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n }`}\n >\n {status === 'all' ? 'All' : statusConfig[status].label}\n </button>\n )\n )}\n </div>\n\n <div className=\"space-y-2\">\n {filteredProjects.length === 0 ? (\n <IllustratedEmptyState\n illustration={searchQuery || statusFilter !== 'all' ? 'empty-search' : 'empty-data'}\n title=\"No projects found\"\n description=\"Try adjusting your search or filters.\"\n />\n ) : (\n filteredProjects.map((project) => {\n const cfg = statusConfig[project.status];\n return (\n <button\n key={project.id}\n onClick={() => {\n setSelectedProjectId(project.id);\n setDetailTab('overview');\n }}\n aria-pressed={selectedProjectId === project.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 selectedProjectId === project.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 <h3 className=\"font-medium text-sm truncate pr-2\">{project.title}</h3>\n <ChevronRight className=\"h-4 w-4 shrink-0 text-text-secondary\" />\n </div>\n <div className=\"mt-2 flex items-center gap-2\">\n <Badge variant={priorityConfig[project.priority].variant} className=\"text-xs\">\n {project.priority}\n </Badge>\n <span className={`flex items-center gap-1 text-xs ${cfg.color}`}>\n <span\n className={`h-1.5 w-1.5 rounded-full ${cfg.dot} ${project.status === 'active' ? 'motion-safe:animate-vc-glow-pulse' : ''}`}\n />\n {cfg.label}\n </span>\n </div>\n <div className=\"mt-2\">\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <span>Progress</span>\n <span className=\"tabular-nums\">{project.progress}%</span>\n </div>\n <div className=\"mt-1 h-1.5 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-1.5 rounded-full bg-accent-blue transition-all\"\n style={{ width: `${project.progress}%` }}\n />\n </div>\n </div>\n </button>\n );\n })\n )}\n </div>\n </div>\n\n {/* Detail panel */}\n <div className=\"space-y-4 lg:col-span-2\">\n {selectedProject ? (\n <>\n {/* Project header card */}\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <CardContent className=\"pt-6\">\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 <Badge variant={priorityConfig[selectedProject.priority].variant}>\n {selectedProject.priority} priority\n </Badge>\n <span\n className={`text-sm font-medium ${statusConfig[selectedProject.status].color}`}\n >\n {statusConfig[selectedProject.status].label}\n </span>\n </div>\n <h2 className=\"text-xl font-bold tracking-tight\">{selectedProject.title}</h2>\n <p className=\"text-sm text-text-secondary\">{selectedProject.description}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-sm text-text-secondary\">Budget</p>\n <p className=\"text-xl font-bold tabular-nums\">\n ${selectedProject.budget.toLocaleString()}\n </p>\n <p className=\"text-xs text-text-secondary tabular-nums\">\n Spent: ${selectedProject.spent.toLocaleString()} (\n {Math.round((selectedProject.spent / selectedProject.budget) * 100)}%)\n </p>\n </div>\n </div>\n\n {/* Progress bar */}\n <div className=\"mt-4\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">Overall Progress</span>\n <span className=\"font-medium tabular-nums\">{selectedProject.progress}%</span>\n </div>\n <div className=\"mt-1 h-3 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-3 rounded-full bg-accent-blue transition-all\"\n style={{ width: `${selectedProject.progress}%` }}\n />\n </div>\n </div>\n\n {/* Quick stats */}\n <div className=\"mt-4 flex flex-wrap gap-4 text-sm\">\n <span className=\"flex items-center gap-1 text-text-secondary\">\n <Calendar className=\"h-4 w-4\" /> {selectedProject.startDate} -{' '}\n {selectedProject.endDate}\n </span>\n <span className=\"flex items-center gap-1 text-text-secondary\">\n <Users className=\"h-4 w-4\" />\n <span className=\"tabular-nums\">{selectedProject.teamMembers.length}</span>{' '}\n members\n </span>\n <span className=\"flex items-center gap-1 text-text-secondary\">\n <Target className=\"h-4 w-4\" />\n <span className=\"tabular-nums\">{selectedProject.milestones.length}</span>{' '}\n milestones\n </span>\n </div>\n\n {/* Tags */}\n {selectedProject.tags.length > 0 && (\n <div className=\"mt-3 flex flex-wrap items-center gap-2\">\n <Tag className=\"h-4 w-4 text-text-secondary\" />\n {selectedProject.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n )}\n </CardContent>\n </GlassCard>\n\n {/* Detail tabs */}\n <div className=\"flex gap-1 border-b border-border-seam\">\n {detailTabs.map(({ key, label }) => (\n <button\n key={key}\n onClick={() => setDetailTab(key)}\n aria-pressed={detailTab === key}\n className={`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 detailTab === key\n ? 'border-accent-blue text-accent-blue'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n }`}\n >\n {label}\n </button>\n ))}\n </div>\n\n {/* Overview tab */}\n {detailTab === 'overview' && (\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <DollarSign className=\"h-4 w-4\" /> Budget Overview\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Total Budget</span>\n <span className=\"font-medium tabular-nums\">\n ${selectedProject.budget.toLocaleString()}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Spent</span>\n <span className=\"font-medium tabular-nums\">\n ${selectedProject.spent.toLocaleString()}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Remaining</span>\n <span className=\"font-medium text-status-success-text tabular-nums\">\n ${(selectedProject.budget - selectedProject.spent).toLocaleString()}\n </span>\n </div>\n <div className=\"h-2 overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-2 rounded-full bg-accent-blue\"\n style={{\n width: `${Math.round((selectedProject.spent / selectedProject.budget) * 100)}%`,\n }}\n />\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" /> Milestone Summary\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {['completed', 'in_progress', 'pending', 'overdue'].map((status) => {\n const count = selectedProject.milestones.filter(\n (m) => m.status === status\n ).length;\n return (\n <div key={status} className=\"flex items-center justify-between text-sm\">\n <span className=\"flex items-center gap-2 text-text-secondary capitalize\">\n <span\n className={`h-1.5 w-1.5 rounded-full ${milestoneStatusDot[status]}`}\n />\n {status.replace('_', ' ')}\n </span>\n <span className=\"font-medium tabular-nums\">{count}</span>\n </div>\n );\n })}\n </CardContent>\n </GlassCard>\n </div>\n )}\n\n {/* Timeline tab */}\n {detailTab === 'timeline' && (\n <Card className=\"border-border-seam\">\n <CardContent className=\"pt-6\">\n <div className=\"relative space-y-0\">\n {selectedProject.milestones.map((milestone, idx) => {\n const isLast = idx === selectedProject.milestones.length - 1;\n return (\n <div key={milestone.id} className=\"relative flex gap-4 pb-8\">\n {/* Timeline line */}\n {!isLast && (\n <div className=\"absolute left-[11px] top-6 h-full w-0.5 bg-border-seam\" />\n )}\n {/* Dot */}\n <div\n className={`relative z-10 mt-1 h-6 w-6 shrink-0 rounded-full ${milestoneStatusDot[milestone.status]} flex items-center justify-center`}\n >\n {milestone.status === 'completed' && (\n <CheckCircle2 className=\"h-4 w-4 text-white\" />\n )}\n {milestone.status === 'in_progress' && (\n <Clock className=\"h-4 w-4 text-white\" />\n )}\n </div>\n {/* Content */}\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <h4 className=\"font-medium\">{milestone.title}</h4>\n <Badge\n variant={priorityConfig[milestone.priority].variant}\n className=\"text-xs\"\n >\n {milestone.priority}\n </Badge>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {milestone.description}\n </p>\n <div className=\"mt-2 flex flex-wrap gap-3 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" /> Due: {milestone.dueDate}\n </span>\n {milestone.completedAt && (\n <span className=\"flex items-center gap-1 text-status-success-text\">\n <CheckCircle2 className=\"h-3 w-3\" /> Completed:{' '}\n {milestone.completedAt}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Milestones tab */}\n {detailTab === 'milestones' && (\n <div className=\"space-y-3\">\n {selectedProject.milestones.map((milestone) => {\n const statusIcons: Record<string, typeof CheckCircle2> = {\n completed: CheckCircle2,\n in_progress: Clock,\n pending: Target,\n overdue: AlertTriangle,\n };\n const Icon = statusIcons[milestone.status] ?? Target;\n return (\n <Card key={milestone.id} className=\"border-border-seam\">\n <CardContent className=\"pt-4\">\n <div className=\"flex items-start gap-3\">\n <Icon\n className={`mt-0.5 h-5 w-5 ${milestoneStatusColor[milestone.status]}`}\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <h4 className=\"font-medium\">{milestone.title}</h4>\n <Badge\n variant={priorityConfig[milestone.priority].variant}\n className=\"text-xs\"\n >\n {milestone.priority}\n </Badge>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {milestone.description}\n </p>\n\n {/* Deliverables */}\n {milestone.deliverables.length > 0 && (\n <div className=\"mt-3\">\n <p className=\"text-xs font-medium text-text-secondary\">\n Deliverables\n </p>\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {milestone.deliverables.map((d) => (\n <Badge key={d} variant=\"outline\" className=\"text-xs\">\n {d}\n </Badge>\n ))}\n </div>\n </div>\n )}\n\n <div className=\"mt-3 flex flex-wrap gap-4 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" /> Due: {milestone.dueDate}\n </span>\n {milestone.completedAt && (\n <span className=\"flex items-center gap-1 text-status-success-text\">\n <CheckCircle2 className=\"h-3 w-3\" /> {milestone.completedAt}\n </span>\n )}\n {milestone.dependencies.length > 0 && (\n <span className=\"flex items-center gap-1\">\n <Flag className=\"h-3 w-3\" />\n <span className=\"tabular-nums\">\n {milestone.dependencies.length}\n </span>{' '}\n dependencies\n </span>\n )}\n </div>\n\n {milestone.notes && (\n <p className=\"mt-2 rounded bg-bg-sunken p-2 text-xs text-text-secondary italic\">\n {milestone.notes}\n </p>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n\n {/* Team tab */}\n {detailTab === 'team' && (\n <Card className=\"border-border-seam\">\n <CardHeader>\n <CardTitle className=\"text-base\">Team Members</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {selectedProject.teamMembers.map((member, idx) => (\n <div\n key={idx}\n className=\"flex items-center gap-3 rounded-lg border border-border-seam p-3\"\n >\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-accent-soft font-semibold text-text-primary\">\n {member.name.charAt(0)}\n </div>\n <div>\n <p className=\"font-medium\">{member.name}</p>\n <p className=\"text-sm text-text-secondary\">{member.role}</p>\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n </>\n ) : (\n <Card className=\"border-border-seam\">\n <CardContent className=\"py-6\">\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title=\"Select a project\"\n description=\"Pick a project from the sidebar to view its details.\"\n />\n </CardContent>\n </Card>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,538 +0,0 @@
1
- import { useProServiceWorldStore as e } from "../store/proserviceworldStore.js";
2
- import { useState as t } from "react";
3
- import { Award as n, Briefcase as r, Calendar as i, CheckCircle as a, MapPin as o, MessageSquare as s, Share2 as c, Star as l, Users as u } from "lucide-react";
4
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
- import { Badge as p, Button as m, CTAOverflowMenu as h, Card as g, CardContent as _, CardHeader as v, CardTitle as y, EmphasisPanel as b, GlassCard as x, IllustratedEmptyState as S, NextSteps as C, PagePurpose as w } from "@burdenoff/fe-libs/ui";
6
- //#region src/proserviceworld/pages/ProviderDetailPage.tsx
7
- function T() {
8
- let { providers: T, services: E, reviews: D } = e(), [O, k] = t("overview"), A = T[0], j = E.filter((e) => e.providerId === A.id), M = D.filter((e) => e.providerName === A.name), N = [
9
- {
10
- id: "overview",
11
- label: "Overview"
12
- },
13
- {
14
- id: "services",
15
- label: `Services (${j.length})`
16
- },
17
- {
18
- id: "reviews",
19
- label: `Reviews (${M.length})`
20
- }
21
- ];
22
- return /* @__PURE__ */ f("div", {
23
- className: "space-y-6 p-6 bg-bg-canvas min-h-screen",
24
- children: [
25
- /* @__PURE__ */ d(w, {
26
- icon: /* @__PURE__ */ d(r, { className: "h-4 w-4" }),
27
- children: "A full picture of this provider before you engage. Review their background, specializations, certifications, and ratings, browse the services they offer, and read client reviews — then contact them or book a consultation with confidence."
28
- }),
29
- /* @__PURE__ */ d(C, {
30
- storageKey: "proserviceworld-provider-detail",
31
- steps: [
32
- {
33
- id: "services",
34
- label: "Browse their services",
35
- description: "See what this provider offers and starting prices.",
36
- icon: /* @__PURE__ */ d(r, { className: "h-4 w-4" }),
37
- onClick: () => k("services")
38
- },
39
- {
40
- id: "reviews",
41
- label: "Read client reviews",
42
- description: "Check ratings and feedback from past clients.",
43
- icon: /* @__PURE__ */ d(l, { className: "h-4 w-4" }),
44
- onClick: () => k("reviews")
45
- },
46
- {
47
- id: "contact",
48
- label: "Contact the provider",
49
- description: "Start a conversation or book a consultation.",
50
- icon: /* @__PURE__ */ d(s, { className: "h-4 w-4" }),
51
- onClick: () => k("overview")
52
- }
53
- ]
54
- }),
55
- /* @__PURE__ */ f("div", {
56
- className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
57
- children: [/* @__PURE__ */ d("div", {
58
- className: "lg:col-span-2",
59
- children: /* @__PURE__ */ d(b, {
60
- className: "relative overflow-hidden",
61
- children: /* @__PURE__ */ f("div", {
62
- className: "flex items-start space-x-6",
63
- children: [/* @__PURE__ */ d("div", {
64
- className: "h-20 w-20 rounded-full bg-accent-soft flex items-center justify-center shrink-0",
65
- children: /* @__PURE__ */ f("span", {
66
- className: "text-text-primary text-2xl font-bold",
67
- children: [A.name.charAt(0), A.name.split(" ")[1]?.charAt(0)]
68
- })
69
- }), /* @__PURE__ */ f("div", {
70
- className: "flex-1",
71
- children: [
72
- /* @__PURE__ */ f("div", {
73
- className: "flex items-center gap-3 mb-1",
74
- children: [/* @__PURE__ */ d("h1", {
75
- className: "text-2xl font-bold tracking-tight",
76
- children: A.businessName
77
- }), A.verified && /* @__PURE__ */ f(p, {
78
- variant: "default",
79
- children: [/* @__PURE__ */ d(a, { className: "h-3 w-3 mr-1" }), "Verified"]
80
- })]
81
- }),
82
- /* @__PURE__ */ d("p", {
83
- className: "text-text-secondary mb-2",
84
- children: A.name
85
- }),
86
- /* @__PURE__ */ d("p", {
87
- className: "text-sm text-text-secondary mb-4",
88
- children: A.tagline
89
- }),
90
- /* @__PURE__ */ f("div", {
91
- className: "flex flex-wrap items-center gap-4 text-sm",
92
- children: [
93
- /* @__PURE__ */ f("div", {
94
- className: "flex items-center",
95
- children: [
96
- /* @__PURE__ */ d(l, { className: "h-4 w-4 text-status-warning-text fill-current mr-1" }),
97
- /* @__PURE__ */ d("span", {
98
- className: "font-medium tabular-nums",
99
- children: A.rating.toFixed(1)
100
- }),
101
- /* @__PURE__ */ f("span", {
102
- className: "text-text-secondary ml-1",
103
- children: [
104
- "(",
105
- A.totalReviews,
106
- " reviews)"
107
- ]
108
- })
109
- ]
110
- }),
111
- /* @__PURE__ */ f("div", {
112
- className: "flex items-center text-text-secondary",
113
- children: [/* @__PURE__ */ d(o, { className: "h-4 w-4 mr-1" }), A.location]
114
- }),
115
- /* @__PURE__ */ f("div", {
116
- className: "flex items-center text-text-secondary",
117
- children: [
118
- /* @__PURE__ */ d(r, { className: "h-4 w-4 mr-1" }),
119
- A.yearsExperience,
120
- " years"
121
- ]
122
- })
123
- ]
124
- })
125
- ]
126
- })]
127
- })
128
- })
129
- }), /* @__PURE__ */ d(x, {
130
- treatment: "glass",
131
- glow: !0,
132
- className: "border-border-seam",
133
- children: /* @__PURE__ */ f(_, {
134
- className: "p-6 space-y-4",
135
- children: [
136
- /* @__PURE__ */ f("div", {
137
- className: "text-center",
138
- children: [/* @__PURE__ */ f("div", {
139
- className: "text-2xl font-bold tabular-nums",
140
- children: [
141
- "$",
142
- A.hourlyRate,
143
- "/hr"
144
- ]
145
- }), /* @__PURE__ */ d("p", {
146
- className: "text-sm text-text-secondary",
147
- children: "Starting rate"
148
- })]
149
- }),
150
- /* @__PURE__ */ f(m, {
151
- className: "w-full",
152
- children: [/* @__PURE__ */ d(s, { className: "h-4 w-4 mr-2" }), "Contact Provider"]
153
- }),
154
- /* @__PURE__ */ d(h, {
155
- className: "justify-center",
156
- actions: [{
157
- label: "Book Consultation",
158
- onSelect: () => {},
159
- icon: /* @__PURE__ */ d(i, { className: "h-4 w-4" })
160
- }, {
161
- label: "Share Profile",
162
- onSelect: () => {},
163
- icon: /* @__PURE__ */ d(c, { className: "h-4 w-4" })
164
- }]
165
- }),
166
- /* @__PURE__ */ f("div", {
167
- className: "grid grid-cols-2 gap-4 text-sm pt-4 border-t border-border-seam",
168
- children: [
169
- /* @__PURE__ */ f("div", {
170
- className: "text-center p-3 bg-bg-sunken rounded",
171
- children: [/* @__PURE__ */ f("div", {
172
- className: "font-semibold tabular-nums",
173
- children: [A.responseTime, "h"]
174
- }), /* @__PURE__ */ d("div", {
175
- className: "text-text-secondary",
176
- children: "Response"
177
- })]
178
- }),
179
- /* @__PURE__ */ f("div", {
180
- className: "text-center p-3 bg-bg-sunken rounded",
181
- children: [/* @__PURE__ */ f("div", {
182
- className: "font-semibold tabular-nums",
183
- children: [A.completionRate, "%"]
184
- }), /* @__PURE__ */ d("div", {
185
- className: "text-text-secondary",
186
- children: "Completion"
187
- })]
188
- }),
189
- /* @__PURE__ */ f("div", {
190
- className: "text-center p-3 bg-bg-sunken rounded",
191
- children: [/* @__PURE__ */ d("div", {
192
- className: "font-semibold tabular-nums",
193
- children: A.projectsCompleted
194
- }), /* @__PURE__ */ d("div", {
195
- className: "text-text-secondary",
196
- children: "Projects"
197
- })]
198
- }),
199
- /* @__PURE__ */ f("div", {
200
- className: "text-center p-3 bg-bg-sunken rounded",
201
- children: [/* @__PURE__ */ d("div", {
202
- className: "font-semibold tabular-nums",
203
- children: A.activeProjects
204
- }), /* @__PURE__ */ d("div", {
205
- className: "text-text-secondary",
206
- children: "Active"
207
- })]
208
- })
209
- ]
210
- })
211
- ]
212
- })
213
- })]
214
- }),
215
- /* @__PURE__ */ d("div", {
216
- className: "border-b border-border-seam",
217
- children: /* @__PURE__ */ d("nav", {
218
- className: "-mb-px flex space-x-8",
219
- children: N.map((e) => /* @__PURE__ */ d("button", {
220
- onClick: () => k(e.id),
221
- "aria-pressed": O === e.id,
222
- className: `py-3 px-1 border-b-2 font-medium text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus ${O === e.id ? "border-accent-blue text-accent-blue" : "border-transparent text-text-secondary hover:text-text-primary"}`,
223
- children: e.label
224
- }, e.id))
225
- })
226
- }),
227
- O === "overview" && /* @__PURE__ */ f("div", {
228
- className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
229
- children: [/* @__PURE__ */ f("div", {
230
- className: "lg:col-span-2 space-y-6",
231
- children: [
232
- /* @__PURE__ */ f(g, {
233
- className: "border-border-seam",
234
- children: [/* @__PURE__ */ d(v, { children: /* @__PURE__ */ d(y, { children: "About" }) }), /* @__PURE__ */ d(_, { children: /* @__PURE__ */ d("p", {
235
- className: "text-text-secondary",
236
- children: A.description
237
- }) })]
238
- }),
239
- /* @__PURE__ */ f(g, {
240
- className: "border-border-seam",
241
- children: [/* @__PURE__ */ d(v, { children: /* @__PURE__ */ d(y, { children: "Specializations" }) }), /* @__PURE__ */ d(_, { children: /* @__PURE__ */ d("div", {
242
- className: "flex flex-wrap gap-2",
243
- children: A.specializations.map((e) => /* @__PURE__ */ d(p, {
244
- variant: "secondary",
245
- children: e
246
- }, e))
247
- }) })]
248
- }),
249
- /* @__PURE__ */ f(g, {
250
- className: "border-border-seam",
251
- children: [/* @__PURE__ */ d(v, { children: /* @__PURE__ */ d(y, { children: "Certifications" }) }), /* @__PURE__ */ d(_, {
252
- className: "space-y-3",
253
- children: A.certifications.map((e) => /* @__PURE__ */ f("div", {
254
- className: "flex items-center gap-3",
255
- children: [/* @__PURE__ */ d(n, { className: "h-5 w-5 text-accent-blue" }), /* @__PURE__ */ d("span", { children: e })]
256
- }, e))
257
- })]
258
- })
259
- ]
260
- }), /* @__PURE__ */ f("div", {
261
- className: "space-y-6",
262
- children: [/* @__PURE__ */ f(g, {
263
- className: "border-border-seam",
264
- children: [/* @__PURE__ */ d(v, { children: /* @__PURE__ */ d(y, { children: "Details" }) }), /* @__PURE__ */ f(_, {
265
- className: "space-y-3 text-sm",
266
- children: [
267
- /* @__PURE__ */ f("div", {
268
- className: "flex justify-between",
269
- children: [/* @__PURE__ */ d("span", {
270
- className: "text-text-secondary",
271
- children: "Location"
272
- }), /* @__PURE__ */ d("span", { children: A.location })]
273
- }),
274
- /* @__PURE__ */ f("div", {
275
- className: "flex justify-between",
276
- children: [/* @__PURE__ */ d("span", {
277
- className: "text-text-secondary",
278
- children: "Languages"
279
- }), /* @__PURE__ */ d("span", { children: A.languages.join(", ") })]
280
- }),
281
- /* @__PURE__ */ f("div", {
282
- className: "flex justify-between",
283
- children: [/* @__PURE__ */ d("span", {
284
- className: "text-text-secondary",
285
- children: "Member Since"
286
- }), /* @__PURE__ */ d("span", { children: new Date(A.joinedDate).toLocaleDateString("en-US", {
287
- month: "short",
288
- year: "numeric"
289
- }) })]
290
- }),
291
- /* @__PURE__ */ f("div", {
292
- className: "flex justify-between",
293
- children: [/* @__PURE__ */ d("span", {
294
- className: "text-text-secondary",
295
- children: "Category"
296
- }), /* @__PURE__ */ d("span", {
297
- className: "capitalize",
298
- children: A.category.replace("_", " ")
299
- })]
300
- })
301
- ]
302
- })]
303
- }), /* @__PURE__ */ f(g, {
304
- className: "border-border-seam",
305
- children: [/* @__PURE__ */ d(v, { children: /* @__PURE__ */ d(y, { children: "Similar Providers" }) }), /* @__PURE__ */ d(_, {
306
- className: "space-y-3",
307
- children: T.filter((e) => e.id !== A.id).slice(0, 3).map((e) => /* @__PURE__ */ f("div", {
308
- className: "flex items-center gap-3",
309
- children: [
310
- /* @__PURE__ */ d("div", {
311
- className: "h-8 w-8 rounded-full bg-bg-sunken flex items-center justify-center text-xs font-medium",
312
- children: e.name.charAt(0)
313
- }),
314
- /* @__PURE__ */ f("div", {
315
- className: "flex-1 min-w-0",
316
- children: [/* @__PURE__ */ d("p", {
317
- className: "text-sm font-medium truncate",
318
- children: e.businessName
319
- }), /* @__PURE__ */ d("p", {
320
- className: "text-xs text-text-secondary",
321
- children: e.specializations[0]
322
- })]
323
- }),
324
- /* @__PURE__ */ f("div", {
325
- className: "flex items-center text-xs",
326
- children: [/* @__PURE__ */ d(l, { className: "h-3 w-3 text-status-warning-text fill-current mr-0.5" }), /* @__PURE__ */ d("span", {
327
- className: "tabular-nums",
328
- children: e.rating.toFixed(1)
329
- })]
330
- })
331
- ]
332
- }, e.id))
333
- })]
334
- })]
335
- })]
336
- }),
337
- O === "services" && /* @__PURE__ */ d("div", {
338
- className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",
339
- children: j.length > 0 ? j.map((e) => /* @__PURE__ */ d(x, {
340
- treatment: "plain",
341
- className: "border-border-seam transition-shadow hover:shadow-pop",
342
- children: /* @__PURE__ */ f(_, {
343
- className: "p-6",
344
- children: [
345
- /* @__PURE__ */ d("h3", {
346
- className: "font-semibold mb-2",
347
- children: e.title
348
- }),
349
- /* @__PURE__ */ d("p", {
350
- className: "text-sm text-text-secondary mb-3 line-clamp-2",
351
- children: e.description
352
- }),
353
- /* @__PURE__ */ d("div", {
354
- className: "flex flex-wrap gap-1 mb-3",
355
- children: e.tags.slice(0, 3).map((e) => /* @__PURE__ */ d(p, {
356
- variant: "outline",
357
- className: "text-xs",
358
- children: e
359
- }, e))
360
- }),
361
- /* @__PURE__ */ f("div", {
362
- className: "flex justify-between border-t border-border-seam pt-3",
363
- children: [/* @__PURE__ */ f("span", {
364
- className: "font-medium tabular-nums",
365
- children: ["From $", e.pricing.basePrice.toLocaleString()]
366
- }), /* @__PURE__ */ f("span", {
367
- className: "text-sm text-text-secondary tabular-nums",
368
- children: [e.duration.typical, " days"]
369
- })]
370
- }),
371
- /* @__PURE__ */ d(m, {
372
- variant: "outline",
373
- size: "sm",
374
- className: "w-full mt-3",
375
- children: "View Details"
376
- })
377
- ]
378
- })
379
- }, e.id)) : /* @__PURE__ */ d("div", {
380
- className: "col-span-full",
381
- children: /* @__PURE__ */ d(S, {
382
- illustration: "empty-data",
383
- title: "No services listed yet",
384
- description: "This provider has not published any services."
385
- })
386
- })
387
- }),
388
- O === "reviews" && /* @__PURE__ */ f("div", {
389
- className: "space-y-4",
390
- children: [/* @__PURE__ */ d(x, {
391
- treatment: "metric",
392
- className: "border-border-seam",
393
- children: /* @__PURE__ */ d(_, {
394
- className: "p-6",
395
- children: /* @__PURE__ */ f("div", {
396
- className: "flex flex-col gap-8 sm:flex-row sm:items-center",
397
- children: [/* @__PURE__ */ f("div", {
398
- className: "text-center",
399
- children: [
400
- /* @__PURE__ */ d("div", {
401
- className: "text-4xl font-bold tabular-nums",
402
- children: A.rating.toFixed(1)
403
- }),
404
- /* @__PURE__ */ d("div", {
405
- className: "flex justify-center mt-1",
406
- children: [
407
- 1,
408
- 2,
409
- 3,
410
- 4,
411
- 5
412
- ].map((e) => /* @__PURE__ */ d(l, { className: `h-4 w-4 ${e <= Math.round(A.rating) ? "text-status-warning-text fill-current" : "text-text-secondary"}` }, e))
413
- }),
414
- /* @__PURE__ */ f("p", {
415
- className: "text-sm text-text-secondary mt-1",
416
- children: [A.totalReviews, " reviews"]
417
- })
418
- ]
419
- }), /* @__PURE__ */ d("div", {
420
- className: "flex-1 space-y-1",
421
- children: [
422
- 5,
423
- 4,
424
- 3,
425
- 2,
426
- 1
427
- ].map((e) => {
428
- let t = M.filter((t) => Math.round(t.rating) === e).length, n = M.length > 0 ? t / M.length * 100 : 0;
429
- return /* @__PURE__ */ f("div", {
430
- className: "flex items-center gap-2",
431
- children: [
432
- /* @__PURE__ */ d("span", {
433
- className: "text-sm w-3 tabular-nums",
434
- children: e
435
- }),
436
- /* @__PURE__ */ d(l, { className: "h-3 w-3 text-status-warning-text fill-current" }),
437
- /* @__PURE__ */ d("div", {
438
- className: "flex-1 bg-bg-sunken rounded-full h-2",
439
- children: /* @__PURE__ */ d("div", {
440
- className: "bg-status-warning-text h-2 rounded-full",
441
- style: { width: `${n}%` }
442
- })
443
- }),
444
- /* @__PURE__ */ d("span", {
445
- className: "text-sm text-text-secondary w-6 text-right tabular-nums",
446
- children: t
447
- })
448
- ]
449
- }, e);
450
- })
451
- })]
452
- })
453
- })
454
- }), M.map((e) => /* @__PURE__ */ d(g, {
455
- className: "border-border-seam",
456
- children: /* @__PURE__ */ f(_, {
457
- className: "p-6",
458
- children: [
459
- /* @__PURE__ */ f("div", {
460
- className: "flex items-center gap-3 mb-3",
461
- children: [/* @__PURE__ */ d("div", {
462
- className: "h-10 w-10 rounded-full bg-accent-soft flex items-center justify-center",
463
- children: /* @__PURE__ */ d("span", {
464
- className: "text-text-primary font-medium",
465
- children: e.clientName.charAt(0)
466
- })
467
- }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ f("div", {
468
- className: "flex items-center gap-2",
469
- children: [/* @__PURE__ */ d("span", {
470
- className: "font-medium",
471
- children: e.clientName
472
- }), /* @__PURE__ */ d("div", {
473
- className: "flex",
474
- children: [
475
- 1,
476
- 2,
477
- 3,
478
- 4,
479
- 5
480
- ].map((t) => /* @__PURE__ */ d(l, { className: `h-3 w-3 ${t <= e.rating ? "text-status-warning-text fill-current" : "text-text-secondary"}` }, t))
481
- })]
482
- }), /* @__PURE__ */ f("p", {
483
- className: "text-xs text-text-secondary",
484
- children: [
485
- e.serviceName,
486
- " -",
487
- " ",
488
- new Date(e.createdAt).toLocaleDateString("en-US", {
489
- month: "long",
490
- day: "numeric",
491
- year: "numeric"
492
- })
493
- ]
494
- })] })]
495
- }),
496
- /* @__PURE__ */ d("p", {
497
- className: "text-sm text-text-secondary mb-3",
498
- children: e.comment
499
- }),
500
- /* @__PURE__ */ f("div", {
501
- className: "flex flex-wrap gap-4 text-xs text-text-secondary",
502
- children: [
503
- /* @__PURE__ */ f("span", {
504
- className: "tabular-nums",
505
- children: ["Value: $", e.projectValue.toLocaleString()]
506
- }),
507
- /* @__PURE__ */ f("span", {
508
- className: "tabular-nums",
509
- children: [
510
- "Duration: ",
511
- e.projectDuration,
512
- " days"
513
- ]
514
- }),
515
- /* @__PURE__ */ f("span", {
516
- className: "flex items-center",
517
- children: [
518
- /* @__PURE__ */ d(u, { className: "h-3 w-3 mr-1" }),
519
- /* @__PURE__ */ d("span", {
520
- className: "tabular-nums",
521
- children: e.helpful
522
- }),
523
- " helpful"
524
- ]
525
- })
526
- ]
527
- })
528
- ]
529
- })
530
- }, e.id))]
531
- })
532
- ]
533
- });
534
- }
535
- //#endregion
536
- export { T as ProviderDetailPage };
537
-
538
- //# sourceMappingURL=ProviderDetailPage.js.map