@contractspec/example.saas-boilerplate 3.7.7 → 3.8.4
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 +36 -24
- package/CHANGELOG.md +72 -0
- package/README.md +1 -0
- package/dist/browser/index.js +371 -92
- package/dist/browser/saas-boilerplate.feature.js +208 -0
- package/dist/browser/ui/SaasDashboard.js +311 -60
- package/dist/browser/ui/SaasDashboard.visualizations.js +249 -0
- package/dist/browser/ui/index.js +362 -92
- package/dist/browser/ui/renderers/index.js +229 -3
- package/dist/browser/ui/renderers/project-list.markdown.js +229 -3
- 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/index.d.ts +1 -0
- package/dist/index.js +371 -92
- package/dist/node/index.js +371 -92
- package/dist/node/saas-boilerplate.feature.js +208 -0
- package/dist/node/ui/SaasDashboard.js +311 -60
- package/dist/node/ui/SaasDashboard.visualizations.js +249 -0
- package/dist/node/ui/index.js +362 -92
- package/dist/node/ui/renderers/index.js +229 -3
- package/dist/node/ui/renderers/project-list.markdown.js +229 -3
- 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/saas-boilerplate.feature.js +208 -0
- package/dist/ui/SaasDashboard.js +311 -60
- package/dist/ui/SaasDashboard.visualizations.d.ts +5 -0
- package/dist/ui/SaasDashboard.visualizations.js +250 -0
- package/dist/ui/index.js +362 -92
- package/dist/ui/renderers/index.js +229 -3
- package/dist/ui/renderers/project-list.markdown.d.ts +1 -1
- package/dist/ui/renderers/project-list.markdown.js +229 -3
- package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
- 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 -13
- package/src/index.ts +1 -0
- package/src/saas-boilerplate.feature.ts +3 -0
- package/src/ui/SaasDashboard.tsx +8 -0
- package/src/ui/SaasDashboard.visualizations.tsx +41 -0
- package/src/ui/renderers/project-list.markdown.ts +39 -15
- package/src/ui/renderers/project-list.renderer.tsx +1 -1
- 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/dist/ui/SaasDashboard.js
CHANGED
|
@@ -1,4 +1,211 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// src/visualizations/catalog.ts
|
|
3
|
+
import {
|
|
4
|
+
defineVisualization,
|
|
5
|
+
VisualizationRegistry
|
|
6
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
7
|
+
var PROJECT_LIST_REF = {
|
|
8
|
+
key: "saas.project.list",
|
|
9
|
+
version: "1.0.0"
|
|
10
|
+
};
|
|
11
|
+
var META = {
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
domain: "saas",
|
|
14
|
+
stability: "experimental",
|
|
15
|
+
owners: ["@example.saas-boilerplate"],
|
|
16
|
+
tags: ["saas", "visualization", "projects"]
|
|
17
|
+
};
|
|
18
|
+
var SaasProjectUsageVisualization = defineVisualization({
|
|
19
|
+
meta: {
|
|
20
|
+
...META,
|
|
21
|
+
key: "saas-boilerplate.visualization.project-usage",
|
|
22
|
+
title: "Project Capacity",
|
|
23
|
+
description: "Current project count against the current plan limit.",
|
|
24
|
+
goal: "Show usage against the active plan allowance.",
|
|
25
|
+
context: "SaaS account overview."
|
|
26
|
+
},
|
|
27
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
28
|
+
visualization: {
|
|
29
|
+
kind: "metric",
|
|
30
|
+
measure: "totalProjects",
|
|
31
|
+
comparisonMeasure: "projectLimit",
|
|
32
|
+
measures: [
|
|
33
|
+
{
|
|
34
|
+
key: "totalProjects",
|
|
35
|
+
label: "Projects",
|
|
36
|
+
dataPath: "totalProjects",
|
|
37
|
+
format: "number"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
key: "projectLimit",
|
|
41
|
+
label: "Plan Limit",
|
|
42
|
+
dataPath: "projectLimit",
|
|
43
|
+
format: "number"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
table: { caption: "Current project count and plan limit." }
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
var SaasProjectStatusVisualization = defineVisualization({
|
|
50
|
+
meta: {
|
|
51
|
+
...META,
|
|
52
|
+
key: "saas-boilerplate.visualization.project-status",
|
|
53
|
+
title: "Project Status",
|
|
54
|
+
description: "Distribution of project states.",
|
|
55
|
+
goal: "Show the mix of active, draft, and archived projects.",
|
|
56
|
+
context: "Project portfolio overview."
|
|
57
|
+
},
|
|
58
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
59
|
+
visualization: {
|
|
60
|
+
kind: "pie",
|
|
61
|
+
nameDimension: "status",
|
|
62
|
+
valueMeasure: "projects",
|
|
63
|
+
dimensions: [
|
|
64
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
65
|
+
],
|
|
66
|
+
measures: [
|
|
67
|
+
{
|
|
68
|
+
key: "projects",
|
|
69
|
+
label: "Projects",
|
|
70
|
+
dataPath: "projects",
|
|
71
|
+
format: "number"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
table: { caption: "Project counts by status." }
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
var SaasProjectTierVisualization = defineVisualization({
|
|
78
|
+
meta: {
|
|
79
|
+
...META,
|
|
80
|
+
key: "saas-boilerplate.visualization.project-tiers",
|
|
81
|
+
title: "Tier Comparison",
|
|
82
|
+
description: "Distribution of projects across tiers.",
|
|
83
|
+
goal: "Compare how the current portfolio is distributed by tier.",
|
|
84
|
+
context: "Plan and packaging overview."
|
|
85
|
+
},
|
|
86
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
87
|
+
visualization: {
|
|
88
|
+
kind: "cartesian",
|
|
89
|
+
variant: "bar",
|
|
90
|
+
xDimension: "tier",
|
|
91
|
+
yMeasures: ["projects"],
|
|
92
|
+
dimensions: [
|
|
93
|
+
{ key: "tier", label: "Tier", dataPath: "tier", type: "category" }
|
|
94
|
+
],
|
|
95
|
+
measures: [
|
|
96
|
+
{
|
|
97
|
+
key: "projects",
|
|
98
|
+
label: "Projects",
|
|
99
|
+
dataPath: "projects",
|
|
100
|
+
format: "number",
|
|
101
|
+
color: "#1d4ed8"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
table: { caption: "Project counts by tier." }
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
var SaasProjectActivityVisualization = defineVisualization({
|
|
108
|
+
meta: {
|
|
109
|
+
...META,
|
|
110
|
+
key: "saas-boilerplate.visualization.project-activity",
|
|
111
|
+
title: "Recent Project Activity",
|
|
112
|
+
description: "Daily project creation activity.",
|
|
113
|
+
goal: "Show recent project activity over time.",
|
|
114
|
+
context: "Project portfolio trend view."
|
|
115
|
+
},
|
|
116
|
+
source: { primary: PROJECT_LIST_REF, resultPath: "data" },
|
|
117
|
+
visualization: {
|
|
118
|
+
kind: "cartesian",
|
|
119
|
+
variant: "line",
|
|
120
|
+
xDimension: "day",
|
|
121
|
+
yMeasures: ["projects"],
|
|
122
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
123
|
+
measures: [
|
|
124
|
+
{
|
|
125
|
+
key: "projects",
|
|
126
|
+
label: "Projects",
|
|
127
|
+
dataPath: "projects",
|
|
128
|
+
format: "number",
|
|
129
|
+
color: "#0f766e"
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
table: { caption: "Daily project creation counts." }
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
var SaasVisualizationSpecs = [
|
|
136
|
+
SaasProjectUsageVisualization,
|
|
137
|
+
SaasProjectStatusVisualization,
|
|
138
|
+
SaasProjectTierVisualization,
|
|
139
|
+
SaasProjectActivityVisualization
|
|
140
|
+
];
|
|
141
|
+
var SaasVisualizationRegistry = new VisualizationRegistry([
|
|
142
|
+
...SaasVisualizationSpecs
|
|
143
|
+
]);
|
|
144
|
+
var SaasVisualizationRefs = SaasVisualizationSpecs.map((spec) => ({
|
|
145
|
+
key: spec.meta.key,
|
|
146
|
+
version: spec.meta.version
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
// src/visualizations/selectors.ts
|
|
150
|
+
function toDayKey(value) {
|
|
151
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
152
|
+
return date.toISOString().slice(0, 10);
|
|
153
|
+
}
|
|
154
|
+
function createSaasVisualizationItems(projects, projectLimit = 10) {
|
|
155
|
+
const statusCounts = new Map;
|
|
156
|
+
const tierCounts = new Map;
|
|
157
|
+
const activityCounts = new Map;
|
|
158
|
+
for (const project of projects) {
|
|
159
|
+
statusCounts.set(project.status, (statusCounts.get(project.status) ?? 0) + 1);
|
|
160
|
+
tierCounts.set(project.tier, (tierCounts.get(project.tier) ?? 0) + 1);
|
|
161
|
+
const day = toDayKey(project.createdAt);
|
|
162
|
+
activityCounts.set(day, (activityCounts.get(day) ?? 0) + 1);
|
|
163
|
+
}
|
|
164
|
+
return [
|
|
165
|
+
{
|
|
166
|
+
key: "saas-capacity",
|
|
167
|
+
spec: SaasProjectUsageVisualization,
|
|
168
|
+
data: { data: [{ totalProjects: projects.length, projectLimit }] },
|
|
169
|
+
title: "Project Capacity",
|
|
170
|
+
description: "Current project count compared to the active limit.",
|
|
171
|
+
height: 220
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
key: "saas-status",
|
|
175
|
+
spec: SaasProjectStatusVisualization,
|
|
176
|
+
data: {
|
|
177
|
+
data: Array.from(statusCounts.entries()).map(([status, count]) => ({
|
|
178
|
+
status,
|
|
179
|
+
projects: count
|
|
180
|
+
}))
|
|
181
|
+
},
|
|
182
|
+
title: "Project Status",
|
|
183
|
+
description: "Status mix across the current project portfolio.",
|
|
184
|
+
height: 260
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
key: "saas-tier",
|
|
188
|
+
spec: SaasProjectTierVisualization,
|
|
189
|
+
data: {
|
|
190
|
+
data: Array.from(tierCounts.entries()).map(([tier, count]) => ({
|
|
191
|
+
tier,
|
|
192
|
+
projects: count
|
|
193
|
+
}))
|
|
194
|
+
},
|
|
195
|
+
title: "Tier Comparison",
|
|
196
|
+
description: "How projects are distributed across tiers."
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
key: "saas-activity",
|
|
200
|
+
spec: SaasProjectActivityVisualization,
|
|
201
|
+
data: {
|
|
202
|
+
data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, projects: count }))
|
|
203
|
+
},
|
|
204
|
+
title: "Recent Project Activity",
|
|
205
|
+
description: "Daily project creation activity."
|
|
206
|
+
}
|
|
207
|
+
];
|
|
208
|
+
}
|
|
2
209
|
// src/ui/hooks/useProjectList.ts
|
|
3
210
|
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
4
211
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
@@ -636,6 +843,46 @@ function ProjectActionsModal({
|
|
|
636
843
|
}, undefined, true, undefined, this);
|
|
637
844
|
}
|
|
638
845
|
|
|
846
|
+
// src/ui/SaasDashboard.visualizations.tsx
|
|
847
|
+
import {
|
|
848
|
+
VisualizationCard,
|
|
849
|
+
VisualizationGrid
|
|
850
|
+
} from "@contractspec/lib.design-system";
|
|
851
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
852
|
+
"use client";
|
|
853
|
+
function SaasVisualizationOverview({
|
|
854
|
+
projects,
|
|
855
|
+
projectLimit
|
|
856
|
+
}) {
|
|
857
|
+
const items = createSaasVisualizationItems(projects, projectLimit);
|
|
858
|
+
return /* @__PURE__ */ jsxDEV3("section", {
|
|
859
|
+
className: "space-y-3",
|
|
860
|
+
children: [
|
|
861
|
+
/* @__PURE__ */ jsxDEV3("div", {
|
|
862
|
+
children: [
|
|
863
|
+
/* @__PURE__ */ jsxDEV3("h3", {
|
|
864
|
+
className: "font-semibold text-lg",
|
|
865
|
+
children: "Portfolio Visualizations"
|
|
866
|
+
}, undefined, false, undefined, this),
|
|
867
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
868
|
+
className: "text-muted-foreground text-sm",
|
|
869
|
+
children: "Contract-backed charts for project mix, capacity, and activity."
|
|
870
|
+
}, undefined, false, undefined, this)
|
|
871
|
+
]
|
|
872
|
+
}, undefined, true, undefined, this),
|
|
873
|
+
/* @__PURE__ */ jsxDEV3(VisualizationGrid, {
|
|
874
|
+
children: items.map((item) => /* @__PURE__ */ jsxDEV3(VisualizationCard, {
|
|
875
|
+
data: item.data,
|
|
876
|
+
description: item.description,
|
|
877
|
+
height: item.height,
|
|
878
|
+
spec: item.spec,
|
|
879
|
+
title: item.title
|
|
880
|
+
}, item.key, false, undefined, this))
|
|
881
|
+
}, undefined, false, undefined, this)
|
|
882
|
+
]
|
|
883
|
+
}, undefined, true, undefined, this);
|
|
884
|
+
}
|
|
885
|
+
|
|
639
886
|
// src/ui/SaasDashboard.tsx
|
|
640
887
|
import {
|
|
641
888
|
Button as Button3,
|
|
@@ -648,7 +895,7 @@ import {
|
|
|
648
895
|
StatusChip
|
|
649
896
|
} from "@contractspec/lib.design-system";
|
|
650
897
|
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
651
|
-
import { jsxDEV as
|
|
898
|
+
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
652
899
|
"use client";
|
|
653
900
|
function getStatusTone(status) {
|
|
654
901
|
switch (status) {
|
|
@@ -683,32 +930,32 @@ function SaasDashboard() {
|
|
|
683
930
|
{ id: "settings", label: "Settings", icon: "\u2699\uFE0F" }
|
|
684
931
|
];
|
|
685
932
|
if (loading && !data) {
|
|
686
|
-
return /* @__PURE__ */
|
|
933
|
+
return /* @__PURE__ */ jsxDEV4(LoaderBlock, {
|
|
687
934
|
label: "Loading dashboard..."
|
|
688
935
|
}, undefined, false, undefined, this);
|
|
689
936
|
}
|
|
690
937
|
if (error) {
|
|
691
|
-
return /* @__PURE__ */
|
|
938
|
+
return /* @__PURE__ */ jsxDEV4(ErrorState, {
|
|
692
939
|
title: "Failed to load dashboard",
|
|
693
940
|
description: error.message,
|
|
694
941
|
onRetry: refetch,
|
|
695
942
|
retryLabel: "Retry"
|
|
696
943
|
}, undefined, false, undefined, this);
|
|
697
944
|
}
|
|
698
|
-
return /* @__PURE__ */
|
|
945
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
699
946
|
className: "space-y-6",
|
|
700
947
|
children: [
|
|
701
|
-
/* @__PURE__ */
|
|
948
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
702
949
|
className: "flex items-center justify-between",
|
|
703
950
|
children: [
|
|
704
|
-
/* @__PURE__ */
|
|
951
|
+
/* @__PURE__ */ jsxDEV4("h2", {
|
|
705
952
|
className: "font-bold text-2xl",
|
|
706
953
|
children: "SaaS Dashboard"
|
|
707
954
|
}, undefined, false, undefined, this),
|
|
708
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
955
|
+
activeTab === "projects" && /* @__PURE__ */ jsxDEV4(Button3, {
|
|
709
956
|
onPress: () => setIsCreateModalOpen(true),
|
|
710
957
|
children: [
|
|
711
|
-
/* @__PURE__ */
|
|
958
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
712
959
|
className: "mr-2",
|
|
713
960
|
children: "+"
|
|
714
961
|
}, undefined, false, undefined, this),
|
|
@@ -717,59 +964,63 @@ function SaasDashboard() {
|
|
|
717
964
|
}, undefined, true, undefined, this)
|
|
718
965
|
]
|
|
719
966
|
}, undefined, true, undefined, this),
|
|
720
|
-
stats && subscription && /* @__PURE__ */
|
|
967
|
+
stats && subscription && /* @__PURE__ */ jsxDEV4(StatCardGroup, {
|
|
721
968
|
children: [
|
|
722
|
-
/* @__PURE__ */
|
|
969
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
723
970
|
label: "Projects",
|
|
724
971
|
value: stats.total.toString()
|
|
725
972
|
}, undefined, false, undefined, this),
|
|
726
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
727
974
|
label: "Active",
|
|
728
975
|
value: stats.activeCount.toString()
|
|
729
976
|
}, undefined, false, undefined, this),
|
|
730
|
-
/* @__PURE__ */
|
|
977
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
731
978
|
label: "Draft",
|
|
732
979
|
value: stats.draftCount.toString()
|
|
733
980
|
}, undefined, false, undefined, this),
|
|
734
|
-
/* @__PURE__ */
|
|
981
|
+
/* @__PURE__ */ jsxDEV4(StatCard, {
|
|
735
982
|
label: "Plan",
|
|
736
983
|
value: subscription.plan,
|
|
737
984
|
hint: subscription.status
|
|
738
985
|
}, undefined, false, undefined, this)
|
|
739
986
|
]
|
|
740
987
|
}, undefined, true, undefined, this),
|
|
741
|
-
/* @__PURE__ */
|
|
988
|
+
data && stats && /* @__PURE__ */ jsxDEV4(SaasVisualizationOverview, {
|
|
989
|
+
projectLimit: stats.projectLimit,
|
|
990
|
+
projects: data.items
|
|
991
|
+
}, undefined, false, undefined, this),
|
|
992
|
+
/* @__PURE__ */ jsxDEV4("nav", {
|
|
742
993
|
className: "flex gap-1 rounded-lg bg-muted p-1",
|
|
743
994
|
role: "tablist",
|
|
744
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
995
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxDEV4("button", {
|
|
745
996
|
type: "button",
|
|
746
997
|
role: "tab",
|
|
747
998
|
"aria-selected": activeTab === tab.id,
|
|
748
999
|
onClick: () => setActiveTab(tab.id),
|
|
749
1000
|
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"}`,
|
|
750
1001
|
children: [
|
|
751
|
-
/* @__PURE__ */
|
|
1002
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
752
1003
|
children: tab.icon
|
|
753
1004
|
}, undefined, false, undefined, this),
|
|
754
1005
|
tab.label
|
|
755
1006
|
]
|
|
756
1007
|
}, tab.id, true, undefined, this))
|
|
757
1008
|
}, undefined, false, undefined, this),
|
|
758
|
-
/* @__PURE__ */
|
|
1009
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
759
1010
|
className: "min-h-[400px]",
|
|
760
1011
|
role: "tabpanel",
|
|
761
1012
|
children: [
|
|
762
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
1013
|
+
activeTab === "projects" && /* @__PURE__ */ jsxDEV4(ProjectsTab, {
|
|
763
1014
|
data,
|
|
764
1015
|
onProjectClick: handleProjectClick
|
|
765
1016
|
}, undefined, false, undefined, this),
|
|
766
|
-
activeTab === "billing" && /* @__PURE__ */
|
|
1017
|
+
activeTab === "billing" && /* @__PURE__ */ jsxDEV4(BillingTab, {
|
|
767
1018
|
subscription
|
|
768
1019
|
}, undefined, false, undefined, this),
|
|
769
|
-
activeTab === "settings" && /* @__PURE__ */
|
|
1020
|
+
activeTab === "settings" && /* @__PURE__ */ jsxDEV4(SettingsTab, {}, undefined, false, undefined, this)
|
|
770
1021
|
]
|
|
771
1022
|
}, undefined, true, undefined, this),
|
|
772
|
-
/* @__PURE__ */
|
|
1023
|
+
/* @__PURE__ */ jsxDEV4(CreateProjectModal, {
|
|
773
1024
|
isOpen: isCreateModalOpen,
|
|
774
1025
|
onClose: () => setIsCreateModalOpen(false),
|
|
775
1026
|
onSubmit: async (input) => {
|
|
@@ -777,7 +1028,7 @@ function SaasDashboard() {
|
|
|
777
1028
|
},
|
|
778
1029
|
isLoading: mutations.createState.loading
|
|
779
1030
|
}, undefined, false, undefined, this),
|
|
780
|
-
/* @__PURE__ */
|
|
1031
|
+
/* @__PURE__ */ jsxDEV4(ProjectActionsModal, {
|
|
781
1032
|
isOpen: isProjectActionsOpen,
|
|
782
1033
|
project: selectedProject,
|
|
783
1034
|
onClose: () => {
|
|
@@ -803,34 +1054,34 @@ function SaasDashboard() {
|
|
|
803
1054
|
}
|
|
804
1055
|
function ProjectsTab({ data, onProjectClick }) {
|
|
805
1056
|
if (!data?.items.length) {
|
|
806
|
-
return /* @__PURE__ */
|
|
1057
|
+
return /* @__PURE__ */ jsxDEV4(EmptyState, {
|
|
807
1058
|
title: "No projects yet",
|
|
808
1059
|
description: "Create your first project to get started."
|
|
809
1060
|
}, undefined, false, undefined, this);
|
|
810
1061
|
}
|
|
811
|
-
return /* @__PURE__ */
|
|
1062
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
812
1063
|
className: "space-y-4",
|
|
813
|
-
children: /* @__PURE__ */
|
|
1064
|
+
children: /* @__PURE__ */ jsxDEV4("div", {
|
|
814
1065
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
|
|
815
|
-
children: data.items.map((project) => /* @__PURE__ */
|
|
1066
|
+
children: data.items.map((project) => /* @__PURE__ */ jsxDEV4(EntityCard, {
|
|
816
1067
|
cardTitle: project.name,
|
|
817
1068
|
cardSubtitle: project.tier,
|
|
818
|
-
meta: /* @__PURE__ */
|
|
1069
|
+
meta: /* @__PURE__ */ jsxDEV4("p", {
|
|
819
1070
|
className: "text-muted-foreground text-sm",
|
|
820
1071
|
children: project.description
|
|
821
1072
|
}, undefined, false, undefined, this),
|
|
822
|
-
chips: /* @__PURE__ */
|
|
1073
|
+
chips: /* @__PURE__ */ jsxDEV4(StatusChip, {
|
|
823
1074
|
tone: getStatusTone(project.status),
|
|
824
1075
|
label: project.status
|
|
825
1076
|
}, undefined, false, undefined, this),
|
|
826
|
-
footer: /* @__PURE__ */
|
|
1077
|
+
footer: /* @__PURE__ */ jsxDEV4("div", {
|
|
827
1078
|
className: "flex w-full items-center justify-between",
|
|
828
1079
|
children: [
|
|
829
|
-
/* @__PURE__ */
|
|
1080
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
830
1081
|
className: "text-muted-foreground text-xs",
|
|
831
1082
|
children: project.updatedAt.toLocaleDateString()
|
|
832
1083
|
}, undefined, false, undefined, this),
|
|
833
|
-
/* @__PURE__ */
|
|
1084
|
+
/* @__PURE__ */ jsxDEV4(Button3, {
|
|
834
1085
|
variant: "ghost",
|
|
835
1086
|
size: "sm",
|
|
836
1087
|
onPress: () => onProjectClick?.(project),
|
|
@@ -845,25 +1096,25 @@ function ProjectsTab({ data, onProjectClick }) {
|
|
|
845
1096
|
function BillingTab({ subscription }) {
|
|
846
1097
|
if (!subscription)
|
|
847
1098
|
return null;
|
|
848
|
-
return /* @__PURE__ */
|
|
1099
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
849
1100
|
className: "space-y-6",
|
|
850
1101
|
children: [
|
|
851
|
-
/* @__PURE__ */
|
|
1102
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
852
1103
|
className: "rounded-xl border border-border bg-card p-6",
|
|
853
1104
|
children: [
|
|
854
|
-
/* @__PURE__ */
|
|
1105
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
855
1106
|
className: "flex items-start justify-between",
|
|
856
1107
|
children: [
|
|
857
|
-
/* @__PURE__ */
|
|
1108
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
858
1109
|
children: [
|
|
859
|
-
/* @__PURE__ */
|
|
1110
|
+
/* @__PURE__ */ jsxDEV4("h3", {
|
|
860
1111
|
className: "font-semibold text-lg",
|
|
861
1112
|
children: [
|
|
862
1113
|
subscription.plan,
|
|
863
1114
|
" Plan"
|
|
864
1115
|
]
|
|
865
1116
|
}, undefined, true, undefined, this),
|
|
866
|
-
/* @__PURE__ */
|
|
1117
|
+
/* @__PURE__ */ jsxDEV4("p", {
|
|
867
1118
|
className: "text-muted-foreground text-sm",
|
|
868
1119
|
children: [
|
|
869
1120
|
"Current period:",
|
|
@@ -874,7 +1125,7 @@ function BillingTab({ subscription }) {
|
|
|
874
1125
|
subscription.currentPeriodEnd.toLocaleDateString()
|
|
875
1126
|
]
|
|
876
1127
|
}, undefined, true, undefined, this),
|
|
877
|
-
/* @__PURE__ */
|
|
1128
|
+
/* @__PURE__ */ jsxDEV4("p", {
|
|
878
1129
|
className: "text-muted-foreground text-sm",
|
|
879
1130
|
children: [
|
|
880
1131
|
"Billing cycle: ",
|
|
@@ -883,21 +1134,21 @@ function BillingTab({ subscription }) {
|
|
|
883
1134
|
}, undefined, true, undefined, this)
|
|
884
1135
|
]
|
|
885
1136
|
}, undefined, true, undefined, this),
|
|
886
|
-
/* @__PURE__ */
|
|
1137
|
+
/* @__PURE__ */ jsxDEV4(StatusChip, {
|
|
887
1138
|
tone: "success",
|
|
888
1139
|
label: subscription.status
|
|
889
1140
|
}, undefined, false, undefined, this)
|
|
890
1141
|
]
|
|
891
1142
|
}, undefined, true, undefined, this),
|
|
892
|
-
/* @__PURE__ */
|
|
1143
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
893
1144
|
className: "mt-4 flex gap-3",
|
|
894
1145
|
children: [
|
|
895
|
-
/* @__PURE__ */
|
|
1146
|
+
/* @__PURE__ */ jsxDEV4(Button3, {
|
|
896
1147
|
variant: "outline",
|
|
897
1148
|
onPress: () => alert("Upgrade clicked!"),
|
|
898
1149
|
children: "Upgrade Plan"
|
|
899
1150
|
}, undefined, false, undefined, this),
|
|
900
|
-
/* @__PURE__ */
|
|
1151
|
+
/* @__PURE__ */ jsxDEV4(Button3, {
|
|
901
1152
|
variant: "ghost",
|
|
902
1153
|
onPress: () => alert("Manage Billing clicked!"),
|
|
903
1154
|
children: "Manage Billing"
|
|
@@ -906,9 +1157,9 @@ function BillingTab({ subscription }) {
|
|
|
906
1157
|
}, undefined, true, undefined, this)
|
|
907
1158
|
]
|
|
908
1159
|
}, undefined, true, undefined, this),
|
|
909
|
-
subscription.cancelAtPeriodEnd && /* @__PURE__ */
|
|
1160
|
+
subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsxDEV4("div", {
|
|
910
1161
|
className: "rounded-xl border border-border bg-destructive/10 p-4 text-destructive",
|
|
911
|
-
children: /* @__PURE__ */
|
|
1162
|
+
children: /* @__PURE__ */ jsxDEV4("p", {
|
|
912
1163
|
className: "font-medium text-sm",
|
|
913
1164
|
children: "\u26A0\uFE0F Your subscription will be cancelled at the end of the current period."
|
|
914
1165
|
}, undefined, false, undefined, this)
|
|
@@ -917,26 +1168,26 @@ function BillingTab({ subscription }) {
|
|
|
917
1168
|
}, undefined, true, undefined, this);
|
|
918
1169
|
}
|
|
919
1170
|
function SettingsTab() {
|
|
920
|
-
return /* @__PURE__ */
|
|
1171
|
+
return /* @__PURE__ */ jsxDEV4("div", {
|
|
921
1172
|
className: "space-y-6",
|
|
922
|
-
children: /* @__PURE__ */
|
|
1173
|
+
children: /* @__PURE__ */ jsxDEV4("div", {
|
|
923
1174
|
className: "rounded-xl border border-border bg-card p-6",
|
|
924
1175
|
children: [
|
|
925
|
-
/* @__PURE__ */
|
|
1176
|
+
/* @__PURE__ */ jsxDEV4("h3", {
|
|
926
1177
|
className: "mb-4 font-semibold text-lg",
|
|
927
1178
|
children: "Organization Settings"
|
|
928
1179
|
}, undefined, false, undefined, this),
|
|
929
|
-
/* @__PURE__ */
|
|
1180
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
930
1181
|
className: "space-y-4",
|
|
931
1182
|
children: [
|
|
932
|
-
/* @__PURE__ */
|
|
1183
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
933
1184
|
children: [
|
|
934
|
-
/* @__PURE__ */
|
|
1185
|
+
/* @__PURE__ */ jsxDEV4("label", {
|
|
935
1186
|
htmlFor: "org-name",
|
|
936
1187
|
className: "font-medium text-sm",
|
|
937
1188
|
children: "Organization Name"
|
|
938
1189
|
}, undefined, false, undefined, this),
|
|
939
|
-
/* @__PURE__ */
|
|
1190
|
+
/* @__PURE__ */ jsxDEV4("input", {
|
|
940
1191
|
id: "org-name",
|
|
941
1192
|
type: "text",
|
|
942
1193
|
defaultValue: "Demo Organization",
|
|
@@ -944,36 +1195,36 @@ function SettingsTab() {
|
|
|
944
1195
|
}, undefined, false, undefined, this)
|
|
945
1196
|
]
|
|
946
1197
|
}, undefined, true, undefined, this),
|
|
947
|
-
/* @__PURE__ */
|
|
1198
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
948
1199
|
children: [
|
|
949
|
-
/* @__PURE__ */
|
|
1200
|
+
/* @__PURE__ */ jsxDEV4("label", {
|
|
950
1201
|
htmlFor: "timezone",
|
|
951
1202
|
className: "font-medium text-sm",
|
|
952
1203
|
children: "Default Timezone"
|
|
953
1204
|
}, undefined, false, undefined, this),
|
|
954
|
-
/* @__PURE__ */
|
|
1205
|
+
/* @__PURE__ */ jsxDEV4("select", {
|
|
955
1206
|
id: "timezone",
|
|
956
1207
|
className: "mt-1 block w-full rounded-md border border-input bg-background px-3 py-2",
|
|
957
1208
|
children: [
|
|
958
|
-
/* @__PURE__ */
|
|
1209
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
959
1210
|
children: "UTC"
|
|
960
1211
|
}, undefined, false, undefined, this),
|
|
961
|
-
/* @__PURE__ */
|
|
1212
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
962
1213
|
children: "America/New_York"
|
|
963
1214
|
}, undefined, false, undefined, this),
|
|
964
|
-
/* @__PURE__ */
|
|
1215
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
965
1216
|
children: "Europe/London"
|
|
966
1217
|
}, undefined, false, undefined, this),
|
|
967
|
-
/* @__PURE__ */
|
|
1218
|
+
/* @__PURE__ */ jsxDEV4("option", {
|
|
968
1219
|
children: "Asia/Tokyo"
|
|
969
1220
|
}, undefined, false, undefined, this)
|
|
970
1221
|
]
|
|
971
1222
|
}, undefined, true, undefined, this)
|
|
972
1223
|
]
|
|
973
1224
|
}, undefined, true, undefined, this),
|
|
974
|
-
/* @__PURE__ */
|
|
1225
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
975
1226
|
className: "pt-2",
|
|
976
|
-
children: /* @__PURE__ */
|
|
1227
|
+
children: /* @__PURE__ */ jsxDEV4(Button3, {
|
|
977
1228
|
onPress: () => alert("Settings saved!"),
|
|
978
1229
|
children: "Save Settings"
|
|
979
1230
|
}, undefined, false, undefined, this)
|