build: include production build artifacts in repo

This commit is contained in:
S. Esmaeili
2026-10-24 10:11:05 +03:30
parent dfd8a82809
commit 7399812d0e
213 changed files with 65702 additions and 2 deletions
+137
View File
@@ -0,0 +1,137 @@
import { z } from "zod";
export declare const ROLES: readonly ["ADMIN", "EDITOR"];
export type Role = (typeof ROLES)[number];
export declare const ROLE_LABELS: Record<Role, string>;
/** Normalize Iranian mobile to `09XXXXXXXXX` (Latin digits). */
export declare function normalizeIrMobile(raw: string): string;
export declare const irMobileSchema: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
export declare const loginSchema: z.ZodObject<{
phone: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
password: z.ZodString;
}, z.core.$strip>;
export type LoginInput = z.infer<typeof loginSchema>;
export declare const changePasswordSchema: z.ZodObject<{
currentPassword: z.ZodString;
newPassword: z.ZodString;
}, z.core.$strip>;
export type ChangePasswordInput = z.infer<typeof changePasswordSchema>;
export declare const userCreateSchema: z.ZodObject<{
phone: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
name: z.ZodString;
role: z.ZodEnum<{
ADMIN: "ADMIN";
EDITOR: "EDITOR";
}>;
password: z.ZodString;
}, z.core.$strip>;
export type UserCreateInput = z.infer<typeof userCreateSchema>;
export declare const userUpdateSchema: z.ZodObject<{
name: z.ZodString;
role: z.ZodEnum<{
ADMIN: "ADMIN";
EDITOR: "EDITOR";
}>;
isActive: z.ZodBoolean;
password: z.ZodOptional<z.ZodString>;
}, z.core.$strip>;
export type UserUpdateInput = z.infer<typeof userUpdateSchema>;
export interface AdminUserDto {
id: number;
phone: string;
name: string;
role: Role;
isActive: boolean;
lastLoginAt: string | null;
createdAt: string;
}
export interface AuthResponse {
accessToken: string;
user: AdminUserDto;
}
export declare const MESSAGE_STATUSES: readonly ["NEW", "READ", "ARCHIVED"];
export type MessageStatus = (typeof MESSAGE_STATUSES)[number];
export declare const MESSAGE_STATUS_LABELS: Record<MessageStatus, string>;
export declare const contactInputSchema: z.ZodObject<{
name: z.ZodString;
org: z.ZodString;
phone: z.ZodString;
message: z.ZodDefault<z.ZodString>;
website: z.ZodOptional<z.ZodString>;
}, z.core.$strip>;
export type ContactInput = z.infer<typeof contactInputSchema>;
export declare const messageUpdateSchema: z.ZodObject<{
status: z.ZodEnum<{
NEW: "NEW";
READ: "READ";
ARCHIVED: "ARCHIVED";
}>;
}, z.core.$strip>;
export interface ContactMessageDto {
id: number;
name: string;
org: string;
phone: string;
message: string;
status: MessageStatus;
createdAt: string;
}
export interface MediaDto {
id: number;
url: string;
alt: string;
mime: string;
size: number;
width: number | null;
height: number | null;
originalName: string;
createdAt: string;
}
export declare const mediaUpdateSchema: z.ZodObject<{
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export interface Paginated<T> {
items: T[];
total: number;
page: number;
pageSize: number;
}
export interface DashboardCategoryStat {
id: number;
name: string;
count: number;
}
export interface DashboardTrendDay {
date: string;
dayName: string;
messages: number;
}
export interface DashboardDto {
categories: number;
products: number;
draftProducts: number;
newMessages: number;
media: number;
recentMessages: ContactMessageDto[];
recentActivity: {
id: number;
action: string;
entity: string;
summary: string;
user: string | null;
createdAt: string;
}[];
categoryStats: DashboardCategoryStat[];
messageBreakdown: {
new: number;
read: number;
archived: number;
total: number;
};
sectionsSummary: {
total: number;
visible: number;
hidden: number;
};
trend: DashboardTrendDay[];
}
//# sourceMappingURL=admin.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"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"}
+80
View File
@@ -0,0 +1,80 @@
import { z } from "zod";
import { req, text } from "./common.js";
export const ROLES = ["ADMIN", "EDITOR"];
export const ROLE_LABELS = {
ADMIN: "مدیر کل",
EDITOR: "ویرایشگر",
};
const password = z.string().min(8, "رمز عبور باید حداقل ۸ کاراکتر باشد").max(128);
const FA_DIGITS = "۰۱۲۳۴۵۶۷۸۹";
const AR_DIGITS = "٠١٢٣٤٥٦٧٨٩";
/** Normalize Iranian mobile to `09XXXXXXXXX` (Latin digits). */
export function normalizeIrMobile(raw) {
let s = raw.trim().replace(/[\s\-()]/g, "");
s = s.replace(/[۰-۹٠-٩]/g, (d) => {
const fa = FA_DIGITS.indexOf(d);
if (fa >= 0)
return String(fa);
const ar = AR_DIGITS.indexOf(d);
return ar >= 0 ? String(ar) : d;
});
if (s.startsWith("+98"))
s = `0${s.slice(3)}`;
else if (s.startsWith("0098"))
s = `0${s.slice(4)}`;
else if (s.startsWith("98") && s.length === 12)
s = `0${s.slice(2)}`;
return s;
}
export const irMobileSchema = z
.string()
.trim()
.min(1, "شماره موبایل را وارد کنید")
.transform(normalizeIrMobile)
.pipe(z.string().regex(/^09\d{9}$/, "شماره موبایل معتبر نیست (مثلاً ۰۹۱۲۱۲۳۴۵۶۷)"));
export const loginSchema = z.object({
phone: irMobileSchema,
password: z.string().min(1, "رمز عبور را وارد کنید").max(128),
});
export const changePasswordSchema = z.object({
currentPassword: z.string().min(1, "رمز فعلی را وارد کنید").max(128),
newPassword: password,
});
export const userCreateSchema = z.object({
phone: irMobileSchema,
name: req(80),
role: z.enum(ROLES),
password,
});
export const userUpdateSchema = z.object({
name: req(80),
role: z.enum(ROLES),
isActive: z.boolean(),
/** set only when resetting the password */
password: password.optional(),
});
/* ---------------- contact messages ---------------- */
export const MESSAGE_STATUSES = ["NEW", "READ", "ARCHIVED"];
export const MESSAGE_STATUS_LABELS = {
NEW: "جدید",
READ: "خوانده‌شده",
ARCHIVED: "بایگانی",
};
export const contactInputSchema = z.object({
name: req(80),
org: req(120),
phone: z
.string()
.trim()
.min(1, "این فیلد الزامی است")
.max(30)
.regex(/^[0-9۰-۹+\-\s()]{5,30}$/, "شماره تماس معتبر نیست"),
message: text(2000),
/** honeypot — real visitors never fill it */
website: z.string().max(200).optional(),
});
export const messageUpdateSchema = z.object({
status: z.enum(MESSAGE_STATUSES),
});
export const mediaUpdateSchema = z.object({ alt: text(200) });
//# sourceMappingURL=admin.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"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"}
+154
View File
@@ -0,0 +1,154 @@
import { z } from "zod";
export declare const productAttributeSchema: z.ZodObject<{
name: z.ZodString;
value: z.ZodString;
}, z.core.$strip>;
export type ProductAttribute = z.infer<typeof productAttributeSchema>;
export declare const productGroupInputSchema: z.ZodObject<{
id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
slug: z.ZodString;
name: z.ZodString;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export type ProductGroupInput = z.infer<typeof productGroupInputSchema>;
export declare const categoryInputSchema: z.ZodObject<{
slug: z.ZodString;
code: z.ZodString;
name: z.ZodString;
nameEn: z.ZodDefault<z.ZodString>;
shortDesc: z.ZodDefault<z.ZodString>;
fullDesc: z.ZodDefault<z.ZodString>;
icon: z.ZodDefault<z.ZodString>;
coverImageId: z.ZodDefault<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
isPublished: z.ZodDefault<z.ZodBoolean>;
seoTitle: z.ZodDefault<z.ZodString>;
seoDescription: z.ZodDefault<z.ZodString>;
groups: z.ZodDefault<z.ZodArray<z.ZodObject<{
id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
slug: z.ZodString;
name: z.ZodString;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>>;
}, z.core.$strip>;
export type CategoryInput = z.infer<typeof categoryInputSchema>;
export declare const productInputSchema: z.ZodObject<{
categoryId: z.ZodCoercedNumber<unknown>;
groupId: z.ZodDefault<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
code: z.ZodString;
slug: z.ZodString;
name: z.ZodString;
nameEn: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
specs: z.ZodDefault<z.ZodArray<z.ZodString>>;
variants: z.ZodDefault<z.ZodArray<z.ZodString>>;
details: z.ZodDefault<z.ZodString>;
brand: z.ZodDefault<z.ZodString>;
origin: z.ZodDefault<z.ZodString>;
sizes: z.ZodDefault<z.ZodArray<z.ZodString>>;
standards: z.ZodDefault<z.ZodArray<z.ZodString>>;
features: z.ZodDefault<z.ZodArray<z.ZodString>>;
applications: z.ZodDefault<z.ZodArray<z.ZodString>>;
attributes: z.ZodDefault<z.ZodArray<z.ZodObject<{
name: z.ZodString;
value: z.ZodString;
}, z.core.$strip>>>;
packaging: z.ZodDefault<z.ZodString>;
minOrder: z.ZodDefault<z.ZodString>;
seoTitle: z.ZodDefault<z.ZodString>;
seoDescription: z.ZodDefault<z.ZodString>;
imageId: z.ZodDefault<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
galleryIds: z.ZodDefault<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
isPublished: z.ZodDefault<z.ZodBoolean>;
}, z.core.$strip>;
export type ProductInput = z.infer<typeof productInputSchema>;
export declare const reorderSchema: z.ZodObject<{
ids: z.ZodArray<z.ZodCoercedNumber<unknown>>;
}, z.core.$strip>;
export type ReorderInput = z.infer<typeof reorderSchema>;
export declare const productListQuerySchema: z.ZodObject<{
categoryId: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
groupId: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
q: z.ZodOptional<z.ZodString>;
status: z.ZodOptional<z.ZodEnum<{
published: "published";
draft: "draft";
}>>;
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
pageSize: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
}, z.core.$strip>;
export type ProductListQuery = z.infer<typeof productListQuerySchema>;
export interface PublicProductGroup {
slug: string;
name: string;
desc: string;
}
export interface PublicProduct {
code: string;
slug: string;
name: string;
nameEn: string;
desc: string;
specs: string[];
variants: string[];
/** image URL, or null when the product has no own photo */
image: string | null;
/** slug of a `PublicCategory.groups` entry */
group: string | null;
}
export interface PublicCategorySummary {
slug: string;
code: string;
name: string;
nameEn: string;
shortDesc: string;
icon: string;
coverImage: string | null;
productCount: number;
}
export interface PublicProductImage {
url: string;
alt: string;
width: number | null;
height: number | null;
}
/** Everything the product page needs (`GET /api/public/products/:slug`) */
export interface PublicProductDetail extends PublicProduct {
details: string;
brand: string;
origin: string;
sizes: string[];
standards: string[];
features: string[];
applications: string[];
attributes: ProductAttribute[];
packaging: string;
minOrder: string;
seoTitle: string;
seoDescription: string;
/** main image first, then the gallery */
images: PublicProductImage[];
groupName: string | null;
category: {
slug: string;
code: string;
name: string;
nameEn: string;
fullDesc: string;
coverImage: string | null;
};
related: PublicProduct[];
updatedAt: string;
}
/** Published product URLs for the sitemap */
export interface PublicProductRef {
slug: string;
updatedAt: string;
}
export interface PublicCategory extends PublicCategorySummary {
fullDesc: string;
seoTitle: string;
seoDescription: string;
groups: PublicProductGroup[];
products: PublicProduct[];
}
//# sourceMappingURL=catalog.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
+66
View File
@@ -0,0 +1,66 @@
import { z } from "zod";
import { idSchema, req, slugSchema, text } from "./common.js";
const shortList = z.array(z.string().trim().min(1).max(120)).max(20).default([]);
export const productAttributeSchema = z.object({
name: req(80),
value: req(300),
});
export const productGroupInputSchema = z.object({
/** present when editing an existing group */
id: idSchema.optional(),
slug: slugSchema,
name: req(120),
desc: text(1000),
});
export const categoryInputSchema = z.object({
slug: slugSchema,
code: req(20),
name: req(120),
nameEn: text(120),
shortDesc: text(500),
fullDesc: text(3000),
icon: text(40),
coverImageId: idSchema.nullable().default(null),
isPublished: z.boolean().default(true),
seoTitle: text(120),
seoDescription: text(300),
groups: z.array(productGroupInputSchema).max(30).default([]),
});
export const productInputSchema = z.object({
categoryId: idSchema,
groupId: idSchema.nullable().default(null),
code: req(30),
slug: slugSchema,
name: req(160),
nameEn: text(160),
desc: text(2000),
specs: shortList,
variants: shortList,
details: text(8000),
brand: text(80),
origin: text(80),
sizes: shortList,
standards: shortList,
features: z.array(z.string().trim().min(1).max(300)).max(30).default([]),
applications: shortList,
attributes: z.array(productAttributeSchema).max(40).default([]),
packaging: text(200),
minOrder: text(120),
seoTitle: text(120),
seoDescription: text(300),
imageId: idSchema.nullable().default(null),
galleryIds: z.array(idSchema).max(12).default([]),
isPublished: z.boolean().default(true),
});
export const reorderSchema = z.object({
ids: z.array(idSchema).min(1).max(1000),
});
export const productListQuerySchema = z.object({
categoryId: idSchema.optional(),
groupId: idSchema.optional(),
q: z.string().trim().max(100).optional(),
status: z.enum(["published", "draft"]).optional(),
page: z.coerce.number().int().min(1).default(1),
pageSize: z.coerce.number().int().min(1).max(200).default(50),
});
//# sourceMappingURL=catalog.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
+27
View File
@@ -0,0 +1,27 @@
import { z } from "zod";
/** Required, trimmed text */
export declare const req: (max?: number) => z.ZodString;
/** Optional, trimmed text (empty string when missing) */
export declare const text: (max?: number) => z.ZodDefault<z.ZodString>;
export declare const idSchema: z.ZodCoercedNumber<unknown>;
export declare const slugSchema: z.ZodString;
export declare const iconNameSchema: z.ZodString;
/** Image stored by URL inside section content */
export declare const imageRefSchema: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export type ImageRef = z.infer<typeof imageRefSchema>;
export declare const linkSchema: z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>;
/** Field validation issue as returned by the API (`path` is dot-joined) */
export interface ValidationIssue {
path: string;
message: string;
}
export declare const toIssues: (error: z.ZodError) => ValidationIssue[];
/** Convert latin digits to Persian digits */
export declare const faNum: (v: number | string) => string;
//# sourceMappingURL=common.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,6BAA6B;AAC7B,eAAO,MAAM,GAAG,GAAI,YAAS,gBAA6D,CAAC;AAC3F,yDAAyD;AACzD,eAAO,MAAM,IAAI,GAAI,YAAS,8BAA2C,CAAC;AAE1E,eAAO,MAAM,QAAQ,6BAAqC,CAAC;AAE3D,eAAO,MAAM,UAAU,aAK4E,CAAC;AAEpG,eAAO,MAAM,cAAc,aAAmC,CAAC;AAE/D,iDAAiD;AACjD,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,UAAU;;;iBAGrB,CAAC;AAEH,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,QAAQ,GAAI,OAAO,CAAC,CAAC,QAAQ,KAAG,eAAe,EAC2B,CAAC;AAExF,6CAA6C;AAC7C,eAAO,MAAM,KAAK,GAAI,GAAG,MAAM,GAAG,MAAM,KAAG,MACgB,CAAC"}
+26
View File
@@ -0,0 +1,26 @@
import { z } from "zod";
/** Required, trimmed text */
export const req = (max = 300) => z.string().trim().min(1, "این فیلد الزامی است").max(max);
/** Optional, trimmed text (empty string when missing) */
export const text = (max = 300) => z.string().trim().max(max).default("");
export const idSchema = z.coerce.number().int().positive();
export const slugSchema = z
.string()
.trim()
.min(1, "این فیلد الزامی است")
.max(80)
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "فقط حروف کوچک انگلیسی، عدد و خط تیره (مثلاً safety-shoes)");
export const iconNameSchema = z.string().trim().min(1).max(80);
/** Image stored by URL inside section content */
export const imageRefSchema = z.object({
url: req(500),
alt: text(200),
});
export const linkSchema = z.object({
label: req(60),
href: req(300),
});
export const toIssues = (error) => error.issues.map((i) => ({ path: i.path.map(String).join("."), message: i.message }));
/** Convert latin digits to Persian digits */
export const faNum = (v) => String(v).replace(/\d/g, (d) => "۰۱۲۳۴۵۶۷۸۹"[Number(d)]);
//# sourceMappingURL=common.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,6BAA6B;AAC7B,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3F,yDAAyD;AACzD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAE1E,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;AAE3D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC;KACxB,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC;KAC7B,GAAG,CAAC,EAAE,CAAC;KACP,KAAK,CAAC,4BAA4B,EAAE,2DAA2D,CAAC,CAAC;AAEpG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAE/D,iDAAiD;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;IACb,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;CACf,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;IACd,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC;CACf,CAAC,CAAC;AAQH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAqB,EAAE,CAC/D,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AAExF,6CAA6C;AAC7C,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAkB,EAAU,EAAE,CAClD,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC"}
+12
View File
@@ -0,0 +1,12 @@
/**
* Vuesax linear icon aliases and recommended picker list.
*/
export declare const ICON_ALIASES: Record<string, string>;
export declare function resolveVuesaxIcon(name: string): string;
/**
* Recommended icon names displayed in pickers and dropdowns
*/
export declare const RECOMMENDED_ICONS: readonly ["shield-tick", "shield-security", "shield-cross", "security-safe", "security-user", "verify", "award", "medal-star", "box-tick", "box", "truck-time", "buildings", "building-4", "buildings-2", "global", "people", "user-tag", "24-support", "call", "sms", "location", "clock", "clipboard-tick", "document-text", "document-filter", "teacher", "status", "search-status", "setting-2", "setting-4", "glass", "tag", "routing-2", "volume-high", "wind-2", "danger", "lamp-on", "gas-station", "hierarchy", "flash", "flash-circle", "tree", "heart-tick", "star", "like-1", "radar-2", "lock", "eye", "gallery", "video-play"];
export declare const ICON_NAMES: readonly ["shield-tick", "shield-security", "shield-cross", "security-safe", "security-user", "verify", "award", "medal-star", "box-tick", "box", "truck-time", "buildings", "building-4", "buildings-2", "global", "people", "user-tag", "24-support", "call", "sms", "location", "clock", "clipboard-tick", "document-text", "document-filter", "teacher", "status", "search-status", "setting-2", "setting-4", "glass", "tag", "routing-2", "volume-high", "wind-2", "danger", "lamp-on", "gas-station", "hierarchy", "flash", "flash-circle", "tree", "heart-tick", "star", "like-1", "radar-2", "lock", "eye", "gallery", "video-play", ...string[]];
export type IconName = string;
//# sourceMappingURL=icons.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmF/C,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAItD;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,8mBAmDpB,CAAC;AAEX,eAAO,MAAM,UAAU,2nBAGb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC"}
+151
View File
@@ -0,0 +1,151 @@
/**
* Vuesax linear icon aliases and recommended picker list.
*/
export const ICON_ALIASES = {
// Navigation & Actions
ArrowLeft: "arrow-left",
ArrowRight: "arrow-right",
ArrowUp: "arrow-up",
ArrowDown: "arrow-down",
ChevronDown: "arrow-down-1",
ChevronUp: "arrow-up-1",
ChevronLeft: "arrow-left-1",
ChevronRight: "arrow-right-1",
Menu: "menu",
X: "close-circle",
Plus: "add",
Trash: "trash",
Edit: "edit-2",
Copy: "copy",
Check: "tick-circle",
Search: "search-normal",
Filter: "filter",
Eye: "eye",
EyeOff: "eye-slash",
ImageOff: "gallery-slash",
Quote: "quote-up",
// Contact & Social
Phone: "call",
Mail: "sms",
MapPin: "location",
Clock: "clock",
Globe: "global",
Send: "send-2",
Instagram: "instagram",
Linkedin: "link",
MessageCircle: "messages-2",
Youtube: "video-play",
AtSign: "sms",
// Equipment & Safety Categories
HardHat: "security-safe",
Glasses: "glass",
Shirt: "tag",
Footprints: "routing-2",
Hand: "shield-tick",
Ear: "volume-high",
Wind: "wind-2",
TriangleAlert: "danger",
Siren: "lamp-on",
TrafficCone: "danger",
Construction: "setting-2",
Factory: "building-4",
Building2: "buildings-2",
Fuel: "gas-station",
Pickaxe: "hierarchy",
Flame: "flash",
Zap: "flash-circle",
Leaf: "tree",
HeartPulse: "heart-tick",
Star: "star",
ThumbsUp: "like-1",
Target: "radar-2",
Lock: "lock",
// Trust, Certifications & Standards
ShieldCheck: "shield-tick",
ShieldPlus: "shield-security",
ShieldAlert: "shield-cross",
BadgeCheck: "verify",
Award: "award",
Medal: "medal-star",
PackageCheck: "box-tick",
Package: "box",
Truck: "truck-time",
Warehouse: "buildings",
Users: "people",
Handshake: "user-tag",
Headset: "24-support",
ClipboardCheck: "clipboard-tick",
FileCheck: "document-text",
FileSearch: "document-filter",
GraduationCap: "teacher",
Gauge: "status",
Microscope: "search-status",
Wrench: "setting-4",
};
export function resolveVuesaxIcon(name) {
if (!name)
return "shield-tick";
if (name in ICON_ALIASES)
return ICON_ALIASES[name];
return name.replace(/^vuesax-linear:/, "");
}
/**
* Recommended icon names displayed in pickers and dropdowns
*/
export const RECOMMENDED_ICONS = [
"shield-tick",
"shield-security",
"shield-cross",
"security-safe",
"security-user",
"verify",
"award",
"medal-star",
"box-tick",
"box",
"truck-time",
"buildings",
"building-4",
"buildings-2",
"global",
"people",
"user-tag",
"24-support",
"call",
"sms",
"location",
"clock",
"clipboard-tick",
"document-text",
"document-filter",
"teacher",
"status",
"search-status",
"setting-2",
"setting-4",
"glass",
"tag",
"routing-2",
"volume-high",
"wind-2",
"danger",
"lamp-on",
"gas-station",
"hierarchy",
"flash",
"flash-circle",
"tree",
"heart-tick",
"star",
"like-1",
"radar-2",
"lock",
"eye",
"gallery",
"video-play",
];
export const ICON_NAMES = [
...RECOMMENDED_ICONS,
...Object.keys(ICON_ALIASES),
];
//# sourceMappingURL=icons.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"icons.js","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"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"}
+13
View File
@@ -0,0 +1,13 @@
export * from "./common.js";
export * from "./icons.js";
export * from "./catalog.js";
export * from "./sections.js";
export * from "./admin.js";
import type { PublicCategorySummary } from "./catalog.js";
import type { SiteSections } from "./sections.js";
/** Everything the home page needs, returned by `GET /api/public/site` in one request */
export interface PublicSite {
sections: SiteSections;
categories: PublicCategorySummary[];
}
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAE3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,wFAAwF;AACxF,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,qBAAqB,EAAE,CAAC;CACrC"}
+6
View File
@@ -0,0 +1,6 @@
export * from "./common.js";
export * from "./icons.js";
export * from "./catalog.js";
export * from "./sections.js";
export * from "./admin.js";
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
+467
View File
@@ -0,0 +1,467 @@
import { z } from "zod";
/**
* Editable website sections. Each key is one row in the `SiteSection` table whose `data`
* column must match the schema below — validated by the API on write and by the admin forms.
*
* Multi-line titles use "\n" for line breaks.
*/
export declare const WEEK_DAYS: readonly ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"];
export declare const SOCIAL_TYPES: readonly ["website", "telegram", "instagram", "linkedin", "whatsapp", "bale", "eitaa", "aparat", "youtube", "email", "phone"];
export type SocialType = (typeof SOCIAL_TYPES)[number];
export declare const sectionHeadSchema: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export type SectionHeadData = z.infer<typeof sectionHeadSchema>;
export declare const settingsSectionSchema: z.ZodObject<{
name: z.ZodString;
nameEn: z.ZodString;
title: z.ZodString;
description: z.ZodString;
phone: z.ZodString;
phoneDisplay: z.ZodString;
email: z.ZodEmail;
address: z.ZodObject<{
street: z.ZodString;
locality: z.ZodString;
country: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
workingHours: z.ZodString;
openingHours: z.ZodObject<{
days: z.ZodArray<z.ZodEnum<{
Saturday: "Saturday";
Sunday: "Sunday";
Monday: "Monday";
Tuesday: "Tuesday";
Wednesday: "Wednesday";
Thursday: "Thursday";
Friday: "Friday";
}>>;
opens: z.ZodString;
closes: z.ZodString;
}, z.core.$strip>;
foundingDate: z.ZodString;
socials: z.ZodArray<z.ZodObject<{
type: z.ZodEnum<{
instagram: "instagram";
phone: "phone";
website: "website";
telegram: "telegram";
linkedin: "linkedin";
whatsapp: "whatsapp";
bale: "bale";
eitaa: "eitaa";
aparat: "aparat";
youtube: "youtube";
email: "email";
}>;
url: z.ZodString;
}, z.core.$strip>>;
ogImage: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
width: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
height: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
}, z.core.$strip>;
}, z.core.$strip>;
export declare const heroSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
badge: z.ZodString;
title: z.ZodString;
titleHighlight: z.ZodString;
intro: z.ZodString;
primaryCta: z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>;
secondaryCta: z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>;
chips: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
miniStats: z.ZodArray<z.ZodObject<{
value: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
image: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
lastInspection: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export declare const tapeSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
items: z.ZodArray<z.ZodString>;
}, z.core.$strip>;
export declare const statsSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
items: z.ZodArray<z.ZodObject<{
end: z.ZodNumber;
suffix: z.ZodDefault<z.ZodString>;
label: z.ZodString;
note: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const productsIntroSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
ctaLabel: z.ZodString;
trust: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
title: z.ZodString;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const aboutSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
body: z.ZodString;
image: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
badge: z.ZodObject<{
value: z.ZodString;
label: z.ZodString;
}, z.core.$strip>;
timeline: z.ZodArray<z.ZodObject<{
year: z.ZodString;
text: z.ZodString;
}, z.core.$strip>>;
features: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const servicesSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
items: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
title: z.ZodString;
desc: z.ZodString;
items: z.ZodArray<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const standardsSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
note: z.ZodDefault<z.ZodString>;
ctaLabel: z.ZodString;
items: z.ZodArray<z.ZodObject<{
code: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const industriesSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
items: z.ZodArray<z.ZodObject<{
name: z.ZodString;
nameEn: z.ZodDefault<z.ZodString>;
count: z.ZodDefault<z.ZodString>;
image: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const testimonialsSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
items: z.ZodArray<z.ZodObject<{
text: z.ZodString;
name: z.ZodString;
role: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
export declare const contactSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
emergencyTitle: z.ZodString;
emergencyText: z.ZodString;
formTag: z.ZodDefault<z.ZodString>;
formTitle: z.ZodString;
successTitle: z.ZodString;
successText: z.ZodString;
}, z.core.$strip>;
export declare const footerSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
about: z.ZodString;
copyright: z.ZodString;
certLine: z.ZodDefault<z.ZodString>;
emergencyNote: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export declare const sectionSchemas: {
readonly settings: z.ZodObject<{
name: z.ZodString;
nameEn: z.ZodString;
title: z.ZodString;
description: z.ZodString;
phone: z.ZodString;
phoneDisplay: z.ZodString;
email: z.ZodEmail;
address: z.ZodObject<{
street: z.ZodString;
locality: z.ZodString;
country: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
workingHours: z.ZodString;
openingHours: z.ZodObject<{
days: z.ZodArray<z.ZodEnum<{
Saturday: "Saturday";
Sunday: "Sunday";
Monday: "Monday";
Tuesday: "Tuesday";
Wednesday: "Wednesday";
Thursday: "Thursday";
Friday: "Friday";
}>>;
opens: z.ZodString;
closes: z.ZodString;
}, z.core.$strip>;
foundingDate: z.ZodString;
socials: z.ZodArray<z.ZodObject<{
type: z.ZodEnum<{
instagram: "instagram";
phone: "phone";
website: "website";
telegram: "telegram";
linkedin: "linkedin";
whatsapp: "whatsapp";
bale: "bale";
eitaa: "eitaa";
aparat: "aparat";
youtube: "youtube";
email: "email";
}>;
url: z.ZodString;
}, z.core.$strip>>;
ogImage: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
width: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
height: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
}, z.core.$strip>;
}, z.core.$strip>;
readonly hero: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
badge: z.ZodString;
title: z.ZodString;
titleHighlight: z.ZodString;
intro: z.ZodString;
primaryCta: z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>;
secondaryCta: z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>;
chips: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
miniStats: z.ZodArray<z.ZodObject<{
value: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
image: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
lastInspection: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
readonly tape: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
items: z.ZodArray<z.ZodString>;
}, z.core.$strip>;
readonly stats: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
items: z.ZodArray<z.ZodObject<{
end: z.ZodNumber;
suffix: z.ZodDefault<z.ZodString>;
label: z.ZodString;
note: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly productsIntro: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
ctaLabel: z.ZodString;
trust: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
title: z.ZodString;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly about: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
body: z.ZodString;
image: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
badge: z.ZodObject<{
value: z.ZodString;
label: z.ZodString;
}, z.core.$strip>;
timeline: z.ZodArray<z.ZodObject<{
year: z.ZodString;
text: z.ZodString;
}, z.core.$strip>>;
features: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly services: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
items: z.ZodArray<z.ZodObject<{
icon: z.ZodString;
title: z.ZodString;
desc: z.ZodString;
items: z.ZodArray<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly standards: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
note: z.ZodDefault<z.ZodString>;
ctaLabel: z.ZodString;
items: z.ZodArray<z.ZodObject<{
code: z.ZodString;
label: z.ZodString;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly industries: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
items: z.ZodArray<z.ZodObject<{
name: z.ZodString;
nameEn: z.ZodDefault<z.ZodString>;
count: z.ZodDefault<z.ZodString>;
image: z.ZodObject<{
url: z.ZodString;
alt: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly testimonials: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
items: z.ZodArray<z.ZodObject<{
text: z.ZodString;
name: z.ZodString;
role: z.ZodDefault<z.ZodString>;
}, z.core.$strip>>;
}, z.core.$strip>;
readonly contact: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
head: z.ZodObject<{
tag: z.ZodString;
title: z.ZodString;
highlight: z.ZodDefault<z.ZodString>;
desc: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
emergencyTitle: z.ZodString;
emergencyText: z.ZodString;
formTag: z.ZodDefault<z.ZodString>;
formTitle: z.ZodString;
successTitle: z.ZodString;
successText: z.ZodString;
}, z.core.$strip>;
readonly footer: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
about: z.ZodString;
copyright: z.ZodString;
certLine: z.ZodDefault<z.ZodString>;
emergencyNote: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
};
export type SectionKey = keyof typeof sectionSchemas;
export declare const SECTION_KEYS: SectionKey[];
export type SectionData<K extends SectionKey> = z.infer<(typeof sectionSchemas)[K]>;
export type SiteSections = {
[K in SectionKey]: SectionData<K>;
};
export type SiteSettings = SectionData<"settings">;
export declare const isSectionKey: (key: string) => key is SectionKey;
/** Persian labels for the admin panel */
export declare const SECTION_LABELS: Record<SectionKey, {
title: string;
desc: string;
}>;
//# sourceMappingURL=sections.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AAEH,eAAO,MAAM,SAAS,yFAQZ,CAAC;AAEX,eAAO,MAAM,YAAY,+HAYf,CAAC;AACX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAKvD,eAAO,MAAM,iBAAiB;;;;;iBAM5B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BhC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAa5B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;iBAY7B,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;iBAKrC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;iBAQ7B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;iBAahC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;iBAMjC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;iBAalC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;iBAIpC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;iBAS/B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;iBAM9B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAajB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,cAAc,CAAC;AACrD,eAAO,MAAM,YAAY,EAAkC,UAAU,EAAE,CAAC;AACxE,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpF,MAAM,MAAM,YAAY,GAAG;KAAG,CAAC,IAAI,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC;CAAE,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;AAEnD,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,GAAG,IAAI,UAAmC,CAAC;AAEtF,yCAAyC;AACzC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAa9E,CAAC"}
+198
View File
@@ -0,0 +1,198 @@
import { z } from "zod";
import { iconNameSchema, imageRefSchema, linkSchema, req, text } from "./common.js";
/**
* Editable website sections. Each key is one row in the `SiteSection` table whose `data`
* column must match the schema below — validated by the API on write and by the admin forms.
*
* Multi-line titles use "\n" for line breaks.
*/
export const WEEK_DAYS = [
"Saturday",
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
];
export const SOCIAL_TYPES = [
"website",
"telegram",
"instagram",
"linkedin",
"whatsapp",
"bale",
"eitaa",
"aparat",
"youtube",
"email",
"phone",
];
const iconLabel = z.object({ icon: iconNameSchema, label: req(80) });
const iconCard = z.object({ icon: iconNameSchema, title: req(80), desc: text(300) });
export const sectionHeadSchema = z.object({
tag: req(80),
title: req(200),
/** optional accented last line of the title */
highlight: text(120),
desc: text(500),
});
export const settingsSectionSchema = z.object({
name: req(80),
nameEn: req(120),
/** default <title> and og:title */
title: req(120),
/** default meta description */
description: req(400),
/** machine-readable phone for tel: links and schema.org, e.g. +98-21-91008800 */
phone: req(30),
phoneDisplay: req(40),
email: z.email("ایمیل معتبر نیست"),
address: z.object({
street: req(200),
locality: req(80),
country: z.string().trim().length(2).default("IR"),
}),
/** human-readable working hours, e.g. «شنبه تا پنجشنبه — ۸:۰۰ تا ۱۷:۰۰» */
workingHours: req(120),
openingHours: z.object({
days: z.array(z.enum(WEEK_DAYS)).max(7),
opens: z.string().regex(/^\d{2}:\d{2}$/, "قالب ساعت باید HH:MM باشد"),
closes: z.string().regex(/^\d{2}:\d{2}$/, "قالب ساعت باید HH:MM باشد"),
}),
foundingDate: z.string().regex(/^\d{4}$/, "سال میلادی چهاررقمی"),
socials: z.array(z.object({ type: z.enum(SOCIAL_TYPES), url: req(300) })).max(12),
ogImage: imageRefSchema.extend({
width: z.number().int().positive().nullable().default(null),
height: z.number().int().positive().nullable().default(null),
}),
});
export const heroSectionSchema = z.object({
enabled: z.boolean().default(true),
badge: req(120),
title: req(80),
titleHighlight: req(80),
intro: req(600),
primaryCta: linkSchema,
secondaryCta: linkSchema,
chips: z.array(iconLabel).max(6),
miniStats: z.array(z.object({ value: req(20), label: req(80) })).max(4),
image: imageRefSchema,
/** «آخرین بازرسی» date shown on the status card */
lastInspection: text(20),
});
export const tapeSectionSchema = z.object({
enabled: z.boolean().default(true),
items: z.array(req(80)).min(1).max(20),
});
export const statsSectionSchema = z.object({
enabled: z.boolean().default(true),
items: z
.array(z.object({
end: z.number().int().min(0).max(1_000_000_000),
suffix: text(5),
label: req(80),
note: text(40),
}))
.max(8),
});
export const productsIntroSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
ctaLabel: req(60),
trust: z.array(iconCard).max(6),
});
export const aboutSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
body: req(2000),
image: imageRefSchema,
badge: z.object({ value: req(20), label: req(80) }),
timeline: z.array(z.object({ year: req(10), text: req(200) })).max(12),
features: z.array(iconLabel).max(6),
});
export const servicesSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
items: z
.array(z.object({
icon: iconNameSchema,
title: req(80),
desc: req(600),
items: z.array(req(120)).max(8),
}))
.max(10),
});
export const standardsSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
note: text(500),
ctaLabel: req(80),
items: z.array(z.object({ code: req(30), label: req(80) })).max(12),
});
export const industriesSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
items: z
.array(z.object({
name: req(60),
nameEn: text(60),
count: text(20),
image: imageRefSchema,
}))
.max(12),
});
export const testimonialsSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
items: z.array(z.object({ text: req(600), name: req(80), role: text(160) })).max(12),
});
export const contactSectionSchema = z.object({
enabled: z.boolean().default(true),
head: sectionHeadSchema,
emergencyTitle: req(80),
emergencyText: req(400),
formTag: text(80),
formTitle: req(160),
successTitle: req(80),
successText: req(300),
});
export const footerSectionSchema = z.object({
enabled: z.boolean().default(true),
about: req(500),
copyright: req(160),
certLine: text(160),
emergencyNote: text(80),
});
export const sectionSchemas = {
settings: settingsSectionSchema,
hero: heroSectionSchema,
tape: tapeSectionSchema,
stats: statsSectionSchema,
productsIntro: productsIntroSectionSchema,
about: aboutSectionSchema,
services: servicesSectionSchema,
standards: standardsSectionSchema,
industries: industriesSectionSchema,
testimonials: testimonialsSectionSchema,
contact: contactSectionSchema,
footer: footerSectionSchema,
};
export const SECTION_KEYS = Object.keys(sectionSchemas);
export const isSectionKey = (key) => key in sectionSchemas;
/** Persian labels for the admin panel */
export const SECTION_LABELS = {
settings: { title: "تنظیمات سایت", desc: "نام، اطلاعات تماس، ساعات کاری، شبکه‌های اجتماعی و سئوی پیش‌فرض" },
hero: { title: "بخش اول (Hero)", desc: "تیتر اصلی، متن معرفی، دکمه‌ها، نشان‌ها و تصویر پس‌زمینه" },
tape: { title: "نوار متحرک", desc: "عبارت‌های نوار زرد متحرک زیر Hero" },
stats: { title: "آمار", desc: "شمارنده‌های عددی" },
productsIntro: { title: "معرفی محصولات", desc: "عنوان بخش محصولات و کارت‌های اعتماد" },
about: { title: "درباره ما", desc: "متن معرفی، تصویر، تایم‌لاین و ویژگی‌ها" },
services: { title: "خدمات", desc: "فهرست خدمات و جزئیات هر خدمت" },
standards: { title: "استانداردها", desc: "استانداردها و گواهی‌نامه‌ها" },
industries: { title: "صنایع", desc: "صنایع تحت پوشش و تصویر هرکدام" },
testimonials: { title: "نظرات مشتریان", desc: "نقل‌قول‌های مشتریان" },
contact: { title: "تماس با ما", desc: "عنوان‌ها و متن‌های فرم تماس" },
footer: { title: "فوتر", desc: "متن معرفی، کپی‌رایت و توضیحات پایین صفحه" },
};
//# sourceMappingURL=sections.js.map
File diff suppressed because one or more lines are too long