robodev 0.11.0 → 0.12.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/package.json +1 -1
- package/src/collect-files.test.ts +19 -0
- package/src/collect-files.ts +1 -0
- package/src/config.test.ts +26 -0
- package/src/config.ts +34 -5
- package/src/emit-starter.test.ts +54 -0
- package/src/emit-starter.ts +47 -13
- package/src/index.ts +37 -4
- package/templates/auth-chat/package.json +1 -1
- package/templates/auth-chat/src/main.tsx +1 -1
- package/templates/backend/package.json +1 -1
- package/templates/catalog.json +1 -1
- package/templates/empty/package.json +1 -1
- package/templates/space/.config/local.spa.template.yml +27 -0
- package/templates/space/.oxlint-base.json +29 -0
- package/templates/space/.oxlintrc.json +78 -0
- package/templates/space/.rulesync/rules/frontend-api-boundary.md +36 -0
- package/templates/space/.rulesync/rules/frontend-component-structure.md +38 -0
- package/templates/space/.rulesync/rules/frontend-forms.md +32 -0
- package/templates/space/.rulesync/rules/frontend-notifications.md +24 -0
- package/templates/space/.rulesync/rules/frontend-povio-components.md +42 -0
- package/templates/space/.rulesync/rules/frontend-povio-ui.md +45 -0
- package/templates/space/.rulesync/rules/frontend-query-autocomplete.md +29 -0
- package/templates/space/.rulesync/rules/frontend-tables-and-lists.md +34 -0
- package/templates/space/.rulesync/rules/frontend-translations.md +26 -0
- package/templates/space/.rulesync/rules/project-overview.md +32 -0
- package/templates/space/.rulesync/rules/robodev-api.md +30 -0
- package/templates/space/.rulesync/rules/robodev-auth.md +40 -0
- package/templates/space/.rulesync/rules/robodev-database.md +22 -0
- package/templates/space/.rulesync/rules/role-based-app-structure.md +36 -0
- package/templates/space/.rulesync/skills/media-feature/SKILL.md +21 -0
- package/templates/space/.rulesync/skills/povio-ui-styling/SKILL.md +208 -0
- package/templates/space/.rulesync/skills/povio-ui-styling/agents/openai.yaml +4 -0
- package/templates/space/.rulesync/skills/robodev-api-route/SKILL.md +13 -0
- package/templates/space/.rulesync/skills/robodev-table/SKILL.md +12 -0
- package/templates/space/README.md +26 -7
- package/templates/space/api/_lib.ts +359 -0
- package/templates/space/api/aliens/labels.ts +19 -0
- package/templates/space/api/files/presigned-url.ts +48 -0
- package/templates/space/api/files/upload.ts +29 -0
- package/templates/space/api/planets/[id]/like.ts +36 -0
- package/templates/space/api/planets/[id].ts +56 -13
- package/templates/space/api/planets/paginate.ts +36 -0
- package/templates/space/api/planets.ts +52 -44
- package/templates/space/apps/fe/index.html +24 -0
- package/templates/space/apps/fe/openapi-codegen.config.ts +37 -0
- package/templates/space/apps/fe/package.json +82 -0
- package/templates/space/apps/fe/public/apple-touch-icon.png +0 -0
- package/templates/space/apps/fe/public/favicon-96x96.png +0 -0
- package/templates/space/apps/fe/public/favicon.ico +0 -0
- package/templates/space/apps/fe/public/favicon.svg +3 -0
- package/templates/space/apps/fe/public/site.webmanifest +21 -0
- package/templates/space/apps/fe/public/web-app-manifest-192x192.png +0 -0
- package/templates/space/apps/fe/public/web-app-manifest-512x512.png +0 -0
- package/templates/space/apps/fe/src/assets/fonts/GeneralSans-Bold.otf +0 -0
- package/templates/space/apps/fe/src/assets/fonts/GeneralSans-Medium.otf +0 -0
- package/templates/space/apps/fe/src/assets/fonts/GeneralSans-Regular.otf +0 -0
- package/templates/space/apps/fe/src/assets/fonts/GeneralSans-Semibold.otf +0 -0
- package/templates/space/apps/fe/src/assets/locales/en/translation.json +301 -0
- package/templates/space/apps/fe/src/assets/locales/sl/translation.json +301 -0
- package/templates/space/apps/fe/src/clients/app-rest-client.ts +15 -0
- package/templates/space/apps/fe/src/clients/auth-token-store.ts +101 -0
- package/templates/space/apps/fe/src/clients/rest/app-error-handler.ts +31 -0
- package/templates/space/apps/fe/src/clients/rest/interceptors/authorization-header.interceptor.ts +15 -0
- package/templates/space/apps/fe/src/clients/rest/interceptors/refresh-token.interceptor.ts +37 -0
- package/templates/space/apps/fe/src/clients/rest/interceptors/response.interceptor.ts +17 -0
- package/templates/space/apps/fe/src/components/404.tsx +18 -0
- package/templates/space/apps/fe/src/components/features/auth/AuthBrandPanel.tsx +60 -0
- package/templates/space/apps/fe/src/components/features/auth/AuthLayout.tsx +23 -0
- package/templates/space/apps/fe/src/components/features/auth/LoginPage.tsx +111 -0
- package/templates/space/apps/fe/src/components/features/auth/RegisterPage.tsx +143 -0
- package/templates/space/apps/fe/src/components/features/home/HomePage.tsx +21 -0
- package/templates/space/apps/fe/src/components/features/planets/details/PlanetDetailsPage.tsx +139 -0
- package/templates/space/apps/fe/src/components/features/planets/details/PlanetEditPage.tsx +266 -0
- package/templates/space/apps/fe/src/components/features/planets/feed/PlanetFeedCard.tsx +131 -0
- package/templates/space/apps/fe/src/components/features/planets/feed/PlanetsFeedPage.tsx +119 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetCard.tsx +89 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetCreateModal.tsx +179 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsFilters.css +3 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsFilters.tsx +73 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsGridPage.tsx +51 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsInfiniteTablePage.tsx +79 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsPage.tsx +65 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsTablePage.tsx +72 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsTableSummary.tsx +29 -0
- package/templates/space/apps/fe/src/components/features/planets/list/PlanetsViewTabs.tsx +79 -0
- package/templates/space/apps/fe/src/components/features/planets/list/table/PlanetsTable.tsx +30 -0
- package/templates/space/apps/fe/src/components/features/planets/list/table/PlanetsTableActions.tsx +64 -0
- package/templates/space/apps/fe/src/components/features/planets/list/table/PlanetsTableInfinite.tsx +36 -0
- package/templates/space/apps/fe/src/components/features/planets/list/table/planetsTableColumns.tsx +72 -0
- package/templates/space/apps/fe/src/components/features/planets/list/table/usePlanetTableFilters.tsx +102 -0
- package/templates/space/apps/fe/src/components/features/profile/ProfilePage.tsx +96 -0
- package/templates/space/apps/fe/src/components/googleAnalytics/GoogleAnalytics.tsx +35 -0
- package/templates/space/apps/fe/src/components/layout/AppLayout.tsx +19 -0
- package/templates/space/apps/fe/src/components/layout/app-header/AppHeader.tsx +93 -0
- package/templates/space/apps/fe/src/components/layout/app-header/MobileNavigation.tsx +53 -0
- package/templates/space/apps/fe/src/components/layout/app-header/NavLink.tsx +29 -0
- package/templates/space/apps/fe/src/components/shared/branding/BrandLogo.tsx +13 -0
- package/templates/space/apps/fe/src/components/shared/error/ErrorFallback.tsx +43 -0
- package/templates/space/apps/fe/src/components/shared/error/ErrorText.tsx +20 -0
- package/templates/space/apps/fe/src/components/shared/error/NotFound.tsx +36 -0
- package/templates/space/apps/fe/src/components/shared/forms/RequiredLabel.tsx +21 -0
- package/templates/space/apps/fe/src/components/shared/forms/RowInputWrapper.tsx +50 -0
- package/templates/space/apps/fe/src/components/shared/head/AppHead.tsx +32 -0
- package/templates/space/apps/fe/src/components/shared/head/DefaultAppHead.tsx +34 -0
- package/templates/space/apps/fe/src/components/shared/layout/LoadingState.tsx +9 -0
- package/templates/space/apps/fe/src/components/shared/layout/ThinPageWrapper.tsx +5 -0
- package/templates/space/apps/fe/src/components/shared/page/PageHeader.tsx +69 -0
- package/templates/space/apps/fe/src/components/shared/ui/Card.tsx +60 -0
- package/templates/space/apps/fe/src/components/shared/ui/GoogleLoginButton.tsx +19 -0
- package/templates/space/apps/fe/src/components/shared/ui/RequiredLabel.tsx +22 -0
- package/templates/space/apps/fe/src/components/shared/ui/TableActions.tsx +22 -0
- package/templates/space/apps/fe/src/config/app.config.ts +35 -0
- package/templates/space/apps/fe/src/config/i18n.ts +43 -0
- package/templates/space/apps/fe/src/config/inits/a11y.ts +14 -0
- package/templates/space/apps/fe/src/config/inits/logger.ts +7 -0
- package/templates/space/apps/fe/src/config/inits/sentry.ts +21 -0
- package/templates/space/apps/fe/src/config/jwt.config.ts +2 -0
- package/templates/space/apps/fe/src/config/query.config.ts +20 -0
- package/templates/space/apps/fe/src/hooks/useAuth.ts +5 -0
- package/templates/space/apps/fe/src/main.tsx +52 -0
- package/templates/space/apps/fe/src/pages/(guest)/login.tsx +23 -0
- package/templates/space/apps/fe/src/pages/(guest)/register.tsx +23 -0
- package/templates/space/apps/fe/src/pages/(guest)/route.tsx +18 -0
- package/templates/space/apps/fe/src/pages/(private)/index.tsx +23 -0
- package/templates/space/apps/fe/src/pages/(private)/planets/$id/edit.tsx +53 -0
- package/templates/space/apps/fe/src/pages/(private)/planets/$id/index.tsx +41 -0
- package/templates/space/apps/fe/src/pages/(private)/planets/index.tsx +24 -0
- package/templates/space/apps/fe/src/pages/(private)/planets-feed.tsx +23 -0
- package/templates/space/apps/fe/src/pages/(private)/profile.tsx +23 -0
- package/templates/space/apps/fe/src/pages/(private)/route.tsx +18 -0
- package/templates/space/apps/fe/src/pages/(public)/auth.tsx +37 -0
- package/templates/space/apps/fe/src/pages/(public)/route.tsx +9 -0
- package/templates/space/apps/fe/src/pages/__root.tsx +164 -0
- package/templates/space/apps/fe/src/providers/AppErrorBoundary.tsx +10 -0
- package/templates/space/apps/fe/src/providers/OpenApiRuntimeProvider.tsx +31 -0
- package/templates/space/apps/fe/src/providers/index.tsx +44 -0
- package/templates/space/apps/fe/src/providers/jwt.provider.tsx +95 -0
- package/templates/space/apps/fe/src/routeTree.gen.ts +309 -0
- package/templates/space/apps/fe/src/styles/base.css +103 -0
- package/templates/space/apps/fe/src/styles/fonts/fonts.tsx +10 -0
- package/templates/space/apps/fe/src/styles/fonts/general-sans.css +31 -0
- package/templates/space/apps/fe/src/styles/globals.css +28 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/button.override.ts +536 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/checkbox.override.ts +71 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/input.override.ts +252 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/label.override.ts +91 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/modal.override.ts +57 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/radio.override.ts +46 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/table.override.ts +104 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/tag.override.ts +66 -0
- package/templates/space/apps/fe/src/styles/overrides/defaults/typography.override.ts +115 -0
- package/templates/space/apps/fe/src/styles/overrides/outline.clsx.ts +10 -0
- package/templates/space/apps/fe/src/styles/overrides/uiOverrides.override.ts +60 -0
- package/templates/space/apps/fe/src/styles/theme.css +2177 -0
- package/templates/space/apps/fe/src/types/i18next.d.ts +12 -0
- package/templates/space/apps/fe/src/types/table.d.ts +17 -0
- package/templates/space/apps/fe/src/types/ui.d.ts +26 -0
- package/templates/space/apps/fe/src/types/vite-env.d.ts +20 -0
- package/templates/space/apps/fe/src/utils/date.utils.ts +17 -0
- package/templates/space/apps/fe/src/utils/image-fallback.ts +9 -0
- package/templates/space/apps/fe/src/utils/media-upload.ts +63 -0
- package/templates/space/apps/fe/src/utils/number.utils.ts +12 -0
- package/templates/space/apps/fe/src/utils/string.utils.ts +5 -0
- package/templates/space/apps/fe/src/vite-env.d.ts +1 -0
- package/templates/space/apps/fe/tsconfig.app.json +32 -0
- package/templates/space/apps/fe/tsconfig.json +9 -0
- package/templates/space/apps/fe/tsconfig.node.json +31 -0
- package/templates/space/apps/fe/vite.config.ts +94 -0
- package/templates/space/database.ts +33 -13
- package/templates/space/openapi.json +1819 -0
- package/templates/space/oxfmt.config.js +23 -0
- package/templates/space/package.json +6 -13
- package/templates/space/rulesync.jsonc +18 -0
- package/templates/space/tsconfig.json +2 -4
- package/templates/space/api/health.ts +0 -7
- package/templates/space/api/launch.ts +0 -29
- package/templates/space/api/me.ts +0 -14
- package/templates/space/api/motto.ts +0 -9
- package/templates/space/api/rockets.ts +0 -43
- package/templates/space/index.html +0 -138
- package/templates/space/src/main.tsx +0 -229
- package/templates/space/vite.config.ts +0 -7
|
@@ -1,60 +1,68 @@
|
|
|
1
|
-
/** GET/POST /api/planets — list (seeds sample rows on first GET) and create planets. */
|
|
2
|
-
import { planets, rockets } from "../database";
|
|
3
1
|
import { defineApi, z } from "@robodev-ai/sdk";
|
|
2
|
+
import {
|
|
3
|
+
ensureSeed,
|
|
4
|
+
enrichOne,
|
|
5
|
+
enrichPlanet,
|
|
6
|
+
fail,
|
|
7
|
+
filterPlanetRows,
|
|
8
|
+
loadLookups,
|
|
9
|
+
parseFilter,
|
|
10
|
+
planets,
|
|
11
|
+
sortPlanets,
|
|
12
|
+
validateAlien,
|
|
13
|
+
validateImage,
|
|
14
|
+
} from "./_lib";
|
|
4
15
|
|
|
5
|
-
const
|
|
6
|
-
const MARS = "22222222-2222-2222-2222-222222222222";
|
|
7
|
-
const KEPLER = "33333333-3333-3333-3333-333333333333";
|
|
8
|
-
const VOYAGER = "44444444-4444-4444-4444-444444444444";
|
|
9
|
-
const ODYSSEY = "55555555-5555-5555-5555-555555555555";
|
|
16
|
+
const imageRequest = z.object({ id: z.string() }).nullish();
|
|
10
17
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
const planetBody = z.object({
|
|
19
|
+
name: z.string().min(1),
|
|
20
|
+
alienId: z.string().nullish(),
|
|
21
|
+
discoveryDate: z.string().nullish(),
|
|
22
|
+
description: z.string().nullish(),
|
|
23
|
+
image: imageRequest,
|
|
16
24
|
});
|
|
17
25
|
|
|
18
26
|
export const get = defineApi({
|
|
19
|
-
|
|
20
|
-
handler: async (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
]);
|
|
33
|
-
} catch {
|
|
34
|
-
// First request won the seed race.
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
const rows = await db.select().from(planets);
|
|
38
|
-
return Planet.array().parse(rows);
|
|
27
|
+
auth: "required",
|
|
28
|
+
handler: async (ctx) => {
|
|
29
|
+
await ensureSeed(ctx.db, ctx.user!.id);
|
|
30
|
+
const rows = await ctx.db.select().from(planets);
|
|
31
|
+
const lookups = await loadLookups(ctx.db);
|
|
32
|
+
const query = ctx.query as Record<string, unknown>;
|
|
33
|
+
const filtered = filterPlanetRows(rows, lookups.alienById, parseFilter(query));
|
|
34
|
+
const order = typeof query.order === "string" ? query.order : undefined;
|
|
35
|
+
return Promise.all(
|
|
36
|
+
sortPlanets(filtered, order).map((row) =>
|
|
37
|
+
enrichPlanet(ctx, row, ctx.user!.id, lookups.alienById, lookups.likes),
|
|
38
|
+
),
|
|
39
|
+
);
|
|
39
40
|
},
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
export const post = defineApi({
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
44
|
+
auth: "required",
|
|
45
|
+
body: planetBody,
|
|
46
|
+
handler: async (ctx) => {
|
|
47
|
+
const alienId = ctx.body.alienId || null;
|
|
48
|
+
if (alienId && !(await validateAlien(ctx.db, alienId))) {
|
|
49
|
+
return fail(404, "Alien not found");
|
|
50
|
+
}
|
|
51
|
+
const image = await validateImage(ctx.db, ctx.body.image, ctx.user!.id);
|
|
52
|
+
if (image && "error" in image) return image.error;
|
|
53
|
+
|
|
54
|
+
const [row] = await ctx.db
|
|
51
55
|
.insert(planets)
|
|
52
56
|
.values({
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
userId: ctx.user!.id,
|
|
58
|
+
creatorName: ctx.user!.name ?? ctx.user!.email,
|
|
59
|
+
alienId,
|
|
60
|
+
discoveryDate: ctx.body.discoveryDate ? new Date(ctx.body.discoveryDate) : null,
|
|
61
|
+
name: ctx.body.name,
|
|
62
|
+
description: ctx.body.description ?? null,
|
|
63
|
+
imageId: image?.id ?? null,
|
|
56
64
|
})
|
|
57
65
|
.returning();
|
|
58
|
-
return
|
|
66
|
+
return enrichOne(ctx, row!, ctx.user!.id);
|
|
59
67
|
},
|
|
60
68
|
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link
|
|
6
|
+
rel="icon"
|
|
7
|
+
type="image/svg+xml"
|
|
8
|
+
href="/favicon.svg"
|
|
9
|
+
/>
|
|
10
|
+
<meta
|
|
11
|
+
name="viewport"
|
|
12
|
+
content="width=device-width, initial-scale=1.0"
|
|
13
|
+
/>
|
|
14
|
+
<title>Space</title>
|
|
15
|
+
</head>
|
|
16
|
+
|
|
17
|
+
<body class="bg-elevation-fill-default-2 text-text-default-1">
|
|
18
|
+
<div id="app"></div>
|
|
19
|
+
<script
|
|
20
|
+
type="module"
|
|
21
|
+
src="/src/main.tsx"
|
|
22
|
+
></script>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* oxlint-disable import/no-nodejs-modules */
|
|
2
|
+
import type { OpenAPICodegenConfig } from "@povio/openapi-codegen-cli";
|
|
3
|
+
import { resolveConfigSync } from "@povio/resolve-config";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
|
|
6
|
+
const COMPACT_OPENAPI_INPUT = "../../openapi.json";
|
|
7
|
+
const repoRoot = resolve(process.cwd(), "../..");
|
|
8
|
+
const env = resolveConfigSync({ cwd: repoRoot, module: "spa", target: "resolved" }) as Record<
|
|
9
|
+
string,
|
|
10
|
+
string | undefined
|
|
11
|
+
>;
|
|
12
|
+
|
|
13
|
+
function resolveLiveOpenApiInput(apiUrl = env.VITE_PUBLIC_API_URL) {
|
|
14
|
+
return `${apiUrl?.replace(/\/+$/, "")}/openapi.json`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function resolveOpenApiInput() {
|
|
18
|
+
return process.env.OPENAPI_INPUT || (process.env.OPENAPI_LIVE === "true" ? resolveLiveOpenApiInput() : COMPACT_OPENAPI_INPUT);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const config: OpenAPICodegenConfig = {
|
|
22
|
+
input: resolveOpenApiInput(),
|
|
23
|
+
output: "src/openapi",
|
|
24
|
+
tsPath: "@/openapi",
|
|
25
|
+
restClientImportPath: "@/clients/app-rest-client",
|
|
26
|
+
clearOutput: true,
|
|
27
|
+
excludeRedundantZodSchemas: false,
|
|
28
|
+
checkAcl: false,
|
|
29
|
+
acl: false,
|
|
30
|
+
replaceOptionalWithNullish: true,
|
|
31
|
+
infiniteQueries: true,
|
|
32
|
+
mutationDefaultOnError: true,
|
|
33
|
+
modelsInCommon: true,
|
|
34
|
+
axiosRequestConfig: true,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default config;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fe",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Space starter frontend",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "bunx --bun vite",
|
|
9
|
+
"build": "bunx --bun vite build",
|
|
10
|
+
"clean": "rimraf dist src/openapi",
|
|
11
|
+
"lint": "oxlint --type-aware . ../../api ../../database.ts --fix",
|
|
12
|
+
"lint:check": "oxlint --type-aware . ../../api ../../database.ts --quiet",
|
|
13
|
+
"format": "oxfmt -c \"../../oxfmt.config.js\" . ../../api ../../database.ts",
|
|
14
|
+
"format:check": "oxfmt -c \"../../oxfmt.config.js\" --check . ../../api ../../database.ts",
|
|
15
|
+
"ts:check": "tsc -b --noEmit",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"check": "bun ts:check && bun lint:check && bun format:check",
|
|
18
|
+
"openapi:gen": "openapi-codegen generate && oxfmt -c \"../../oxfmt.config.js\" ./src/openapi",
|
|
19
|
+
"openapi:check": "openapi-codegen check"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@casl/ability": "^6.8.1",
|
|
23
|
+
"@casl/react": "^5.0.1",
|
|
24
|
+
"@fontsource-variable/geist": "^5.2.8",
|
|
25
|
+
"@fontsource-variable/inter": "^5.2.8",
|
|
26
|
+
"@internationalized/date": "^3.11.0",
|
|
27
|
+
"@povio/openapi-codegen-cli": "3.1.0",
|
|
28
|
+
"@povio/resolve-config": "1.3.0",
|
|
29
|
+
"@povio/ui": "3.4.0-rc.12",
|
|
30
|
+
"@sentry/react": "^10.38.0",
|
|
31
|
+
"@tanstack/devtools-vite": "^0.3.11",
|
|
32
|
+
"@tanstack/react-devtools": "^0.8.1",
|
|
33
|
+
"@tanstack/react-form": "^1.33.2",
|
|
34
|
+
"@tanstack/react-query": "^5.90.21",
|
|
35
|
+
"@tanstack/react-query-devtools": "~5.90.0",
|
|
36
|
+
"@tanstack/react-router": "^1.136.8",
|
|
37
|
+
"@tanstack/react-router-devtools": "^1.136.8",
|
|
38
|
+
"@tanstack/react-table": "^8.21.3",
|
|
39
|
+
"@tanstack/router-core": "^1.136.8",
|
|
40
|
+
"@tanstack/router-plugin": "^1.136.8",
|
|
41
|
+
"axios": "^1.13.2",
|
|
42
|
+
"class-variance-authority": "^0.7.1",
|
|
43
|
+
"clsx": "^2.1.1",
|
|
44
|
+
"i18next": "^25.7.3",
|
|
45
|
+
"loglevel": "^1.9.2",
|
|
46
|
+
"lucide-react": "^1.28.0",
|
|
47
|
+
"luxon": "^3.7.2",
|
|
48
|
+
"react": "19.2.4",
|
|
49
|
+
"react-aria": "^3.46.0",
|
|
50
|
+
"react-aria-components": "^1.15.1",
|
|
51
|
+
"react-dom": "19.2.4",
|
|
52
|
+
"react-i18next": "^16.5.1",
|
|
53
|
+
"web-vitals": "^5.1.0",
|
|
54
|
+
"zod": "^4.4.3",
|
|
55
|
+
"zustand": "^5.0.9"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@axe-core/react": "^4.11.0",
|
|
59
|
+
"@povio/react-scan": "0.0.0",
|
|
60
|
+
"@povio/vite-plugin-react-scan": "0.0.2",
|
|
61
|
+
"@tailwindcss/vite": "^4.2.1",
|
|
62
|
+
"@types/luxon": "^3.7.1",
|
|
63
|
+
"@types/node": "^24.10.9",
|
|
64
|
+
"@types/react": "^19.2.7",
|
|
65
|
+
"@types/react-dom": "^19.2.3",
|
|
66
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
67
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
68
|
+
"babel-plugin-react-compiler": "1.0.0",
|
|
69
|
+
"oxfmt": "^0.45.0",
|
|
70
|
+
"oxlint": "1.60.0",
|
|
71
|
+
"oxlint-tsgolint": "0.21.0",
|
|
72
|
+
"react-icons-sprite": "^1.1.1",
|
|
73
|
+
"rimraf": "^6.1.2",
|
|
74
|
+
"tailwindcss": "^4.2.4",
|
|
75
|
+
"tailwindcss-react-aria-components": "^2.1.0",
|
|
76
|
+
"tsx": "^4.22.1",
|
|
77
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
78
|
+
"vite": "^8.0.0",
|
|
79
|
+
"vite-plugin-devtools-json": "^1.0.0",
|
|
80
|
+
"vitest": "^3.2.4"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="239.36" height="239.36"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="239.36" height="239.36"><svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 239.36 239.36"><defs><style>.cls-1{fill:#3c60ad;}.cls-2{fill:none;}.cls-3{clip-path:url(#clip-path);}.cls-4{mask:url(#mask);}.cls-5{fill:#fff;}</style><clipPath id="clip-path"><rect class="cls-2" width="239.36" height="239.36"></rect></clipPath><mask id="mask" x="0" y="0" width="239.36" height="239.36" maskUnits="userSpaceOnUse"><g id="mask0_21778_2258" data-name="mask0 21778 2258"><path class="cls-1" d="M0,29.92A29.93,29.93,0,0,1,29.92,0H209.44a29.93,29.93,0,0,1,29.92,29.92V209.44a29.93,29.93,0,0,1-29.92,29.92H29.92A29.93,29.93,0,0,1,0,209.44Z"></path></g></mask></defs><g class="cls-3"><g class="cls-4"><path class="cls-5" d="M0,29.92A29.93,29.93,0,0,1,29.92,0H209.44a29.93,29.93,0,0,1,29.92,29.92V209.44a29.93,29.93,0,0,1-29.92,29.92H29.92A29.93,29.93,0,0,1,0,209.44Z"></path><path d="M119.8,49.55c26.68,0,48.41,22.8,48.5,50.63,0,28.18-21.73,51.06-48.5,51.06A46.64,46.64,0,0,1,83.31,133.4v56.54h-12V100.27C71.29,72.35,93,49.55,119.8,49.55Zm0,12.29c-20.15,0-36.49,17.22-36.49,38.43,0,21.46,16.34,39,36.49,39s36.39-17.5,36.48-39C156.28,79.06,139.94,61.84,119.8,61.84Z"></path></g></g></svg></svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
|
|
2
|
+
@media (prefers-color-scheme: dark) { :root { filter: none; } }
|
|
3
|
+
</style></svg>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Povio",
|
|
3
|
+
"short_name": "Povio",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "/web-app-manifest-192x192.png",
|
|
7
|
+
"sizes": "192x192",
|
|
8
|
+
"type": "image/png",
|
|
9
|
+
"purpose": "maskable"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"src": "/web-app-manifest-512x512.png",
|
|
13
|
+
"sizes": "512x512",
|
|
14
|
+
"type": "image/png",
|
|
15
|
+
"purpose": "maskable"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"theme_color": "#ffffff",
|
|
19
|
+
"background_color": "#ffffff",
|
|
20
|
+
"display": "standalone"
|
|
21
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
{
|
|
2
|
+
"appName": "Tiny Template",
|
|
3
|
+
"appDescription": "A template for building web applications",
|
|
4
|
+
"shared": {
|
|
5
|
+
"notFound": {
|
|
6
|
+
"head": {
|
|
7
|
+
"title": "Page not found",
|
|
8
|
+
"description": "The page you are looking for doesn't exist."
|
|
9
|
+
},
|
|
10
|
+
"heading": "Page not found",
|
|
11
|
+
"subheading": "The page you are looking for doesn't exist.",
|
|
12
|
+
"homeBtn": "Go to home"
|
|
13
|
+
},
|
|
14
|
+
"errorFallback": {
|
|
15
|
+
"heading": "Something went wrong",
|
|
16
|
+
"subheading": "Error: {{error}}",
|
|
17
|
+
"retryBtn": "Try again"
|
|
18
|
+
},
|
|
19
|
+
"apiErrors": {
|
|
20
|
+
"requestFailed": "Request failed: {{error}}",
|
|
21
|
+
"unknown": "An unknown error occurred."
|
|
22
|
+
},
|
|
23
|
+
"seedData": {
|
|
24
|
+
"actionButton": "Reset seed data",
|
|
25
|
+
"confirmation": {
|
|
26
|
+
"heading": "Reset seed data?",
|
|
27
|
+
"description": "This will reset all local data to the initial seed state.",
|
|
28
|
+
"confirm": "Reset",
|
|
29
|
+
"cancel": "Cancel"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"actions": {
|
|
33
|
+
"back": "Back"
|
|
34
|
+
},
|
|
35
|
+
"fakeMailbox": {
|
|
36
|
+
"title": "Fake mailbox",
|
|
37
|
+
"open": "Open fake mailbox",
|
|
38
|
+
"close": "Close fake mailbox",
|
|
39
|
+
"empty": "No emails yet.",
|
|
40
|
+
"from": "From",
|
|
41
|
+
"to": "To",
|
|
42
|
+
"cc": "Cc",
|
|
43
|
+
"bcc": "Bcc",
|
|
44
|
+
"replyTo": "Reply to",
|
|
45
|
+
"openPopup": "Open popup",
|
|
46
|
+
"popupBlocked": {
|
|
47
|
+
"heading": "Email popup was blocked",
|
|
48
|
+
"description": "Your browser blocked the automatic email window. Allow popups for this site or open this message now.",
|
|
49
|
+
"open": "Open email",
|
|
50
|
+
"cancel": "Keep unread"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"auth": {
|
|
55
|
+
"wrapper": {
|
|
56
|
+
"title": "Administration portal",
|
|
57
|
+
"description": "Tiny",
|
|
58
|
+
"watermark": "© {{year}} Tiny • Developed and maintained by Povio"
|
|
59
|
+
},
|
|
60
|
+
"shared": {
|
|
61
|
+
"errors": {
|
|
62
|
+
"invalidCredentials": "Invalid email or password.",
|
|
63
|
+
"userAlreadyExists": "An account with this email already exists.",
|
|
64
|
+
"identityNotFound": "We could not find this account.",
|
|
65
|
+
"notConfirmed": "This account has not been confirmed yet."
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"login": {
|
|
69
|
+
"head": {
|
|
70
|
+
"title": "Login",
|
|
71
|
+
"description": "Login to your account"
|
|
72
|
+
},
|
|
73
|
+
"form": {
|
|
74
|
+
"title": "Login",
|
|
75
|
+
"email": "Email",
|
|
76
|
+
"emailPlaceholder": "Enter your email",
|
|
77
|
+
"password": "Password",
|
|
78
|
+
"passwordPlaceholder": "Enter your password",
|
|
79
|
+
"submit": "Login",
|
|
80
|
+
"submitLoading": "Logging in...",
|
|
81
|
+
"demoLogin": "Login as demo user",
|
|
82
|
+
"noAccount": "Don't have an account?",
|
|
83
|
+
"registerLink": "Register",
|
|
84
|
+
"loginFailed": "Login failed",
|
|
85
|
+
"resetSeedData": "Reset seed data"
|
|
86
|
+
},
|
|
87
|
+
"confirmations": {
|
|
88
|
+
"resetSeed": {
|
|
89
|
+
"heading": "Reset seed data?",
|
|
90
|
+
"description": "This will reset all local data to the initial seed state.",
|
|
91
|
+
"confirm": "Reset",
|
|
92
|
+
"cancel": "Cancel"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"register": {
|
|
97
|
+
"head": {
|
|
98
|
+
"title": "Register",
|
|
99
|
+
"description": "Create a new account"
|
|
100
|
+
},
|
|
101
|
+
"form": {
|
|
102
|
+
"title": "Register",
|
|
103
|
+
"description": "Create a new account",
|
|
104
|
+
"email": "Email",
|
|
105
|
+
"emailPlaceholder": "Enter your email",
|
|
106
|
+
"name": "Name",
|
|
107
|
+
"namePlaceholder": "Enter your name",
|
|
108
|
+
"password": "Password",
|
|
109
|
+
"passwordPlaceholder": "Enter your password",
|
|
110
|
+
"confirmPassword": "Confirm password",
|
|
111
|
+
"confirmPasswordPlaceholder": "Confirm your password",
|
|
112
|
+
"confirmPasswordRequired": "Confirm password is required",
|
|
113
|
+
"passwordsDoNotMatch": "Passwords do not match",
|
|
114
|
+
"passwordRequirements": "Password must be at least 12 characters long.",
|
|
115
|
+
"submit": "Register",
|
|
116
|
+
"registrationFailed": "Registration failed",
|
|
117
|
+
"hasAccount": "Already have an account?",
|
|
118
|
+
"loginLink": "Login"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"setPassword": {
|
|
122
|
+
"form": {
|
|
123
|
+
"title": "Set your password",
|
|
124
|
+
"welcome": "Welcome, {{firstName}} {{lastName}}. Please set your password to complete your account.",
|
|
125
|
+
"tokenNote": "Enter the invitation token you received by email.",
|
|
126
|
+
"token": "Invitation token",
|
|
127
|
+
"tokenPlaceholder": "Enter your invitation token",
|
|
128
|
+
"tokenChecking": "Checking token...",
|
|
129
|
+
"tokenError": "{{error}}",
|
|
130
|
+
"invalidToken": "Invalid or expired token",
|
|
131
|
+
"email": "Email",
|
|
132
|
+
"password": "Password",
|
|
133
|
+
"passwordPlaceholder": "Enter your password",
|
|
134
|
+
"confirmPassword": "Confirm password",
|
|
135
|
+
"confirmPasswordPlaceholder": "Confirm your password",
|
|
136
|
+
"passwordRequirements": "Password must be at least 8 characters long.",
|
|
137
|
+
"submit": "Set password",
|
|
138
|
+
"setPasswordFailed": "Setting password failed",
|
|
139
|
+
"hasPassword": "Already have a password?",
|
|
140
|
+
"loginLink": "Login"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"layout": {
|
|
145
|
+
"header": {
|
|
146
|
+
"logo": "Tiny",
|
|
147
|
+
"openMenu": "Open menu",
|
|
148
|
+
"closeMenu": "Close menu",
|
|
149
|
+
"nav": {
|
|
150
|
+
"home": "Home",
|
|
151
|
+
"planets": "Planets",
|
|
152
|
+
"planetsFeed": "Planets feed"
|
|
153
|
+
},
|
|
154
|
+
"profile": "Profile",
|
|
155
|
+
"logout": "Logout"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"home": {
|
|
159
|
+
"head": {
|
|
160
|
+
"title": "Home",
|
|
161
|
+
"description": "Welcome to the app!"
|
|
162
|
+
},
|
|
163
|
+
"title": "Home",
|
|
164
|
+
"message": "Welcome to the app!"
|
|
165
|
+
},
|
|
166
|
+
"planets": {
|
|
167
|
+
"detail": {
|
|
168
|
+
"back": "Back to Planets",
|
|
169
|
+
"notFound": "Planet not found.",
|
|
170
|
+
"description": "Description",
|
|
171
|
+
"details": "Details",
|
|
172
|
+
"created": "Created",
|
|
173
|
+
"updated": "Last updated",
|
|
174
|
+
"discoveryDate": "Discovery date",
|
|
175
|
+
"createdBy": "Created by"
|
|
176
|
+
},
|
|
177
|
+
"page": {
|
|
178
|
+
"title": "Planets",
|
|
179
|
+
"headTitle": "Planets",
|
|
180
|
+
"headDescription": "Manage your planets",
|
|
181
|
+
"addPlanet": "Add planet",
|
|
182
|
+
"empty": "No planets yet. Add your first one."
|
|
183
|
+
},
|
|
184
|
+
"views": {
|
|
185
|
+
"label": "Planet view",
|
|
186
|
+
"grid": "Grid",
|
|
187
|
+
"table": "Table",
|
|
188
|
+
"infinite": "Infinite table"
|
|
189
|
+
},
|
|
190
|
+
"filters": {
|
|
191
|
+
"search": "Search",
|
|
192
|
+
"alien": "Alien",
|
|
193
|
+
"alienPlaceholder": "All aliens",
|
|
194
|
+
"discoveryDate": "Discovery date",
|
|
195
|
+
"discoveryDatePlaceholder": "Any date",
|
|
196
|
+
"clearAll": "Clear all"
|
|
197
|
+
},
|
|
198
|
+
"create": {
|
|
199
|
+
"title": "Create planet",
|
|
200
|
+
"name": "Name",
|
|
201
|
+
"namePlaceholder": "Planet name",
|
|
202
|
+
"alien": "Alien",
|
|
203
|
+
"alienPlaceholder": "Select an alien",
|
|
204
|
+
"discoveryDate": "Discovery date",
|
|
205
|
+
"discoveryDatePlaceholder": "Select a discovery date",
|
|
206
|
+
"description": "Description",
|
|
207
|
+
"descriptionPlaceholder": "Optional description",
|
|
208
|
+
"image": "Image",
|
|
209
|
+
"imageEmptyText": "No image",
|
|
210
|
+
"imageUploadText": "Upload",
|
|
211
|
+
"imageBrowseText": "Browse",
|
|
212
|
+
"submit": "Create",
|
|
213
|
+
"cancel": "Cancel",
|
|
214
|
+
"success": "Planet created",
|
|
215
|
+
"error": "Failed to create planet"
|
|
216
|
+
},
|
|
217
|
+
"edit": {
|
|
218
|
+
"title": "Edit planet",
|
|
219
|
+
"name": "Name",
|
|
220
|
+
"namePlaceholder": "Planet name",
|
|
221
|
+
"alien": "Alien",
|
|
222
|
+
"alienPlaceholder": "Select an alien",
|
|
223
|
+
"discoveryDate": "Discovery date",
|
|
224
|
+
"discoveryDatePlaceholder": "Select a discovery date",
|
|
225
|
+
"description": "Description",
|
|
226
|
+
"descriptionPlaceholder": "Optional description",
|
|
227
|
+
"image": "Image",
|
|
228
|
+
"imageEmptyText": "No image",
|
|
229
|
+
"imageUploadText": "Upload",
|
|
230
|
+
"imageBrowseText": "Browse",
|
|
231
|
+
"submit": "Save",
|
|
232
|
+
"cancel": "Cancel",
|
|
233
|
+
"success": "Planet updated",
|
|
234
|
+
"error": "Failed to update planet"
|
|
235
|
+
},
|
|
236
|
+
"card": {
|
|
237
|
+
"createdBy": "Created by {{name}} on {{date}}",
|
|
238
|
+
"alien": "Alien: {{name}}",
|
|
239
|
+
"unknownCreator": "Unknown"
|
|
240
|
+
},
|
|
241
|
+
"table": {
|
|
242
|
+
"allLoaded": "All results are shown",
|
|
243
|
+
"showing": "Showing {{displayed}} of {{total}}",
|
|
244
|
+
"name": "Name",
|
|
245
|
+
"description": "Description",
|
|
246
|
+
"alien": "Alien",
|
|
247
|
+
"discoveryDate": "Discovery date",
|
|
248
|
+
"creator": "Creator",
|
|
249
|
+
"actions": "Actions"
|
|
250
|
+
},
|
|
251
|
+
"actions": {
|
|
252
|
+
"edit": "Edit",
|
|
253
|
+
"remove": "Remove"
|
|
254
|
+
},
|
|
255
|
+
"removeConfirm": {
|
|
256
|
+
"heading": "Remove planet?",
|
|
257
|
+
"description": "Are you sure you want to remove \"{{name}}\"? This cannot be undone.",
|
|
258
|
+
"confirm": "Remove",
|
|
259
|
+
"cancel": "Cancel",
|
|
260
|
+
"success": "Planet removed",
|
|
261
|
+
"error": "Failed to remove planet"
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
"planetsFeed": {
|
|
265
|
+
"page": {
|
|
266
|
+
"title": "Planets feed",
|
|
267
|
+
"headTitle": "Planets feed",
|
|
268
|
+
"headDescription": "Scroll through planets and their aliens",
|
|
269
|
+
"empty": "No planets to show.",
|
|
270
|
+
"end": "You reached the end."
|
|
271
|
+
},
|
|
272
|
+
"card": {
|
|
273
|
+
"like": "Like ({{count}})",
|
|
274
|
+
"liked": "Liked ({{count}})",
|
|
275
|
+
"discovered": "Discovered {{date}}",
|
|
276
|
+
"alienLabel": "Alien on this planet",
|
|
277
|
+
"creatorLabel": "Created by",
|
|
278
|
+
"noAlien": "No alien assigned"
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
"profile": {
|
|
282
|
+
"head": {
|
|
283
|
+
"title": "Profile",
|
|
284
|
+
"description": "Your profile"
|
|
285
|
+
},
|
|
286
|
+
"form": {
|
|
287
|
+
"title": "Profile",
|
|
288
|
+
"description": "Update your profile details",
|
|
289
|
+
"email": "Email",
|
|
290
|
+
"emailPlaceholder": "Enter your email",
|
|
291
|
+
"name": "Name",
|
|
292
|
+
"namePlaceholder": "Enter your name",
|
|
293
|
+
"submit": "Save",
|
|
294
|
+
"submitLoading": "Saving...",
|
|
295
|
+
"notifications": {
|
|
296
|
+
"success": "Profile updated",
|
|
297
|
+
"error": "Failed to update profile"
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|