robodev 0.23.0 → 0.25.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/emit-starter.test.ts +36 -0
- package/templates/auth-chat/package.json +1 -1
- package/templates/backend/package.json +1 -1
- package/templates/catalog.json +5 -0
- package/templates/empty/package.json +1 -1
- package/templates/marketplace/.config/local.spa.template.yml +27 -0
- package/templates/marketplace/.oxlint-base.json +29 -0
- package/templates/marketplace/.oxlintrc.json +78 -0
- package/templates/marketplace/.rulesync/rules/frontend-api-boundary.md +36 -0
- package/templates/marketplace/.rulesync/rules/frontend-component-structure.md +38 -0
- package/templates/marketplace/.rulesync/rules/frontend-forms.md +32 -0
- package/templates/marketplace/.rulesync/rules/frontend-notifications.md +24 -0
- package/templates/marketplace/.rulesync/rules/frontend-povio-components.md +42 -0
- package/templates/marketplace/.rulesync/rules/frontend-povio-ui.md +45 -0
- package/templates/marketplace/.rulesync/rules/frontend-query-autocomplete.md +29 -0
- package/templates/marketplace/.rulesync/rules/frontend-tables-and-lists.md +34 -0
- package/templates/marketplace/.rulesync/rules/frontend-translations.md +26 -0
- package/templates/marketplace/.rulesync/rules/project-overview.md +32 -0
- package/templates/marketplace/.rulesync/rules/robodev-api.md +30 -0
- package/templates/marketplace/.rulesync/rules/robodev-auth.md +40 -0
- package/templates/marketplace/.rulesync/rules/robodev-database.md +22 -0
- package/templates/marketplace/.rulesync/rules/role-based-app-structure.md +36 -0
- package/templates/marketplace/.rulesync/skills/media-feature/SKILL.md +21 -0
- package/templates/marketplace/.rulesync/skills/povio-ui-styling/SKILL.md +208 -0
- package/templates/marketplace/.rulesync/skills/povio-ui-styling/agents/openai.yaml +4 -0
- package/templates/marketplace/.rulesync/skills/robodev-api-route/SKILL.md +13 -0
- package/templates/marketplace/.rulesync/skills/robodev-table/SKILL.md +12 -0
- package/templates/marketplace/README.md +40 -0
- package/templates/marketplace/api/_lib.seed.test.ts +10 -0
- package/templates/marketplace/api/_lib.ts +734 -0
- package/templates/marketplace/api/cart/[id].ts +51 -0
- package/templates/marketplace/api/cart.ts +70 -0
- package/templates/marketplace/api/categories.ts +11 -0
- package/templates/marketplace/api/checkout.ts +157 -0
- package/templates/marketplace/api/health.ts +7 -0
- package/templates/marketplace/api/listings/[id].ts +101 -0
- package/templates/marketplace/api/listings/paginate.ts +29 -0
- package/templates/marketplace/api/listings.ts +90 -0
- package/templates/marketplace/api/me.ts +14 -0
- package/templates/marketplace/api/orders/[id]/complete.ts +27 -0
- package/templates/marketplace/api/orders/[id]/ship.ts +24 -0
- package/templates/marketplace/api/orders/[id].ts +15 -0
- package/templates/marketplace/api/purchases.ts +19 -0
- package/templates/marketplace/api/reviews.ts +58 -0
- package/templates/marketplace/api/sales.ts +19 -0
- package/templates/marketplace/api/watches/[listingId].ts +18 -0
- package/templates/marketplace/api/watches.ts +51 -0
- package/templates/marketplace/apps/fe/index.html +24 -0
- package/templates/marketplace/apps/fe/openapi-codegen.config.ts +72 -0
- package/templates/marketplace/apps/fe/package.json +84 -0
- package/templates/marketplace/apps/fe/public/apple-touch-icon.png +0 -0
- package/templates/marketplace/apps/fe/public/favicon-96x96.png +0 -0
- package/templates/marketplace/apps/fe/public/favicon.ico +0 -0
- package/templates/marketplace/apps/fe/public/favicon.svg +3 -0
- package/templates/marketplace/apps/fe/public/site.webmanifest +21 -0
- package/templates/marketplace/apps/fe/public/web-app-manifest-192x192.png +0 -0
- package/templates/marketplace/apps/fe/public/web-app-manifest-512x512.png +0 -0
- package/templates/marketplace/apps/fe/src/assets/fonts/GeneralSans-Bold.otf +0 -0
- package/templates/marketplace/apps/fe/src/assets/fonts/GeneralSans-Medium.otf +0 -0
- package/templates/marketplace/apps/fe/src/assets/fonts/GeneralSans-Regular.otf +0 -0
- package/templates/marketplace/apps/fe/src/assets/fonts/GeneralSans-Semibold.otf +0 -0
- package/templates/marketplace/apps/fe/src/assets/locales/en/translation.json +336 -0
- package/templates/marketplace/apps/fe/src/assets/locales/sl/translation.json +336 -0
- package/templates/marketplace/apps/fe/src/clients/app-rest-client.ts +15 -0
- package/templates/marketplace/apps/fe/src/clients/auth-token-store.ts +101 -0
- package/templates/marketplace/apps/fe/src/clients/rest/app-error-handler.ts +31 -0
- package/templates/marketplace/apps/fe/src/clients/rest/interceptors/authorization-header.interceptor.ts +15 -0
- package/templates/marketplace/apps/fe/src/clients/rest/interceptors/refresh-token.interceptor.ts +37 -0
- package/templates/marketplace/apps/fe/src/clients/rest/interceptors/response.interceptor.ts +17 -0
- package/templates/marketplace/apps/fe/src/components/404.tsx +18 -0
- package/templates/marketplace/apps/fe/src/components/features/auth/AuthBrandPanel.tsx +60 -0
- package/templates/marketplace/apps/fe/src/components/features/auth/AuthLayout.tsx +23 -0
- package/templates/marketplace/apps/fe/src/components/features/auth/LoginPage.tsx +111 -0
- package/templates/marketplace/apps/fe/src/components/features/auth/RegisterPage.tsx +143 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/BrowsePage.tsx +76 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/CartPage.tsx +88 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/CheckoutPage.tsx +193 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/ListingCard.tsx +50 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/ListingDetailsPage.tsx +194 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/ListingForm.tsx +278 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/ListingFormPage.tsx +27 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/ListingGallery.tsx +54 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/MyListingsPage.tsx +137 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/OrderStatusTag.tsx +24 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/OrderSummaryCard.tsx +39 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/OrdersPage.tsx +236 -0
- package/templates/marketplace/apps/fe/src/components/features/marketplace/WatchlistPage.tsx +56 -0
- package/templates/marketplace/apps/fe/src/components/features/profile/ProfilePage.tsx +96 -0
- package/templates/marketplace/apps/fe/src/components/googleAnalytics/GoogleAnalytics.tsx +35 -0
- package/templates/marketplace/apps/fe/src/components/layout/AppLayout.tsx +19 -0
- package/templates/marketplace/apps/fe/src/components/layout/app-header/AppHeader.tsx +95 -0
- package/templates/marketplace/apps/fe/src/components/layout/app-header/MobileNavigation.tsx +55 -0
- package/templates/marketplace/apps/fe/src/components/layout/app-header/NavLink.tsx +29 -0
- package/templates/marketplace/apps/fe/src/components/shared/branding/BrandLogo.tsx +13 -0
- package/templates/marketplace/apps/fe/src/components/shared/error/ErrorFallback.tsx +43 -0
- package/templates/marketplace/apps/fe/src/components/shared/error/ErrorText.tsx +20 -0
- package/templates/marketplace/apps/fe/src/components/shared/error/NotFound.tsx +36 -0
- package/templates/marketplace/apps/fe/src/components/shared/forms/RequiredLabel.tsx +21 -0
- package/templates/marketplace/apps/fe/src/components/shared/forms/RowInputWrapper.tsx +50 -0
- package/templates/marketplace/apps/fe/src/components/shared/head/AppHead.tsx +32 -0
- package/templates/marketplace/apps/fe/src/components/shared/head/DefaultAppHead.tsx +34 -0
- package/templates/marketplace/apps/fe/src/components/shared/layout/LoadingState.tsx +9 -0
- package/templates/marketplace/apps/fe/src/components/shared/layout/ThinPageWrapper.tsx +5 -0
- package/templates/marketplace/apps/fe/src/components/shared/page/PageHeader.tsx +69 -0
- package/templates/marketplace/apps/fe/src/components/shared/ui/Card.tsx +60 -0
- package/templates/marketplace/apps/fe/src/components/shared/ui/GoogleLoginButton.tsx +19 -0
- package/templates/marketplace/apps/fe/src/components/shared/ui/RequiredLabel.tsx +22 -0
- package/templates/marketplace/apps/fe/src/components/shared/ui/TableActions.tsx +22 -0
- package/templates/marketplace/apps/fe/src/config/app.config.ts +35 -0
- package/templates/marketplace/apps/fe/src/config/i18n.ts +43 -0
- package/templates/marketplace/apps/fe/src/config/inits/a11y.ts +14 -0
- package/templates/marketplace/apps/fe/src/config/inits/logger.ts +7 -0
- package/templates/marketplace/apps/fe/src/config/inits/sentry.ts +21 -0
- package/templates/marketplace/apps/fe/src/config/jwt.config.ts +2 -0
- package/templates/marketplace/apps/fe/src/config/query.config.ts +20 -0
- package/templates/marketplace/apps/fe/src/hooks/useAuth.ts +5 -0
- package/templates/marketplace/apps/fe/src/main.tsx +52 -0
- package/templates/marketplace/apps/fe/src/pages/(guest)/login.tsx +23 -0
- package/templates/marketplace/apps/fe/src/pages/(guest)/register.tsx +23 -0
- package/templates/marketplace/apps/fe/src/pages/(guest)/route.tsx +18 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/cart.tsx +22 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/checkout.tsx +22 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/index.tsx +22 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/listings/$id/index.tsx +37 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/my-listings.tsx +32 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/orders/$id.tsx +40 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/orders/index.tsx +22 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/profile.tsx +23 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/route.tsx +18 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/sales.tsx +22 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/sell/$id.tsx +44 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/sell/index.tsx +15 -0
- package/templates/marketplace/apps/fe/src/pages/(private)/watchlist.tsx +22 -0
- package/templates/marketplace/apps/fe/src/pages/(public)/auth.tsx +37 -0
- package/templates/marketplace/apps/fe/src/pages/(public)/route.tsx +9 -0
- package/templates/marketplace/apps/fe/src/pages/__root.tsx +164 -0
- package/templates/marketplace/apps/fe/src/providers/AppErrorBoundary.tsx +10 -0
- package/templates/marketplace/apps/fe/src/providers/OpenApiRuntimeProvider.tsx +31 -0
- package/templates/marketplace/apps/fe/src/providers/index.tsx +44 -0
- package/templates/marketplace/apps/fe/src/providers/jwt.provider.tsx +95 -0
- package/templates/marketplace/apps/fe/src/routeTree.gen.ts +435 -0
- package/templates/marketplace/apps/fe/src/styles/base.css +103 -0
- package/templates/marketplace/apps/fe/src/styles/fonts/fonts.tsx +10 -0
- package/templates/marketplace/apps/fe/src/styles/fonts/general-sans.css +31 -0
- package/templates/marketplace/apps/fe/src/styles/globals.css +28 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/button.override.ts +536 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/checkbox.override.ts +71 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/input.override.ts +252 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/label.override.ts +91 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/modal.override.ts +57 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/radio.override.ts +46 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/table.override.ts +104 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/tag.override.ts +66 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/defaults/typography.override.ts +115 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/outline.clsx.ts +10 -0
- package/templates/marketplace/apps/fe/src/styles/overrides/uiOverrides.override.ts +60 -0
- package/templates/marketplace/apps/fe/src/styles/theme.css +2177 -0
- package/templates/marketplace/apps/fe/src/types/i18next.d.ts +12 -0
- package/templates/marketplace/apps/fe/src/types/table.d.ts +17 -0
- package/templates/marketplace/apps/fe/src/types/ui.d.ts +26 -0
- package/templates/marketplace/apps/fe/src/types/vite-env.d.ts +20 -0
- package/templates/marketplace/apps/fe/src/utils/date.utils.ts +17 -0
- package/templates/marketplace/apps/fe/src/utils/image-fallback.ts +9 -0
- package/templates/marketplace/apps/fe/src/utils/listing-form.test.ts +69 -0
- package/templates/marketplace/apps/fe/src/utils/listing-form.ts +77 -0
- package/templates/marketplace/apps/fe/src/utils/listing-submit.ts +29 -0
- package/templates/marketplace/apps/fe/src/utils/number.utils.ts +12 -0
- package/templates/marketplace/apps/fe/src/utils/string.utils.ts +5 -0
- package/templates/marketplace/apps/fe/src/vite-env.d.ts +1 -0
- package/templates/marketplace/apps/fe/tsconfig.app.json +32 -0
- package/templates/marketplace/apps/fe/tsconfig.json +9 -0
- package/templates/marketplace/apps/fe/tsconfig.node.json +31 -0
- package/templates/marketplace/apps/fe/vite.config.ts +125 -0
- package/templates/marketplace/database.ts +154 -0
- package/templates/marketplace/openapi.json +2303 -0
- package/templates/marketplace/oxfmt.config.js +23 -0
- package/templates/marketplace/package.json +18 -0
- package/templates/marketplace/rulesync.jsonc +18 -0
- package/templates/marketplace/tsconfig.json +11 -0
- package/templates/space/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineApi, desc, eq } from "@robodev-ai/sdk";
|
|
2
|
+
import { orderItems, orders, toOrderDto } from "./_lib";
|
|
3
|
+
|
|
4
|
+
export const get = defineApi({
|
|
5
|
+
auth: "required",
|
|
6
|
+
handler: async (ctx) => {
|
|
7
|
+
const rows = await ctx.db
|
|
8
|
+
.select()
|
|
9
|
+
.from(orders)
|
|
10
|
+
.where(eq(orders.sellerId, ctx.user!.id))
|
|
11
|
+
.orderBy(desc(orders.createdAt));
|
|
12
|
+
const result = [];
|
|
13
|
+
for (const order of rows) {
|
|
14
|
+
const items = await ctx.db.select().from(orderItems).where(eq(orderItems.orderId, order.id));
|
|
15
|
+
result.push(toOrderDto(order, items));
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { and, defineApi, eq } from "@robodev-ai/sdk";
|
|
2
|
+
import { fail, watches } from "../_lib";
|
|
3
|
+
|
|
4
|
+
const remove = defineApi({
|
|
5
|
+
auth: "required",
|
|
6
|
+
handler: async (ctx) => {
|
|
7
|
+
const [row] = await ctx.db
|
|
8
|
+
.select()
|
|
9
|
+
.from(watches)
|
|
10
|
+
.where(and(eq(watches.userId, ctx.user!.id), eq(watches.listingId, ctx.params.listingId)))
|
|
11
|
+
.limit(1);
|
|
12
|
+
if (!row) return fail(404, "Watch not found");
|
|
13
|
+
await ctx.db.delete(watches).where(eq(watches.id, row.id));
|
|
14
|
+
return { status: 204, body: null };
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export { remove as delete };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { and, defineApi, eq, z } from "@robodev-ai/sdk";
|
|
2
|
+
import { enrichOne, fail, findListing, watches } from "./_lib";
|
|
3
|
+
|
|
4
|
+
const watchBody = z.object({
|
|
5
|
+
listingId: z.string().min(1),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const get = defineApi({
|
|
9
|
+
auth: "required",
|
|
10
|
+
handler: async (ctx) => {
|
|
11
|
+
const rows = await ctx.db.select().from(watches).where(eq(watches.userId, ctx.user!.id));
|
|
12
|
+
const items = [];
|
|
13
|
+
for (const row of rows) {
|
|
14
|
+
const listing = await findListing(ctx.db, row.listingId);
|
|
15
|
+
if (!listing) continue;
|
|
16
|
+
items.push({
|
|
17
|
+
id: row.id,
|
|
18
|
+
userId: row.userId,
|
|
19
|
+
listingId: row.listingId,
|
|
20
|
+
listing: await enrichOne(ctx, listing, ctx.user!.id),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return items;
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const post = defineApi({
|
|
28
|
+
auth: "required",
|
|
29
|
+
body: watchBody,
|
|
30
|
+
handler: async (ctx) => {
|
|
31
|
+
const listing = await findListing(ctx.db, ctx.body.listingId);
|
|
32
|
+
if (!listing) return fail(404, "Listing not found");
|
|
33
|
+
const [current] = await ctx.db
|
|
34
|
+
.select()
|
|
35
|
+
.from(watches)
|
|
36
|
+
.where(and(eq(watches.userId, ctx.user!.id), eq(watches.listingId, listing.id)))
|
|
37
|
+
.limit(1);
|
|
38
|
+
const [row] = current
|
|
39
|
+
? [current]
|
|
40
|
+
: await ctx.db
|
|
41
|
+
.insert(watches)
|
|
42
|
+
.values({ userId: ctx.user!.id, listingId: listing.id })
|
|
43
|
+
.returning();
|
|
44
|
+
return {
|
|
45
|
+
id: row!.id,
|
|
46
|
+
userId: row!.userId,
|
|
47
|
+
listingId: row!.listingId,
|
|
48
|
+
listing: await enrichOne(ctx, listing, ctx.user!.id),
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -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>Marketplace</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,72 @@
|
|
|
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 { readFileSync } from "node:fs";
|
|
5
|
+
import { join, resolve } from "node:path";
|
|
6
|
+
|
|
7
|
+
const COMPACT_OPENAPI_INPUT = "../../openapi.json";
|
|
8
|
+
const repoRoot = resolve(process.cwd(), "../..");
|
|
9
|
+
|
|
10
|
+
function readDotEnvKey(root: string, key: string): string | undefined {
|
|
11
|
+
try {
|
|
12
|
+
const content = readFileSync(join(root, ".env"), "utf8");
|
|
13
|
+
const line = content.split(/\r?\n/).find((row) => row.startsWith(`${key}=`));
|
|
14
|
+
const value = line?.slice(key.length + 1).trim();
|
|
15
|
+
return value || undefined;
|
|
16
|
+
} catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function loadResolvedSpaEnv(cwd: string): Record<string, string | undefined> {
|
|
22
|
+
try {
|
|
23
|
+
const resolved = resolveConfigSync({ cwd, module: "spa", target: "resolved" });
|
|
24
|
+
if (resolved && typeof resolved === "object") {
|
|
25
|
+
return resolved as Record<string, string | undefined>;
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
// unnamed or missing spa manifest
|
|
29
|
+
}
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const env = loadResolvedSpaEnv(repoRoot);
|
|
34
|
+
|
|
35
|
+
function fallbackApiUrl(): string {
|
|
36
|
+
return (
|
|
37
|
+
env.VITE_PUBLIC_API_URL ||
|
|
38
|
+
process.env.VITE_PUBLIC_API_URL ||
|
|
39
|
+
readDotEnvKey(repoRoot, "VITE_PUBLIC_API_URL") ||
|
|
40
|
+
"http://localhost:4000"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function resolveLiveOpenApiInput(apiUrl = fallbackApiUrl()) {
|
|
45
|
+
const usable = apiUrl.trim();
|
|
46
|
+
if (!usable) return COMPACT_OPENAPI_INPUT;
|
|
47
|
+
return `${usable.replace(/\/+$/, "")}/openapi.json`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function resolveOpenApiInput() {
|
|
51
|
+
if (process.env.OPENAPI_INPUT) return process.env.OPENAPI_INPUT;
|
|
52
|
+
if (process.env.OPENAPI_LIVE === "true") return resolveLiveOpenApiInput();
|
|
53
|
+
return COMPACT_OPENAPI_INPUT;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const config: OpenAPICodegenConfig = {
|
|
57
|
+
input: resolveOpenApiInput(),
|
|
58
|
+
output: "src/openapi",
|
|
59
|
+
tsPath: "@/openapi",
|
|
60
|
+
restClientImportPath: "@/clients/app-rest-client",
|
|
61
|
+
clearOutput: true,
|
|
62
|
+
excludeRedundantZodSchemas: false,
|
|
63
|
+
checkAcl: false,
|
|
64
|
+
acl: false,
|
|
65
|
+
replaceOptionalWithNullish: true,
|
|
66
|
+
infiniteQueries: true,
|
|
67
|
+
mutationDefaultOnError: true,
|
|
68
|
+
modelsInCommon: true,
|
|
69
|
+
axiosRequestConfig: true,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default config;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fe",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Marketplace starter frontend",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "bunx --bun vite",
|
|
9
|
+
"build": "bun run openapi:gen && 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
|
+
"@hookform/resolvers": "^5.2.2",
|
|
27
|
+
"@internationalized/date": "^3.11.0",
|
|
28
|
+
"@povio/openapi-codegen-cli": "3.1.0",
|
|
29
|
+
"@povio/resolve-config": "1.3.0",
|
|
30
|
+
"@povio/ui": "3.4.0-rc.12",
|
|
31
|
+
"@sentry/react": "^10.38.0",
|
|
32
|
+
"@tanstack/devtools-vite": "^0.3.11",
|
|
33
|
+
"@tanstack/react-devtools": "^0.8.1",
|
|
34
|
+
"@tanstack/react-form": "^1.33.2",
|
|
35
|
+
"@tanstack/react-query": "^5.90.21",
|
|
36
|
+
"@tanstack/react-query-devtools": "~5.90.0",
|
|
37
|
+
"@tanstack/react-router": "^1.136.8",
|
|
38
|
+
"@tanstack/react-router-devtools": "^1.136.8",
|
|
39
|
+
"@tanstack/react-table": "^8.21.3",
|
|
40
|
+
"@tanstack/router-core": "^1.136.8",
|
|
41
|
+
"@tanstack/router-plugin": "^1.136.8",
|
|
42
|
+
"axios": "^1.13.2",
|
|
43
|
+
"class-variance-authority": "^0.7.1",
|
|
44
|
+
"clsx": "^2.1.1",
|
|
45
|
+
"i18next": "^25.7.3",
|
|
46
|
+
"loglevel": "^1.9.2",
|
|
47
|
+
"lucide-react": "^1.28.0",
|
|
48
|
+
"luxon": "^3.7.2",
|
|
49
|
+
"react": "19.2.4",
|
|
50
|
+
"react-aria": "^3.46.0",
|
|
51
|
+
"react-aria-components": "^1.15.1",
|
|
52
|
+
"react-dom": "19.2.4",
|
|
53
|
+
"react-hook-form": "^7.65.0",
|
|
54
|
+
"react-i18next": "^16.5.1",
|
|
55
|
+
"web-vitals": "^5.1.0",
|
|
56
|
+
"zod": "^4.4.3",
|
|
57
|
+
"zustand": "^5.0.9"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@axe-core/react": "^4.11.0",
|
|
61
|
+
"@povio/react-scan": "0.0.0",
|
|
62
|
+
"@povio/vite-plugin-react-scan": "0.0.2",
|
|
63
|
+
"@tailwindcss/vite": "^4.2.1",
|
|
64
|
+
"@types/luxon": "^3.7.1",
|
|
65
|
+
"@types/node": "^24.10.9",
|
|
66
|
+
"@types/react": "^19.2.7",
|
|
67
|
+
"@types/react-dom": "^19.2.3",
|
|
68
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
69
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
70
|
+
"babel-plugin-react-compiler": "1.0.0",
|
|
71
|
+
"oxfmt": "^0.45.0",
|
|
72
|
+
"oxlint": "1.60.0",
|
|
73
|
+
"oxlint-tsgolint": "0.21.0",
|
|
74
|
+
"react-icons-sprite": "^1.1.1",
|
|
75
|
+
"rimraf": "^6.1.2",
|
|
76
|
+
"tailwindcss": "^4.2.4",
|
|
77
|
+
"tailwindcss-react-aria-components": "^2.1.0",
|
|
78
|
+
"tsx": "^4.22.1",
|
|
79
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
80
|
+
"vite": "^8.0.0",
|
|
81
|
+
"vite-plugin-devtools-json": "^1.0.0",
|
|
82
|
+
"vitest": "^3.2.4"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
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
|
+
}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
{
|
|
2
|
+
"appName": "Marketplace",
|
|
3
|
+
"appDescription": "Buy-It-Now goods marketplace",
|
|
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
|
+
"browse": "Browse",
|
|
151
|
+
"sell": "Sell",
|
|
152
|
+
"watchlist": "Watchlist",
|
|
153
|
+
"orders": "Orders",
|
|
154
|
+
"cart": "Cart"
|
|
155
|
+
},
|
|
156
|
+
"profile": "Profile",
|
|
157
|
+
"logout": "Logout"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"browse": {
|
|
161
|
+
"head": {
|
|
162
|
+
"title": "Browse",
|
|
163
|
+
"description": "Find goods for sale"
|
|
164
|
+
},
|
|
165
|
+
"title": "Browse",
|
|
166
|
+
"search": "Search",
|
|
167
|
+
"searchPlaceholder": "Search listings",
|
|
168
|
+
"allCategories": "All categories",
|
|
169
|
+
"empty": "No listings match your search."
|
|
170
|
+
},
|
|
171
|
+
"listing": {
|
|
172
|
+
"notFound": "Listing not found.",
|
|
173
|
+
"soldOut": "Sold out",
|
|
174
|
+
"inactive": "Inactive",
|
|
175
|
+
"seller": "Seller",
|
|
176
|
+
"category": "Category",
|
|
177
|
+
"shipping": "Shipping",
|
|
178
|
+
"shippingDays": "{{count}} days",
|
|
179
|
+
"quantity": "Quantity",
|
|
180
|
+
"inStock": "{{count}} available",
|
|
181
|
+
"rating": "Seller rating {{rating}}",
|
|
182
|
+
"noRating": "No seller reviews yet",
|
|
183
|
+
"addToCart": "Add to cart",
|
|
184
|
+
"addedToCart": "Added to cart",
|
|
185
|
+
"addToCartError": "Could not add to cart",
|
|
186
|
+
"watchError": "Could not update watchlist",
|
|
187
|
+
"watch": "Watch",
|
|
188
|
+
"unwatch": "Unwatch",
|
|
189
|
+
"ownListing": "This is your listing",
|
|
190
|
+
"images": "Images",
|
|
191
|
+
"description": "Description",
|
|
192
|
+
"price": "Price",
|
|
193
|
+
"reviews": "Reviews",
|
|
194
|
+
"noReviews": "No reviews yet."
|
|
195
|
+
},
|
|
196
|
+
"sell": {
|
|
197
|
+
"head": {
|
|
198
|
+
"title": "Sell",
|
|
199
|
+
"description": "Your listings"
|
|
200
|
+
},
|
|
201
|
+
"title": "My listings",
|
|
202
|
+
"create": "New listing",
|
|
203
|
+
"empty": "You have no listings yet.",
|
|
204
|
+
"soldOut": "Sold out",
|
|
205
|
+
"inactive": "Inactive",
|
|
206
|
+
"edit": "Edit",
|
|
207
|
+
"deactivate": "Deactivate",
|
|
208
|
+
"deactivateSuccess": "Listing deactivated",
|
|
209
|
+
"deactivateError": "Could not deactivate listing"
|
|
210
|
+
},
|
|
211
|
+
"listingForm": {
|
|
212
|
+
"createTitle": "New listing",
|
|
213
|
+
"editTitle": "Edit listing",
|
|
214
|
+
"title": "Title",
|
|
215
|
+
"titlePlaceholder": "What are you selling?",
|
|
216
|
+
"description": "Description",
|
|
217
|
+
"descriptionPlaceholder": "Describe the item",
|
|
218
|
+
"category": "Category",
|
|
219
|
+
"price": "Price (USD)",
|
|
220
|
+
"quantity": "Quantity",
|
|
221
|
+
"shipping": "Shipping (USD)",
|
|
222
|
+
"shippingDays": "Shipping days",
|
|
223
|
+
"images": "Photos",
|
|
224
|
+
"imageEmptyText": "No photos yet",
|
|
225
|
+
"imageUploadText": "Upload",
|
|
226
|
+
"imageBrowseText": "Browse",
|
|
227
|
+
"removeImage": "Remove photo",
|
|
228
|
+
"submitCreate": "List item",
|
|
229
|
+
"submitEdit": "Save listing",
|
|
230
|
+
"cancel": "Cancel",
|
|
231
|
+
"createSuccess": "Listing created",
|
|
232
|
+
"createError": "Could not create listing",
|
|
233
|
+
"updateSuccess": "Listing updated",
|
|
234
|
+
"updateError": "Could not update listing"
|
|
235
|
+
},
|
|
236
|
+
"cart": {
|
|
237
|
+
"head": {
|
|
238
|
+
"title": "Cart",
|
|
239
|
+
"description": "Items you are buying"
|
|
240
|
+
},
|
|
241
|
+
"title": "Cart",
|
|
242
|
+
"empty": "Your cart is empty.",
|
|
243
|
+
"checkout": "Checkout",
|
|
244
|
+
"remove": "Remove",
|
|
245
|
+
"quantity": "Quantity",
|
|
246
|
+
"updateError": "Could not update cart",
|
|
247
|
+
"removeError": "Could not remove item",
|
|
248
|
+
"subtotal": "Subtotal",
|
|
249
|
+
"shipping": "Shipping"
|
|
250
|
+
},
|
|
251
|
+
"checkout": {
|
|
252
|
+
"head": {
|
|
253
|
+
"title": "Checkout",
|
|
254
|
+
"description": "Pay for your cart"
|
|
255
|
+
},
|
|
256
|
+
"title": "Checkout",
|
|
257
|
+
"shipping": "Shipping address",
|
|
258
|
+
"name": "Full name",
|
|
259
|
+
"line1": "Address line 1",
|
|
260
|
+
"line2": "Address line 2",
|
|
261
|
+
"city": "City",
|
|
262
|
+
"region": "Region",
|
|
263
|
+
"postal": "Postal code",
|
|
264
|
+
"country": "Country",
|
|
265
|
+
"card": "Card (not charged)",
|
|
266
|
+
"cardNumber": "Card number",
|
|
267
|
+
"expiry": "Expiry",
|
|
268
|
+
"cvc": "CVC",
|
|
269
|
+
"submit": "Place order",
|
|
270
|
+
"success": "Order placed",
|
|
271
|
+
"error": "Checkout failed",
|
|
272
|
+
"empty": "Your cart is empty."
|
|
273
|
+
},
|
|
274
|
+
"orders": {
|
|
275
|
+
"head": {
|
|
276
|
+
"title": "Orders",
|
|
277
|
+
"description": "Purchases and sales"
|
|
278
|
+
},
|
|
279
|
+
"title": "Orders",
|
|
280
|
+
"purchases": "Purchases",
|
|
281
|
+
"sales": "Sales",
|
|
282
|
+
"emptyPurchases": "No purchases yet.",
|
|
283
|
+
"emptySales": "No sales yet.",
|
|
284
|
+
"view": "View",
|
|
285
|
+
"status": {
|
|
286
|
+
"paid": "Paid",
|
|
287
|
+
"shipped": "Shipped",
|
|
288
|
+
"completed": "Completed"
|
|
289
|
+
},
|
|
290
|
+
"total": "Total",
|
|
291
|
+
"ship": "Mark shipped",
|
|
292
|
+
"complete": "Mark completed",
|
|
293
|
+
"shipSuccess": "Order marked shipped",
|
|
294
|
+
"shipError": "Could not ship order",
|
|
295
|
+
"completeSuccess": "Order completed",
|
|
296
|
+
"completeError": "Could not complete order",
|
|
297
|
+
"notFound": "Order not found.",
|
|
298
|
+
"review": "Write a review",
|
|
299
|
+
"reviewRating": "Rating",
|
|
300
|
+
"reviewBody": "Review",
|
|
301
|
+
"reviewSubmit": "Submit review",
|
|
302
|
+
"reviewSuccess": "Review saved",
|
|
303
|
+
"reviewError": "Could not save review",
|
|
304
|
+
"reviewed": "Reviewed"
|
|
305
|
+
},
|
|
306
|
+
"watchlist": {
|
|
307
|
+
"head": {
|
|
308
|
+
"title": "Watchlist",
|
|
309
|
+
"description": "Listings you are watching"
|
|
310
|
+
},
|
|
311
|
+
"title": "Watchlist",
|
|
312
|
+
"empty": "You are not watching any listings.",
|
|
313
|
+
"remove": "Remove",
|
|
314
|
+
"removeError": "Could not remove watch"
|
|
315
|
+
},
|
|
316
|
+
"profile": {
|
|
317
|
+
"head": {
|
|
318
|
+
"title": "Profile",
|
|
319
|
+
"description": "Your profile"
|
|
320
|
+
},
|
|
321
|
+
"form": {
|
|
322
|
+
"title": "Profile",
|
|
323
|
+
"description": "Update your profile details",
|
|
324
|
+
"email": "Email",
|
|
325
|
+
"emailPlaceholder": "Enter your email",
|
|
326
|
+
"name": "Name",
|
|
327
|
+
"namePlaceholder": "Enter your name",
|
|
328
|
+
"submit": "Save",
|
|
329
|
+
"submitLoading": "Saving...",
|
|
330
|
+
"notifications": {
|
|
331
|
+
"success": "Profile updated",
|
|
332
|
+
"error": "Failed to update profile"
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|