@contractspec/example.saas-boilerplate 3.7.6 → 3.8.2
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/.turbo/turbo-build.log +39 -27
- package/AGENTS.md +50 -27
- package/CHANGELOG.md +36 -0
- package/README.md +65 -144
- package/dist/billing/billing.event.js +1 -1
- package/dist/billing/index.d.ts +6 -6
- package/dist/billing/index.js +1 -1
- package/dist/browser/billing/billing.event.js +1 -1
- package/dist/browser/billing/index.js +1 -1
- package/dist/browser/index.js +1147 -869
- package/dist/browser/project/index.js +209 -209
- package/dist/browser/project/project.event.js +1 -1
- package/dist/browser/saas-boilerplate.feature.js +208 -0
- package/dist/browser/ui/SaasDashboard.js +356 -105
- package/dist/browser/ui/SaasDashboard.visualizations.js +249 -0
- package/dist/browser/ui/SaasProjectList.js +7 -7
- package/dist/browser/ui/SaasSettingsPanel.js +12 -12
- package/dist/browser/ui/hooks/index.js +2 -2
- package/dist/browser/ui/hooks/useProjectList.js +1 -1
- package/dist/browser/ui/hooks/useProjectMutations.js +1 -1
- package/dist/browser/ui/index.js +790 -521
- package/dist/browser/ui/modals/CreateProjectModal.js +10 -10
- package/dist/browser/ui/modals/ProjectActionsModal.js +13 -13
- package/dist/browser/ui/modals/index.js +23 -23
- package/dist/browser/ui/renderers/index.js +341 -115
- package/dist/browser/ui/renderers/project-list.markdown.js +229 -3
- package/dist/browser/ui/renderers/project-list.renderer.js +7 -7
- package/dist/browser/visualizations/catalog.js +155 -0
- package/dist/browser/visualizations/index.js +217 -0
- package/dist/browser/visualizations/selectors.js +210 -0
- package/dist/handlers/index.d.ts +2 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1147 -869
- package/dist/node/billing/billing.event.js +1 -1
- package/dist/node/billing/index.js +1 -1
- package/dist/node/index.js +1147 -869
- package/dist/node/project/index.js +209 -209
- package/dist/node/project/project.event.js +1 -1
- package/dist/node/saas-boilerplate.feature.js +208 -0
- package/dist/node/ui/SaasDashboard.js +356 -105
- package/dist/node/ui/SaasDashboard.visualizations.js +249 -0
- package/dist/node/ui/SaasProjectList.js +7 -7
- package/dist/node/ui/SaasSettingsPanel.js +12 -12
- package/dist/node/ui/hooks/index.js +2 -2
- package/dist/node/ui/hooks/useProjectList.js +1 -1
- package/dist/node/ui/hooks/useProjectMutations.js +1 -1
- package/dist/node/ui/index.js +790 -521
- package/dist/node/ui/modals/CreateProjectModal.js +10 -10
- package/dist/node/ui/modals/ProjectActionsModal.js +13 -13
- package/dist/node/ui/modals/index.js +23 -23
- package/dist/node/ui/renderers/index.js +341 -115
- package/dist/node/ui/renderers/project-list.markdown.js +229 -3
- package/dist/node/ui/renderers/project-list.renderer.js +7 -7
- package/dist/node/visualizations/catalog.js +155 -0
- package/dist/node/visualizations/index.js +217 -0
- package/dist/node/visualizations/selectors.js +210 -0
- package/dist/presentations/index.d.ts +1 -1
- package/dist/project/index.d.ts +7 -7
- package/dist/project/index.js +209 -209
- package/dist/project/project.event.js +1 -1
- package/dist/saas-boilerplate.feature.js +208 -0
- package/dist/settings/index.d.ts +1 -1
- package/dist/ui/SaasDashboard.js +356 -105
- package/dist/ui/SaasDashboard.visualizations.d.ts +5 -0
- package/dist/ui/SaasDashboard.visualizations.js +250 -0
- package/dist/ui/SaasProjectList.js +7 -7
- package/dist/ui/SaasSettingsPanel.js +12 -12
- package/dist/ui/hooks/index.d.ts +2 -2
- package/dist/ui/hooks/index.js +2 -2
- package/dist/ui/hooks/useProjectList.d.ts +5 -0
- package/dist/ui/hooks/useProjectList.js +1 -1
- package/dist/ui/hooks/useProjectMutations.d.ts +8 -0
- package/dist/ui/hooks/useProjectMutations.js +1 -1
- package/dist/ui/index.d.ts +4 -4
- package/dist/ui/index.js +790 -521
- package/dist/ui/modals/CreateProjectModal.js +10 -10
- package/dist/ui/modals/ProjectActionsModal.js +13 -13
- package/dist/ui/modals/index.js +23 -23
- package/dist/ui/renderers/index.d.ts +1 -1
- package/dist/ui/renderers/index.js +341 -115
- package/dist/ui/renderers/project-list.markdown.js +229 -3
- package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
- package/dist/ui/renderers/project-list.renderer.js +7 -7
- package/dist/visualizations/catalog.d.ts +11 -0
- package/dist/visualizations/catalog.js +156 -0
- package/dist/visualizations/index.d.ts +2 -0
- package/dist/visualizations/index.js +218 -0
- package/dist/visualizations/selectors.d.ts +8 -0
- package/dist/visualizations/selectors.js +211 -0
- package/dist/visualizations/selectors.test.d.ts +1 -0
- package/package.json +70 -14
- package/src/billing/billing.entity.ts +132 -132
- package/src/billing/billing.enum.ts +9 -9
- package/src/billing/billing.event.ts +71 -71
- package/src/billing/billing.handler.ts +87 -87
- package/src/billing/billing.operations.ts +158 -158
- package/src/billing/billing.presentation.ts +45 -45
- package/src/billing/billing.schema.ts +76 -76
- package/src/billing/index.ts +43 -48
- package/src/dashboard/dashboard.presentation.ts +45 -45
- package/src/dashboard/index.ts +2 -2
- package/src/docs/saas-boilerplate.docblock.ts +43 -43
- package/src/example.ts +32 -32
- package/src/handlers/index.ts +9 -9
- package/src/handlers/saas.handlers.ts +250 -249
- package/src/index.ts +41 -41
- package/src/presentations/index.ts +18 -20
- package/src/project/index.ts +45 -50
- package/src/project/project.entity.ts +68 -68
- package/src/project/project.enum.ts +8 -8
- package/src/project/project.event.ts +79 -79
- package/src/project/project.handler.ts +103 -103
- package/src/project/project.operations.ts +236 -236
- package/src/project/project.presentation.ts +46 -46
- package/src/project/project.schema.ts +90 -90
- package/src/saas-boilerplate.feature.ts +103 -100
- package/src/seeders/index.ts +20 -20
- package/src/settings/index.ts +2 -3
- package/src/settings/settings.entity.ts +65 -65
- package/src/settings/settings.enum.ts +4 -4
- package/src/shared/mock-data.ts +92 -92
- package/src/shared/overlay-types.ts +23 -23
- package/src/tests/operations.test-spec.ts +96 -96
- package/src/ui/SaasDashboard.tsx +278 -270
- package/src/ui/SaasDashboard.visualizations.tsx +41 -0
- package/src/ui/SaasProjectList.tsx +90 -90
- package/src/ui/SaasSettingsPanel.tsx +84 -84
- package/src/ui/hooks/index.ts +3 -3
- package/src/ui/hooks/useProjectList.ts +69 -68
- package/src/ui/hooks/useProjectMutations.ts +144 -143
- package/src/ui/index.ts +8 -12
- package/src/ui/modals/CreateProjectModal.tsx +154 -154
- package/src/ui/modals/ProjectActionsModal.tsx +321 -321
- package/src/ui/overlays/demo-overlays.ts +49 -49
- package/src/ui/renderers/index.ts +5 -4
- package/src/ui/renderers/project-list.markdown.ts +229 -205
- package/src/ui/renderers/project-list.renderer.tsx +14 -13
- package/src/visualizations/catalog.ts +153 -0
- package/src/visualizations/index.ts +2 -0
- package/src/visualizations/selectors.test.ts +25 -0
- package/src/visualizations/selectors.ts +85 -0
- package/tsconfig.json +7 -8
- package/tsdown.config.js +7 -3
|
@@ -1,6 +1,213 @@
|
|
|
1
|
+
// src/visualizations/catalog.ts
|
|
2
|
+
import {
|
|
3
|
+
defineVisualization,
|
|
4
|
+
VisualizationRegistry
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
6
|
+
var PROJECT_LIST_REF = {
|
|
7
|
+
key: "saas.project.list",
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
};
|
|
10
|
+
var META = {
|
|
11
|
+
version: "1.0.0",
|
|
12
|
+
domain: "saas",
|
|
13
|
+
stability: "experimental",
|
|
14
|
+
owners: ["@example.saas-boilerplate"],
|
|
15
|
+
tags: ["saas", "visualization", "projects"]
|
|
16
|
+
};
|
|
17
|
+
var SaasProjectUsageVisualization = defineVisualization({
|
|
18
|
+
meta: {
|
|
19
|
+
...META,
|
|
20
|
+
key: "saas-boilerplate.visualization.project-usage",
|
|
21
|
+
title: "Project Capacity",
|
|
22
|
+
description: "Current project count against the current plan limit.",
|
|
23
|
+
goal: "Show usage against the active plan allowance.",
|
|
24
|
+
context: "SaaS account overview."
|
|
25
|
+
},
|
|
26
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
27
|
+
visualization: {
|
|
28
|
+
kind: "metric",
|
|
29
|
+
measure: "totalProjects",
|
|
30
|
+
comparisonMeasure: "projectLimit",
|
|
31
|
+
measures: [
|
|
32
|
+
{
|
|
33
|
+
key: "totalProjects",
|
|
34
|
+
label: "Projects",
|
|
35
|
+
dataPath: "totalProjects",
|
|
36
|
+
format: "number"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: "projectLimit",
|
|
40
|
+
label: "Plan Limit",
|
|
41
|
+
dataPath: "projectLimit",
|
|
42
|
+
format: "number"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
table: { caption: "Current project count and plan limit." }
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
var SaasProjectStatusVisualization = defineVisualization({
|
|
49
|
+
meta: {
|
|
50
|
+
...META,
|
|
51
|
+
key: "saas-boilerplate.visualization.project-status",
|
|
52
|
+
title: "Project Status",
|
|
53
|
+
description: "Distribution of project states.",
|
|
54
|
+
goal: "Show the mix of active, draft, and archived projects.",
|
|
55
|
+
context: "Project portfolio overview."
|
|
56
|
+
},
|
|
57
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
58
|
+
visualization: {
|
|
59
|
+
kind: "pie",
|
|
60
|
+
nameDimension: "status",
|
|
61
|
+
valueMeasure: "projects",
|
|
62
|
+
dimensions: [
|
|
63
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
64
|
+
],
|
|
65
|
+
measures: [
|
|
66
|
+
{
|
|
67
|
+
key: "projects",
|
|
68
|
+
label: "Projects",
|
|
69
|
+
dataPath: "projects",
|
|
70
|
+
format: "number"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
table: { caption: "Project counts by status." }
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
var SaasProjectTierVisualization = defineVisualization({
|
|
77
|
+
meta: {
|
|
78
|
+
...META,
|
|
79
|
+
key: "saas-boilerplate.visualization.project-tiers",
|
|
80
|
+
title: "Tier Comparison",
|
|
81
|
+
description: "Distribution of projects across tiers.",
|
|
82
|
+
goal: "Compare how the current portfolio is distributed by tier.",
|
|
83
|
+
context: "Plan and packaging overview."
|
|
84
|
+
},
|
|
85
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
86
|
+
visualization: {
|
|
87
|
+
kind: "cartesian",
|
|
88
|
+
variant: "bar",
|
|
89
|
+
xDimension: "tier",
|
|
90
|
+
yMeasures: ["projects"],
|
|
91
|
+
dimensions: [
|
|
92
|
+
{ key: "tier", label: "Tier", dataPath: "tier", type: "category" }
|
|
93
|
+
],
|
|
94
|
+
measures: [
|
|
95
|
+
{
|
|
96
|
+
key: "projects",
|
|
97
|
+
label: "Projects",
|
|
98
|
+
dataPath: "projects",
|
|
99
|
+
format: "number",
|
|
100
|
+
color: "#1d4ed8"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
table: { caption: "Project counts by tier." }
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
var SaasProjectActivityVisualization = defineVisualization({
|
|
107
|
+
meta: {
|
|
108
|
+
...META,
|
|
109
|
+
key: "saas-boilerplate.visualization.project-activity",
|
|
110
|
+
title: "Recent Project Activity",
|
|
111
|
+
description: "Daily project creation activity.",
|
|
112
|
+
goal: "Show recent project activity over time.",
|
|
113
|
+
context: "Project portfolio trend view."
|
|
114
|
+
},
|
|
115
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
116
|
+
visualization: {
|
|
117
|
+
kind: "cartesian",
|
|
118
|
+
variant: "line",
|
|
119
|
+
xDimension: "day",
|
|
120
|
+
yMeasures: ["projects"],
|
|
121
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
122
|
+
measures: [
|
|
123
|
+
{
|
|
124
|
+
key: "projects",
|
|
125
|
+
label: "Projects",
|
|
126
|
+
dataPath: "projects",
|
|
127
|
+
format: "number",
|
|
128
|
+
color: "#0f766e"
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
table: { caption: "Daily project creation counts." }
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
var SaasVisualizationSpecs = [
|
|
135
|
+
SaasProjectUsageVisualization,
|
|
136
|
+
SaasProjectStatusVisualization,
|
|
137
|
+
SaasProjectTierVisualization,
|
|
138
|
+
SaasProjectActivityVisualization
|
|
139
|
+
];
|
|
140
|
+
var SaasVisualizationRegistry = new VisualizationRegistry([
|
|
141
|
+
...SaasVisualizationSpecs
|
|
142
|
+
]);
|
|
143
|
+
var SaasVisualizationRefs = SaasVisualizationSpecs.map((spec) => ({
|
|
144
|
+
key: spec.meta.key,
|
|
145
|
+
version: spec.meta.version
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
// src/visualizations/selectors.ts
|
|
149
|
+
function toDayKey(value) {
|
|
150
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
151
|
+
return date.toISOString().slice(0, 10);
|
|
152
|
+
}
|
|
153
|
+
function createSaasVisualizationItems(projects, projectLimit = 10) {
|
|
154
|
+
const statusCounts = new Map;
|
|
155
|
+
const tierCounts = new Map;
|
|
156
|
+
const activityCounts = new Map;
|
|
157
|
+
for (const project of projects) {
|
|
158
|
+
statusCounts.set(project.status, (statusCounts.get(project.status) ?? 0) + 1);
|
|
159
|
+
tierCounts.set(project.tier, (tierCounts.get(project.tier) ?? 0) + 1);
|
|
160
|
+
const day = toDayKey(project.createdAt);
|
|
161
|
+
activityCounts.set(day, (activityCounts.get(day) ?? 0) + 1);
|
|
162
|
+
}
|
|
163
|
+
return [
|
|
164
|
+
{
|
|
165
|
+
key: "saas-capacity",
|
|
166
|
+
spec: SaasProjectUsageVisualization,
|
|
167
|
+
data: { data: [{ totalProjects: projects.length, projectLimit }] },
|
|
168
|
+
title: "Project Capacity",
|
|
169
|
+
description: "Current project count compared to the active limit.",
|
|
170
|
+
height: 220
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
key: "saas-status",
|
|
174
|
+
spec: SaasProjectStatusVisualization,
|
|
175
|
+
data: {
|
|
176
|
+
data: Array.from(statusCounts.entries()).map(([status, count]) => ({
|
|
177
|
+
status,
|
|
178
|
+
projects: count
|
|
179
|
+
}))
|
|
180
|
+
},
|
|
181
|
+
title: "Project Status",
|
|
182
|
+
description: "Status mix across the current project portfolio.",
|
|
183
|
+
height: 260
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
key: "saas-tier",
|
|
187
|
+
spec: SaasProjectTierVisualization,
|
|
188
|
+
data: {
|
|
189
|
+
data: Array.from(tierCounts.entries()).map(([tier, count]) => ({
|
|
190
|
+
tier,
|
|
191
|
+
projects: count
|
|
192
|
+
}))
|
|
193
|
+
},
|
|
194
|
+
title: "Tier Comparison",
|
|
195
|
+
description: "How projects are distributed across tiers."
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
key: "saas-activity",
|
|
199
|
+
spec: SaasProjectActivityVisualization,
|
|
200
|
+
data: {
|
|
201
|
+
data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, projects: count }))
|
|
202
|
+
},
|
|
203
|
+
title: "Recent Project Activity",
|
|
204
|
+
description: "Daily project creation activity."
|
|
205
|
+
}
|
|
206
|
+
];
|
|
207
|
+
}
|
|
1
208
|
// src/ui/hooks/useProjectList.ts
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
209
|
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
210
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
4
211
|
function useProjectList(options = {}) {
|
|
5
212
|
const { handlers, projectId } = useTemplateRuntime();
|
|
6
213
|
const { saas } = handlers;
|
|
@@ -63,8 +270,8 @@ function useProjectList(options = {}) {
|
|
|
63
270
|
}
|
|
64
271
|
|
|
65
272
|
// src/ui/hooks/useProjectMutations.ts
|
|
66
|
-
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
67
273
|
import { useTemplateRuntime as useTemplateRuntime2 } from "@contractspec/lib.example-shared-ui";
|
|
274
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
68
275
|
function useProjectMutations(options = {}) {
|
|
69
276
|
const { handlers, projectId } = useTemplateRuntime2();
|
|
70
277
|
const { saas } = handlers;
|
|
@@ -152,8 +359,8 @@ function useProjectMutations(options = {}) {
|
|
|
152
359
|
}
|
|
153
360
|
|
|
154
361
|
// src/ui/modals/CreateProjectModal.tsx
|
|
155
|
-
import { useState as useState3 } from "react";
|
|
156
362
|
import { Button, Input } from "@contractspec/lib.design-system";
|
|
363
|
+
import { useState as useState3 } from "react";
|
|
157
364
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
158
365
|
"use client";
|
|
159
366
|
var TIERS = [
|
|
@@ -198,7 +405,7 @@ function CreateProjectModal({
|
|
|
198
405
|
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
199
406
|
children: [
|
|
200
407
|
/* @__PURE__ */ jsxDEV("div", {
|
|
201
|
-
className: "bg-background/80
|
|
408
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
202
409
|
onClick: onClose,
|
|
203
410
|
role: "button",
|
|
204
411
|
tabIndex: 0,
|
|
@@ -209,10 +416,10 @@ function CreateProjectModal({
|
|
|
209
416
|
"aria-label": "Close modal"
|
|
210
417
|
}, undefined, false, undefined, this),
|
|
211
418
|
/* @__PURE__ */ jsxDEV("div", {
|
|
212
|
-
className: "
|
|
419
|
+
className: "relative z-10 w-full max-w-md rounded-xl border border-border bg-card p-6 shadow-xl",
|
|
213
420
|
children: [
|
|
214
421
|
/* @__PURE__ */ jsxDEV("h2", {
|
|
215
|
-
className: "mb-4 text-xl
|
|
422
|
+
className: "mb-4 font-semibold text-xl",
|
|
216
423
|
children: "Create New Project"
|
|
217
424
|
}, undefined, false, undefined, this),
|
|
218
425
|
/* @__PURE__ */ jsxDEV("form", {
|
|
@@ -223,7 +430,7 @@ function CreateProjectModal({
|
|
|
223
430
|
children: [
|
|
224
431
|
/* @__PURE__ */ jsxDEV("label", {
|
|
225
432
|
htmlFor: "project-name",
|
|
226
|
-
className: "
|
|
433
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
227
434
|
children: "Project Name *"
|
|
228
435
|
}, undefined, false, undefined, this),
|
|
229
436
|
/* @__PURE__ */ jsxDEV(Input, {
|
|
@@ -239,7 +446,7 @@ function CreateProjectModal({
|
|
|
239
446
|
children: [
|
|
240
447
|
/* @__PURE__ */ jsxDEV("label", {
|
|
241
448
|
htmlFor: "project-description",
|
|
242
|
-
className: "
|
|
449
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
243
450
|
children: "Description"
|
|
244
451
|
}, undefined, false, undefined, this),
|
|
245
452
|
/* @__PURE__ */ jsxDEV("textarea", {
|
|
@@ -249,7 +456,7 @@ function CreateProjectModal({
|
|
|
249
456
|
placeholder: "Describe what this project is about...",
|
|
250
457
|
rows: 3,
|
|
251
458
|
disabled: isLoading,
|
|
252
|
-
className: "
|
|
459
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
|
|
253
460
|
}, undefined, false, undefined, this)
|
|
254
461
|
]
|
|
255
462
|
}, undefined, true, undefined, this),
|
|
@@ -257,7 +464,7 @@ function CreateProjectModal({
|
|
|
257
464
|
children: [
|
|
258
465
|
/* @__PURE__ */ jsxDEV("label", {
|
|
259
466
|
htmlFor: "project-tier",
|
|
260
|
-
className: "
|
|
467
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
261
468
|
children: "Tier"
|
|
262
469
|
}, undefined, false, undefined, this),
|
|
263
470
|
/* @__PURE__ */ jsxDEV("select", {
|
|
@@ -265,7 +472,7 @@ function CreateProjectModal({
|
|
|
265
472
|
value: tier,
|
|
266
473
|
onChange: (e) => setTier(e.target.value),
|
|
267
474
|
disabled: isLoading,
|
|
268
|
-
className: "
|
|
475
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50",
|
|
269
476
|
children: TIERS.map((t) => /* @__PURE__ */ jsxDEV("option", {
|
|
270
477
|
value: t.value,
|
|
271
478
|
children: t.label
|
|
@@ -274,7 +481,7 @@ function CreateProjectModal({
|
|
|
274
481
|
]
|
|
275
482
|
}, undefined, true, undefined, this),
|
|
276
483
|
error && /* @__PURE__ */ jsxDEV("div", {
|
|
277
|
-
className: "bg-destructive/10
|
|
484
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
278
485
|
children: error
|
|
279
486
|
}, undefined, false, undefined, this),
|
|
280
487
|
/* @__PURE__ */ jsxDEV("div", {
|
|
@@ -303,8 +510,8 @@ function CreateProjectModal({
|
|
|
303
510
|
}
|
|
304
511
|
|
|
305
512
|
// src/ui/modals/ProjectActionsModal.tsx
|
|
306
|
-
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
307
513
|
import { Button as Button2, Input as Input2 } from "@contractspec/lib.design-system";
|
|
514
|
+
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
308
515
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
309
516
|
"use client";
|
|
310
517
|
function ProjectActionsModal({
|
|
@@ -397,7 +604,7 @@ function ProjectActionsModal({
|
|
|
397
604
|
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
398
605
|
children: [
|
|
399
606
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
400
|
-
className: "bg-background/80
|
|
607
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
401
608
|
onClick: handleClose,
|
|
402
609
|
role: "button",
|
|
403
610
|
tabIndex: 0,
|
|
@@ -408,13 +615,13 @@ function ProjectActionsModal({
|
|
|
408
615
|
"aria-label": "Close modal"
|
|
409
616
|
}, undefined, false, undefined, this),
|
|
410
617
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
411
|
-
className: "
|
|
618
|
+
className: "relative z-10 w-full max-w-md rounded-xl border border-border bg-card p-6 shadow-xl",
|
|
412
619
|
children: [
|
|
413
620
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
414
|
-
className: "
|
|
621
|
+
className: "mb-4 border-border border-b pb-4",
|
|
415
622
|
children: [
|
|
416
623
|
/* @__PURE__ */ jsxDEV2("h2", {
|
|
417
|
-
className: "text-xl
|
|
624
|
+
className: "font-semibold text-xl",
|
|
418
625
|
children: project.name
|
|
419
626
|
}, undefined, false, undefined, this),
|
|
420
627
|
/* @__PURE__ */ jsxDEV2("p", {
|
|
@@ -496,7 +703,7 @@ function ProjectActionsModal({
|
|
|
496
703
|
children: [
|
|
497
704
|
/* @__PURE__ */ jsxDEV2("label", {
|
|
498
705
|
htmlFor: "edit-name",
|
|
499
|
-
className: "
|
|
706
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
500
707
|
children: "Project Name *"
|
|
501
708
|
}, undefined, false, undefined, this),
|
|
502
709
|
/* @__PURE__ */ jsxDEV2(Input2, {
|
|
@@ -511,7 +718,7 @@ function ProjectActionsModal({
|
|
|
511
718
|
children: [
|
|
512
719
|
/* @__PURE__ */ jsxDEV2("label", {
|
|
513
720
|
htmlFor: "edit-description",
|
|
514
|
-
className: "
|
|
721
|
+
className: "mb-1 block font-medium text-muted-foreground text-sm",
|
|
515
722
|
children: "Description"
|
|
516
723
|
}, undefined, false, undefined, this),
|
|
517
724
|
/* @__PURE__ */ jsxDEV2("textarea", {
|
|
@@ -520,12 +727,12 @@ function ProjectActionsModal({
|
|
|
520
727
|
onChange: (e) => setDescription(e.target.value),
|
|
521
728
|
rows: 3,
|
|
522
729
|
disabled: isLoading,
|
|
523
|
-
className: "
|
|
730
|
+
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
|
|
524
731
|
}, undefined, false, undefined, this)
|
|
525
732
|
]
|
|
526
733
|
}, undefined, true, undefined, this),
|
|
527
734
|
error && /* @__PURE__ */ jsxDEV2("div", {
|
|
528
|
-
className: "bg-destructive/10
|
|
735
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
529
736
|
children: error
|
|
530
737
|
}, undefined, false, undefined, this),
|
|
531
738
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
@@ -555,7 +762,7 @@ function ProjectActionsModal({
|
|
|
555
762
|
"Are you sure you want to archive",
|
|
556
763
|
" ",
|
|
557
764
|
/* @__PURE__ */ jsxDEV2("span", {
|
|
558
|
-
className: "text-foreground
|
|
765
|
+
className: "font-medium text-foreground",
|
|
559
766
|
children: project.name
|
|
560
767
|
}, undefined, false, undefined, this),
|
|
561
768
|
"?"
|
|
@@ -566,7 +773,7 @@ function ProjectActionsModal({
|
|
|
566
773
|
children: "Archived projects can be restored later."
|
|
567
774
|
}, undefined, false, undefined, this),
|
|
568
775
|
error && /* @__PURE__ */ jsxDEV2("div", {
|
|
569
|
-
className: "bg-destructive/10
|
|
776
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
570
777
|
children: error
|
|
571
778
|
}, undefined, false, undefined, this),
|
|
572
779
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
@@ -596,7 +803,7 @@ function ProjectActionsModal({
|
|
|
596
803
|
"Are you sure you want to delete",
|
|
597
804
|
" ",
|
|
598
805
|
/* @__PURE__ */ jsxDEV2("span", {
|
|
599
|
-
className: "text-foreground
|
|
806
|
+
className: "font-medium text-foreground",
|
|
600
807
|
children: project.name
|
|
601
808
|
}, undefined, false, undefined, this),
|
|
602
809
|
"?"
|
|
@@ -607,7 +814,7 @@ function ProjectActionsModal({
|
|
|
607
814
|
children: "This action cannot be undone."
|
|
608
815
|
}, undefined, false, undefined, this),
|
|
609
816
|
error && /* @__PURE__ */ jsxDEV2("div", {
|
|
610
|
-
className: "bg-destructive/10
|
|
817
|
+
className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
|
|
611
818
|
children: error
|
|
612
819
|
}, undefined, false, undefined, this),
|
|
613
820
|
/* @__PURE__ */ jsxDEV2("div", {
|
|
@@ -635,19 +842,59 @@ function ProjectActionsModal({
|
|
|
635
842
|
}, undefined, true, undefined, this);
|
|
636
843
|
}
|
|
637
844
|
|
|
845
|
+
// src/ui/SaasDashboard.visualizations.tsx
|
|
846
|
+
import {
|
|
847
|
+
VisualizationCard,
|
|
848
|
+
VisualizationGrid
|
|
849
|
+
} from "@contractspec/lib.design-system";
|
|
850
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
851
|
+
"use client";
|
|
852
|
+
function SaasVisualizationOverview({
|
|
853
|
+
projects,
|
|
854
|
+
projectLimit
|
|
855
|
+
}) {
|
|
856
|
+
const items = createSaasVisualizationItems(projects, projectLimit);
|
|
857
|
+
return /* @__PURE__ */ jsxDEV3("section", {
|
|
858
|
+
className: "space-y-3",
|
|
859
|
+
children: [
|
|
860
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
861
|
+
children: [
|
|
862
|
+
/* @__PURE__ */ jsxDEV3("h3", {
|
|
863
|
+
className: "font-semibold text-lg",
|
|
864
|
+
children: "Portfolio Visualizations"
|
|
865
|
+
}, undefined, false, undefined, this),
|
|
866
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
867
|
+
className: "text-muted-foreground text-sm",
|
|
868
|
+
children: "Contract-backed charts for project mix, capacity, and activity."
|
|
869
|
+
}, undefined, false, undefined, this)
|
|
870
|
+
]
|
|
871
|
+
}, undefined, true, undefined, this),
|
|
872
|
+
/* @__PURE__ */ jsxDEV3(VisualizationGrid, {
|
|
873
|
+
children: items.map((item) => /* @__PURE__ */ jsxDEV3(VisualizationCard, {
|
|
874
|
+
data: item.data,
|
|
875
|
+
description: item.description,
|
|
876
|
+
height: item.height,
|
|
877
|
+
spec: item.spec,
|
|
878
|
+
title: item.title
|
|
879
|
+
}, item.key, false, undefined, this))
|
|
880
|
+
}, undefined, false, undefined, this)
|
|
881
|
+
]
|
|
882
|
+
}, undefined, true, undefined, this);
|
|
883
|
+
}
|
|
884
|
+
|
|
638
885
|
// src/ui/SaasDashboard.tsx
|
|
639
|
-
import { useState as useState5, useCallback as useCallback3 } from "react";
|
|
640
886
|
import {
|
|
641
|
-
|
|
642
|
-
StatCardGroup,
|
|
643
|
-
StatusChip,
|
|
644
|
-
EntityCard,
|
|
887
|
+
Button as Button3,
|
|
645
888
|
EmptyState,
|
|
646
|
-
|
|
889
|
+
EntityCard,
|
|
647
890
|
ErrorState,
|
|
648
|
-
|
|
891
|
+
LoaderBlock,
|
|
892
|
+
StatCard,
|
|
893
|
+
StatCardGroup,
|
|
894
|
+
StatusChip
|
|
649
895
|
} from "@contractspec/lib.design-system";
|
|
650
|
-
import {
|
|
896
|
+
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
897
|
+
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
651
898
|
"use client";
|
|
652
899
|
function getStatusTone(status) {
|
|
653
900
|
switch (status) {
|
|
@@ -682,32 +929,32 @@ function SaasDashboard() {
|
|
|
682
929
|
{ id: "settings", label: "Settings", icon: "⚙️" }
|
|
683
930
|
];
|
|
684
931
|
if (loading && !data) {
|
|
685
|
-
return /* @__PURE__ */
|
|
932
|
+
return /* @__PURE__ */ jsxDEV4(LoaderBlock, {
|
|
686
933
|
label: "Loading dashboard..."
|
|
687
934
|
}, undefined, false, undefined, this);
|
|
688
935
|
}
|
|
689
936
|
if (error) {
|
|
690
|
-
return /* @__PURE__ */
|
|
937
|
+
return /* @__PURE__ */ jsxDEV4(ErrorState, {
|
|
691
938
|
title: "Failed to load dashboard",
|
|
692
939
|
description: error.message,
|
|
693
940
|
onRetry: refetch,
|
|
694
941
|
retryLabel: "Retry"
|
|
695
942
|
}, undefined, false, undefined, this);
|
|
696
943
|
}
|
|
697
|
-
return /* @__PURE__ */
|
|
944
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
698
945
|
className: "space-y-6",
|
|
699
946
|
children: [
|
|
700
|
-
/* @__PURE__ */
|
|
947
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
701
948
|
className: "flex items-center justify-between",
|
|
702
949
|
children: [
|
|
703
|
-
/* @__PURE__ */
|
|
704
|
-
className: "text-2xl
|
|
950
|
+
/* @__PURE__ */ jsxDEV4("h2", {
|
|
951
|
+
className: "font-bold text-2xl",
|
|
705
952
|
children: "SaaS Dashboard"
|
|
706
953
|
}, undefined, false, undefined, this),
|
|
707
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
954
|
+
activeTab === "projects" && /* @__PURE__ */ jsxDEV4(Button3, {
|
|
708
955
|
onPress: () => setIsCreateModalOpen(true),
|
|
709
956
|
children: [
|
|
710
|
-
/* @__PURE__ */
|
|
957
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
711
958
|
className: "mr-2",
|
|
712
959
|
children: "+"
|
|
713
960
|
}, undefined, false, undefined, this),
|
|
@@ -716,59 +963,63 @@ function SaasDashboard() {
|
|
|
716
963
|
}, undefined, true, undefined, this)
|
|
717
964
|
]
|
|
718
965
|
}, undefined, true, undefined, this),
|
|
719
|
-
stats && subscription && /* @__PURE__ */
|
|
966
|
+
stats && subscription && /* @__PURE__ */ jsxDEV4(StatCardGroup, {
|
|
720
967
|
children: [
|
|
721
|
-
/* @__PURE__ */
|
|
968
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
722
969
|
label: "Projects",
|
|
723
970
|
value: stats.total.toString()
|
|
724
971
|
}, undefined, false, undefined, this),
|
|
725
|
-
/* @__PURE__ */
|
|
972
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
726
973
|
label: "Active",
|
|
727
974
|
value: stats.activeCount.toString()
|
|
728
975
|
}, undefined, false, undefined, this),
|
|
729
|
-
/* @__PURE__ */
|
|
976
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
730
977
|
label: "Draft",
|
|
731
978
|
value: stats.draftCount.toString()
|
|
732
979
|
}, undefined, false, undefined, this),
|
|
733
|
-
/* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
734
981
|
label: "Plan",
|
|
735
982
|
value: subscription.plan,
|
|
736
983
|
hint: subscription.status
|
|
737
984
|
}, undefined, false, undefined, this)
|
|
738
985
|
]
|
|
739
986
|
}, undefined, true, undefined, this),
|
|
740
|
-
/* @__PURE__ */
|
|
741
|
-
|
|
987
|
+
data && stats && /* @__PURE__ */ jsxDEV4(SaasVisualizationOverview, {
|
|
988
|
+
projectLimit: stats.projectLimit,
|
|
989
|
+
projects: data.items
|
|
990
|
+
}, undefined, false, undefined, this),
|
|
991
|
+
/* @__PURE__ */ jsxDEV4("nav", {
|
|
992
|
+
className: "flex gap-1 rounded-lg bg-muted p-1",
|
|
742
993
|
role: "tablist",
|
|
743
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
994
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxDEV4("button", {
|
|
744
995
|
type: "button",
|
|
745
996
|
role: "tab",
|
|
746
997
|
"aria-selected": activeTab === tab.id,
|
|
747
998
|
onClick: () => setActiveTab(tab.id),
|
|
748
|
-
className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm
|
|
999
|
+
className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
|
|
749
1000
|
children: [
|
|
750
|
-
/* @__PURE__ */
|
|
1001
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
751
1002
|
children: tab.icon
|
|
752
1003
|
}, undefined, false, undefined, this),
|
|
753
1004
|
tab.label
|
|
754
1005
|
]
|
|
755
1006
|
}, tab.id, true, undefined, this))
|
|
756
1007
|
}, undefined, false, undefined, this),
|
|
757
|
-
/* @__PURE__ */
|
|
1008
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
758
1009
|
className: "min-h-[400px]",
|
|
759
1010
|
role: "tabpanel",
|
|
760
1011
|
children: [
|
|
761
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
1012
|
+
activeTab === "projects" && /* @__PURE__ */ jsxDEV4(ProjectsTab, {
|
|
762
1013
|
data,
|
|
763
1014
|
onProjectClick: handleProjectClick
|
|
764
1015
|
}, undefined, false, undefined, this),
|
|
765
|
-
activeTab === "billing" && /* @__PURE__ */
|
|
1016
|
+
activeTab === "billing" && /* @__PURE__ */ jsxDEV4(BillingTab, {
|
|
766
1017
|
subscription
|
|
767
1018
|
}, undefined, false, undefined, this),
|
|
768
|
-
activeTab === "settings" && /* @__PURE__ */
|
|
1019
|
+
activeTab === "settings" && /* @__PURE__ */ jsxDEV4(SettingsTab, {}, undefined, false, undefined, this)
|
|
769
1020
|
]
|
|
770
1021
|
}, undefined, true, undefined, this),
|
|
771
|
-
/* @__PURE__ */
|
|
1022
|
+
/* @__PURE__ */ jsxDEV4(CreateProjectModal, {
|
|
772
1023
|
isOpen: isCreateModalOpen,
|
|
773
1024
|
onClose: () => setIsCreateModalOpen(false),
|
|
774
1025
|
onSubmit: async (input) => {
|
|
@@ -776,7 +1027,7 @@ function SaasDashboard() {
|
|
|
776
1027
|
},
|
|
777
1028
|
isLoading: mutations.createState.loading
|
|
778
1029
|
}, undefined, false, undefined, this),
|
|
779
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsxDEV4(ProjectActionsModal, {
|
|
780
1031
|
isOpen: isProjectActionsOpen,
|
|
781
1032
|
project: selectedProject,
|
|
782
1033
|
onClose: () => {
|
|
@@ -802,34 +1053,34 @@ function SaasDashboard() {
|
|
|
802
1053
|
}
|
|
803
1054
|
function ProjectsTab({ data, onProjectClick }) {
|
|
804
1055
|
if (!data?.items.length) {
|
|
805
|
-
return /* @__PURE__ */
|
|
1056
|
+
return /* @__PURE__ */ jsxDEV4(EmptyState, {
|
|
806
1057
|
title: "No projects yet",
|
|
807
1058
|
description: "Create your first project to get started."
|
|
808
1059
|
}, undefined, false, undefined, this);
|
|
809
1060
|
}
|
|
810
|
-
return /* @__PURE__ */
|
|
1061
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
811
1062
|
className: "space-y-4",
|
|
812
|
-
children: /* @__PURE__ */
|
|
1063
|
+
children: /* @__PURE__ */ jsxDEV4("div", {
|
|
813
1064
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
|
|
814
|
-
children: data.items.map((project) => /* @__PURE__ */
|
|
1065
|
+
children: data.items.map((project) => /* @__PURE__ */ jsxDEV4(EntityCard, {
|
|
815
1066
|
cardTitle: project.name,
|
|
816
1067
|
cardSubtitle: project.tier,
|
|
817
|
-
meta: /* @__PURE__ */
|
|
1068
|
+
meta: /* @__PURE__ */ jsxDEV4("p", {
|
|
818
1069
|
className: "text-muted-foreground text-sm",
|
|
819
1070
|
children: project.description
|
|
820
1071
|
}, undefined, false, undefined, this),
|
|
821
|
-
chips: /* @__PURE__ */
|
|
1072
|
+
chips: /* @__PURE__ */ jsxDEV4(StatusChip, {
|
|
822
1073
|
tone: getStatusTone(project.status),
|
|
823
1074
|
label: project.status
|
|
824
1075
|
}, undefined, false, undefined, this),
|
|
825
|
-
footer: /* @__PURE__ */
|
|
1076
|
+
footer: /* @__PURE__ */ jsxDEV4("div", {
|
|
826
1077
|
className: "flex w-full items-center justify-between",
|
|
827
1078
|
children: [
|
|
828
|
-
/* @__PURE__ */
|
|
1079
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
829
1080
|
className: "text-muted-foreground text-xs",
|
|
830
1081
|
children: project.updatedAt.toLocaleDateString()
|
|
831
1082
|
}, undefined, false, undefined, this),
|
|
832
|
-
/* @__PURE__ */
|
|
1083
|
+
/* @__PURE__ */ jsxDEV4(Button3, {
|
|
833
1084
|
variant: "ghost",
|
|
834
1085
|
size: "sm",
|
|
835
1086
|
onPress: () => onProjectClick?.(project),
|
|
@@ -844,25 +1095,25 @@ function ProjectsTab({ data, onProjectClick }) {
|
|
|
844
1095
|
function BillingTab({ subscription }) {
|
|
845
1096
|
if (!subscription)
|
|
846
1097
|
return null;
|
|
847
|
-
return /* @__PURE__ */
|
|
1098
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
848
1099
|
className: "space-y-6",
|
|
849
1100
|
children: [
|
|
850
|
-
/* @__PURE__ */
|
|
851
|
-
className: "border-border bg-card
|
|
1101
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
1102
|
+
className: "rounded-xl border border-border bg-card p-6",
|
|
852
1103
|
children: [
|
|
853
|
-
/* @__PURE__ */
|
|
1104
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
854
1105
|
className: "flex items-start justify-between",
|
|
855
1106
|
children: [
|
|
856
|
-
/* @__PURE__ */
|
|
1107
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
857
1108
|
children: [
|
|
858
|
-
/* @__PURE__ */
|
|
859
|
-
className: "text-lg
|
|
1109
|
+
/* @__PURE__ */ jsxDEV4("h3", {
|
|
1110
|
+
className: "font-semibold text-lg",
|
|
860
1111
|
children: [
|
|
861
1112
|
subscription.plan,
|
|
862
1113
|
" Plan"
|
|
863
1114
|
]
|
|
864
1115
|
}, undefined, true, undefined, this),
|
|
865
|
-
/* @__PURE__ */
|
|
1116
|
+
/* @__PURE__ */ jsxDEV4("p", {
|
|
866
1117
|
className: "text-muted-foreground text-sm",
|
|
867
1118
|
children: [
|
|
868
1119
|
"Current period:",
|
|
@@ -873,7 +1124,7 @@ function BillingTab({ subscription }) {
|
|
|
873
1124
|
subscription.currentPeriodEnd.toLocaleDateString()
|
|
874
1125
|
]
|
|
875
1126
|
}, undefined, true, undefined, this),
|
|
876
|
-
/* @__PURE__ */
|
|
1127
|
+
/* @__PURE__ */ jsxDEV4("p", {
|
|
877
1128
|
className: "text-muted-foreground text-sm",
|
|
878
1129
|
children: [
|
|
879
1130
|
"Billing cycle: ",
|
|
@@ -882,21 +1133,21 @@ function BillingTab({ subscription }) {
|
|
|
882
1133
|
}, undefined, true, undefined, this)
|
|
883
1134
|
]
|
|
884
1135
|
}, undefined, true, undefined, this),
|
|
885
|
-
/* @__PURE__ */
|
|
1136
|
+
/* @__PURE__ */ jsxDEV4(StatusChip, {
|
|
886
1137
|
tone: "success",
|
|
887
1138
|
label: subscription.status
|
|
888
1139
|
}, undefined, false, undefined, this)
|
|
889
1140
|
]
|
|
890
1141
|
}, undefined, true, undefined, this),
|
|
891
|
-
/* @__PURE__ */
|
|
1142
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
892
1143
|
className: "mt-4 flex gap-3",
|
|
893
1144
|
children: [
|
|
894
|
-
/* @__PURE__ */
|
|
1145
|
+
/* @__PURE__ */ jsxDEV4(Button3, {
|
|
895
1146
|
variant: "outline",
|
|
896
1147
|
onPress: () => alert("Upgrade clicked!"),
|
|
897
1148
|
children: "Upgrade Plan"
|
|
898
1149
|
}, undefined, false, undefined, this),
|
|
899
|
-
/* @__PURE__ */
|
|
1150
|
+
/* @__PURE__ */ jsxDEV4(Button3, {
|
|
900
1151
|
variant: "ghost",
|
|
901
1152
|
onPress: () => alert("Manage Billing clicked!"),
|
|
902
1153
|
children: "Manage Billing"
|
|
@@ -905,10 +1156,10 @@ function BillingTab({ subscription }) {
|
|
|
905
1156
|
}, undefined, true, undefined, this)
|
|
906
1157
|
]
|
|
907
1158
|
}, undefined, true, undefined, this),
|
|
908
|
-
subscription.cancelAtPeriodEnd && /* @__PURE__ */
|
|
909
|
-
className: "border-border bg-destructive/10 text-destructive
|
|
910
|
-
children: /* @__PURE__ */
|
|
911
|
-
className: "text-sm
|
|
1159
|
+
subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsxDEV4("div", {
|
|
1160
|
+
className: "rounded-xl border border-border bg-destructive/10 p-4 text-destructive",
|
|
1161
|
+
children: /* @__PURE__ */ jsxDEV4("p", {
|
|
1162
|
+
className: "font-medium text-sm",
|
|
912
1163
|
children: "⚠️ Your subscription will be cancelled at the end of the current period."
|
|
913
1164
|
}, undefined, false, undefined, this)
|
|
914
1165
|
}, undefined, false, undefined, this)
|
|
@@ -916,63 +1167,63 @@ function BillingTab({ subscription }) {
|
|
|
916
1167
|
}, undefined, true, undefined, this);
|
|
917
1168
|
}
|
|
918
1169
|
function SettingsTab() {
|
|
919
|
-
return /* @__PURE__ */
|
|
1170
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
920
1171
|
className: "space-y-6",
|
|
921
|
-
children: /* @__PURE__ */
|
|
922
|
-
className: "border-border bg-card
|
|
1172
|
+
children: /* @__PURE__ */ jsxDEV4("div", {
|
|
1173
|
+
className: "rounded-xl border border-border bg-card p-6",
|
|
923
1174
|
children: [
|
|
924
|
-
/* @__PURE__ */
|
|
925
|
-
className: "mb-4 text-lg
|
|
1175
|
+
/* @__PURE__ */ jsxDEV4("h3", {
|
|
1176
|
+
className: "mb-4 font-semibold text-lg",
|
|
926
1177
|
children: "Organization Settings"
|
|
927
1178
|
}, undefined, false, undefined, this),
|
|
928
|
-
/* @__PURE__ */
|
|
1179
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
929
1180
|
className: "space-y-4",
|
|
930
1181
|
children: [
|
|
931
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
932
1183
|
children: [
|
|
933
|
-
/* @__PURE__ */
|
|
1184
|
+
/* @__PURE__ */ jsxDEV4("label", {
|
|
934
1185
|
htmlFor: "org-name",
|
|
935
|
-
className: "text-sm
|
|
1186
|
+
className: "font-medium text-sm",
|
|
936
1187
|
children: "Organization Name"
|
|
937
1188
|
}, undefined, false, undefined, this),
|
|
938
|
-
/* @__PURE__ */
|
|
1189
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
939
1190
|
id: "org-name",
|
|
940
1191
|
type: "text",
|
|
941
1192
|
defaultValue: "Demo Organization",
|
|
942
|
-
className: "
|
|
1193
|
+
className: "mt-1 block w-full rounded-md border border-input bg-background px-3 py-2"
|
|
943
1194
|
}, undefined, false, undefined, this)
|
|
944
1195
|
]
|
|
945
1196
|
}, undefined, true, undefined, this),
|
|
946
|
-
/* @__PURE__ */
|
|
1197
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
947
1198
|
children: [
|
|
948
|
-
/* @__PURE__ */
|
|
1199
|
+
/* @__PURE__ */ jsxDEV4("label", {
|
|
949
1200
|
htmlFor: "timezone",
|
|
950
|
-
className: "text-sm
|
|
1201
|
+
className: "font-medium text-sm",
|
|
951
1202
|
children: "Default Timezone"
|
|
952
1203
|
}, undefined, false, undefined, this),
|
|
953
|
-
/* @__PURE__ */
|
|
1204
|
+
/* @__PURE__ */ jsxDEV4("select", {
|
|
954
1205
|
id: "timezone",
|
|
955
|
-
className: "
|
|
1206
|
+
className: "mt-1 block w-full rounded-md border border-input bg-background px-3 py-2",
|
|
956
1207
|
children: [
|
|
957
|
-
/* @__PURE__ */
|
|
1208
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
958
1209
|
children: "UTC"
|
|
959
1210
|
}, undefined, false, undefined, this),
|
|
960
|
-
/* @__PURE__ */
|
|
1211
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
961
1212
|
children: "America/New_York"
|
|
962
1213
|
}, undefined, false, undefined, this),
|
|
963
|
-
/* @__PURE__ */
|
|
1214
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
964
1215
|
children: "Europe/London"
|
|
965
1216
|
}, undefined, false, undefined, this),
|
|
966
|
-
/* @__PURE__ */
|
|
1217
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
967
1218
|
children: "Asia/Tokyo"
|
|
968
1219
|
}, undefined, false, undefined, this)
|
|
969
1220
|
]
|
|
970
1221
|
}, undefined, true, undefined, this)
|
|
971
1222
|
]
|
|
972
1223
|
}, undefined, true, undefined, this),
|
|
973
|
-
/* @__PURE__ */
|
|
1224
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
974
1225
|
className: "pt-2",
|
|
975
|
-
children: /* @__PURE__ */
|
|
1226
|
+
children: /* @__PURE__ */ jsxDEV4(Button3, {
|
|
976
1227
|
onPress: () => alert("Settings saved!"),
|
|
977
1228
|
children: "Save Settings"
|
|
978
1229
|
}, undefined, false, undefined, this)
|