feat: full site build — Project/Melody schema (Option A), admin CRUD, public sections, uploads, email+SMTP, internal analytics, legal pages, docs

This commit is contained in:
2026-08-05 20:53:40 +02:00
parent d87f3033c6
commit c26f41511f
122 changed files with 15068 additions and 41 deletions
+18
View File
@@ -10,9 +10,18 @@ const ar: Dictionary = {
themeDark: "داكن",
nav: {
home: "الرئيسية",
projects: "المشاريع",
apps: "التطبيقات",
melodies: "الألحان",
about: "من أنا",
contact: "تواصل",
},
legal: {
label: "الصفحات الرسمية",
privacy: "الخصوصية",
terms: "شروط الاستخدام",
impressum: "Impressum · بيانات المزوّد",
},
footerRights: "{year} جميع الحقوق محفوظة",
variants: {
comingSoon: {
@@ -92,6 +101,15 @@ const ar: Dictionary = {
channelsTitle: "روابطك المباشرة",
channelCta: "فتح الرابط",
channelFallback: "ستظهر القناة هنا بعد إضافة الرابط الفعلي",
formName: "الاسم",
formEmail: "البريد الإلكتروني",
formMessage: "الرسالة",
formSubmit: "إرسال الرسالة",
formSending: "جارٍ الإرسال…",
formSuccess: "تم استلام رسالتك، وسأعود إليك قريباً.",
formSavedWarning: "تم حفظ رسالتك، لكن تعذّر إرسال إشعار البريد حالياً.",
formInvalid: "تحقق من الاسم والبريد والرسالة وحاول مجدداً.",
formRateLimit: "تم تجاوز الحد المؤقت للإرسال. حاول بعد قليل.",
channels: [
{ key: "email", name: "البريد الإلكتروني", hint: "للتواصل المهني المباشر والاستفسارات" },
{ key: "linkedin", name: "لينكدإن", hint: "للعلاقات المهنية والعرض السريع للخبرات" },
+18
View File
@@ -10,9 +10,18 @@ const en: Dictionary = {
themeDark: "Dark",
nav: {
home: "Home",
projects: "Projects",
apps: "Apps",
melodies: "Melodies",
about: "About",
contact: "Contact",
},
legal: {
label: "Legal pages",
privacy: "Privacy",
terms: "Terms",
impressum: "Legal notice",
},
footerRights: "{year} All rights reserved",
variants: {
comingSoon: {
@@ -92,6 +101,15 @@ const en: Dictionary = {
channelsTitle: "Direct contact links",
channelCta: "Open link",
channelFallback: "This channel will appear once the real link is added",
formName: "Name",
formEmail: "Email",
formMessage: "Message",
formSubmit: "Send message",
formSending: "Sending…",
formSuccess: "Your message was received. Ill get back to you soon.",
formSavedWarning: "Your message was saved, but the email notification could not be sent right now.",
formInvalid: "Check your name, email, and message, then try again.",
formRateLimit: "The temporary sending limit was reached. Please try again later.",
channels: [
{ key: "email", name: "Email", hint: "For direct professional contact and project inquiries" },
{ key: "linkedin", name: "LinkedIn", hint: "For professional background and networking" },
+18
View File
@@ -17,9 +17,18 @@ export type CommonContent = {
themeDark: string;
nav: {
home: string;
projects: string;
apps: string;
melodies: string;
about: string;
contact: string;
};
legal: {
label: string;
privacy: string;
terms: string;
impressum: string;
};
footerRights: string;
variants: ModeVariants<CommonVariantContent>;
};
@@ -66,6 +75,15 @@ export type ContactContent = {
channelsTitle: string;
channelCta: string;
channelFallback: string;
formName: string;
formEmail: string;
formMessage: string;
formSubmit: string;
formSending: string;
formSuccess: string;
formSavedWarning: string;
formInvalid: string;
formRateLimit: string;
channels: ContactChannelContent[];
};