crewos 0.1.0
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/app/.env.example +1 -0
- package/app/index.html +50 -0
- package/app/package.json +25 -0
- package/app/public/favicon.svg +1 -0
- package/app/public/images/cursor-ide-guiiding.png +0 -0
- package/app/public/images/gpt.jpg +0 -0
- package/app/src/app.jsx +22 -0
- package/app/src/components/ConfirmModal.jsx +50 -0
- package/app/src/components/Icons.jsx +377 -0
- package/app/src/components/RedirectRoute.jsx +14 -0
- package/app/src/components/SplashScreen.jsx +15 -0
- package/app/src/hooks/useAuth.js +28 -0
- package/app/src/index.css +268 -0
- package/app/src/main.jsx +5 -0
- package/app/src/navigations/AuthRoutes.jsx +15 -0
- package/app/src/navigations/MainRoutes.jsx +15 -0
- package/app/src/navigations/OnboardingRoutes.jsx +15 -0
- package/app/src/navigations/index.jsx +37 -0
- package/app/src/pages/Home/index.jsx +2095 -0
- package/app/src/pages/Login/index.jsx +118 -0
- package/app/src/pages/Onboarding/index.jsx +550 -0
- package/app/src/services/api.js +46 -0
- package/app/src/services/auth.service.js +3 -0
- package/app/src/services/config.service.js +13 -0
- package/app/src/services/member.service.js +7 -0
- package/app/src/services/onboarding.service.js +17 -0
- package/app/src/services/role.service.js +6 -0
- package/app/src/services/task.service.js +22 -0
- package/app/src/stores/auth.store.js +7 -0
- package/app/src/utils/environments.js +5 -0
- package/app/vite.config.js +10 -0
- package/app/yarn.lock +1337 -0
- package/backend/package-lock.json +918 -0
- package/backend/package.json +18 -0
- package/backend/src/configs/db.config.js +40 -0
- package/backend/src/controllers/auth.controller.js +19 -0
- package/backend/src/controllers/config.controller.js +23 -0
- package/backend/src/controllers/member.controller.js +30 -0
- package/backend/src/controllers/models.controller.js +25 -0
- package/backend/src/controllers/onboarding.controller.js +49 -0
- package/backend/src/controllers/role.controller.js +17 -0
- package/backend/src/controllers/task.controller.js +63 -0
- package/backend/src/index.js +36 -0
- package/backend/src/middlewares/onboarding.guard.js +14 -0
- package/backend/src/routes/auth.route.js +8 -0
- package/backend/src/routes/config.route.js +11 -0
- package/backend/src/routes/index.js +22 -0
- package/backend/src/routes/member.route.js +11 -0
- package/backend/src/routes/models.route.js +8 -0
- package/backend/src/routes/onboarding.route.js +13 -0
- package/backend/src/routes/role.route.js +9 -0
- package/backend/src/routes/task.route.js +20 -0
- package/backend/src/services/auth.service.js +14 -0
- package/backend/src/services/config.service.js +176 -0
- package/backend/src/services/data/roles.json +474 -0
- package/backend/src/services/member.service.js +77 -0
- package/backend/src/services/onboarding.service.js +328 -0
- package/backend/src/services/role.service.js +23 -0
- package/backend/src/services/task.service.js +665 -0
- package/backend/src/utils/catcher.js +9 -0
- package/backend/src/utils/sanitize.js +13 -0
- package/backend/yarn.lock +513 -0
- package/bin/crewos.js +307 -0
- package/package.json +11 -0
package/app/.env.example
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_BACKEND_URL=
|
package/app/index.html
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
+
<link rel="apple-touch-icon" href="/favicon.svg" />
|
|
7
|
+
<meta name="theme-color" content="#08110c" />
|
|
8
|
+
<meta name="application-name" content="crewOS" />
|
|
9
|
+
<meta name="apple-mobile-web-app-title" content="crewOS" />
|
|
10
|
+
<meta
|
|
11
|
+
name="description"
|
|
12
|
+
content="crewOS - The operating system for AI-powered development teams."
|
|
13
|
+
/>
|
|
14
|
+
<meta name="robots" content="index,follow" />
|
|
15
|
+
<meta
|
|
16
|
+
name="keywords"
|
|
17
|
+
content="crewOS, AI development, team collaboration, task management, developer tools"
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
<meta property="og:type" content="website" />
|
|
21
|
+
<meta property="og:site_name" content="crewOS" />
|
|
22
|
+
<meta property="og:title" content="crewOS" />
|
|
23
|
+
<meta
|
|
24
|
+
property="og:description"
|
|
25
|
+
content="The operating system for AI-powered development teams."
|
|
26
|
+
/>
|
|
27
|
+
<meta property="og:image" content="/favicon.svg" />
|
|
28
|
+
|
|
29
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
30
|
+
<meta name="twitter:title" content="crewOS" />
|
|
31
|
+
<meta
|
|
32
|
+
name="twitter:description"
|
|
33
|
+
content="The operating system for AI-powered development teams."
|
|
34
|
+
/>
|
|
35
|
+
<meta name="twitter:image" content="/favicon.svg" />
|
|
36
|
+
|
|
37
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
38
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
39
|
+
<link
|
|
40
|
+
href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@400;500;600;700&display=swap"
|
|
41
|
+
rel="stylesheet"
|
|
42
|
+
/>
|
|
43
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
44
|
+
<title>crewOS</title>
|
|
45
|
+
</head>
|
|
46
|
+
<body>
|
|
47
|
+
<div id="app"></div>
|
|
48
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
49
|
+
</body>
|
|
50
|
+
</html>
|
package/app/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "crewos-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"preview": "vite preview",
|
|
9
|
+
"build": "vite build"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@preact/signals": "^2.8.1",
|
|
13
|
+
"axios": "^1.13.6",
|
|
14
|
+
"preact": "^10.27.2",
|
|
15
|
+
"preact-iso": "^2.11.1",
|
|
16
|
+
"preact-render-to-string": "^6.6.6",
|
|
17
|
+
"sonner": "^2.0.7"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@preact/preset-vite": "^2.10.2",
|
|
21
|
+
"@tailwindcss/vite": "^4.2.1",
|
|
22
|
+
"tailwindcss": "^4.2.1",
|
|
23
|
+
"vite": "^7.3.1"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" x="0" y="0" viewBox="0 0 362.05 512" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g><g data-name="Layer 2"><path d="M360.58 214.71a15 15 0 0 0-13.58-8.53H203.51l77.06-185.41A15 15 0 0 0 266.71 0H103.37A15 15 0 0 0 89 10.71L.63 306.6A15 15 0 0 0 15 325.9h138.6l-43.34 167.33a15 15 0 0 0 26.22 13.18l222.25-275.8a15 15 0 0 0 1.85-15.9z" data-name="lighting bolt" fill="#22c55e" opacity="1" data-original="#000000" class=""></path></g></g></svg>
|
|
Binary file
|
|
Binary file
|
package/app/src/app.jsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Navigations from './navigations';
|
|
2
|
+
import { Toaster } from 'sonner';
|
|
3
|
+
|
|
4
|
+
const App = () => {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
<Navigations />
|
|
8
|
+
<Toaster
|
|
9
|
+
richColors
|
|
10
|
+
position="top-right"
|
|
11
|
+
closeButton
|
|
12
|
+
toastOptions={{
|
|
13
|
+
style: {
|
|
14
|
+
fontFamily: 'var(--font-sans)',
|
|
15
|
+
},
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default App;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const ConfirmModal = ({
|
|
2
|
+
open,
|
|
3
|
+
title,
|
|
4
|
+
description,
|
|
5
|
+
confirmText = 'Confirm',
|
|
6
|
+
cancelText = 'Cancel',
|
|
7
|
+
confirmVariant = 'danger',
|
|
8
|
+
loading = false,
|
|
9
|
+
onConfirm,
|
|
10
|
+
onCancel,
|
|
11
|
+
}) => {
|
|
12
|
+
if (!open) return null;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div class="fixed inset-0 z-50 flex items-center justify-center px-4">
|
|
16
|
+
<button
|
|
17
|
+
type="button"
|
|
18
|
+
class="absolute inset-0 bg-black/70 backdrop-blur-sm"
|
|
19
|
+
aria-label="Close confirm dialog"
|
|
20
|
+
onClick={onCancel}
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<div class="relative z-10 w-full max-w-md p-5 sm:p-6 bg-zinc-900 border border-zinc-800">
|
|
24
|
+
<p class="text-base font-semibold text-zinc-100">{title}</p>
|
|
25
|
+
<p class="mt-2 text-sm text-zinc-400">{description}</p>
|
|
26
|
+
|
|
27
|
+
<div class="mt-5 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
|
|
28
|
+
<button
|
|
29
|
+
type="button"
|
|
30
|
+
class="inline-flex items-center gap-3 px-4 py-2 text-sm font-semibold uppercase tracking-wide border border-zinc-700 text-zinc-300 hover:border-zinc-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed justify-center sm:w-auto"
|
|
31
|
+
disabled={loading}
|
|
32
|
+
onClick={onCancel}
|
|
33
|
+
>
|
|
34
|
+
{cancelText}
|
|
35
|
+
</button>
|
|
36
|
+
<button
|
|
37
|
+
type="button"
|
|
38
|
+
class={`inline-flex items-center gap-3 px-4 py-2 text-sm font-semibold uppercase tracking-wide transition-colors disabled:opacity-50 disabled:cursor-not-allowed justify-center sm:w-auto ${confirmVariant === 'danger' ? 'border border-red-800 text-red-400 hover:bg-red-950' : 'border border-zinc-700 text-zinc-300 hover:border-zinc-500'}`}
|
|
39
|
+
disabled={loading}
|
|
40
|
+
onClick={onConfirm}
|
|
41
|
+
>
|
|
42
|
+
{loading ? 'Processing...' : confirmText}
|
|
43
|
+
</button>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default ConfirmModal;
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
export const IconGoogle = (props) => (
|
|
2
|
+
<svg viewBox="0 0 24 24" {...props}>
|
|
3
|
+
<path
|
|
4
|
+
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
|
5
|
+
fill="#4285F4"
|
|
6
|
+
/>
|
|
7
|
+
<path
|
|
8
|
+
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
|
9
|
+
fill="#34A853"
|
|
10
|
+
/>
|
|
11
|
+
<path
|
|
12
|
+
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l3.66-2.84z"
|
|
13
|
+
fill="#FBBC05"
|
|
14
|
+
/>
|
|
15
|
+
<path
|
|
16
|
+
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
|
17
|
+
fill="#EA4335"
|
|
18
|
+
/>
|
|
19
|
+
</svg>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export const IconDashboard = (props) => (
|
|
23
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
24
|
+
<rect x="3" y="3" width="8" height="8" rx="2" fill="currentColor" />
|
|
25
|
+
<rect
|
|
26
|
+
x="13"
|
|
27
|
+
y="3"
|
|
28
|
+
width="8"
|
|
29
|
+
height="5"
|
|
30
|
+
rx="2"
|
|
31
|
+
fill="currentColor"
|
|
32
|
+
opacity="0.8"
|
|
33
|
+
/>
|
|
34
|
+
<rect x="13" y="10" width="8" height="11" rx="2" fill="currentColor" />
|
|
35
|
+
<rect
|
|
36
|
+
x="3"
|
|
37
|
+
y="13"
|
|
38
|
+
width="8"
|
|
39
|
+
height="8"
|
|
40
|
+
rx="2"
|
|
41
|
+
fill="currentColor"
|
|
42
|
+
opacity="0.8"
|
|
43
|
+
/>
|
|
44
|
+
</svg>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const IconKey = (props) => (
|
|
48
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
49
|
+
<circle cx="8" cy="12" r="4" stroke="currentColor" strokeWidth="2" />
|
|
50
|
+
<path
|
|
51
|
+
d="M12 12h9m-3 0v3m-3-3v2"
|
|
52
|
+
stroke="currentColor"
|
|
53
|
+
strokeWidth="2"
|
|
54
|
+
strokeLinecap="round"
|
|
55
|
+
/>
|
|
56
|
+
</svg>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const IconWallet = (props) => (
|
|
60
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
61
|
+
<rect
|
|
62
|
+
x="3"
|
|
63
|
+
y="6"
|
|
64
|
+
width="18"
|
|
65
|
+
height="12"
|
|
66
|
+
rx="3"
|
|
67
|
+
stroke="currentColor"
|
|
68
|
+
strokeWidth="2"
|
|
69
|
+
/>
|
|
70
|
+
<path d="M16 11h5v4h-5a2 2 0 0 1 0-4z" fill="currentColor" opacity="0.85" />
|
|
71
|
+
</svg>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
export const IconDocs = (props) => (
|
|
75
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
76
|
+
<path
|
|
77
|
+
d="M7 4h8l4 4v12H7a3 3 0 1 0 0-6h12"
|
|
78
|
+
stroke="currentColor"
|
|
79
|
+
strokeWidth="2"
|
|
80
|
+
strokeLinejoin="round"
|
|
81
|
+
/>
|
|
82
|
+
<path d="M15 4v4h4" stroke="currentColor" strokeWidth="2" />
|
|
83
|
+
</svg>
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
export const IconLogout = (props) => (
|
|
87
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
88
|
+
<path
|
|
89
|
+
d="M9 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h3"
|
|
90
|
+
stroke="currentColor"
|
|
91
|
+
strokeWidth="2"
|
|
92
|
+
strokeLinecap="round"
|
|
93
|
+
/>
|
|
94
|
+
<path
|
|
95
|
+
d="M13 16l4-4-4-4"
|
|
96
|
+
stroke="currentColor"
|
|
97
|
+
strokeWidth="2"
|
|
98
|
+
strokeLinecap="round"
|
|
99
|
+
strokeLinejoin="round"
|
|
100
|
+
/>
|
|
101
|
+
<path
|
|
102
|
+
d="M17 12H9"
|
|
103
|
+
stroke="currentColor"
|
|
104
|
+
strokeWidth="2"
|
|
105
|
+
strokeLinecap="round"
|
|
106
|
+
/>
|
|
107
|
+
</svg>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
export const IconMenu = (props) => (
|
|
111
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
112
|
+
<path
|
|
113
|
+
d="M4 7h16M4 12h16M4 17h16"
|
|
114
|
+
stroke="currentColor"
|
|
115
|
+
strokeWidth="2"
|
|
116
|
+
strokeLinecap="round"
|
|
117
|
+
/>
|
|
118
|
+
</svg>
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
export const IconCopy = (props) => (
|
|
122
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
123
|
+
<rect
|
|
124
|
+
x="9"
|
|
125
|
+
y="9"
|
|
126
|
+
width="11"
|
|
127
|
+
height="11"
|
|
128
|
+
rx="2"
|
|
129
|
+
stroke="currentColor"
|
|
130
|
+
strokeWidth="2"
|
|
131
|
+
/>
|
|
132
|
+
<path
|
|
133
|
+
d="M6 15H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"
|
|
134
|
+
stroke="currentColor"
|
|
135
|
+
strokeWidth="2"
|
|
136
|
+
strokeLinecap="round"
|
|
137
|
+
/>
|
|
138
|
+
</svg>
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
export const IconEdit = (props) => (
|
|
142
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
143
|
+
<path
|
|
144
|
+
d="M4 20h4l10-10-4-4L4 16v4z"
|
|
145
|
+
stroke="currentColor"
|
|
146
|
+
strokeWidth="2"
|
|
147
|
+
strokeLinejoin="round"
|
|
148
|
+
/>
|
|
149
|
+
<path
|
|
150
|
+
d="M12.5 7.5l4 4"
|
|
151
|
+
stroke="currentColor"
|
|
152
|
+
strokeWidth="2"
|
|
153
|
+
strokeLinecap="round"
|
|
154
|
+
/>
|
|
155
|
+
</svg>
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
export const IconTrash = (props) => (
|
|
159
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
160
|
+
<path
|
|
161
|
+
d="M4 7h16"
|
|
162
|
+
stroke="currentColor"
|
|
163
|
+
strokeWidth="2"
|
|
164
|
+
strokeLinecap="round"
|
|
165
|
+
/>
|
|
166
|
+
<path
|
|
167
|
+
d="M10 11v6M14 11v6"
|
|
168
|
+
stroke="currentColor"
|
|
169
|
+
strokeWidth="2"
|
|
170
|
+
strokeLinecap="round"
|
|
171
|
+
/>
|
|
172
|
+
<path
|
|
173
|
+
d="M6 7l1 12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-12"
|
|
174
|
+
stroke="currentColor"
|
|
175
|
+
strokeWidth="2"
|
|
176
|
+
strokeLinejoin="round"
|
|
177
|
+
/>
|
|
178
|
+
<path
|
|
179
|
+
d="M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"
|
|
180
|
+
stroke="currentColor"
|
|
181
|
+
strokeWidth="2"
|
|
182
|
+
/>
|
|
183
|
+
</svg>
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
export const IconRefresh = (props) => (
|
|
187
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
188
|
+
<path
|
|
189
|
+
d="M20 7v5h-5"
|
|
190
|
+
stroke="currentColor"
|
|
191
|
+
strokeWidth="2"
|
|
192
|
+
strokeLinecap="round"
|
|
193
|
+
strokeLinejoin="round"
|
|
194
|
+
/>
|
|
195
|
+
<path
|
|
196
|
+
d="M4 17v-5h5"
|
|
197
|
+
stroke="currentColor"
|
|
198
|
+
strokeWidth="2"
|
|
199
|
+
strokeLinecap="round"
|
|
200
|
+
strokeLinejoin="round"
|
|
201
|
+
/>
|
|
202
|
+
<path
|
|
203
|
+
d="M20 12a8 8 0 0 0-14-5M4 12a8 8 0 0 0 14 5"
|
|
204
|
+
stroke="currentColor"
|
|
205
|
+
strokeWidth="2"
|
|
206
|
+
strokeLinecap="round"
|
|
207
|
+
/>
|
|
208
|
+
</svg>
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
export const IconCheck = (props) => (
|
|
212
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
213
|
+
<path
|
|
214
|
+
d="M5 13l4 4L19 7"
|
|
215
|
+
stroke="currentColor"
|
|
216
|
+
strokeWidth="2"
|
|
217
|
+
strokeLinecap="round"
|
|
218
|
+
strokeLinejoin="round"
|
|
219
|
+
/>
|
|
220
|
+
</svg>
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
export const IconLogo = ({ fill = '#22c55e', className, ...props }) => (
|
|
224
|
+
<svg viewBox="0 0 362.05 512" className={className} {...props}>
|
|
225
|
+
<g>
|
|
226
|
+
<g data-name="Layer 2">
|
|
227
|
+
<path
|
|
228
|
+
d="M360.58 214.71a15 15 0 0 0-13.58-8.53H203.51l77.06-185.41A15 15 0 0 0 266.71 0H103.37A15 15 0 0 0 89 10.71L.63 306.6A15 15 0 0 0 15 325.9h138.6l-43.34 167.33a15 15 0 0 0 26.22 13.18l222.25-275.8a15 15 0 0 0 1.85-15.9z"
|
|
229
|
+
data-name="lighting bolt"
|
|
230
|
+
fill={fill}
|
|
231
|
+
></path>
|
|
232
|
+
</g>
|
|
233
|
+
</g>
|
|
234
|
+
</svg>
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
export const IconTelegram = (props) => (
|
|
238
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
239
|
+
<path
|
|
240
|
+
d="M21.5 4.5L18.8 19.6c-.2 1.1-.8 1.4-1.7.9l-4.8-3.5-2.3 2.2c-.2.3-.5.5-1 .5l.4-4.9 8.8-8c.4-.3-.1-.5-.5-.2L6.7 13 2 11.5c-1.1-.3-1.1-1.1.2-1.6L20.8 3c1-.4 1.8.2 1.7 1.5z"
|
|
241
|
+
fill="currentColor"
|
|
242
|
+
/>
|
|
243
|
+
</svg>
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
export const IconChevronLeft = (props) => (
|
|
247
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
248
|
+
<path
|
|
249
|
+
d="M15 6l-6 6 6 6"
|
|
250
|
+
stroke="currentColor"
|
|
251
|
+
strokeWidth="2"
|
|
252
|
+
strokeLinecap="round"
|
|
253
|
+
strokeLinejoin="round"
|
|
254
|
+
/>
|
|
255
|
+
</svg>
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
export const IconChevronRight = (props) => (
|
|
259
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
260
|
+
<path
|
|
261
|
+
d="M9 6l6 6-6 6"
|
|
262
|
+
stroke="currentColor"
|
|
263
|
+
strokeWidth="2"
|
|
264
|
+
strokeLinecap="round"
|
|
265
|
+
strokeLinejoin="round"
|
|
266
|
+
/>
|
|
267
|
+
</svg>
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
export const IconBank = (props) => (
|
|
271
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
272
|
+
<path
|
|
273
|
+
d="M3 9l9-5 9 5"
|
|
274
|
+
stroke="currentColor"
|
|
275
|
+
strokeWidth="2"
|
|
276
|
+
strokeLinecap="round"
|
|
277
|
+
strokeLinejoin="round"
|
|
278
|
+
/>
|
|
279
|
+
<path
|
|
280
|
+
d="M5 10v8M9 10v8M15 10v8M19 10v8"
|
|
281
|
+
stroke="currentColor"
|
|
282
|
+
strokeWidth="2"
|
|
283
|
+
strokeLinecap="round"
|
|
284
|
+
/>
|
|
285
|
+
<path
|
|
286
|
+
d="M3 20h18"
|
|
287
|
+
stroke="currentColor"
|
|
288
|
+
strokeWidth="2"
|
|
289
|
+
strokeLinecap="round"
|
|
290
|
+
/>
|
|
291
|
+
</svg>
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
export const IconCard = (props) => (
|
|
295
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
296
|
+
<rect
|
|
297
|
+
x="3"
|
|
298
|
+
y="5"
|
|
299
|
+
width="18"
|
|
300
|
+
height="14"
|
|
301
|
+
rx="3"
|
|
302
|
+
stroke="currentColor"
|
|
303
|
+
strokeWidth="2"
|
|
304
|
+
/>
|
|
305
|
+
<path d="M3 10h18" stroke="currentColor" strokeWidth="2" />
|
|
306
|
+
<path
|
|
307
|
+
d="M7 15h4"
|
|
308
|
+
stroke="currentColor"
|
|
309
|
+
strokeWidth="2"
|
|
310
|
+
strokeLinecap="round"
|
|
311
|
+
/>
|
|
312
|
+
</svg>
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
export const IconCoin = (props) => (
|
|
316
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
317
|
+
<circle cx="12" cy="12" r="8" stroke="currentColor" strokeWidth="2" />
|
|
318
|
+
<path
|
|
319
|
+
d="M12 8v8M9.5 10.5c0-1.1 1.1-2 2.5-2s2.5.9 2.5 2-1.1 2-2.5 2-2.5.9-2.5 2 1.1 2 2.5 2 2.5-.9 2.5-2"
|
|
320
|
+
stroke="currentColor"
|
|
321
|
+
strokeWidth="2"
|
|
322
|
+
strokeLinecap="round"
|
|
323
|
+
/>
|
|
324
|
+
</svg>
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
export const IconClock = (props) => (
|
|
328
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
329
|
+
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2" />
|
|
330
|
+
<path
|
|
331
|
+
d="M12 7v5l3 2"
|
|
332
|
+
stroke="currentColor"
|
|
333
|
+
strokeWidth="2"
|
|
334
|
+
strokeLinecap="round"
|
|
335
|
+
strokeLinejoin="round"
|
|
336
|
+
/>
|
|
337
|
+
</svg>
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
export const IconInfo = (props) => (
|
|
341
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
342
|
+
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2" />
|
|
343
|
+
<path
|
|
344
|
+
d="M12 11v5"
|
|
345
|
+
stroke="currentColor"
|
|
346
|
+
strokeWidth="2"
|
|
347
|
+
strokeLinecap="round"
|
|
348
|
+
/>
|
|
349
|
+
<circle cx="12" cy="8" r="1" fill="currentColor" />
|
|
350
|
+
</svg>
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
export const IconPlay = (props) => (
|
|
354
|
+
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
355
|
+
<path
|
|
356
|
+
d="M6 4l14 8-14 8V4z"
|
|
357
|
+
fill="currentColor"
|
|
358
|
+
/>
|
|
359
|
+
</svg>
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
export const IconEye = ({ off, ...props }) => (
|
|
363
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
|
|
364
|
+
{off ? (
|
|
365
|
+
<>
|
|
366
|
+
<path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94" />
|
|
367
|
+
<path d="M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19" />
|
|
368
|
+
<line x1="1" y1="1" x2="23" y2="23" />
|
|
369
|
+
</>
|
|
370
|
+
) : (
|
|
371
|
+
<>
|
|
372
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
|
373
|
+
<circle cx="12" cy="12" r="3" />
|
|
374
|
+
</>
|
|
375
|
+
)}
|
|
376
|
+
</svg>
|
|
377
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect } from 'preact/hooks';
|
|
2
|
+
import { useLocation } from 'preact-iso';
|
|
3
|
+
|
|
4
|
+
const RedirectRoute = ({ to }) => {
|
|
5
|
+
const { route } = useLocation();
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
route(to);
|
|
9
|
+
}, [route, to]);
|
|
10
|
+
|
|
11
|
+
return null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default RedirectRoute;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const SplashScreen = () => (
|
|
2
|
+
<div class="ui-page px-6 py-12">
|
|
3
|
+
<div class="ui-card flex items-center gap-4 p-8">
|
|
4
|
+
<div class="h-10 w-10 rounded-full border-4 border-[var(--color-border)] border-t-[var(--color-primary)] animate-spin" />
|
|
5
|
+
<div>
|
|
6
|
+
<p class="text-sm font-semibold text-[var(--color-text)]">
|
|
7
|
+
crewOS
|
|
8
|
+
</p>
|
|
9
|
+
<p class="text-xs text-[var(--color-muted)]">Loading workspace...</p>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default SplashScreen;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useEffect } from 'preact/hooks';
|
|
2
|
+
|
|
3
|
+
import { auth as authStore } from '../stores/auth.store';
|
|
4
|
+
import { getMe } from '../services/auth.service';
|
|
5
|
+
|
|
6
|
+
export const useAuth = () => {
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const check = async () => {
|
|
9
|
+
try {
|
|
10
|
+
const res = await getMe();
|
|
11
|
+
authStore.value = {
|
|
12
|
+
user: { authenticated: true },
|
|
13
|
+
initialized: true,
|
|
14
|
+
onboardingCompleted: res.data?.onboardingCompleted || false,
|
|
15
|
+
};
|
|
16
|
+
} catch {
|
|
17
|
+
localStorage.removeItem('crewos_token');
|
|
18
|
+
authStore.value = {
|
|
19
|
+
user: null,
|
|
20
|
+
initialized: true,
|
|
21
|
+
onboardingCompleted: false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
check();
|
|
27
|
+
}, []);
|
|
28
|
+
};
|