@burdenoff/microfe-crewfoundry 2026.1013.2 → 2026.1029.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.
- package/dist/crewfoundry/CrewFoundryRoot.d.ts.map +1 -1
- package/dist/crewfoundry/CrewFoundryRoot.js +160 -256
- package/dist/crewfoundry/CrewFoundryRoot.js.map +1 -1
- package/dist/crewfoundry/CrewFoundryRoutes.d.ts.map +1 -1
- package/dist/crewfoundry/CrewFoundryRoutes.js +152 -192
- package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
- package/dist/crewfoundry/components/InlineError.d.ts +5 -0
- package/dist/crewfoundry/components/InlineError.d.ts.map +1 -0
- package/dist/crewfoundry/components/InlineError.js +17 -0
- package/dist/crewfoundry/components/InlineError.js.map +1 -0
- package/dist/crewfoundry/components/marketplace/BookServiceModal.d.ts +14 -0
- package/dist/crewfoundry/components/marketplace/BookServiceModal.d.ts.map +1 -0
- package/dist/crewfoundry/components/marketplace/BookServiceModal.js +75 -0
- package/dist/crewfoundry/components/marketplace/BookServiceModal.js.map +1 -0
- package/dist/crewfoundry/components/marketplace/MarketplaceTabs.d.ts +24 -0
- package/dist/crewfoundry/components/marketplace/MarketplaceTabs.d.ts.map +1 -0
- package/dist/crewfoundry/components/marketplace/MarketplaceTabs.js +47 -0
- package/dist/crewfoundry/components/marketplace/MarketplaceTabs.js.map +1 -0
- package/dist/crewfoundry/components/marketplace/ServiceListingModal.d.ts +12 -0
- package/dist/crewfoundry/components/marketplace/ServiceListingModal.d.ts.map +1 -0
- package/dist/crewfoundry/components/marketplace/ServiceListingModal.js +123 -0
- package/dist/crewfoundry/components/marketplace/ServiceListingModal.js.map +1 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js +4 -118
- package/dist/crewfoundry/components/viz/PathSteps.js +3 -68
- package/dist/crewfoundry/components/viz/lib/geometry.js +5 -13
- package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -1
- package/dist/crewfoundry/lib/analytics.d.ts +1 -6
- package/dist/crewfoundry/lib/analytics.d.ts.map +1 -1
- package/dist/crewfoundry/lib/analytics.js +3 -18
- package/dist/crewfoundry/lib/analytics.js.map +1 -1
- package/dist/crewfoundry/lib/companyFinance.d.ts +3 -7
- package/dist/crewfoundry/lib/companyFinance.d.ts.map +1 -1
- package/dist/crewfoundry/lib/companyFinance.js +3 -8
- package/dist/crewfoundry/lib/companyFinance.js.map +1 -1
- package/dist/crewfoundry/lib/learning.d.ts +12 -0
- package/dist/crewfoundry/lib/learning.d.ts.map +1 -0
- package/dist/crewfoundry/lib/learning.js +26 -0
- package/dist/crewfoundry/lib/learning.js.map +1 -0
- package/dist/crewfoundry/lib/marketplace.d.ts +30 -0
- package/dist/crewfoundry/lib/marketplace.d.ts.map +1 -0
- package/dist/crewfoundry/lib/marketplace.js +91 -0
- package/dist/crewfoundry/lib/marketplace.js.map +1 -0
- package/dist/crewfoundry/lib/useEnsureLoaded.d.ts +7 -0
- package/dist/crewfoundry/lib/useEnsureLoaded.d.ts.map +1 -0
- package/dist/crewfoundry/lib/useEnsureLoaded.js +25 -0
- package/dist/crewfoundry/lib/useEnsureLoaded.js.map +1 -0
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +12 -25
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +145 -157
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +14 -14
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +14 -14
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +71 -33
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +247 -173
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.d.ts +12 -0
- package/dist/crewfoundry/pages/LearningCoursesPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +307 -293
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.d.ts +2 -0
- package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.d.ts.map +1 -0
- package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.js +223 -0
- package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.js.map +1 -0
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.d.ts +4 -0
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +115 -160
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +165 -75
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.d.ts +7 -0
- package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.d.ts.map +1 -0
- package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.js +175 -0
- package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.js.map +1 -0
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +182 -223
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +168 -227
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +127 -290
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.d.ts +138 -78
- package/dist/crewfoundry/store/crewfoundryStore.d.ts.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +323 -244
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/dist/crewfoundry/utils/dateUtils.d.ts +5 -0
- package/dist/crewfoundry/utils/dateUtils.d.ts.map +1 -1
- package/dist/crewfoundry/utils/dateUtils.js +10 -1
- package/dist/crewfoundry/utils/dateUtils.js.map +1 -1
- package/dist/generated/global-types.d.ts +5145 -1627
- package/dist/generated/global-types.d.ts.map +1 -1
- package/dist/generated/wspace-types.d.ts +100373 -34602
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/utils/pageContext.d.ts.map +1 -1
- package/dist/utils/pageContext.js +0 -1
- package/dist/utils/pageContext.js.map +1 -1
- package/package.json +1 -1
- package/dist/crewfoundry/components/viz/CertificateCard.js.map +0 -1
- package/dist/crewfoundry/components/viz/PathSteps.js.map +0 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +0 -53
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +0 -107
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +0 -62
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +0 -37
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +0 -111
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +0 -309
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningLearningPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +0 -200
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +0 -190
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +0 -230
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +0 -293
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +0 -163
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.d.ts +0 -2
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +0 -365
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +0 -224
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +0 -180
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +0 -38
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +0 -204
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +0 -55
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +0 -335
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +0 -160
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +0 -80
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +0 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.d.ts +0 -2
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.d.ts.map +0 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +0 -191
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +0 -1
- package/dist/crewfoundry/utils/courseProgress.d.ts +0 -33
- package/dist/crewfoundry/utils/courseProgress.d.ts.map +0 -1
- package/dist/crewfoundry/utils/courseProgress.js +0 -46
- package/dist/crewfoundry/utils/courseProgress.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentsPaymentMethodsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsPaymentMethodsPagePage.tsx"],"sourcesContent":["import { useNavigate } from 'react-router';\nimport {\n Badge,\n Button,\n CardContent,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Building2, CreditCard, ExternalLink } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\n// Payment methods are owned by the platform Billing module (global billing\n// account), not by CrewFoundry. We read the real methods surfaced via the\n// billing overlap and send all add/manage actions to Billing settings — there\n// is deliberately no crew-local payment-method store.\nconst BILLING_PAYMENT_METHODS_ROUTE = '/billing/payment-methods';\n\nexport function PaymentsPaymentMethodsPagePage() {\n const navigate = useNavigate();\n const { paymentMethods } = useCrewFoundryStore();\n\n const goToBilling = () => navigate(BILLING_PAYMENT_METHODS_ROUTE);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Payment Methods</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Managed in your platform Billing settings</p>\n <PagePurpose className=\"mt-1\">\n Manage how you pay and get paid — cards, bank accounts, and payout methods are held\n securely in Billing settings.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={goToBilling}>\n <ExternalLink className=\"mr-1 h-4 w-4\" />\n Manage in Billing settings\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n {paymentMethods.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No payment methods\"\n description=\"Payment methods live in your platform Billing settings. Add a card or bank account there to pay and get paid.\"\n action={\n <Button size=\"sm\" onClick={goToBilling}>\n <ExternalLink className=\"mr-1 h-4 w-4\" />\n Open Billing settings\n </Button>\n }\n />\n </div>\n ) : (\n paymentMethods.map((method, _idx) => (\n <GlassCard key={method.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0}>\n <CardContent className=\"p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n {method.type === 'bank' ? (\n <Building2 className=\"h-5 w-5 text-text-secondary\" />\n ) : (\n <CreditCard className=\"h-5 w-5 text-text-secondary\" />\n )}\n <div>\n <p className=\"text-sm font-medium\">{method.name}</p>\n <p className=\"text-xs text-text-secondary\">{method.bank}</p>\n </div>\n </div>\n <Badge\n variant={method.status === 'primary' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {formatEnumLabel(method.status)}\n </Badge>\n </div>\n <div className=\"flex items-center justify-between text-sm text-text-secondary\">\n <span>•••• •••• •••• {method.last4}</span>\n {method.expiry ? <span>Exp: {method.expiry}</span> : null}\n </div>\n </CardContent>\n </GlassCard>\n ))\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAkBA,IAAM,IAAgC;AAEtC,SAAgB,IAAiC;CAC/C,IAAM,IAAW,GAAa,EACxB,EAAE,sBAAmB,GAAqB,EAE1C,UAAoB,EAAS,EAA8B;AAEjE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UAAc,mBAA8B,CAAA;KACzC,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eAA8B;KAA6C,CAAA;IACxF,kBAAC,GAAD;KAAa,WAAU;eAAO;KAGhB,CAAA;IACV,EAAA,CAAA,EACN,kBAAC,GAAD;IAAQ,MAAK;IAAK,SAAS;cAA3B,CACE,kBAAC,GAAD,EAAc,WAAU,gBAAiB,CAAA,EAAA,6BAElC;MACL;MAEN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAe,WAAW,IACzB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,cAAa;KACb,OAAM;KACN,aAAY;KACZ,QACE,kBAAC,GAAD;MAAQ,MAAK;MAAK,SAAS;gBAA3B,CACE,kBAAC,GAAD,EAAc,WAAU,gBAAiB,CAAA,EAAA,wBAElC;;KAEX,CAAA;IACE,CAAA,GAEN,EAAe,KAAK,GAAQ,MAC1B,kBAAC,GAAD;IAA2B,WAAW,MAAS,IAAI,UAAU;IAAS,MAAM,MAAS;cACnF,kBAAC,GAAD;KAAa,WAAU;eAAvB,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,EAAO,SAAS,SACf,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA,GAErD,kBAAC,GAAD,EAAY,WAAU,+BAAgC,CAAA,EAExD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAuB,EAAO;QAAS,CAAA,EACpD,kBAAC,KAAD;QAAG,WAAU;kBAA+B,EAAO;QAAS,CAAA,CACxD,EAAA,CAAA,CACF;UACN,kBAAC,GAAD;OACE,SAAS,EAAO,WAAW,YAAY,YAAY;OACnD,WAAU;iBAET,EAAgB,EAAO,OAAO;OACzB,CAAA,CACJ;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD,EAAA,UAAA,CAAM,mBAAgB,EAAO,MAAa,EAAA,CAAA,EACzC,EAAO,SAAS,kBAAC,QAAD,EAAA,UAAA,CAAM,SAAM,EAAO,OAAc,EAAA,CAAA,GAAG,KACjD;QACM;;IACJ,EA1BI,EAAO,GA0BX,CACZ;GAEA,CAAA,CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentsSecurityPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/PaymentsSecurityPagePage.tsx"],"names":[],"mappings":"AAuCA,wBAAgB,wBAAwB,gCAkMvC"}
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import { useMemo as t } from "react";
|
|
3
|
-
import { AlertTriangle as n, CheckCircle as r, Shield as i, ShieldCheck as a } from "lucide-react";
|
|
4
|
-
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
5
|
-
import { Badge as c, Button as l, Card as u, CardContent as d, CardDescription as f, CardHeader as p, CardTitle as m, GlassCard as h, GradientText as g, IllustratedEmptyState as _, PagePurpose as v } from "@burdenoff/fe-libs/ui";
|
|
6
|
-
//#region src/crewfoundry/pages/PaymentsSecurityPagePage.tsx
|
|
7
|
-
var y = (e) => {
|
|
8
|
-
let t = new Date(e);
|
|
9
|
-
if (Number.isNaN(t.getTime())) return "recently";
|
|
10
|
-
let n = Math.max(1, Math.floor((Date.now() - t.getTime()) / (1e3 * 60 * 60)));
|
|
11
|
-
return n < 24 ? `${n}h ago` : `${Math.floor(n / 24)}d ago`;
|
|
12
|
-
};
|
|
13
|
-
function b() {
|
|
14
|
-
let { notifications: b, invoices: x, payrollRecords: S } = e(), C = t(() => {
|
|
15
|
-
let e = x.filter((e) => e.status === "overdue").length, t = S.filter((e) => e.status === "failed").length, n = b.filter((e) => e.type === "error").length, r = b.filter((e) => e.type === "warning").length;
|
|
16
|
-
return [
|
|
17
|
-
{
|
|
18
|
-
name: "Overdue invoices",
|
|
19
|
-
detail: e > 0 ? `${e} invoice${e === 1 ? "" : "s"} past due` : "No overdue invoices",
|
|
20
|
-
status: e > 0 ? "warning" : "ok"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
name: "Payroll runs",
|
|
24
|
-
detail: t > 0 ? `${t} failed payroll run${t === 1 ? "" : "s"}` : "All payroll runs healthy",
|
|
25
|
-
status: t > 0 ? "warning" : "ok"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: "Critical alerts",
|
|
29
|
-
detail: n > 0 ? `${n} unresolved critical alert${n === 1 ? "" : "s"}` : "No critical alerts",
|
|
30
|
-
status: n > 0 ? "warning" : "ok"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
name: "Open warnings",
|
|
34
|
-
detail: r > 0 ? `${r} open warning${r === 1 ? "" : "s"}` : "No open warnings",
|
|
35
|
-
status: r > 0 ? "warning" : "ok"
|
|
36
|
-
}
|
|
37
|
-
];
|
|
38
|
-
}, [
|
|
39
|
-
x,
|
|
40
|
-
b,
|
|
41
|
-
S
|
|
42
|
-
]), w = t(() => b.slice(0, 6).map((e) => {
|
|
43
|
-
let t = e.type === "error" ? "medium" : e.type === "warning" ? "low" : "info";
|
|
44
|
-
return {
|
|
45
|
-
id: e.id,
|
|
46
|
-
message: e.message,
|
|
47
|
-
severity: t,
|
|
48
|
-
time: y(e.createdAt)
|
|
49
|
-
};
|
|
50
|
-
}), [b]), T = C.filter((e) => e.status === "warning").length, E = C.filter((e) => e.status === "ok").length;
|
|
51
|
-
return /* @__PURE__ */ s("div", {
|
|
52
|
-
className: "space-y-6 p-6",
|
|
53
|
-
children: [
|
|
54
|
-
/* @__PURE__ */ s("div", {
|
|
55
|
-
className: "flex items-center justify-between",
|
|
56
|
-
children: [/* @__PURE__ */ s("div", { children: [
|
|
57
|
-
/* @__PURE__ */ o("h1", {
|
|
58
|
-
className: "text-2xl font-semibold",
|
|
59
|
-
children: /* @__PURE__ */ o(g, { children: "Payment Security" })
|
|
60
|
-
}),
|
|
61
|
-
/* @__PURE__ */ o("p", {
|
|
62
|
-
className: "text-sm text-text-secondary",
|
|
63
|
-
children: "Account health and payment alerts"
|
|
64
|
-
}),
|
|
65
|
-
/* @__PURE__ */ o(v, {
|
|
66
|
-
className: "mt-1",
|
|
67
|
-
children: "Protect your account and payments — review live health signals and alerts derived from your invoices, payroll, and activity."
|
|
68
|
-
})
|
|
69
|
-
] }), /* @__PURE__ */ s(l, {
|
|
70
|
-
variant: "outline",
|
|
71
|
-
size: "sm",
|
|
72
|
-
disabled: !0,
|
|
73
|
-
"aria-label": "Run external security audit (coming soon)",
|
|
74
|
-
title: "External security audit is coming soon",
|
|
75
|
-
children: [
|
|
76
|
-
/* @__PURE__ */ o(i, { className: "mr-1 h-4 w-4" }),
|
|
77
|
-
"Run Audit",
|
|
78
|
-
/* @__PURE__ */ o(c, {
|
|
79
|
-
variant: "secondary",
|
|
80
|
-
className: "ml-1 text-[9px]",
|
|
81
|
-
children: "Soon"
|
|
82
|
-
})
|
|
83
|
-
]
|
|
84
|
-
})]
|
|
85
|
-
}),
|
|
86
|
-
/* @__PURE__ */ s("div", {
|
|
87
|
-
className: "grid gap-4 md:grid-cols-3",
|
|
88
|
-
children: [
|
|
89
|
-
/* @__PURE__ */ s(h, {
|
|
90
|
-
treatment: "glass",
|
|
91
|
-
glow: !0,
|
|
92
|
-
className: "border-border-seam",
|
|
93
|
-
children: [/* @__PURE__ */ s(p, {
|
|
94
|
-
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
95
|
-
children: [/* @__PURE__ */ o(m, {
|
|
96
|
-
className: "text-sm font-medium",
|
|
97
|
-
children: "Needs Attention"
|
|
98
|
-
}), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" })]
|
|
99
|
-
}), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ o("div", {
|
|
100
|
-
className: "text-2xl font-bold tabular-nums",
|
|
101
|
-
children: T
|
|
102
|
-
}) })]
|
|
103
|
-
}),
|
|
104
|
-
/* @__PURE__ */ s(h, {
|
|
105
|
-
treatment: "metric",
|
|
106
|
-
className: "border-border-seam",
|
|
107
|
-
children: [/* @__PURE__ */ s(p, {
|
|
108
|
-
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
109
|
-
children: [/* @__PURE__ */ o(m, {
|
|
110
|
-
className: "text-sm font-medium",
|
|
111
|
-
children: "All Clear"
|
|
112
|
-
}), /* @__PURE__ */ o(a, { className: "h-4 w-4 text-status-success-text" })]
|
|
113
|
-
}), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ s("div", {
|
|
114
|
-
className: "text-2xl font-bold tabular-nums",
|
|
115
|
-
children: [
|
|
116
|
-
E,
|
|
117
|
-
"/",
|
|
118
|
-
C.length
|
|
119
|
-
]
|
|
120
|
-
}) })]
|
|
121
|
-
}),
|
|
122
|
-
/* @__PURE__ */ s(h, {
|
|
123
|
-
treatment: "metric",
|
|
124
|
-
className: "border-border-seam",
|
|
125
|
-
children: [/* @__PURE__ */ s(p, {
|
|
126
|
-
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
127
|
-
children: [/* @__PURE__ */ o(m, {
|
|
128
|
-
className: "text-sm font-medium",
|
|
129
|
-
children: "Active Alerts"
|
|
130
|
-
}), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" })]
|
|
131
|
-
}), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ o("div", {
|
|
132
|
-
className: "text-2xl font-bold tabular-nums",
|
|
133
|
-
children: w.length
|
|
134
|
-
}) })]
|
|
135
|
-
})
|
|
136
|
-
]
|
|
137
|
-
}),
|
|
138
|
-
/* @__PURE__ */ s(u, { children: [/* @__PURE__ */ s(p, { children: [/* @__PURE__ */ o(m, { children: "Account & Payment Health" }), /* @__PURE__ */ o(f, { children: "Live checks derived from your invoices, payroll, and alerts — not compliance certifications." })] }), /* @__PURE__ */ o(d, {
|
|
139
|
-
className: "space-y-3",
|
|
140
|
-
children: C.map((e) => /* @__PURE__ */ s("div", {
|
|
141
|
-
className: "flex items-center justify-between rounded border p-3",
|
|
142
|
-
children: [/* @__PURE__ */ s("div", {
|
|
143
|
-
className: "flex items-center gap-2",
|
|
144
|
-
children: [e.status === "ok" ? /* @__PURE__ */ o(r, { className: "h-4 w-4 text-status-success-text" }) : /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" }), /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
|
|
145
|
-
className: "text-sm font-medium",
|
|
146
|
-
children: e.name
|
|
147
|
-
}), /* @__PURE__ */ o("p", {
|
|
148
|
-
className: "text-xs text-text-secondary",
|
|
149
|
-
children: e.detail
|
|
150
|
-
})] })]
|
|
151
|
-
}), /* @__PURE__ */ o(c, {
|
|
152
|
-
variant: e.status === "ok" ? "default" : "secondary",
|
|
153
|
-
className: "text-[10px]",
|
|
154
|
-
children: e.status === "ok" ? "clear" : "attention"
|
|
155
|
-
})]
|
|
156
|
-
}, e.name))
|
|
157
|
-
})] }),
|
|
158
|
-
/* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o(p, { children: /* @__PURE__ */ o(m, { children: "Recent Alerts" }) }), /* @__PURE__ */ o(d, {
|
|
159
|
-
className: "space-y-3",
|
|
160
|
-
children: w.length === 0 ? /* @__PURE__ */ o(_, {
|
|
161
|
-
illustration: "empty-notifications",
|
|
162
|
-
title: "No alerts",
|
|
163
|
-
description: "Payment and account alerts will show up here."
|
|
164
|
-
}) : w.map((e) => /* @__PURE__ */ s("div", {
|
|
165
|
-
className: "flex items-center justify-between rounded border p-3",
|
|
166
|
-
children: [/* @__PURE__ */ s("div", {
|
|
167
|
-
className: "flex items-center gap-2",
|
|
168
|
-
children: [/* @__PURE__ */ o(n, { className: `h-4 w-4 ${e.severity === "medium" ? "text-status-warning-text" : e.severity === "low" ? "text-status-info-text" : "text-text-secondary"}` }), /* @__PURE__ */ o("span", {
|
|
169
|
-
className: "text-sm",
|
|
170
|
-
children: e.message
|
|
171
|
-
})]
|
|
172
|
-
}), /* @__PURE__ */ s("div", {
|
|
173
|
-
className: "flex items-center gap-2",
|
|
174
|
-
children: [/* @__PURE__ */ o("span", {
|
|
175
|
-
className: "text-xs text-text-secondary",
|
|
176
|
-
children: e.time
|
|
177
|
-
}), /* @__PURE__ */ o(c, {
|
|
178
|
-
variant: "outline",
|
|
179
|
-
className: "text-[10px]",
|
|
180
|
-
children: e.severity
|
|
181
|
-
})]
|
|
182
|
-
})]
|
|
183
|
-
}, e.id))
|
|
184
|
-
})] })
|
|
185
|
-
]
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
//#endregion
|
|
189
|
-
export { b as PaymentsSecurityPagePage };
|
|
190
|
-
|
|
191
|
-
//# sourceMappingURL=PaymentsSecurityPagePage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentsSecurityPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsSecurityPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { AlertTriangle, CheckCircle, Shield, ShieldCheck } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype HealthCheck = {\n name: string;\n detail: string;\n status: 'ok' | 'warning';\n};\n\ntype SecurityAlert = {\n id: string;\n message: string;\n severity: 'medium' | 'low' | 'info';\n time: string;\n};\n\nconst timeAgo = (value: string): string => {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return 'recently';\n }\n const hours = Math.max(1, Math.floor((Date.now() - parsed.getTime()) / (1000 * 60 * 60)));\n return hours < 24 ? `${hours}h ago` : `${Math.floor(hours / 24)}d ago`;\n};\n\nexport function PaymentsSecurityPagePage() {\n const { notifications, invoices, payrollRecords } = useCrewFoundryStore();\n\n const healthChecks = useMemo<HealthCheck[]>(() => {\n const overdueInvoices = invoices.filter((invoice) => invoice.status === 'overdue').length;\n const failedPayroll = payrollRecords.filter((record) => record.status === 'failed').length;\n const criticalAlerts = notifications.filter((note) => note.type === 'error').length;\n const openWarnings = notifications.filter((note) => note.type === 'warning').length;\n\n return [\n {\n name: 'Overdue invoices',\n detail:\n overdueInvoices > 0\n ? `${overdueInvoices} invoice${overdueInvoices === 1 ? '' : 's'} past due`\n : 'No overdue invoices',\n status: overdueInvoices > 0 ? 'warning' : 'ok',\n },\n {\n name: 'Payroll runs',\n detail:\n failedPayroll > 0\n ? `${failedPayroll} failed payroll run${failedPayroll === 1 ? '' : 's'}`\n : 'All payroll runs healthy',\n status: failedPayroll > 0 ? 'warning' : 'ok',\n },\n {\n name: 'Critical alerts',\n detail:\n criticalAlerts > 0\n ? `${criticalAlerts} unresolved critical alert${criticalAlerts === 1 ? '' : 's'}`\n : 'No critical alerts',\n status: criticalAlerts > 0 ? 'warning' : 'ok',\n },\n {\n name: 'Open warnings',\n detail:\n openWarnings > 0\n ? `${openWarnings} open warning${openWarnings === 1 ? '' : 's'}`\n : 'No open warnings',\n status: openWarnings > 0 ? 'warning' : 'ok',\n },\n ];\n }, [invoices, notifications, payrollRecords]);\n\n const recentAlerts = useMemo<SecurityAlert[]>(() => {\n return notifications.slice(0, 6).map((notification) => {\n const severity: SecurityAlert['severity'] =\n notification.type === 'error' ? 'medium' : notification.type === 'warning' ? 'low' : 'info';\n\n return {\n id: notification.id,\n message: notification.message,\n severity,\n time: timeAgo(notification.createdAt),\n };\n });\n }, [notifications]);\n\n const attentionNeeded = healthChecks.filter((check) => check.status === 'warning').length;\n const allClear = healthChecks.filter((check) => check.status === 'ok').length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Payment Security</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Account health and payment alerts</p>\n <PagePurpose className=\"mt-1\">\n Protect your account and payments — review live health signals and alerts derived from\n your invoices, payroll, and activity.\n </PagePurpose>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled\n aria-label=\"Run external security audit (coming soon)\"\n title=\"External security audit is coming soon\"\n >\n <Shield className=\"mr-1 h-4 w-4\" />\n Run Audit\n <Badge variant=\"secondary\" className=\"ml-1 text-[9px]\">\n Soon\n </Badge>\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Needs Attention</CardTitle>\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{attentionNeeded}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">All Clear</CardTitle>\n <ShieldCheck className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {allClear}/{healthChecks.length}\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Active Alerts</CardTitle>\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{recentAlerts.length}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Account & Payment Health</CardTitle>\n <CardDescription>\n Live checks derived from your invoices, payroll, and alerts — not compliance\n certifications.\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {healthChecks.map((check) => (\n <div key={check.name} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-2\">\n {check.status === 'ok' ? (\n <CheckCircle className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n )}\n <div>\n <p className=\"text-sm font-medium\">{check.name}</p>\n <p className=\"text-xs text-text-secondary\">{check.detail}</p>\n </div>\n </div>\n <Badge\n variant={check.status === 'ok' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {check.status === 'ok' ? 'clear' : 'attention'}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Recent Alerts</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {recentAlerts.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No alerts\"\n description=\"Payment and account alerts will show up here.\"\n />\n ) : (\n recentAlerts.map((alert) => (\n <div key={alert.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-2\">\n <AlertTriangle\n className={`h-4 w-4 ${\n alert.severity === 'medium'\n ? 'text-status-warning-text'\n : alert.severity === 'low'\n ? 'text-status-info-text'\n : 'text-text-secondary'\n }`}\n />\n <span className=\"text-sm\">{alert.message}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-secondary\">{alert.time}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {alert.severity}\n </Badge>\n </div>\n </div>\n ))\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-user course progress, persisted client-side.
|
|
3
|
-
*
|
|
4
|
-
* The CrewFoundry backend models a course only as an aggregate (enrolled /
|
|
5
|
-
* completed counts + a `modules` integer) — there is no per-user, per-module
|
|
6
|
-
* completion record and no mark-complete mutation. Rather than fabricate a
|
|
7
|
-
* progress number, this stores the learner's OWN real interactions (the modules
|
|
8
|
-
* they mark complete in the course player) in localStorage, so progress, hours
|
|
9
|
-
* and certificates reflect genuine user activity and persist across reloads.
|
|
10
|
-
*
|
|
11
|
-
* When a backend progress entity is added, these helpers become the single
|
|
12
|
-
* place to swap the storage layer for the real mutation/query.
|
|
13
|
-
*/
|
|
14
|
-
export interface CourseProgress {
|
|
15
|
-
/** Zero-based indexes of modules the learner has marked complete. */
|
|
16
|
-
completed: number[];
|
|
17
|
-
/** ISO timestamp of when the course first reached 100%. */
|
|
18
|
-
completedAt?: string;
|
|
19
|
-
}
|
|
20
|
-
type ProgressMap = Record<string, CourseProgress>;
|
|
21
|
-
/** Read a single course's progress (never throws; empty when absent). */
|
|
22
|
-
export declare function readCourseProgress(courseId: string): CourseProgress;
|
|
23
|
-
/** Read every course's progress as a map keyed by course id. */
|
|
24
|
-
export declare function readAllCourseProgress(): ProgressMap;
|
|
25
|
-
/**
|
|
26
|
-
* Persist the set of completed module indexes for a course and return the saved
|
|
27
|
-
* progress. Stamps `completedAt` the first time the course reaches 100%.
|
|
28
|
-
*/
|
|
29
|
-
export declare function writeCourseProgress(courseId: string, completed: number[], totalModules: number): CourseProgress;
|
|
30
|
-
/** Completion percentage (0–100) for a course given its module count. */
|
|
31
|
-
export declare function progressPercent(progress: CourseProgress, totalModules: number): number;
|
|
32
|
-
export {};
|
|
33
|
-
//# sourceMappingURL=courseProgress.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"courseProgress.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/utils/courseProgress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AA6ClD,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAEnE;AAED,gEAAgE;AAChE,wBAAgB,qBAAqB,IAAI,WAAW,CAOnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,EAAE,MAAM,GACnB,cAAc,CAchB;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAKtF"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
//#region src/crewfoundry/utils/courseProgress.ts
|
|
2
|
-
var e = "crewfoundry:course-progress:v1";
|
|
3
|
-
function t() {
|
|
4
|
-
if (typeof window > "u") return {};
|
|
5
|
-
try {
|
|
6
|
-
let t = window.localStorage.getItem(e);
|
|
7
|
-
if (!t) return {};
|
|
8
|
-
let n = JSON.parse(t);
|
|
9
|
-
return !n || typeof n != "object" ? {} : n;
|
|
10
|
-
} catch {
|
|
11
|
-
return {};
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
function n(t) {
|
|
15
|
-
if (!(typeof window > "u")) try {
|
|
16
|
-
window.localStorage.setItem(e, JSON.stringify(t));
|
|
17
|
-
} catch {}
|
|
18
|
-
}
|
|
19
|
-
function r(e) {
|
|
20
|
-
return !e || !Array.isArray(e.completed) ? { completed: [] } : {
|
|
21
|
-
completed: [...new Set(e.completed.filter((e) => typeof e == "number" && e >= 0))].sort((e, t) => e - t),
|
|
22
|
-
completedAt: typeof e.completedAt == "string" ? e.completedAt : void 0
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
function i(e) {
|
|
26
|
-
return r(t()[e]);
|
|
27
|
-
}
|
|
28
|
-
function a() {
|
|
29
|
-
let e = t(), n = {};
|
|
30
|
-
for (let [t, i] of Object.entries(e)) n[t] = r(i);
|
|
31
|
-
return n;
|
|
32
|
-
}
|
|
33
|
-
function o(e, i, a) {
|
|
34
|
-
let o = t(), s = r(o[e]), c = [...new Set(i.filter((e) => typeof e == "number" && e >= 0))].sort((e, t) => e - t), l = {
|
|
35
|
-
completed: c,
|
|
36
|
-
completedAt: a > 0 && c.length >= a ? s.completedAt ?? (/* @__PURE__ */ new Date()).toISOString() : void 0
|
|
37
|
-
};
|
|
38
|
-
return o[e] = l, n(o), l;
|
|
39
|
-
}
|
|
40
|
-
function s(e, t) {
|
|
41
|
-
return t <= 0 ? 0 : Math.min(100, Math.round(e.completed.length / t * 100));
|
|
42
|
-
}
|
|
43
|
-
//#endregion
|
|
44
|
-
export { s as progressPercent, a as readAllCourseProgress, i as readCourseProgress, o as writeCourseProgress };
|
|
45
|
-
|
|
46
|
-
//# sourceMappingURL=courseProgress.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"courseProgress.js","names":[],"sources":["../../../src/crewfoundry/utils/courseProgress.ts"],"sourcesContent":["/**\n * Per-user course progress, persisted client-side.\n *\n * The CrewFoundry backend models a course only as an aggregate (enrolled /\n * completed counts + a `modules` integer) — there is no per-user, per-module\n * completion record and no mark-complete mutation. Rather than fabricate a\n * progress number, this stores the learner's OWN real interactions (the modules\n * they mark complete in the course player) in localStorage, so progress, hours\n * and certificates reflect genuine user activity and persist across reloads.\n *\n * When a backend progress entity is added, these helpers become the single\n * place to swap the storage layer for the real mutation/query.\n */\n\nconst PROGRESS_KEY = 'crewfoundry:course-progress:v1';\n\nexport interface CourseProgress {\n /** Zero-based indexes of modules the learner has marked complete. */\n completed: number[];\n /** ISO timestamp of when the course first reached 100%. */\n completedAt?: string;\n}\n\ntype ProgressMap = Record<string, CourseProgress>;\n\nfunction readMap(): ProgressMap {\n if (typeof window === 'undefined') {\n return {};\n }\n try {\n const raw = window.localStorage.getItem(PROGRESS_KEY);\n if (!raw) {\n return {};\n }\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== 'object') {\n return {};\n }\n return parsed as ProgressMap;\n } catch {\n return {};\n }\n}\n\nfunction writeMap(map: ProgressMap): void {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(PROGRESS_KEY, JSON.stringify(map));\n } catch {\n /* storage unavailable / quota exceeded — progress is best-effort */\n }\n}\n\nfunction sanitize(entry: CourseProgress | undefined): CourseProgress {\n if (!entry || !Array.isArray(entry.completed)) {\n return { completed: [] };\n }\n const completed = [\n ...new Set(entry.completed.filter((n) => typeof n === 'number' && n >= 0)),\n ].sort((a, b) => a - b);\n return {\n completed,\n completedAt: typeof entry.completedAt === 'string' ? entry.completedAt : undefined,\n };\n}\n\n/** Read a single course's progress (never throws; empty when absent). */\nexport function readCourseProgress(courseId: string): CourseProgress {\n return sanitize(readMap()[courseId]);\n}\n\n/** Read every course's progress as a map keyed by course id. */\nexport function readAllCourseProgress(): ProgressMap {\n const map = readMap();\n const out: ProgressMap = {};\n for (const [id, entry] of Object.entries(map)) {\n out[id] = sanitize(entry);\n }\n return out;\n}\n\n/**\n * Persist the set of completed module indexes for a course and return the saved\n * progress. Stamps `completedAt` the first time the course reaches 100%.\n */\nexport function writeCourseProgress(\n courseId: string,\n completed: number[],\n totalModules: number\n): CourseProgress {\n const map = readMap();\n const previous = sanitize(map[courseId]);\n const nextCompleted = [...new Set(completed.filter((n) => typeof n === 'number' && n >= 0))].sort(\n (a, b) => a - b\n );\n const reached100 = totalModules > 0 && nextCompleted.length >= totalModules;\n const entry: CourseProgress = {\n completed: nextCompleted,\n completedAt: reached100 ? (previous.completedAt ?? new Date().toISOString()) : undefined,\n };\n map[courseId] = entry;\n writeMap(map);\n return entry;\n}\n\n/** Completion percentage (0–100) for a course given its module count. */\nexport function progressPercent(progress: CourseProgress, totalModules: number): number {\n if (totalModules <= 0) {\n return 0;\n }\n return Math.min(100, Math.round((progress.completed.length / totalModules) * 100));\n}\n"],"mappings":";AAcA,IAAM,IAAe;AAWrB,SAAS,IAAuB;AAC9B,KAAI,OAAO,SAAW,IACpB,QAAO,EAAE;AAEX,KAAI;EACF,IAAM,IAAM,OAAO,aAAa,QAAQ,EAAa;AACrD,MAAI,CAAC,EACH,QAAO,EAAE;EAEX,IAAM,IAAkB,KAAK,MAAM,EAAI;AAIvC,SAHI,CAAC,KAAU,OAAO,KAAW,WACxB,EAAE,GAEJ;SACD;AACN,SAAO,EAAE;;;AAIb,SAAS,EAAS,GAAwB;AACpC,cAAO,SAAW,KAGtB,KAAI;AACF,SAAO,aAAa,QAAQ,GAAc,KAAK,UAAU,EAAI,CAAC;SACxD;;AAKV,SAAS,EAAS,GAAmD;AAOnE,QANI,CAAC,KAAS,CAAC,MAAM,QAAQ,EAAM,UAAU,GACpC,EAAE,WAAW,EAAE,EAAE,GAKnB;EACL,WAJgB,CAChB,GAAG,IAAI,IAAI,EAAM,UAAU,QAAQ,MAAM,OAAO,KAAM,YAAY,KAAK,EAAE,CAAC,CAC3E,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;EAGrB,aAAa,OAAO,EAAM,eAAgB,WAAW,EAAM,cAAc,KAAA;EAC1E;;AAIH,SAAgB,EAAmB,GAAkC;AACnE,QAAO,EAAS,GAAS,CAAC,GAAU;;AAItC,SAAgB,IAAqC;CACnD,IAAM,IAAM,GAAS,EACf,IAAmB,EAAE;AAC3B,MAAK,IAAM,CAAC,GAAI,MAAU,OAAO,QAAQ,EAAI,CAC3C,GAAI,KAAM,EAAS,EAAM;AAE3B,QAAO;;AAOT,SAAgB,EACd,GACA,GACA,GACgB;CAChB,IAAM,IAAM,GAAS,EACf,IAAW,EAAS,EAAI,GAAU,EAClC,IAAgB,CAAC,GAAG,IAAI,IAAI,EAAU,QAAQ,MAAM,OAAO,KAAM,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,MAC1F,GAAG,MAAM,IAAI,EACf,EAEK,IAAwB;EAC5B,WAAW;EACX,aAHiB,IAAe,KAAK,EAAc,UAAU,IAGlC,EAAS,gCAAe,IAAI,MAAM,EAAC,aAAa,GAAI,KAAA;EAChF;AAGD,QAFA,EAAI,KAAY,GAChB,EAAS,EAAI,EACN;;AAIT,SAAgB,EAAgB,GAA0B,GAA8B;AAItF,QAHI,KAAgB,IACX,IAEF,KAAK,IAAI,KAAK,KAAK,MAAO,EAAS,UAAU,SAAS,IAAgB,IAAI,CAAC"}
|