HẠO NAM ADMINẢnh · Media Manager · Bài viết · V0.6
Trung tâm quản trị website

Ảnh và bài viết.
Quản lý trong một nơi.

Giữ nguyên công cụ crop ảnh Hero, đồng thời tạo bài viết dài, ảnh đại diện, SEO và một số thông tin vận hành thường xuyên thay đổi.

Kết nối Supabase

Cấu hình chỉ lưu trên trình duyệt này. Không nhập Secret key hoặc Service Role key.

Chưa kết nối
Bảo mật: chỉ dùng Publishable key hoặc anon key. RLS vẫn là lớp quyết định quyền đọc và chỉnh sửa.
Không dùng máy công cộng. Có thể xóa cấu hình bất cứ lúc nào.
`);w.document.close();}); const SETTINGS={phone_main:el.phone,zalo_url:el.zalo,course_price_note:el.price,next_course_date:el.courseDate,enrollment_notice:el.notice,service_area:el.area}; async function loadSettings(){if(!await ensureSession())return;setPill(el.settingsStatus,'Đang tải','warn');const {data,error}=await cms.from(SETTINGS_TABLE).select('*').order('sort_order');if(error){setPill(el.settingsStatus,'Lỗi bảng settings','bad');return notify(error.message,'error');}(data||[]).forEach(row=>{if(SETTINGS[row.setting_key])SETTINGS[row.setting_key].value=row.value||''});setPill(el.settingsStatus,'Đã tải','ok');} el.settingsForm.addEventListener('submit',async e=>{e.preventDefault();if(!await ensureSession())return;el.saveSettings.disabled=true;setPill(el.settingsStatus,'Đang lưu','warn');const types={phone_main:'phone',zalo_url:'url',course_price_note:'text',next_course_date:'date',enrollment_notice:'notice',service_area:'text'},labels={phone_main:'Số điện thoại chính',zalo_url:'Đường dẫn Zalo',course_price_note:'Thông tin học phí',next_course_date:'Ngày khai giảng gần nhất',enrollment_notice:'Thông báo tuyển sinh',service_area:'Khu vực đào tạo'};const rows=Object.entries(SETTINGS).map(([key,input],i)=>({setting_key:key,label:labels[key],value:input.value.trim(),value_type:types[key],sort_order:(i+1)*10,is_public:true}));const {error}=await cms.from(SETTINGS_TABLE).upsert(rows,{onConflict:'setting_key'});el.saveSettings.disabled=false;if(error){setPill(el.settingsStatus,'Lưu thất bại','bad');return notify(error.message,'error');}setPill(el.settingsStatus,'Đã lưu','ok');notify('Đã lưu thông tin nhanh.','success');}); const observer=new MutationObserver(()=>{const workspace=q('workspace');if(workspace&&!workspace.classList.contains('hidden'))ensureSession();});observer.observe(document.body,{subtree:true,attributes:true,attributeFilter:['class']}); cms.auth.onAuthStateChange((_event,s)=>{session=s;if(!s){posts=[];resetEditor();}}); resetEditor(); window.HAO_NAM_CMS=Object.freeze({reloadPosts:ensurePosts,loadSettings}); })();