@burdenoff/microfe-coolandlovely 2026.625.2 → 2026.628.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 (165) hide show
  1. package/dist/coolandlovely/CoolAndLovelyRoot.js +66 -122
  2. package/dist/coolandlovely/CoolAndLovelyRoot.js.map +1 -1
  3. package/dist/coolandlovely/CoolAndLovelyRoutes.js +87 -175
  4. package/dist/coolandlovely/CoolAndLovelyRoutes.js.map +1 -1
  5. package/dist/coolandlovely/components/Field.js +81 -0
  6. package/dist/coolandlovely/components/Field.js.map +1 -0
  7. package/dist/coolandlovely/components/StateViews.js +34 -0
  8. package/dist/coolandlovely/components/StateViews.js.map +1 -0
  9. package/dist/coolandlovely/components/StatusBadge.js +25 -22
  10. package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
  11. package/dist/coolandlovely/components/TagList.js +21 -0
  12. package/dist/coolandlovely/components/TagList.js.map +1 -0
  13. package/dist/coolandlovely/components/Thumbnail.js +29 -0
  14. package/dist/coolandlovely/components/Thumbnail.js.map +1 -0
  15. package/dist/coolandlovely/context/CoolAndLovelyContext.js +10 -10
  16. package/dist/coolandlovely/context/CoolAndLovelyContext.js.map +1 -1
  17. package/dist/coolandlovely/hooks/index.js +1 -0
  18. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js +462 -169
  19. package/dist/coolandlovely/hooks/useCoolAndLovelyApi.js.map +1 -1
  20. package/dist/coolandlovely/pages/HomePage.js +251 -845
  21. package/dist/coolandlovely/pages/HomePage.js.map +1 -1
  22. package/dist/coolandlovely/pages/brands/BrandDetailPage.js +319 -0
  23. package/dist/coolandlovely/pages/brands/BrandDetailPage.js.map +1 -0
  24. package/dist/coolandlovely/pages/brands/BrandFormPage.js +190 -0
  25. package/dist/coolandlovely/pages/brands/BrandFormPage.js.map +1 -0
  26. package/dist/coolandlovely/pages/brands/BrandsListPage.js +158 -0
  27. package/dist/coolandlovely/pages/brands/BrandsListPage.js.map +1 -0
  28. package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js +253 -0
  29. package/dist/coolandlovely/pages/collaborations/CollaborationDetailPage.js.map +1 -0
  30. package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js +206 -0
  31. package/dist/coolandlovely/pages/collaborations/CollaborationFormPage.js.map +1 -0
  32. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js +129 -0
  33. package/dist/coolandlovely/pages/collaborations/CollaborationsListPage.js.map +1 -0
  34. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js +217 -0
  35. package/dist/coolandlovely/pages/collections/CollectionDetailPage.js.map +1 -0
  36. package/dist/coolandlovely/pages/collections/CollectionFormPage.js +217 -0
  37. package/dist/coolandlovely/pages/collections/CollectionFormPage.js.map +1 -0
  38. package/dist/coolandlovely/pages/collections/CollectionsListPage.js +122 -0
  39. package/dist/coolandlovely/pages/collections/CollectionsListPage.js.map +1 -0
  40. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js +230 -0
  41. package/dist/coolandlovely/pages/items/StyleItemDetailPage.js.map +1 -0
  42. package/dist/coolandlovely/pages/items/StyleItemFormPage.js +276 -0
  43. package/dist/coolandlovely/pages/items/StyleItemFormPage.js.map +1 -0
  44. package/dist/coolandlovely/pages/items/StyleItemsListPage.js +170 -0
  45. package/dist/coolandlovely/pages/items/StyleItemsListPage.js.map +1 -0
  46. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js +124 -0
  47. package/dist/coolandlovely/pages/lookbooks/LookbookDetailPage.js.map +1 -0
  48. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js +156 -0
  49. package/dist/coolandlovely/pages/lookbooks/LookbooksListPage.js.map +1 -0
  50. package/dist/coolandlovely/pages/looks/LookDetailPage.js +238 -0
  51. package/dist/coolandlovely/pages/looks/LookDetailPage.js.map +1 -0
  52. package/dist/coolandlovely/pages/looks/LookFormPage.js +209 -0
  53. package/dist/coolandlovely/pages/looks/LookFormPage.js.map +1 -0
  54. package/dist/coolandlovely/pages/looks/LooksListPage.js +181 -0
  55. package/dist/coolandlovely/pages/looks/LooksListPage.js.map +1 -0
  56. package/dist/coolandlovely/pages/profile/StyleProfilePage.js +224 -0
  57. package/dist/coolandlovely/pages/profile/StyleProfilePage.js.map +1 -0
  58. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js +173 -0
  59. package/dist/coolandlovely/pages/wardrobe/WardrobeFormPage.js.map +1 -0
  60. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js +172 -0
  61. package/dist/coolandlovely/pages/wardrobe/WardrobeListPage.js.map +1 -0
  62. package/dist/coolandlovely/store/coolandlovelyStore.js +2 -6
  63. package/dist/coolandlovely/store/coolandlovelyStore.js.map +1 -1
  64. package/dist/coolandlovely/utils/formatters.js +31 -23
  65. package/dist/coolandlovely/utils/formatters.js.map +1 -1
  66. package/dist/coolandlovely/utils/icons.js +34 -0
  67. package/dist/coolandlovely/utils/icons.js.map +1 -0
  68. package/dist/index.js +4 -4
  69. package/package.json +1 -1
  70. package/dist/coolandlovely/components/InvestmentCard.js +0 -98
  71. package/dist/coolandlovely/components/InvestmentCard.js.map +0 -1
  72. package/dist/coolandlovely/components/RatingDisplay.js +0 -35
  73. package/dist/coolandlovely/components/RatingDisplay.js.map +0 -1
  74. package/dist/coolandlovely/mocks/data.js +0 -1517
  75. package/dist/coolandlovely/mocks/data.js.map +0 -1
  76. package/dist/coolandlovely/mocks/users.js +0 -34
  77. package/dist/coolandlovely/mocks/users.js.map +0 -1
  78. package/dist/coolandlovely/pages/admin/AdminAnalyticsPage.js +0 -651
  79. package/dist/coolandlovely/pages/admin/AdminAnalyticsPage.js.map +0 -1
  80. package/dist/coolandlovely/pages/admin/AdminDashboard.js +0 -673
  81. package/dist/coolandlovely/pages/admin/AdminDashboard.js.map +0 -1
  82. package/dist/coolandlovely/pages/admin/AdminFinancialPage.js +0 -427
  83. package/dist/coolandlovely/pages/admin/AdminFinancialPage.js.map +0 -1
  84. package/dist/coolandlovely/pages/admin/AdminOrdersPage.js +0 -665
  85. package/dist/coolandlovely/pages/admin/AdminOrdersPage.js.map +0 -1
  86. package/dist/coolandlovely/pages/admin/AdminProfilePage.js +0 -264
  87. package/dist/coolandlovely/pages/admin/AdminProfilePage.js.map +0 -1
  88. package/dist/coolandlovely/pages/admin/AdminSettingsPage.js +0 -654
  89. package/dist/coolandlovely/pages/admin/AdminSettingsPage.js.map +0 -1
  90. package/dist/coolandlovely/pages/admin/CartManagementPage.js +0 -874
  91. package/dist/coolandlovely/pages/admin/CartManagementPage.js.map +0 -1
  92. package/dist/coolandlovely/pages/admin/UserManagementPage.js +0 -898
  93. package/dist/coolandlovely/pages/admin/UserManagementPage.js.map +0 -1
  94. package/dist/coolandlovely/pages/cart-owner/AnalyticsDashboard.js +0 -842
  95. package/dist/coolandlovely/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
  96. package/dist/coolandlovely/pages/cart-owner/BusinessSettingsPage.js +0 -705
  97. package/dist/coolandlovely/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
  98. package/dist/coolandlovely/pages/cart-owner/CartOwnerDashboard.js +0 -802
  99. package/dist/coolandlovely/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
  100. package/dist/coolandlovely/pages/cart-owner/CartOwnerProfilePage.js +0 -891
  101. package/dist/coolandlovely/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
  102. package/dist/coolandlovely/pages/cart-owner/CartServiceConfigPage.js +0 -639
  103. package/dist/coolandlovely/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
  104. package/dist/coolandlovely/pages/cart-owner/InventoryManagementPage.js +0 -914
  105. package/dist/coolandlovely/pages/cart-owner/InventoryManagementPage.js.map +0 -1
  106. package/dist/coolandlovely/pages/cart-owner/OrderManagementPage.js +0 -882
  107. package/dist/coolandlovely/pages/cart-owner/OrderManagementPage.js.map +0 -1
  108. package/dist/coolandlovely/pages/cart-owner/StaffManagementPage.js +0 -831
  109. package/dist/coolandlovely/pages/cart-owner/StaffManagementPage.js.map +0 -1
  110. package/dist/coolandlovely/pages/common/HelpSupportPage.js +0 -1325
  111. package/dist/coolandlovely/pages/common/HelpSupportPage.js.map +0 -1
  112. package/dist/coolandlovely/pages/common/NotificationCenterPage.js +0 -671
  113. package/dist/coolandlovely/pages/common/NotificationCenterPage.js.map +0 -1
  114. package/dist/coolandlovely/pages/common/SettingsPage.js +0 -973
  115. package/dist/coolandlovely/pages/common/SettingsPage.js.map +0 -1
  116. package/dist/coolandlovely/pages/customer/BookingDetailsPage.js +0 -630
  117. package/dist/coolandlovely/pages/customer/BookingDetailsPage.js.map +0 -1
  118. package/dist/coolandlovely/pages/customer/CartDetailPage.js +0 -623
  119. package/dist/coolandlovely/pages/customer/CartDetailPage.js.map +0 -1
  120. package/dist/coolandlovely/pages/customer/CartDiscoveryPage.js +0 -558
  121. package/dist/coolandlovely/pages/customer/CartDiscoveryPage.js.map +0 -1
  122. package/dist/coolandlovely/pages/customer/CheckoutPage.js +0 -529
  123. package/dist/coolandlovely/pages/customer/CheckoutPage.js.map +0 -1
  124. package/dist/coolandlovely/pages/customer/CustomerDashboard.js +0 -538
  125. package/dist/coolandlovely/pages/customer/CustomerDashboard.js.map +0 -1
  126. package/dist/coolandlovely/pages/customer/CustomerProfilePage.js +0 -658
  127. package/dist/coolandlovely/pages/customer/CustomerProfilePage.js.map +0 -1
  128. package/dist/coolandlovely/pages/customer/DirectServiceBookingPage.js +0 -632
  129. package/dist/coolandlovely/pages/customer/DirectServiceBookingPage.js.map +0 -1
  130. package/dist/coolandlovely/pages/customer/FavoritesPage.js +0 -487
  131. package/dist/coolandlovely/pages/customer/FavoritesPage.js.map +0 -1
  132. package/dist/coolandlovely/pages/customer/OrderHistoryPage.js +0 -447
  133. package/dist/coolandlovely/pages/customer/OrderHistoryPage.js.map +0 -1
  134. package/dist/coolandlovely/pages/customer/OrderTrackingPage.js +0 -425
  135. package/dist/coolandlovely/pages/customer/OrderTrackingPage.js.map +0 -1
  136. package/dist/coolandlovely/pages/customer/PaymentMethodsPage.js +0 -494
  137. package/dist/coolandlovely/pages/customer/PaymentMethodsPage.js.map +0 -1
  138. package/dist/coolandlovely/pages/customer/ReviewsPage.js +0 -616
  139. package/dist/coolandlovely/pages/customer/ReviewsPage.js.map +0 -1
  140. package/dist/coolandlovely/pages/customer/SavedAddressesPage.js +0 -449
  141. package/dist/coolandlovely/pages/customer/SavedAddressesPage.js.map +0 -1
  142. package/dist/coolandlovely/pages/investor/InvestmentDetailsPage.js +0 -887
  143. package/dist/coolandlovely/pages/investor/InvestmentDetailsPage.js.map +0 -1
  144. package/dist/coolandlovely/pages/investor/InvestmentOpportunitiesPage.js +0 -945
  145. package/dist/coolandlovely/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
  146. package/dist/coolandlovely/pages/investor/InvestorAnalyticsPage.js +0 -687
  147. package/dist/coolandlovely/pages/investor/InvestorAnalyticsPage.js.map +0 -1
  148. package/dist/coolandlovely/pages/investor/InvestorDashboard.js +0 -455
  149. package/dist/coolandlovely/pages/investor/InvestorDashboard.js.map +0 -1
  150. package/dist/coolandlovely/pages/investor/InvestorInvestmentsPage.js +0 -405
  151. package/dist/coolandlovely/pages/investor/InvestorInvestmentsPage.js.map +0 -1
  152. package/dist/coolandlovely/pages/investor/InvestorPortfolioPage.js +0 -602
  153. package/dist/coolandlovely/pages/investor/InvestorPortfolioPage.js.map +0 -1
  154. package/dist/coolandlovely/pages/investor/InvestorProfilePage.js +0 -1070
  155. package/dist/coolandlovely/pages/investor/InvestorProfilePage.js.map +0 -1
  156. package/dist/coolandlovely/pages/worker/TaskDetailsPage.js +0 -533
  157. package/dist/coolandlovely/pages/worker/TaskDetailsPage.js.map +0 -1
  158. package/dist/coolandlovely/pages/worker/WorkerDashboard.js +0 -671
  159. package/dist/coolandlovely/pages/worker/WorkerDashboard.js.map +0 -1
  160. package/dist/coolandlovely/pages/worker/WorkerOrdersPage.js +0 -680
  161. package/dist/coolandlovely/pages/worker/WorkerOrdersPage.js.map +0 -1
  162. package/dist/coolandlovely/pages/worker/WorkerProfilePage.js +0 -692
  163. package/dist/coolandlovely/pages/worker/WorkerProfilePage.js.map +0 -1
  164. package/dist/coolandlovely/pages/worker/WorkerSchedulePage.js +0 -583
  165. package/dist/coolandlovely/pages/worker/WorkerSchedulePage.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollaborationDetailPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collaborations/CollaborationDetailPage.tsx"],"sourcesContent":["/**\n * Collaboration Detail Page\n * @module coolandlovely/pages/collaborations\n *\n * Single collaboration (`cooCollaboration`) with validated lifecycle\n * transitions (`cooTransitionCollaboration`), its brand and attributed looks.\n */\n\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Loader2, Handshake, Store, Sparkles } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { TagList } from '../../components/TagList';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCollaboration, useTransitionCollaboration } from '../../hooks';\nimport { formatPrice, formatDate, titleCase } from '../../utils/formatters';\nimport type { CooCollaborationStatus } from '../../types';\n\n/** Allowed next states per the svc collaboration state machine (UX guidance;\n * the service is authoritative and rejects illegal jumps). */\nconst NEXT_STATES: Record<CooCollaborationStatus, CooCollaborationStatus[]> = {\n PROPOSED: ['ACCEPTED', 'DECLINED', 'CANCELLED'],\n ACCEPTED: ['IN_PROGRESS', 'CANCELLED'],\n IN_PROGRESS: ['PUBLISHED', 'CANCELLED'],\n PUBLISHED: [],\n DECLINED: [],\n CANCELLED: [],\n};\n\nexport function CollaborationDetailPage() {\n const { collaborationId } = useParams<{ collaborationId: string }>();\n const { navigateTo } = useCoolAndLovely();\n const query = useCollaboration(collaborationId);\n const transition = useTransitionCollaboration();\n\n if (query.isLoading) {\n return (\n <PageLayout title=\"Collaboration\">\n <LoadingView label=\"Loading collaboration…\" />\n </PageLayout>\n );\n }\n\n if (query.isError || !query.data) {\n return (\n <PageLayout title=\"Collaboration\">\n <ErrorView title=\"Collaboration not found\" onRetry={() => void query.refetch()} />\n </PageLayout>\n );\n }\n\n const collab = query.data;\n const looks = collab.looks ?? [];\n const nextStates = NEXT_STATES[collab.status];\n\n return (\n <PageLayout\n title={collab.title}\n description={collab.brand?.name ?? undefined}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collaborations')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2\">\n <GlassCard treatment=\"glass\" className=\"p-6\">\n <div className=\"flex items-center gap-3\">\n <Thumbnail icon={<Handshake className=\"h-6 w-6\" />} seed={collab.id} className=\"h-12 w-12 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"truncate text-xl font-semibold text-text-primary\">{collab.title}</h2>\n <p className=\"text-xs text-text-secondary\">{titleCase(collab.role)} collaboration</p>\n </div>\n <StatusBadge status={collab.status} />\n </div>\n {collab.brief && <p className=\"mt-4 text-sm text-text-secondary\">{collab.brief}</p>}\n {collab.tags.length > 0 && <TagList tags={collab.tags} className=\"mt-4\" tone=\"accent\" />}\n </GlassCard>\n\n {/* Attributed looks */}\n <section className=\"mt-6\">\n <h3 className=\"mb-3 text-lg font-semibold text-text-primary\">\n Attributed looks ({looks.length})\n </h3>\n {looks.length === 0 ? (\n <p className=\"rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary\">\n No looks attributed to this collaboration yet.\n </p>\n ) : (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n {looks.map((look) => (\n <button\n key={look.id}\n type=\"button\"\n onClick={() => navigateTo(`/looks/${look.id}`)}\n className=\"overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <Thumbnail icon={<Sparkles className=\"h-6 w-6\" />} seed={look.id} className=\"h-24 w-full\" />\n <div className=\"p-3\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{look.title}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{titleCase(look.occasion)}</p>\n </div>\n </button>\n ))}\n </div>\n )}\n </section>\n </div>\n\n <div className=\"space-y-4\">\n <GlassCard treatment=\"insight\" className=\"p-5\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">Lifecycle</h3>\n <div className=\"mb-3 flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">Current:</span>\n <StatusBadge status={collab.status} />\n </div>\n {nextStates.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">This collaboration is in a terminal state.</p>\n ) : (\n <div className=\"flex flex-col gap-2\">\n {nextStates.map((next) => (\n <button\n key={next}\n type=\"button\"\n disabled={transition.isPending}\n onClick={() => transition.mutate({ id: collab.id, status: next })}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50\"\n >\n {transition.isPending && <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />}\n Move to {titleCase(next)}\n </button>\n ))}\n </div>\n )}\n {transition.isError && (\n <p className=\"mt-2 text-xs text-status-error-text\">\n {transition.error instanceof Error ? transition.error.message : 'Transition failed'}\n </p>\n )}\n </GlassCard>\n\n <GlassCard treatment=\"plain\" className=\"p-5\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">Terms</h3>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Role</dt>\n <dd className=\"text-text-primary\">{titleCase(collab.role)}</dd>\n </div>\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Compensation</dt>\n <dd className=\"text-text-primary\">{formatPrice(collab.compensation, collab.currency)}</dd>\n </div>\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Starts</dt>\n <dd className=\"text-text-primary\">\n {collab.startDate\n ? formatDate(collab.startDate, { hour: undefined, minute: undefined })\n : '—'}\n </dd>\n </div>\n <div className=\"flex justify-between gap-2\">\n <dt className=\"text-text-secondary\">Ends</dt>\n <dd className=\"text-text-primary\">\n {collab.endDate\n ? formatDate(collab.endDate, { hour: undefined, minute: undefined })\n : '—'}\n </dd>\n </div>\n </dl>\n </GlassCard>\n\n {collab.brand && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/brands/${collab.brand?.id}`)}\n className=\"flex w-full items-center gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n <Thumbnail icon={<Store className=\"h-5 w-5\" />} seed={collab.brand.id} className=\"h-10 w-10 shrink-0\" />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{collab.brand.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">View brand</p>\n </div>\n </button>\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,206 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { useBrands as n, useCreateCollaboration as r } from "../../hooks/useCoolAndLovelyApi.js";
4
+ import "../../hooks/index.js";
5
+ import { parseCsv as i, titleCase as a } from "../../utils/formatters.js";
6
+ import { SelectField as o, TextAreaField as s, TextField as c } from "../../components/Field.js";
7
+ import { useMemo as l, useState as u } from "react";
8
+ import { ArrowLeft as d, Handshake as f, Loader2 as p, Save as m } from "lucide-react";
9
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
10
+ import { GlassCard as _ } from "@burdenoff/fe-libs/ui";
11
+ //#region src/coolandlovely/pages/collaborations/CollaborationFormPage.tsx
12
+ var v = [
13
+ "CREATOR",
14
+ "BRAND",
15
+ "STYLIST",
16
+ "PHOTOGRAPHER"
17
+ ];
18
+ function y(e) {
19
+ if (!e) return;
20
+ let t = new Date(e);
21
+ return Number.isNaN(t.getTime()) ? void 0 : t.toISOString();
22
+ }
23
+ function b() {
24
+ let { navigateTo: b, currentUser: x } = e(), S = r(), C = n({ pagination: {
25
+ limit: 100,
26
+ offset: 0
27
+ } }), [w, T] = u({
28
+ brandId: "",
29
+ creatorId: x?.id ?? "",
30
+ title: "",
31
+ brief: "",
32
+ role: "CREATOR",
33
+ compensation: "",
34
+ currency: "USD",
35
+ tags: "",
36
+ startDate: "",
37
+ endDate: ""
38
+ }), [E, D] = u({}), O = (e, t) => T((n) => ({
39
+ ...n,
40
+ [e]: t
41
+ })), k = l(() => (C.data?.items ?? []).map((e) => ({
42
+ value: e.id,
43
+ label: e.name
44
+ })), [C.data]), A = v.map((e) => ({
45
+ value: e,
46
+ label: a(e)
47
+ })), j = () => {
48
+ let e = {};
49
+ return w.title.trim() || (e.title = "Title is required"), w.brandId || (e.brandId = "Brand is required"), w.creatorId.trim() || (e.creatorId = "Creator is required"), w.compensation && Number.isNaN(Number(w.compensation)) && (e.compensation = "Must be a number"), D(e), Object.keys(e).length === 0;
50
+ };
51
+ return /* @__PURE__ */ h(t, {
52
+ title: "New collaboration",
53
+ description: "Propose a brand × creator partnership",
54
+ actions: /* @__PURE__ */ g("button", {
55
+ type: "button",
56
+ onClick: () => b("/collaborations"),
57
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
58
+ children: [/* @__PURE__ */ h(d, { className: "h-4 w-4" }), " Cancel"]
59
+ }),
60
+ children: /* @__PURE__ */ h("form", {
61
+ onSubmit: (e) => {
62
+ e.preventDefault(), j() && S.mutate({
63
+ brandId: w.brandId,
64
+ creatorId: w.creatorId.trim(),
65
+ title: w.title.trim(),
66
+ brief: w.brief.trim() || void 0,
67
+ role: w.role,
68
+ compensation: w.compensation ? Number(w.compensation) : void 0,
69
+ currency: w.currency.trim() || void 0,
70
+ tags: i(w.tags),
71
+ startDate: y(w.startDate),
72
+ endDate: y(w.endDate)
73
+ }, { onSuccess: (e) => b(`/collaborations/${e.id}`) });
74
+ },
75
+ className: "mx-auto max-w-2xl",
76
+ children: /* @__PURE__ */ g(_, {
77
+ treatment: "plain",
78
+ className: "p-6",
79
+ children: [
80
+ /* @__PURE__ */ g("div", {
81
+ className: "mb-6 flex items-center gap-3",
82
+ children: [/* @__PURE__ */ h("div", {
83
+ className: "flex h-11 w-11 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text",
84
+ children: /* @__PURE__ */ h(f, { className: "h-5 w-5" })
85
+ }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h2", {
86
+ className: "text-base font-semibold text-text-primary",
87
+ children: "Collaboration details"
88
+ }), /* @__PURE__ */ h("p", {
89
+ className: "text-xs text-text-secondary",
90
+ children: "Created in the Proposed state."
91
+ })] })]
92
+ }),
93
+ /* @__PURE__ */ g("div", {
94
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
95
+ children: [/* @__PURE__ */ h(o, {
96
+ id: "brandId",
97
+ label: "Brand",
98
+ value: w.brandId,
99
+ onChange: (e) => O("brandId", e),
100
+ options: k,
101
+ required: !0,
102
+ placeholder: C.isLoading ? "Loading brands…" : "Select a brand",
103
+ error: E.brandId
104
+ }), /* @__PURE__ */ h(o, {
105
+ id: "role",
106
+ label: "Role",
107
+ value: w.role,
108
+ onChange: (e) => O("role", e),
109
+ options: A
110
+ })]
111
+ }),
112
+ /* @__PURE__ */ h(c, {
113
+ id: "title",
114
+ label: "Title",
115
+ value: w.title,
116
+ onChange: (e) => O("title", e),
117
+ placeholder: "Summer capsule edit",
118
+ required: !0,
119
+ error: E.title,
120
+ className: "mt-4"
121
+ }),
122
+ /* @__PURE__ */ h(c, {
123
+ id: "creatorId",
124
+ label: "Creator ID",
125
+ value: w.creatorId,
126
+ onChange: (e) => O("creatorId", e),
127
+ placeholder: "creator user id",
128
+ required: !0,
129
+ hint: "Defaults to you. Paste another user's id to credit a different creator.",
130
+ error: E.creatorId,
131
+ className: "mt-4"
132
+ }),
133
+ /* @__PURE__ */ h(s, {
134
+ id: "brief",
135
+ label: "Brief",
136
+ value: w.brief,
137
+ onChange: (e) => O("brief", e),
138
+ placeholder: "What is this collaboration about…",
139
+ rows: 4,
140
+ className: "mt-4"
141
+ }),
142
+ /* @__PURE__ */ g("div", {
143
+ className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
144
+ children: [/* @__PURE__ */ h(c, {
145
+ id: "compensation",
146
+ label: "Compensation",
147
+ type: "number",
148
+ value: w.compensation,
149
+ onChange: (e) => O("compensation", e),
150
+ placeholder: "0.00",
151
+ error: E.compensation
152
+ }), /* @__PURE__ */ h(c, {
153
+ id: "currency",
154
+ label: "Currency",
155
+ value: w.currency,
156
+ onChange: (e) => O("currency", e),
157
+ placeholder: "USD"
158
+ })]
159
+ }),
160
+ /* @__PURE__ */ g("div", {
161
+ className: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2",
162
+ children: [/* @__PURE__ */ h(c, {
163
+ id: "startDate",
164
+ label: "Start date",
165
+ type: "date",
166
+ value: w.startDate,
167
+ onChange: (e) => O("startDate", e)
168
+ }), /* @__PURE__ */ h(c, {
169
+ id: "endDate",
170
+ label: "End date",
171
+ type: "date",
172
+ value: w.endDate,
173
+ onChange: (e) => O("endDate", e)
174
+ })]
175
+ }),
176
+ /* @__PURE__ */ h(c, {
177
+ id: "tags",
178
+ label: "Tags",
179
+ value: w.tags,
180
+ onChange: (e) => O("tags", e),
181
+ placeholder: "capsule, sustainable",
182
+ hint: "Comma-separated",
183
+ className: "mt-4"
184
+ }),
185
+ S.isError && /* @__PURE__ */ h("p", {
186
+ className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
187
+ children: S.error instanceof Error ? S.error.message : "Something went wrong"
188
+ }),
189
+ /* @__PURE__ */ h("div", {
190
+ className: "mt-6 flex justify-end gap-2",
191
+ children: /* @__PURE__ */ g("button", {
192
+ type: "submit",
193
+ disabled: S.isPending,
194
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50",
195
+ children: [S.isPending ? /* @__PURE__ */ h(p, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ h(m, { className: "h-4 w-4" }), "Create collaboration"]
196
+ })
197
+ })
198
+ ]
199
+ })
200
+ })
201
+ });
202
+ }
203
+ //#endregion
204
+ export { b as CollaborationFormPage };
205
+
206
+ //# sourceMappingURL=CollaborationFormPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollaborationFormPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collaborations/CollaborationFormPage.tsx"],"sourcesContent":["/**\n * Collaboration Create Page\n * @module coolandlovely/pages/collaborations\n *\n * Drives `cooCreateCollaboration`. Brand and creator are required by the svc\n * input; the creator defaults to the current user (you propose as a creator)\n * but can be overridden.\n */\n\nimport { useMemo, useState } from 'react';\nimport { ArrowLeft, Loader2, Save, Handshake } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { TextField, TextAreaField, SelectField } from '../../components/Field';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCreateCollaboration, useBrands } from '../../hooks';\nimport { parseCsv, titleCase } from '../../utils/formatters';\nimport type { CooCollaboratorRole } from '../../types';\n\nconst ROLES: CooCollaboratorRole[] = ['CREATOR', 'BRAND', 'STYLIST', 'PHOTOGRAPHER'];\n\ninterface FormState {\n brandId: string;\n creatorId: string;\n title: string;\n brief: string;\n role: CooCollaboratorRole;\n compensation: string;\n currency: string;\n tags: string;\n startDate: string;\n endDate: string;\n}\n\nfunction toIso(date: string): string | undefined {\n if (!date) return undefined;\n const d = new Date(date);\n return Number.isNaN(d.getTime()) ? undefined : d.toISOString();\n}\n\nexport function CollaborationFormPage() {\n const { navigateTo, currentUser } = useCoolAndLovely();\n const createCollaboration = useCreateCollaboration();\n const brands = useBrands({ pagination: { limit: 100, offset: 0 } });\n\n const [form, setForm] = useState<FormState>({\n brandId: '',\n creatorId: currentUser?.id ?? '',\n title: '',\n brief: '',\n role: 'CREATOR',\n compensation: '',\n currency: 'USD',\n tags: '',\n startDate: '',\n endDate: '',\n });\n const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) =>\n setForm((f) => ({ ...f, [key]: value }));\n\n const brandOptions = useMemo(\n () => (brands.data?.items ?? []).map((b) => ({ value: b.id, label: b.name })),\n [brands.data]\n );\n const roleOptions = ROLES.map((r) => ({ value: r, label: titleCase(r) }));\n\n const validate = (): boolean => {\n const next: Partial<Record<keyof FormState, string>> = {};\n if (!form.title.trim()) next.title = 'Title is required';\n if (!form.brandId) next.brandId = 'Brand is required';\n if (!form.creatorId.trim()) next.creatorId = 'Creator is required';\n if (form.compensation && Number.isNaN(Number(form.compensation)))\n next.compensation = 'Must be a number';\n setErrors(next);\n return Object.keys(next).length === 0;\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!validate()) return;\n\n createCollaboration.mutate(\n {\n brandId: form.brandId,\n creatorId: form.creatorId.trim(),\n title: form.title.trim(),\n brief: form.brief.trim() || undefined,\n role: form.role,\n compensation: form.compensation ? Number(form.compensation) : undefined,\n currency: form.currency.trim() || undefined,\n tags: parseCsv(form.tags),\n startDate: toIso(form.startDate),\n endDate: toIso(form.endDate),\n },\n { onSuccess: (c) => navigateTo(`/collaborations/${c.id}`) }\n );\n };\n\n return (\n <PageLayout\n title=\"New collaboration\"\n description=\"Propose a brand × creator partnership\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collaborations')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Cancel\n </button>\n }\n >\n <form onSubmit={handleSubmit} className=\"mx-auto max-w-2xl\">\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-11 w-11 items-center justify-center rounded-lg bg-status-warning-bg-subtle text-status-warning-text\">\n <Handshake className=\"h-5 w-5\" />\n </div>\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">Collaboration details</h2>\n <p className=\"text-xs text-text-secondary\">Created in the Proposed state.</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <SelectField\n id=\"brandId\"\n label=\"Brand\"\n value={form.brandId}\n onChange={(v) => setField('brandId', v)}\n options={brandOptions}\n required\n placeholder={brands.isLoading ? 'Loading brands…' : 'Select a brand'}\n error={errors.brandId}\n />\n <SelectField\n id=\"role\"\n label=\"Role\"\n value={form.role}\n onChange={(v) => setField('role', v as CooCollaboratorRole)}\n options={roleOptions}\n />\n </div>\n\n <TextField\n id=\"title\"\n label=\"Title\"\n value={form.title}\n onChange={(v) => setField('title', v)}\n placeholder=\"Summer capsule edit\"\n required\n error={errors.title}\n className=\"mt-4\"\n />\n\n <TextField\n id=\"creatorId\"\n label=\"Creator ID\"\n value={form.creatorId}\n onChange={(v) => setField('creatorId', v)}\n placeholder=\"creator user id\"\n required\n hint=\"Defaults to you. Paste another user's id to credit a different creator.\"\n error={errors.creatorId}\n className=\"mt-4\"\n />\n\n <TextAreaField\n id=\"brief\"\n label=\"Brief\"\n value={form.brief}\n onChange={(v) => setField('brief', v)}\n placeholder=\"What is this collaboration about…\"\n rows={4}\n className=\"mt-4\"\n />\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"compensation\"\n label=\"Compensation\"\n type=\"number\"\n value={form.compensation}\n onChange={(v) => setField('compensation', v)}\n placeholder=\"0.00\"\n error={errors.compensation}\n />\n <TextField\n id=\"currency\"\n label=\"Currency\"\n value={form.currency}\n onChange={(v) => setField('currency', v)}\n placeholder=\"USD\"\n />\n </div>\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <TextField\n id=\"startDate\"\n label=\"Start date\"\n type=\"date\"\n value={form.startDate}\n onChange={(v) => setField('startDate', v)}\n />\n <TextField\n id=\"endDate\"\n label=\"End date\"\n type=\"date\"\n value={form.endDate}\n onChange={(v) => setField('endDate', v)}\n />\n </div>\n\n <TextField\n id=\"tags\"\n label=\"Tags\"\n value={form.tags}\n onChange={(v) => setField('tags', v)}\n placeholder=\"capsule, sustainable\"\n hint=\"Comma-separated\"\n className=\"mt-4\"\n />\n\n {createCollaboration.isError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {createCollaboration.error instanceof Error\n ? createCollaboration.error.message\n : 'Something went wrong'}\n </p>\n )}\n\n <div className=\"mt-6 flex justify-end gap-2\">\n <button\n type=\"submit\"\n disabled={createCollaboration.isPending}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {createCollaboration.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n Create collaboration\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { StatusBadge as r } from "../../components/StatusBadge.js";
5
+ import { ErrorView as i, LoadingView as a } from "../../components/StateViews.js";
6
+ import { Thumbnail as o } from "../../components/Thumbnail.js";
7
+ import { useCollaborations as s } from "../../hooks/useCoolAndLovelyApi.js";
8
+ import "../../hooks/index.js";
9
+ import { formatDate as c, formatPrice as l, titleCase as u } from "../../utils/formatters.js";
10
+ import { EmptyState as d } from "../../components/EmptyState.js";
11
+ import { useState as f } from "react";
12
+ import { Handshake as p, Plus as m } from "lucide-react";
13
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
14
+ //#region src/coolandlovely/pages/collaborations/CollaborationsListPage.tsx
15
+ var _ = [
16
+ {
17
+ value: "ALL",
18
+ label: "All"
19
+ },
20
+ {
21
+ value: "PROPOSED",
22
+ label: "Proposed"
23
+ },
24
+ {
25
+ value: "ACCEPTED",
26
+ label: "Accepted"
27
+ },
28
+ {
29
+ value: "IN_PROGRESS",
30
+ label: "In progress"
31
+ },
32
+ {
33
+ value: "PUBLISHED",
34
+ label: "Published"
35
+ },
36
+ {
37
+ value: "DECLINED",
38
+ label: "Declined"
39
+ },
40
+ {
41
+ value: "CANCELLED",
42
+ label: "Cancelled"
43
+ }
44
+ ];
45
+ function v() {
46
+ let { navigateTo: v } = e(), [y, b] = f("ALL"), x = s({ status: y === "ALL" ? void 0 : y }), S = x.data ?? [];
47
+ return /* @__PURE__ */ g(n, {
48
+ title: "Collaborations",
49
+ description: "Brand × creator partnerships with a real lifecycle",
50
+ actions: /* @__PURE__ */ g("button", {
51
+ type: "button",
52
+ onClick: () => v("/collaborations/new"),
53
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
54
+ children: [/* @__PURE__ */ h(m, { className: "h-4 w-4" }), " New collaboration"]
55
+ }),
56
+ children: [/* @__PURE__ */ h("div", {
57
+ className: "mb-6 flex flex-wrap items-center gap-2",
58
+ children: _.map((e) => /* @__PURE__ */ h("button", {
59
+ type: "button",
60
+ onClick: () => b(e.value),
61
+ className: t("rounded-full px-3 py-1.5 text-sm font-medium transition-colors", y === e.value ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken text-text-secondary hover:text-text-primary"),
62
+ children: e.label
63
+ }, e.value))
64
+ }), x.isLoading ? /* @__PURE__ */ h(a, { label: "Loading collaborations…" }) : x.isError ? /* @__PURE__ */ h(i, { onRetry: () => void x.refetch() }) : S.length === 0 ? /* @__PURE__ */ h(d, {
65
+ illustration: "empty-data",
66
+ icon: /* @__PURE__ */ h(p, { className: "h-10 w-10" }),
67
+ title: "No collaborations yet",
68
+ description: "Propose a brand × creator partnership to get started.",
69
+ action: /* @__PURE__ */ g("button", {
70
+ type: "button",
71
+ onClick: () => v("/collaborations/new"),
72
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
73
+ children: [/* @__PURE__ */ h(m, { className: "h-4 w-4" }), " New collaboration"]
74
+ })
75
+ }) : /* @__PURE__ */ h("div", {
76
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
77
+ children: S.map((e) => /* @__PURE__ */ g("button", {
78
+ type: "button",
79
+ onClick: () => v(`/collaborations/${e.id}`),
80
+ className: "flex flex-col rounded-lg border border-border-seam bg-bg-surface p-4 text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md",
81
+ children: [
82
+ /* @__PURE__ */ g("div", {
83
+ className: "flex items-start gap-3",
84
+ children: [
85
+ /* @__PURE__ */ h(o, {
86
+ icon: /* @__PURE__ */ h(p, { className: "h-5 w-5" }),
87
+ seed: e.id,
88
+ className: "h-11 w-11 shrink-0"
89
+ }),
90
+ /* @__PURE__ */ g("div", {
91
+ className: "min-w-0 flex-1",
92
+ children: [/* @__PURE__ */ h("h3", {
93
+ className: "truncate text-base font-semibold text-text-primary",
94
+ children: e.title
95
+ }), e.brand?.name && /* @__PURE__ */ h("p", {
96
+ className: "truncate text-xs text-text-secondary",
97
+ children: e.brand.name
98
+ })]
99
+ }),
100
+ /* @__PURE__ */ h(r, { status: e.status })
101
+ ]
102
+ }),
103
+ e.brief && /* @__PURE__ */ h("p", {
104
+ className: "mt-3 line-clamp-2 text-sm text-text-secondary",
105
+ children: e.brief
106
+ }),
107
+ /* @__PURE__ */ g("div", {
108
+ className: "mt-3 flex items-center justify-between text-xs text-text-secondary",
109
+ children: [/* @__PURE__ */ h("span", {
110
+ className: "rounded-full bg-bg-sunken px-2 py-0.5",
111
+ children: u(e.role)
112
+ }), /* @__PURE__ */ h("span", { children: l(e.compensation, e.currency) })]
113
+ }),
114
+ e.startDate && /* @__PURE__ */ g("p", {
115
+ className: "mt-2 text-xs text-text-secondary",
116
+ children: ["Starts ", c(e.startDate, {
117
+ hour: void 0,
118
+ minute: void 0
119
+ })]
120
+ })
121
+ ]
122
+ }, e.id))
123
+ })]
124
+ });
125
+ }
126
+ //#endregion
127
+ export { v as CollaborationsListPage };
128
+
129
+ //# sourceMappingURL=CollaborationsListPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollaborationsListPage.js","names":[],"sources":["../../../../src/coolandlovely/pages/collaborations/CollaborationsListPage.tsx"],"sourcesContent":["/**\n * Collaborations List Page\n * @module coolandlovely/pages/collaborations\n *\n * Lists brand × creator partnerships (`cooListCollaborations`) with status\n * filter.\n */\n\nimport { useState } from 'react';\nimport { Plus, Handshake } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Thumbnail } from '../../components/Thumbnail';\nimport { useCoolAndLovely } from '../../context/CoolAndLovelyContext';\nimport { useCollaborations } from '../../hooks';\nimport { formatPrice, formatDate, titleCase } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { CooCollaborationStatus } from '../../types';\n\nconst STATUS_OPTIONS: Array<{ value: CooCollaborationStatus | 'ALL'; label: string }> = [\n { value: 'ALL', label: 'All' },\n { value: 'PROPOSED', label: 'Proposed' },\n { value: 'ACCEPTED', label: 'Accepted' },\n { value: 'IN_PROGRESS', label: 'In progress' },\n { value: 'PUBLISHED', label: 'Published' },\n { value: 'DECLINED', label: 'Declined' },\n { value: 'CANCELLED', label: 'Cancelled' },\n];\n\nexport function CollaborationsListPage() {\n const { navigateTo } = useCoolAndLovely();\n const [status, setStatus] = useState<CooCollaborationStatus | 'ALL'>('ALL');\n\n const query = useCollaborations({ status: status === 'ALL' ? undefined : status });\n const collaborations = query.data ?? [];\n\n return (\n <PageLayout\n title=\"Collaborations\"\n description=\"Brand × creator partnerships with a real lifecycle\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collaborations/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New collaboration\n </button>\n }\n >\n <div className=\"mb-6 flex flex-wrap items-center gap-2\">\n {STATUS_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => setStatus(opt.value)}\n className={cn(\n 'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',\n status === opt.value\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary hover:text-text-primary'\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n\n {query.isLoading ? (\n <LoadingView label=\"Loading collaborations…\" />\n ) : query.isError ? (\n <ErrorView onRetry={() => void query.refetch()} />\n ) : collaborations.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Handshake className=\"h-10 w-10\" />}\n title=\"No collaborations yet\"\n description=\"Propose a brand × creator partnership to get started.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/collaborations/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" /> New collaboration\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {collaborations.map((c) => (\n <button\n key={c.id}\n type=\"button\"\n onClick={() => navigateTo(`/collaborations/${c.id}`)}\n className=\"flex flex-col rounded-lg border border-border-seam bg-bg-surface p-4 text-left shadow-sm transition-all hover:border-accent-foreground/20 hover:shadow-md\"\n >\n <div className=\"flex items-start gap-3\">\n <Thumbnail icon={<Handshake className=\"h-5 w-5\" />} seed={c.id} className=\"h-11 w-11 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">{c.title}</h3>\n {c.brand?.name && (\n <p className=\"truncate text-xs text-text-secondary\">{c.brand.name}</p>\n )}\n </div>\n <StatusBadge status={c.status} />\n </div>\n {c.brief && <p className=\"mt-3 line-clamp-2 text-sm text-text-secondary\">{c.brief}</p>}\n <div className=\"mt-3 flex items-center justify-between text-xs text-text-secondary\">\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5\">{titleCase(c.role)}</span>\n <span>{formatPrice(c.compensation, c.currency)}</span>\n </div>\n {c.startDate && (\n <p className=\"mt-2 text-xs text-text-secondary\">\n Starts {formatDate(c.startDate, { hour: undefined, minute: undefined })}\n </p>\n )}\n </button>\n ))}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAqBA,IAAM,IAAkF;CACtF;EAAE,OAAO;EAAO,OAAO;EAAO;CAC9B;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAe,OAAO;EAAe;CAC9C;EAAE,OAAO;EAAa,OAAO;EAAa;CAC1C;EAAE,OAAO;EAAY,OAAO;EAAY;CACxC;EAAE,OAAO;EAAa,OAAO;EAAa;CAC3C;AAED,SAAgB,IAAyB;CACvC,IAAM,EAAE,kBAAe,GAAkB,EACnC,CAAC,GAAQ,KAAa,EAAyC,MAAM,EAErE,IAAQ,EAAkB,EAAE,QAAQ,MAAW,QAAQ,KAAA,IAAY,GAAQ,CAAC,EAC5E,IAAiB,EAAM,QAAQ,EAAE;AAEvC,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAW,sBAAsB;GAChD,WAAU;aAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,qBACrB;;YAVb,CAaE,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAe,KAAK,MACnB,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe,EAAU,EAAI,MAAM;IACnC,WAAW,EACT,kEACA,MAAW,EAAI,QACX,kDACA,2DACL;cAEA,EAAI;IACE,EAXF,EAAI,MAWF,CACT;GACE,CAAA,EAEL,EAAM,YACL,kBAAC,GAAD,EAAa,OAAM,2BAA4B,CAAA,GAC7C,EAAM,UACR,kBAAC,GAAD,EAAW,eAAe,KAAK,EAAM,SAAS,EAAI,CAAA,GAChD,EAAe,WAAW,IAC5B,kBAAC,GAAD;GACE,cAAa;GACb,MAAM,kBAAC,GAAD,EAAW,WAAU,aAAc,CAAA;GACzC,OAAM;GACN,aAAY;GACZ,QACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,sBAAsB;IAChD,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,qBACrB;;GAEX,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAe,KAAK,MACnB,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe,EAAW,mBAAmB,EAAE,KAAK;IACpD,WAAU;cAJZ;KAME,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QAAW,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;QAAE,MAAM,EAAE;QAAI,WAAU;QAAuB,CAAA;OACjG,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBAAsD,EAAE;SAAW,CAAA,EAChF,EAAE,OAAO,QACR,kBAAC,KAAD;SAAG,WAAU;mBAAwC,EAAE,MAAM;SAAS,CAAA,CAEpE;;OACN,kBAAC,GAAD,EAAa,QAAQ,EAAE,QAAU,CAAA;OAC7B;;KACL,EAAE,SAAS,kBAAC,KAAD;MAAG,WAAU;gBAAiD,EAAE;MAAU,CAAA;KACtF,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAyC,EAAU,EAAE,KAAK;OAAQ,CAAA,EAClF,kBAAC,QAAD,EAAA,UAAO,EAAY,EAAE,cAAc,EAAE,SAAS,EAAQ,CAAA,CAClD;;KACL,EAAE,aACD,kBAAC,KAAD;MAAG,WAAU;gBAAb,CAAgD,WACtC,EAAW,EAAE,WAAW;OAAE,MAAM,KAAA;OAAW,QAAQ,KAAA;OAAW,CAAC,CACrE;;KAEC;MAzBF,EAAE,GAyBA,CACT;GACE,CAAA,CAEG"}
@@ -0,0 +1,217 @@
1
+ import { useCoolAndLovely as e } from "../../context/CoolAndLovelyContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { StatusBadge as n } from "../../components/StatusBadge.js";
4
+ import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
5
+ import { Thumbnail as a } from "../../components/Thumbnail.js";
6
+ import { useCollection as o, usePublishCollection as s } from "../../hooks/useCoolAndLovelyApi.js";
7
+ import "../../hooks/index.js";
8
+ import { formatDate as c, formatPrice as l, titleCase as u } from "../../utils/formatters.js";
9
+ import { TagList as d } from "../../components/TagList.js";
10
+ import { categoryIcon as f } from "../../utils/icons.js";
11
+ import { ArrowLeft as p, Loader2 as m, Pencil as h, Plus as g, Rocket as _, Shapes as v, Store as y } from "lucide-react";
12
+ import { useParams as b } from "react-router-dom";
13
+ import { jsx as x, jsxs as S } from "react/jsx-runtime";
14
+ import { GlassCard as C } from "@burdenoff/fe-libs/ui";
15
+ //#region src/coolandlovely/pages/collections/CollectionDetailPage.tsx
16
+ function w() {
17
+ let { collectionId: w } = b(), { navigateTo: T } = e(), E = o(w), D = s();
18
+ if (E.isLoading) return /* @__PURE__ */ x(t, {
19
+ title: "Collection",
20
+ children: /* @__PURE__ */ x(i, { label: "Loading collection…" })
21
+ });
22
+ if (E.isError || !E.data) return /* @__PURE__ */ x(t, {
23
+ title: "Collection",
24
+ children: /* @__PURE__ */ x(r, {
25
+ title: "Collection not found",
26
+ onRetry: () => void E.refetch()
27
+ })
28
+ });
29
+ let O = E.data, k = O.items ?? [], A = O.status === "DRAFT" || O.status === "SCHEDULED";
30
+ return /* @__PURE__ */ x(t, {
31
+ title: O.name,
32
+ description: O.brand?.name ?? void 0,
33
+ actions: /* @__PURE__ */ S("div", {
34
+ className: "flex items-center gap-2",
35
+ children: [
36
+ /* @__PURE__ */ S("button", {
37
+ type: "button",
38
+ onClick: () => T("/collections"),
39
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
40
+ children: [/* @__PURE__ */ x(p, { className: "h-4 w-4" }), " Back"]
41
+ }),
42
+ /* @__PURE__ */ S("button", {
43
+ type: "button",
44
+ onClick: () => T(`/collections/${O.id}/edit`),
45
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
46
+ children: [/* @__PURE__ */ x(h, { className: "h-4 w-4" }), " Edit"]
47
+ }),
48
+ A && /* @__PURE__ */ S("button", {
49
+ type: "button",
50
+ disabled: D.isPending,
51
+ onClick: () => D.mutate(O.id),
52
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50",
53
+ children: [D.isPending ? /* @__PURE__ */ x(m, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ x(_, { className: "h-4 w-4" }), "Publish"]
54
+ })
55
+ ]
56
+ }),
57
+ children: /* @__PURE__ */ S("div", {
58
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
59
+ children: [/* @__PURE__ */ S("div", {
60
+ className: "lg:col-span-2",
61
+ children: [/* @__PURE__ */ S(C, {
62
+ treatment: "glass",
63
+ className: "overflow-hidden p-0",
64
+ children: [/* @__PURE__ */ x(a, {
65
+ icon: /* @__PURE__ */ x(v, { className: "h-12 w-12" }),
66
+ seed: O.id,
67
+ className: "h-40 w-full"
68
+ }), /* @__PURE__ */ S("div", {
69
+ className: "p-6",
70
+ children: [
71
+ /* @__PURE__ */ S("div", {
72
+ className: "flex items-center gap-2",
73
+ children: [/* @__PURE__ */ x("h2", {
74
+ className: "text-xl font-semibold text-text-primary",
75
+ children: O.name
76
+ }), /* @__PURE__ */ x(n, {
77
+ status: O.status,
78
+ className: "ml-auto"
79
+ })]
80
+ }),
81
+ O.description && /* @__PURE__ */ x("p", {
82
+ className: "mt-3 text-sm text-text-secondary",
83
+ children: O.description
84
+ }),
85
+ O.tags.length > 0 && /* @__PURE__ */ x(d, {
86
+ tags: O.tags,
87
+ className: "mt-4"
88
+ })
89
+ ]
90
+ })]
91
+ }), /* @__PURE__ */ S("section", {
92
+ className: "mt-6",
93
+ children: [
94
+ /* @__PURE__ */ S("h3", {
95
+ className: "mb-3 text-lg font-semibold text-text-primary",
96
+ children: [
97
+ "Items (",
98
+ k.length,
99
+ ")"
100
+ ]
101
+ }),
102
+ k.length === 0 ? /* @__PURE__ */ x("p", {
103
+ className: "rounded-lg border border-border-seam bg-bg-surface p-4 text-sm text-text-secondary",
104
+ children: "No items in this collection yet."
105
+ }) : /* @__PURE__ */ x("div", {
106
+ className: "grid grid-cols-2 gap-3 sm:grid-cols-3",
107
+ children: k.map((e) => /* @__PURE__ */ S("button", {
108
+ type: "button",
109
+ onClick: () => T(`/items/${e.id}`),
110
+ className: "overflow-hidden rounded-lg border border-border-seam bg-bg-surface text-left transition-all hover:border-accent-foreground/20 hover:shadow-md",
111
+ children: [/* @__PURE__ */ x(a, {
112
+ icon: f(e.category, 24),
113
+ seed: e.id,
114
+ className: "h-24 w-full"
115
+ }), /* @__PURE__ */ S("div", {
116
+ className: "p-3",
117
+ children: [/* @__PURE__ */ x("p", {
118
+ className: "truncate text-sm font-medium text-text-primary",
119
+ children: e.name
120
+ }), /* @__PURE__ */ x("p", {
121
+ className: "mt-0.5 text-xs text-text-secondary",
122
+ children: l(e.price, e.currency)
123
+ })]
124
+ })]
125
+ }, e.id))
126
+ }),
127
+ /* @__PURE__ */ S("button", {
128
+ type: "button",
129
+ onClick: () => T(`/items/new?brandId=${O.brandId}&collectionId=${O.id}`),
130
+ className: "mt-3 inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
131
+ children: [/* @__PURE__ */ x(g, { className: "h-4 w-4" }), " Add item to this collection"]
132
+ })
133
+ ]
134
+ })]
135
+ }), /* @__PURE__ */ S("div", {
136
+ className: "space-y-4",
137
+ children: [
138
+ /* @__PURE__ */ S(C, {
139
+ treatment: "plain",
140
+ className: "p-5",
141
+ children: [/* @__PURE__ */ x("h3", {
142
+ className: "mb-3 text-sm font-semibold text-text-primary",
143
+ children: "Details"
144
+ }), /* @__PURE__ */ S("dl", {
145
+ className: "space-y-2 text-sm",
146
+ children: [
147
+ /* @__PURE__ */ S("div", {
148
+ className: "flex justify-between gap-2",
149
+ children: [/* @__PURE__ */ x("dt", {
150
+ className: "text-text-secondary",
151
+ children: "Season"
152
+ }), /* @__PURE__ */ x("dd", {
153
+ className: "text-text-primary",
154
+ children: u(O.season)
155
+ })]
156
+ }),
157
+ /* @__PURE__ */ S("div", {
158
+ className: "flex justify-between gap-2",
159
+ children: [/* @__PURE__ */ x("dt", {
160
+ className: "text-text-secondary",
161
+ children: "Publish at"
162
+ }), /* @__PURE__ */ x("dd", {
163
+ className: "text-text-primary",
164
+ children: O.publishAt ? c(O.publishAt, {
165
+ hour: void 0,
166
+ minute: void 0
167
+ }) : "—"
168
+ })]
169
+ }),
170
+ /* @__PURE__ */ S("div", {
171
+ className: "flex justify-between gap-2",
172
+ children: [/* @__PURE__ */ x("dt", {
173
+ className: "text-text-secondary",
174
+ children: "Ends at"
175
+ }), /* @__PURE__ */ x("dd", {
176
+ className: "text-text-primary",
177
+ children: O.endAt ? c(O.endAt, {
178
+ hour: void 0,
179
+ minute: void 0
180
+ }) : "—"
181
+ })]
182
+ })
183
+ ]
184
+ })]
185
+ }),
186
+ O.brand && /* @__PURE__ */ S("button", {
187
+ type: "button",
188
+ onClick: () => T(`/brands/${O.brand?.id}`),
189
+ className: "flex w-full items-center gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken/50",
190
+ children: [/* @__PURE__ */ x(a, {
191
+ icon: /* @__PURE__ */ x(y, { className: "h-5 w-5" }),
192
+ seed: O.brand.id,
193
+ className: "h-10 w-10 shrink-0"
194
+ }), /* @__PURE__ */ S("div", {
195
+ className: "min-w-0",
196
+ children: [/* @__PURE__ */ x("p", {
197
+ className: "truncate text-sm font-medium text-text-primary",
198
+ children: O.brand.name
199
+ }), /* @__PURE__ */ x("p", {
200
+ className: "truncate text-xs text-text-secondary",
201
+ children: "View brand"
202
+ })]
203
+ })]
204
+ }),
205
+ D.isError && /* @__PURE__ */ x("p", {
206
+ className: "rounded-lg bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text",
207
+ children: D.error instanceof Error ? D.error.message : "Publish failed"
208
+ })
209
+ ]
210
+ })]
211
+ })
212
+ });
213
+ }
214
+ //#endregion
215
+ export { w as CollectionDetailPage };
216
+
217
+ //# sourceMappingURL=CollectionDetailPage.js.map