feat(admin): editable contact fields in sections and larger logos

Allow address, phone, map, and related site chrome to be edited from contact/settings for all editors, and enlarge brand marks on login, header, and preloader.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
S. Esmaeili
2026-11-12 18:42:59 +03:30
co-authored by Cursor
parent cad1a8652e
commit 9ad88af20f
26 changed files with 285 additions and 108 deletions
+20
View File
@@ -28,6 +28,7 @@ export declare const settingsSectionSchema: z.ZodObject<{
locality: z.ZodString;
country: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
mapUrl: z.ZodDefault<z.ZodString>;
workingHours: z.ZodString;
openingHours: z.ZodObject<{
days: z.ZodArray<z.ZodEnum<{
@@ -43,6 +44,10 @@ export declare const settingsSectionSchema: z.ZodObject<{
closes: z.ZodString;
}, z.core.$strip>;
foundingDate: z.ZodString;
headerCta: z.ZodDefault<z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>>;
socials: z.ZodArray<z.ZodObject<{
type: z.ZodEnum<{
instagram: "instagram";
@@ -224,6 +229,8 @@ export declare const contactSectionSchema: z.ZodObject<{
formTitle: z.ZodString;
successTitle: z.ZodString;
successText: z.ZodString;
submitLabel: z.ZodDefault<z.ZodString>;
resetLabel: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export declare const footerSectionSchema: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
@@ -231,6 +238,9 @@ export declare const footerSectionSchema: z.ZodObject<{
copyright: z.ZodString;
certLine: z.ZodDefault<z.ZodString>;
emergencyNote: z.ZodDefault<z.ZodString>;
linksTitle: z.ZodDefault<z.ZodString>;
productsTitle: z.ZodDefault<z.ZodString>;
contactTitle: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
export declare const sectionSchemas: {
readonly settings: z.ZodObject<{
@@ -246,6 +256,7 @@ export declare const sectionSchemas: {
locality: z.ZodString;
country: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
mapUrl: z.ZodDefault<z.ZodString>;
workingHours: z.ZodString;
openingHours: z.ZodObject<{
days: z.ZodArray<z.ZodEnum<{
@@ -261,6 +272,10 @@ export declare const sectionSchemas: {
closes: z.ZodString;
}, z.core.$strip>;
foundingDate: z.ZodString;
headerCta: z.ZodDefault<z.ZodObject<{
label: z.ZodString;
href: z.ZodString;
}, z.core.$strip>>;
socials: z.ZodArray<z.ZodObject<{
type: z.ZodEnum<{
instagram: "instagram";
@@ -442,6 +457,8 @@ export declare const sectionSchemas: {
formTitle: z.ZodString;
successTitle: z.ZodString;
successText: z.ZodString;
submitLabel: z.ZodDefault<z.ZodString>;
resetLabel: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
readonly footer: z.ZodObject<{
enabled: z.ZodDefault<z.ZodBoolean>;
@@ -449,6 +466,9 @@ export declare const sectionSchemas: {
copyright: z.ZodString;
certLine: z.ZodDefault<z.ZodString>;
emergencyNote: z.ZodDefault<z.ZodString>;
linksTitle: z.ZodDefault<z.ZodString>;
productsTitle: z.ZodDefault<z.ZodString>;
contactTitle: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
};
export type SectionKey = keyof typeof sectionSchemas;
+1 -1
View File
@@ -1 +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"}
{"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiChC,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;;;;;;;;;;;;;;;;iBAa/B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;iBAU9B,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"}
+14 -2
View File
@@ -53,6 +53,8 @@ export const settingsSectionSchema = z.object({
locality: req(80),
country: z.string().trim().length(2).default("IR"),
}),
/** Google Maps / Neshan / etc. share link shown next to the address */
mapUrl: text(500),
/** human-readable working hours, e.g. «شنبه تا پنجشنبه — ۸:۰۰ تا ۱۷:۰۰» */
workingHours: req(120),
openingHours: z.object({
@@ -61,6 +63,8 @@ export const settingsSectionSchema = z.object({
closes: z.string().regex(/^\d{2}:\d{2}$/, "قالب ساعت باید HH:MM باشد"),
}),
foundingDate: z.string().regex(/^\d{4}$/, "سال میلادی چهاررقمی"),
/** sticky header CTA (e.g. «درخواست مشاوره») */
headerCta: linkSchema.default({ label: "درخواست مشاوره", href: "/#contact" }),
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),
@@ -156,6 +160,10 @@ export const contactSectionSchema = z.object({
formTitle: req(160),
successTitle: req(80),
successText: req(300),
/** submit button on the contact form */
submitLabel: req(80).default("ارسال درخواست مشاوره"),
/** button shown after a successful submit */
resetLabel: req(80).default("ثبت درخواست جدید"),
});
export const footerSectionSchema = z.object({
enabled: z.boolean().default(true),
@@ -163,6 +171,10 @@ export const footerSectionSchema = z.object({
copyright: req(160),
certLine: text(160),
emergencyNote: text(80),
/** column headings under the brand block */
linksTitle: req(40).default("دسترسی"),
productsTitle: req(40).default("محصولات"),
contactTitle: req(40).default("ارتباط"),
});
export const sectionSchemas = {
settings: settingsSectionSchema,
@@ -192,7 +204,7 @@ export const SECTION_LABELS = {
standards: { title: "استانداردها", desc: "استانداردها و گواهی‌نامه‌ها" },
industries: { title: "صنایع", desc: "صنایع تحت پوشش و تصویر هرکدام" },
testimonials: { title: "نظرات مشتریان", desc: "نقل‌قول‌های مشتریان" },
contact: { title: "تماس با ما", desc: "عنوان‌ها و متن‌های فرم تماس" },
footer: { title: "فوتر", desc: "متن معرفی، کپی‌رایت و توضیحات پایین صفحه" },
contact: { title: "تماس با ما", desc: "عنوان‌ها، متن‌های فرم، و ویرایش نشانی و اطلاعات تماس" },
footer: { title: "فوتر", desc: "متن معرفی، عناوین ستون‌ها، کپی‌رایت و توضیحات پایین صفحه" },
};
//# sourceMappingURL=sections.js.map
File diff suppressed because one or more lines are too long
+14 -2
View File
@@ -61,6 +61,8 @@ export const settingsSectionSchema = z.object({
locality: req(80),
country: z.string().trim().length(2).default("IR"),
}),
/** Google Maps / Neshan / etc. share link shown next to the address */
mapUrl: text(500),
/** human-readable working hours, e.g. «شنبه تا پنجشنبه — ۸:۰۰ تا ۱۷:۰۰» */
workingHours: req(120),
openingHours: z.object({
@@ -69,6 +71,8 @@ export const settingsSectionSchema = z.object({
closes: z.string().regex(/^\d{2}:\d{2}$/, "قالب ساعت باید HH:MM باشد"),
}),
foundingDate: z.string().regex(/^\d{4}$/, "سال میلادی چهاررقمی"),
/** sticky header CTA (e.g. «درخواست مشاوره») */
headerCta: linkSchema.default({ label: "درخواست مشاوره", href: "/#contact" }),
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),
@@ -180,6 +184,10 @@ export const contactSectionSchema = z.object({
formTitle: req(160),
successTitle: req(80),
successText: req(300),
/** submit button on the contact form */
submitLabel: req(80).default("ارسال درخواست مشاوره"),
/** button shown after a successful submit */
resetLabel: req(80).default("ثبت درخواست جدید"),
});
export const footerSectionSchema = z.object({
@@ -188,6 +196,10 @@ export const footerSectionSchema = z.object({
copyright: req(160),
certLine: text(160),
emergencyNote: text(80),
/** column headings under the brand block */
linksTitle: req(40).default("دسترسی"),
productsTitle: req(40).default("محصولات"),
contactTitle: req(40).default("ارتباط"),
});
export const sectionSchemas = {
@@ -225,6 +237,6 @@ export const SECTION_LABELS: Record<SectionKey, { title: string; desc: string }>
standards: { title: "استانداردها", desc: "استانداردها و گواهی‌نامه‌ها" },
industries: { title: "صنایع", desc: "صنایع تحت پوشش و تصویر هرکدام" },
testimonials: { title: "نظرات مشتریان", desc: "نقل‌قول‌های مشتریان" },
contact: { title: "تماس با ما", desc: "عنوان‌ها و متن‌های فرم تماس" },
footer: { title: "فوتر", desc: "متن معرفی، کپی‌رایت و توضیحات پایین صفحه" },
contact: { title: "تماس با ما", desc: "عنوان‌ها، متن‌های فرم، و ویرایش نشانی و اطلاعات تماس" },
footer: { title: "فوتر", desc: "متن معرفی، عناوین ستون‌ها، کپی‌رایت و توضیحات پایین صفحه" },
};