mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
feat(contacts): add contacts page with per-store management and supplier email field
- New contacts table (group_id, name, role, phone, email, notes) per store - Suppliers table: add email field with form and card display - Page /contacts: two-column layout (suppliers read-only / free contacts CRUD) - Permissions: read all roles, create/edit/delete admin + directeur + manager - Admin can filter contacts by store; other roles see their own stores only - Migration SQL: 20260515_add_contacts_and_supplier_email.sql Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
40cf456a64
commit
805664dc32
8 files changed
+736
-6
No files matched your search
@@ -119,6 +119,7 @@ import {
|
||||
insertUtilitiesSchema,
|
||||
insertAvoirSchema,
|
||||
insertReconciliationCommentSchema,
|
||||
insertContactSchema,
|
||||
users, groups, userGroups, suppliers, orders, deliveries, publicities, publicityParticipations,
|
||||
customerOrders, nocodbConfig, dlcProducts, tasks, invoiceVerificationCache, dashboardMessages, webhookBapConfig,
|
||||
utilities,
|
||||
@@ -1191,6 +1192,76 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
// Contacts routes
|
||||
app.get('/api/contacts', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
const user = await storage.getUserWithGroups(req.user.claims ? req.user.claims.sub : req.user.id);
|
||||
if (!user) return res.status(404).json({ message: "User not found" });
|
||||
|
||||
let groupIds: number[] | undefined;
|
||||
if (user.role !== 'admin') {
|
||||
groupIds = (user.userGroups || []).map((ug: any) => ug.groupId);
|
||||
} else if (req.query.groupId) {
|
||||
groupIds = [parseInt(req.query.groupId as string)];
|
||||
}
|
||||
|
||||
const result = await storage.getContacts(groupIds);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error("Error fetching contacts:", error);
|
||||
res.status(500).json({ message: "Failed to fetch contacts" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/contacts', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
|
||||
if (!user || !['admin', 'directeur', 'manager'].includes(user.role)) {
|
||||
return res.status(403).json({ message: "Insufficient permissions" });
|
||||
}
|
||||
const data = insertContactSchema.parse(req.body);
|
||||
const contact = await storage.createContact(data);
|
||||
res.json(contact);
|
||||
} catch (error: any) {
|
||||
if (error.name === 'ZodError') {
|
||||
return res.status(400).json({ message: "Validation failed", errors: error.errors });
|
||||
}
|
||||
console.error("Error creating contact:", error);
|
||||
res.status(500).json({ message: "Failed to create contact" });
|
||||
}
|
||||
});
|
||||
|
||||
app.put('/api/contacts/:id', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
|
||||
if (!user || !['admin', 'directeur', 'manager'].includes(user.role)) {
|
||||
return res.status(403).json({ message: "Insufficient permissions" });
|
||||
}
|
||||
const id = parseInt(req.params.id);
|
||||
const data = insertContactSchema.partial().parse(req.body);
|
||||
const contact = await storage.updateContact(id, data);
|
||||
res.json(contact);
|
||||
} catch (error) {
|
||||
console.error("Error updating contact:", error);
|
||||
res.status(500).json({ message: "Failed to update contact" });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete('/api/contacts/:id', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
|
||||
if (!user || !['admin', 'directeur', 'manager'].includes(user.role)) {
|
||||
return res.status(403).json({ message: "Insufficient permissions" });
|
||||
}
|
||||
const id = parseInt(req.params.id);
|
||||
await storage.deleteContact(id);
|
||||
res.json({ message: "Contact deleted successfully" });
|
||||
} catch (error) {
|
||||
console.error("Error deleting contact:", error);
|
||||
res.status(500).json({ message: "Failed to delete contact" });
|
||||
}
|
||||
});
|
||||
|
||||
// Orders routes
|
||||
app.get('/api/orders', isAuthenticated, async (req: any, res) => {
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user