feat(settings): connect General Settings to real backend category endpoints with live persistence

This commit is contained in:
Inamul-hasan-tec
2026-08-08 16:48:01 +05:30
parent b76227e674
commit e8edab84b9
2 changed files with 53 additions and 54 deletions
+45 -3
View File
@@ -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;
}
};