feat(settings): connect General Settings to real backend category endpoints with live persistence
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { User, Bell, Shield, Plug, Key, Palette, Globe, Database, MessageSquare, Webhook, Box, ChevronRight } from "lucide-react";
|
||||
import { User, Bell, Shield, Plug, Key, Palette, Globe, Database, MessageSquare, Webhook, Box, ChevronRight, Save } from "lucide-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import type { RootState } from "../../../store";
|
||||
@@ -7,6 +7,8 @@ import { PageWrapper } from "../../../components/layouts/PageWrapper";
|
||||
import { Button } from "../../../components/customs/Button";
|
||||
import { Breadcrumb } from "../../../components/layouts/Breadcrumb";
|
||||
import { Radio } from "../../../components/customs/Radio";
|
||||
import { settingsService } from "../services/settings.service";
|
||||
import { notify } from "../../../services/toast";
|
||||
|
||||
export default function SettingList() {
|
||||
const navigate = useNavigate();
|
||||
@@ -15,6 +17,7 @@ export default function SettingList() {
|
||||
const [activeTab, setActiveTab] = useState("General");
|
||||
const [requireApproval, setRequireApproval] = useState(true);
|
||||
const [autoPublish, setAutoPublish] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const [orgName, setOrgName] = useState(user?.tenant?.name || "Organization");
|
||||
const [subdomain, setSubdomain] = useState(user?.tenant?.tenant_code || user?.tenant?.domain || "org");
|
||||
@@ -28,6 +31,42 @@ export default function SettingList() {
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
// Load category settings from API when tab changes
|
||||
useEffect(() => {
|
||||
const loadSettings = async () => {
|
||||
try {
|
||||
const cat = activeTab.toLowerCase();
|
||||
const data = await settingsService.getCategorySettings(cat);
|
||||
if (data) {
|
||||
if (data.orgName) setOrgName(data.orgName);
|
||||
if (data.subdomain) setSubdomain(data.subdomain);
|
||||
if (data.requireApproval !== undefined) setRequireApproval(data.requireApproval);
|
||||
if (data.autoPublish !== undefined) setAutoPublish(data.autoPublish);
|
||||
}
|
||||
} catch (err) {
|
||||
// Silently fallback to defaults
|
||||
}
|
||||
};
|
||||
loadSettings();
|
||||
}, [activeTab]);
|
||||
|
||||
const handleSaveGeneral = async () => {
|
||||
setSaving(true);
|
||||
try {
|
||||
await settingsService.updateCategorySettings("general", {
|
||||
orgName,
|
||||
subdomain,
|
||||
requireApproval,
|
||||
autoPublish
|
||||
});
|
||||
notify.success("General settings saved successfully!");
|
||||
} catch (err: any) {
|
||||
notify.error(err?.message || "Failed to save settings");
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const horizontalTabs = [
|
||||
{ id: "General", icon: User },
|
||||
{ id: "Notifications", icon: Bell },
|
||||
@@ -151,8 +190,11 @@ export default function SettingList() {
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-3 px-6 py-4 border-t border-primary/5 bg-gradient-to-r from-surface to-primary/5/30">
|
||||
<Button variant="ghost" className="text-muted-foreground hover:text-foreground hover:bg-background">Cancel</Button>
|
||||
<Button className="bg-primary hover:bg-primary-hover text-white">Save Changes</Button>
|
||||
<Button variant="ghost" className="text-muted-foreground hover:text-foreground hover:bg-background" onClick={() => window.location.reload()}>Cancel</Button>
|
||||
<Button className="bg-primary hover:bg-primary-hover text-white flex items-center gap-2" loading={saving} onClick={handleSaveGeneral}>
|
||||
<Save className="w-4 h-4" />
|
||||
Save Changes
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,55 +1,12 @@
|
||||
import type { Setting, SettingCreateRequest, SettingUpdateRequest } from '../types/settings.types';
|
||||
|
||||
const STORAGE_KEY = 'pim_settings';
|
||||
|
||||
const getStored = (): Setting[] => {
|
||||
const stored = localStorage.getItem(STORAGE_KEY);
|
||||
if (!stored) return [];
|
||||
return JSON.parse(stored);
|
||||
};
|
||||
|
||||
const setStored = (items: Setting[]) => {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(items));
|
||||
};
|
||||
import axiosInstance from '../../../api/axiosInstance';
|
||||
|
||||
export const settingsService = {
|
||||
getAll: async (): Promise<Setting[]> => {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(getStored()), 300));
|
||||
},
|
||||
getById: async (id: string): Promise<Setting | undefined> => {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(getStored().find(p => p.id === id)), 200));
|
||||
},
|
||||
create: async (req: SettingCreateRequest): Promise<Setting> => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
const list = getStored();
|
||||
const newItem: Setting = { ...req, id: String(Date.now()), createdAt: new Date().toISOString() };
|
||||
list.push(newItem);
|
||||
setStored(list);
|
||||
resolve(newItem);
|
||||
}, 300);
|
||||
});
|
||||
},
|
||||
update: async (id: string, req: SettingUpdateRequest): Promise<Setting> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const list = getStored();
|
||||
const index = list.findIndex(p => p.id === id);
|
||||
if (index === -1) { reject(new Error('Not found')); return; }
|
||||
const updated = { ...list[index], ...req };
|
||||
list[index] = updated;
|
||||
setStored(list);
|
||||
resolve(updated);
|
||||
}, 300);
|
||||
});
|
||||
},
|
||||
delete: async (id: string): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
const list = getStored().filter(p => p.id !== id);
|
||||
setStored(list);
|
||||
resolve(true);
|
||||
}, 300);
|
||||
});
|
||||
getCategorySettings: async (category: string) => {
|
||||
const response = await axiosInstance.get(`/settings/by-category/${category}`);
|
||||
return response.data.data;
|
||||
},
|
||||
updateCategorySettings: async (category: string, data: Record<string, any>) => {
|
||||
const response = await axiosInstance.put(`/settings/by-category/${category}`, data);
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user