"use client"; import { useCallback, useEffect, useState } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Eye, Pencil, ImageIcon, Loader2, Plus, Trash2 } from "lucide-react"; import Swal from "sweetalert2"; import type { CmsAboutContent, CmsHeroContent, CmsPartnerContent, CmsPopupContent, CmsProductContent, CmsServiceContent, } from "@/types/cms-landing"; import { apiDataList, apiPayload, apiRows, deleteAboutUsContentImage, deleteOurProductContent, deleteOurServiceContent, deletePartnerContent, deletePopupNews, getAboutContentsList, getHeroContent, getOurProductContent, getOurServiceContent, getPartnerContents, getPopupNewsList, saveAboutContent, saveAboutUsMediaUrl, saveHeroContent, saveHeroImage, saveOurProductContent, saveOurServiceContent, savePartnerContent, saveOurProductImage, saveOurServiceImage, savePopupNews, savePopupNewsImage, updateAboutContent, updateHeroContent, updateHeroImage, updateOurProductContent, updateOurProductImage, updateOurServiceContent, updateOurServiceImage, updatePartnerContent, updatePopupNews, } from "@/service/cms-landing"; export default function ContentWebsite() { const [activeTab, setActiveTab] = useState("hero"); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [heroId, setHeroId] = useState(null); const [heroImageId, setHeroImageId] = useState(null); const [heroPrimary, setHeroPrimary] = useState(""); const [heroSecondary, setHeroSecondary] = useState(""); const [heroDesc, setHeroDesc] = useState(""); const [heroCta1, setHeroCta1] = useState(""); const [heroCta2, setHeroCta2] = useState(""); const [heroImgUrl, setHeroImgUrl] = useState(""); const [aboutId, setAboutId] = useState(null); const [aboutPrimary, setAboutPrimary] = useState(""); const [aboutSecondary, setAboutSecondary] = useState(""); const [aboutDesc, setAboutDesc] = useState(""); const [aboutCta1, setAboutCta1] = useState(""); const [aboutCta2, setAboutCta2] = useState(""); const [aboutMediaUrl, setAboutMediaUrl] = useState(""); const [aboutMediaImageId, setAboutMediaImageId] = useState( null, ); const [aboutMediaLoadedUrl, setAboutMediaLoadedUrl] = useState(""); const [products, setProducts] = useState([]); const [productEditId, setProductEditId] = useState(null); const [productPrimary, setProductPrimary] = useState(""); const [productSecondary, setProductSecondary] = useState(""); const [productDesc, setProductDesc] = useState(""); const [productImgUrl, setProductImgUrl] = useState(""); const [productImageId, setProductImageId] = useState(null); const [productModalOpen, setProductModalOpen] = useState(false); const [services, setServices] = useState([]); const [serviceEditId, setServiceEditId] = useState(null); const [servicePrimary, setServicePrimary] = useState(""); const [serviceSecondary, setServiceSecondary] = useState(""); const [serviceDesc, setServiceDesc] = useState(""); const [serviceImgUrl, setServiceImgUrl] = useState(""); const [serviceImageId, setServiceImageId] = useState(null); const [serviceModalOpen, setServiceModalOpen] = useState(false); const [partners, setPartners] = useState([]); const [partnerTitle, setPartnerTitle] = useState(""); const [partnerImgUrl, setPartnerImgUrl] = useState(""); const [editingPartnerId, setEditingPartnerId] = useState(null); const [partnerModalOpen, setPartnerModalOpen] = useState(false); const [popups, setPopups] = useState([]); const [popupEditId, setPopupEditId] = useState(null); const [popupPrimary, setPopupPrimary] = useState(""); const [popupSecondary, setPopupSecondary] = useState(""); const [popupDesc, setPopupDesc] = useState(""); const [popupCta1, setPopupCta1] = useState(""); const [popupCta2, setPopupCta2] = useState(""); const [popupImgUrl, setPopupImgUrl] = useState(""); const [popupModalOpen, setPopupModalOpen] = useState(false); const loadAll = useCallback(async () => { setLoading(true); try { const heroRes = await getHeroContent(); const hero = apiPayload(heroRes) as CmsHeroContent | null; if (hero?.id) { setHeroId(hero.id); setHeroPrimary(hero.primary_title ?? ""); setHeroSecondary(hero.secondary_title ?? ""); setHeroDesc(hero.description ?? ""); setHeroCta1(hero.primary_cta ?? ""); setHeroCta2(hero.secondary_cta_text ?? ""); const first = hero.images?.[0]; if (first?.image_url) { setHeroImgUrl(first.image_url); setHeroImageId(first.id ?? null); } else { setHeroImgUrl(""); setHeroImageId(null); } } else { setHeroId(null); setHeroImageId(null); setHeroPrimary(""); setHeroSecondary(""); setHeroDesc(""); setHeroCta1(""); setHeroCta2(""); setHeroImgUrl(""); } const aboutRes = await getAboutContentsList(); const aboutList = apiRows(aboutRes) as CmsAboutContent[]; const ab = aboutList[0]; if (ab) { setAboutId(ab.id); setAboutPrimary(ab.primary_title ?? ""); setAboutSecondary(ab.secondary_title ?? ""); setAboutDesc(ab.description ?? ""); setAboutCta1(ab.primary_cta ?? ""); setAboutCta2(ab.secondary_cta_text ?? ""); const am = ab.images?.[0]; const murl = am?.media_url?.trim() ?? ""; setAboutMediaUrl(murl); setAboutMediaLoadedUrl(murl); setAboutMediaImageId(am?.id ?? null); } else { setAboutId(null); setAboutPrimary(""); setAboutSecondary(""); setAboutDesc(""); setAboutCta1(""); setAboutCta2(""); setAboutMediaUrl(""); setAboutMediaLoadedUrl(""); setAboutMediaImageId(null); } const prRes = await getOurProductContent(); setProducts(apiDataList(prRes)); const svRes = await getOurServiceContent(); setServices(apiDataList(svRes)); const parRes = await getPartnerContents(); const parList = apiPayload(parRes) as CmsPartnerContent[] | null; setPartners(Array.isArray(parList) ? parList : []); const popRes = await getPopupNewsList(1, 50); setPopups(apiRows(popRes) as CmsPopupContent[]); } finally { setLoading(false); } }, []); useEffect(() => { loadAll(); }, [loadAll]); async function saveHeroTab() { if (!heroPrimary.trim()) { await Swal.fire({ icon: "warning", title: "Main title is required" }); return; } setSaving(true); try { const body = { primary_title: heroPrimary, secondary_title: heroSecondary, description: heroDesc, primary_cta: heroCta1, secondary_cta_text: heroCta2, }; let hid = heroId; if (!hid) { const res = await saveHeroContent(body); const created = apiPayload(res) as CmsHeroContent | null; if (!created?.id) { await Swal.fire({ icon: "error", title: "Failed to create hero content" }); return; } hid = created.id; setHeroId(hid); } else { const res = await updateHeroContent(hid, body); if (res?.error) { await Swal.fire({ icon: "error", title: "Update failed", text: String(res.message ?? "") }); return; } } if (heroImgUrl.trim() && hid) { if (heroImageId) { await updateHeroImage(heroImageId, { image_url: heroImgUrl.trim() }); } else { await saveHeroImage({ hero_content_id: hid, image_url: heroImgUrl.trim(), }); } } await Swal.fire({ icon: "success", title: "Hero section saved", timer: 1600, showConfirmButton: false }); await loadAll(); } finally { setSaving(false); } } async function saveAboutTab() { if (!aboutPrimary.trim()) { await Swal.fire({ icon: "warning", title: "Main title is required" }); return; } setSaving(true); try { const body: Record = { primary_title: aboutPrimary, secondary_title: aboutSecondary, description: aboutDesc, primary_cta: aboutCta1, secondary_cta_text: aboutCta2, }; let aid = aboutId; if (aboutId == null) { const res = await saveAboutContent(body); if (res?.error) { await Swal.fire({ icon: "error", title: "Save failed", text: String(res.message ?? "") }); return; } const created = apiPayload(res) as CmsAboutContent | null; aid = created?.id ?? null; if (aid != null) setAboutId(aid); } else { const res = await updateAboutContent(aboutId, body); if (res?.error) { await Swal.fire({ icon: "error", title: "Update failed", text: String(res.message ?? "") }); return; } } const url = aboutMediaUrl.trim(); if (aid != null) { if (!url) { if (aboutMediaImageId != null) { await deleteAboutUsContentImage(aboutMediaImageId); } } else if (url !== aboutMediaLoadedUrl || aboutMediaImageId == null) { if (aboutMediaImageId != null) { await deleteAboutUsContentImage(aboutMediaImageId); } const mres = await saveAboutUsMediaUrl({ about_us_content_id: aid, media_url: url, }); if (mres?.error) { await Swal.fire({ icon: "error", title: "Media URL failed", text: String(mres.message ?? ""), }); return; } } } await Swal.fire({ icon: "success", title: "About Us saved", timer: 1600, showConfirmButton: false }); await loadAll(); } finally { setSaving(false); } } function beginEditProduct(p: CmsProductContent | null) { if (!p) { setProductEditId(null); setProductPrimary(""); setProductSecondary(""); setProductDesc(""); setProductImgUrl(""); setProductImageId(null); return; } setProductEditId(p.id); setProductPrimary(p.primary_title ?? ""); setProductSecondary(p.secondary_title ?? ""); setProductDesc(p.description ?? ""); const im = p.images?.[0]; setProductImgUrl(im?.image_url?.trim() ?? ""); setProductImageId(im?.id ?? null); } function openProductModalCreate() { beginEditProduct(null); setProductModalOpen(true); } function openProductModalEdit(p: CmsProductContent) { beginEditProduct(p); setProductModalOpen(true); } async function saveProductDraft() { if (!productPrimary.trim()) { await Swal.fire({ icon: "warning", title: "Product title is required" }); return; } setSaving(true); try { const body = { primary_title: productPrimary, secondary_title: productSecondary, description: productDesc, }; let pid = productEditId; if (!pid) { const res = await saveOurProductContent(body); const created = apiPayload(res) as CmsProductContent | null; if (!created?.id) { await Swal.fire({ icon: "error", title: "Failed to create product" }); return; } pid = created.id; } else { const res = await updateOurProductContent(pid, body); if (res?.error) { await Swal.fire({ icon: "error", title: "Update failed", text: String(res.message ?? "") }); return; } } if (productImgUrl.trim() && pid) { if (productImageId) { await updateOurProductImage(productImageId, { image_url: productImgUrl.trim() }); } else { await saveOurProductImage({ our_product_content_id: pid, image_url: productImgUrl.trim(), }); } } await Swal.fire({ icon: "success", title: "Product saved", timer: 1400, showConfirmButton: false }); await loadAll(); beginEditProduct(null); setProductModalOpen(false); } finally { setSaving(false); } } async function removeProduct(id: string) { const ok = await Swal.fire({ icon: "warning", title: "Delete this product?", showCancelButton: true, }); if (!ok.isConfirmed) return; setSaving(true); try { await deleteOurProductContent(id); if (productEditId === id) { beginEditProduct(null); setProductModalOpen(false); } await loadAll(); } finally { setSaving(false); } } function beginEditService(s: CmsServiceContent | null) { if (!s) { setServiceEditId(null); setServicePrimary(""); setServiceSecondary(""); setServiceDesc(""); setServiceImgUrl(""); setServiceImageId(null); return; } setServiceEditId(s.id); setServicePrimary(s.primary_title ?? ""); setServiceSecondary(s.secondary_title ?? ""); setServiceDesc(s.description ?? ""); const im = s.images?.[0]; setServiceImgUrl(im?.image_url?.trim() ?? ""); setServiceImageId(im?.id != null ? String(im.id) : null); } function openServiceModalCreate() { beginEditService(null); setServiceModalOpen(true); } function openServiceModalEdit(s: CmsServiceContent) { beginEditService(s); setServiceModalOpen(true); } async function saveServiceDraft() { if (!servicePrimary.trim()) { await Swal.fire({ icon: "warning", title: "Service title is required" }); return; } setSaving(true); try { const body = { primary_title: servicePrimary, secondary_title: serviceSecondary, description: serviceDesc, }; let sid = serviceEditId; if (sid == null) { const res = await saveOurServiceContent(body); const created = apiPayload(res) as CmsServiceContent | null; if (created?.id == null) { await Swal.fire({ icon: "error", title: "Failed to create service" }); return; } sid = created.id; } else { const res = await updateOurServiceContent(sid, body); if (res?.error) { await Swal.fire({ icon: "error", title: "Update failed", text: String(res.message ?? "") }); return; } } if (serviceImgUrl.trim() && sid != null) { if (serviceImageId) { await updateOurServiceImage(serviceImageId, { image_url: serviceImgUrl.trim() }); } else { await saveOurServiceImage({ our_service_content_id: sid, image_url: serviceImgUrl.trim(), }); } } await Swal.fire({ icon: "success", title: "Service saved", timer: 1400, showConfirmButton: false }); await loadAll(); beginEditService(null); setServiceModalOpen(false); } finally { setSaving(false); } } async function removeService(id: number) { const ok = await Swal.fire({ icon: "warning", title: "Delete this service?", showCancelButton: true, }); if (!ok.isConfirmed) return; setSaving(true); try { await deleteOurServiceContent(id); if (serviceEditId === id) { beginEditService(null); setServiceModalOpen(false); } await loadAll(); } finally { setSaving(false); } } function beginEditPartner(p: CmsPartnerContent | null) { if (!p) { setEditingPartnerId(null); setPartnerTitle(""); setPartnerImgUrl(""); return; } setEditingPartnerId(p.id); setPartnerTitle(p.primary_title ?? ""); setPartnerImgUrl(p.image_url ?? ""); } function openPartnerModalCreate() { beginEditPartner(null); setPartnerModalOpen(true); } function openPartnerModalEdit(p: CmsPartnerContent) { beginEditPartner(p); setPartnerModalOpen(true); } async function savePartnerRow() { if (!partnerTitle.trim()) { await Swal.fire({ icon: "warning", title: "Partner name is required" }); return; } setSaving(true); try { const body = { primary_title: partnerTitle.trim(), image_url: partnerImgUrl.trim() || undefined, }; if (editingPartnerId) { const res = await updatePartnerContent(editingPartnerId, body); if (res?.error) { await Swal.fire({ icon: "error", title: "Update failed", text: String(res.message ?? "") }); return; } } else { const res = await savePartnerContent(body); if (res?.error) { await Swal.fire({ icon: "error", title: "Save failed", text: String(res.message ?? "") }); return; } } beginEditPartner(null); setPartnerModalOpen(false); await Swal.fire({ icon: "success", title: "Partner saved", timer: 1400, showConfirmButton: false }); await loadAll(); } finally { setSaving(false); } } async function removePartner(id: string) { const ok = await Swal.fire({ icon: "warning", title: "Delete this partner?", showCancelButton: true, }); if (!ok.isConfirmed) return; setSaving(true); try { await deletePartnerContent(id); if (editingPartnerId === id) { beginEditPartner(null); setPartnerModalOpen(false); } await loadAll(); } finally { setSaving(false); } } function beginEditPopup(p: CmsPopupContent | null) { if (!p) { setPopupEditId(null); setPopupPrimary(""); setPopupSecondary(""); setPopupDesc(""); setPopupCta1(""); setPopupCta2(""); setPopupImgUrl(""); return; } setPopupEditId(p.id); setPopupPrimary(p.primary_title ?? ""); setPopupSecondary(p.secondary_title ?? ""); setPopupDesc(p.description ?? ""); setPopupCta1(p.primary_cta ?? ""); setPopupCta2(p.secondary_cta_text ?? ""); setPopupImgUrl(p.images?.[0]?.media_url?.trim() ?? ""); } function openPopupModalCreate() { beginEditPopup(null); setPopupModalOpen(true); } function openPopupModalEdit(p: CmsPopupContent) { beginEditPopup(p); setPopupModalOpen(true); } async function savePopupDraft() { if (!popupPrimary.trim()) { await Swal.fire({ icon: "warning", title: "Main title is required" }); return; } setSaving(true); try { const body = { primary_title: popupPrimary, secondary_title: popupSecondary, description: popupDesc, primary_cta: popupCta1, secondary_cta_text: popupCta2, }; let pid = popupEditId; if (pid == null) { const res = await savePopupNews(body); if (res?.error) { await Swal.fire({ icon: "error", title: "Save failed", text: String(res.message ?? "") }); return; } const listRes = await getPopupNewsList(1, 50); const rows = apiRows(listRes) as CmsPopupContent[]; pid = rows.length > 0 ? Math.max(...rows.map((r) => r.id)) : null; } else { const res = await updatePopupNews(pid, { id: pid, ...body }); if (res?.error) { await Swal.fire({ icon: "error", title: "Update failed", text: String(res.message ?? "") }); return; } } if (popupImgUrl.trim() && pid != null) { await savePopupNewsImage({ popup_news_content_id: pid, media_url: popupImgUrl.trim(), }); } await Swal.fire({ icon: "success", title: "Pop up saved", timer: 1600, showConfirmButton: false }); await loadAll(); beginEditPopup(null); setPopupModalOpen(false); } finally { setSaving(false); } } async function removePopup(id: number) { const ok = await Swal.fire({ icon: "warning", title: "Delete this pop up?", showCancelButton: true, }); if (!ok.isConfirmed) return; setSaving(true); try { await deletePopupNews(id); if (popupEditId === id) { beginEditPopup(null); setPopupModalOpen(false); } await loadAll(); } finally { setSaving(false); } } if (loading) { return (
); } return (

Content Website

Update homepage content, products, services, and partners.

Hero Section About Us Our Products Our Services Technology Partners Pop Up
setHeroPrimary(e.target.value)} placeholder="Headline" />
setHeroSecondary(e.target.value)} />