133 lines
5.5 KiB
TypeScript
133 lines
5.5 KiB
TypeScript
import { Router } from "express";
|
||
import { db } from "@workspace/db";
|
||
import { storeSettingsTable } from "@workspace/db/schema";
|
||
|
||
const router = Router();
|
||
|
||
export const DEFAULT_SETTINGS: Record<string, string> = {
|
||
// Branding
|
||
store_name_ar: "متجر اكسترا",
|
||
store_name_en: "eXtra Store",
|
||
store_icon: "⚡",
|
||
store_logo_url: "",
|
||
primary_color: "#f97316",
|
||
|
||
// Announcement bar
|
||
announcement_enabled: "true",
|
||
announcement_text: "🎉 شحن مجاني على جميع الطلبات فوق 200 ر.س | عروض حصرية كل يوم",
|
||
announcement_text_en: "🎉 Free shipping on all orders over 200 SAR | Exclusive deals every day",
|
||
announcement_color: "#f97316",
|
||
announcement_text_color: "#ffffff",
|
||
|
||
// Hero section
|
||
hero_enabled: "true",
|
||
hero_title_ar: "أفضل الإلكترونيات\nفي المملكة العربية السعودية",
|
||
hero_title_en: "Best Electronics\nin Saudi Arabia",
|
||
hero_subtitle_ar: "اكتشف أحدث الهواتف، اللابتوبات، الأجهزة المنزلية والمزيد بأسعار لا تُضاهى",
|
||
hero_subtitle_en: "Discover the latest phones, laptops, home appliances and more at unbeatable prices",
|
||
hero_cta_ar: "تسوق الآن",
|
||
hero_cta_en: "Shop Now",
|
||
hero_cta_link: "/category/0",
|
||
hero_badge_ar: "⚡ عروض حصرية لفترة محدودة",
|
||
hero_badge_en: "⚡ Exclusive limited-time offers",
|
||
hero_bg_image: "",
|
||
hero_accent_color: "#f97316",
|
||
|
||
// Home sections
|
||
section_trending_enabled: "true",
|
||
section_trending_title_ar: "الأكثر رواجاً",
|
||
section_trending_title_en: "Trending",
|
||
section_trending_icon: "🔥",
|
||
section_bestseller_enabled: "true",
|
||
section_bestseller_title_ar: "الأكثر مبيعاً",
|
||
section_bestseller_title_en: "Best Sellers",
|
||
section_bestseller_icon: "⭐",
|
||
section_new_enabled: "true",
|
||
section_new_title_ar: "وصل حديثاً",
|
||
section_new_title_en: "New Arrivals",
|
||
section_new_icon: "✨",
|
||
|
||
// Promo banners (JSON array)
|
||
promo_banners: "[]",
|
||
|
||
// Extra categories section
|
||
extra_section_enabled: "true",
|
||
extra_section_title_ar: "اكسترا — إلكترونيات وأجهزة",
|
||
extra_section_title_en: "eXtra — Electronics & Appliances",
|
||
|
||
// Shein section
|
||
shein_section_enabled: "true",
|
||
shein_section_title_ar: "أزياء، جمال ومنزل",
|
||
shein_section_title_en: "Fashion, Beauty & Home",
|
||
|
||
// Footer
|
||
footer_tagline_ar: "متجرك المفضل للإلكترونيات والأزياء في المملكة",
|
||
|
||
// Cart & Checkout settings
|
||
cart_free_shipping_riyadh: "100",
|
||
cart_free_shipping_other: "200",
|
||
cart_delivery_fee_riyadh: "15",
|
||
cart_delivery_fee_other: "30",
|
||
cart_min_order: "0",
|
||
cart_max_qty: "10",
|
||
cart_banner_enabled: "false",
|
||
cart_banner_text: "🚚 التوصيل خلال 2-3 أيام عمل | شحن مجاني فوق 200 ر.س",
|
||
cart_banner_color: "#1a1a1a",
|
||
cart_payment_mada: "true",
|
||
cart_payment_visa: "true",
|
||
cart_payment_applepay: "true",
|
||
cart_payment_stcpay: "true",
|
||
cart_checkout_note: "",
|
||
|
||
// Delivery page conditions (JSON array)
|
||
delivery_conditions: JSON.stringify([
|
||
{ id: "1", text: "التوصيل لجميع مناطق المملكة العربية السعودية خلال 3–7 أيام عمل حسب المدينة.", text_en: "Delivery to all regions of Saudi Arabia within 3–7 business days depending on the city.", visible: true },
|
||
{ id: "2", text: "الشحن مجاني للطلبات التي تتجاوز 200 ر.س.", text_en: "Free shipping on orders over 200 SAR.", visible: true },
|
||
{ id: "3", text: "سيتم التواصل معك عبر رقم الجوال لتأكيد الطلب وتحديد موعد التوصيل.", text_en: "We will contact you via mobile to confirm the order and schedule delivery.", visible: true },
|
||
{ id: "4", text: "في حال الغياب وقت التوصيل، يُعاد الطلب للمستودع ويُتواصل معك لإعادة الجدولة.", text_en: "If absent during delivery, the order will be returned to the warehouse and we will contact you to reschedule.", visible: true },
|
||
{ id: "5", text: "قد تختلف مواعيد التوصيل خلال المواسم والإجازات الرسمية.", text_en: "Delivery times may vary during peak seasons and official holidays.", visible: true }
|
||
]),
|
||
};
|
||
|
||
// Public GET — no auth required (storefront reads this)
|
||
router.get("/public-settings", async (_req, res) => {
|
||
try {
|
||
const rows = await db.select().from(storeSettingsTable);
|
||
const settings = { ...DEFAULT_SETTINGS };
|
||
rows.forEach(r => { settings[r.key] = r.value; });
|
||
res.json(settings);
|
||
} catch {
|
||
res.json(DEFAULT_SETTINGS);
|
||
}
|
||
});
|
||
|
||
// Admin GET
|
||
router.get("/admin/store-settings", async (_req, res) => {
|
||
try {
|
||
const rows = await db.select().from(storeSettingsTable);
|
||
const settings = { ...DEFAULT_SETTINGS };
|
||
rows.forEach(r => { settings[r.key] = r.value; });
|
||
res.json(settings);
|
||
} catch {
|
||
res.status(500).json({ error: "Failed to fetch settings" });
|
||
}
|
||
});
|
||
|
||
// Admin PUT
|
||
router.put("/admin/store-settings", async (req, res) => {
|
||
try {
|
||
const updates = req.body as Record<string, string>;
|
||
for (const [key, value] of Object.entries(updates)) {
|
||
if (typeof value !== "string") continue;
|
||
await db.insert(storeSettingsTable)
|
||
.values({ key, value })
|
||
.onConflictDoUpdate({ target: storeSettingsTable.key, set: { value, updated_at: new Date() } });
|
||
}
|
||
res.json({ ok: true });
|
||
} catch {
|
||
res.status(500).json({ error: "Failed to save settings" });
|
||
}
|
||
});
|
||
|
||
export default router;
|