feat: add settings UI for webhook toggles
- Add settings store (src/lib/settings.ts) for persistent configuration - Add settings API route for CRUD operations - Add settings page with webhook toggles for order events - Update webhook handlers to check settings before sending emails - Settings include: webhook enable/disable, admin/customer notification toggles - Email configuration: from name, from email, admin emails, store/dashboard URLs
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
|
||||
export interface WebhookSettings {
|
||||
orderCreated: {
|
||||
enabled: boolean;
|
||||
sendAdminNotification: boolean;
|
||||
sendCustomerNotification: boolean;
|
||||
};
|
||||
orderFulfilled: {
|
||||
enabled: boolean;
|
||||
sendAdminNotification: boolean;
|
||||
sendCustomerNotification: boolean;
|
||||
};
|
||||
orderCancelled: {
|
||||
enabled: boolean;
|
||||
sendAdminNotification: boolean;
|
||||
sendCustomerNotification: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EmailSettings {
|
||||
fromEmail: string;
|
||||
fromName: string;
|
||||
adminEmails: string[];
|
||||
siteUrl: string;
|
||||
dashboardUrl: string;
|
||||
}
|
||||
|
||||
export interface AppSettings {
|
||||
webhooks: WebhookSettings;
|
||||
email: EmailSettings;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: AppSettings = {
|
||||
webhooks: {
|
||||
orderCreated: {
|
||||
enabled: true,
|
||||
sendAdminNotification: true,
|
||||
sendCustomerNotification: true,
|
||||
},
|
||||
orderFulfilled: {
|
||||
enabled: true,
|
||||
sendAdminNotification: true,
|
||||
sendCustomerNotification: true,
|
||||
},
|
||||
orderCancelled: {
|
||||
enabled: true,
|
||||
sendAdminNotification: true,
|
||||
sendCustomerNotification: true,
|
||||
},
|
||||
},
|
||||
email: {
|
||||
fromEmail: process.env.FROM_EMAIL || "support@mail.manoonoils.com",
|
||||
fromName: process.env.FROM_NAME || "ManoonOils",
|
||||
adminEmails: process.env.ADMIN_EMAILS?.split(",").map((e) => e.trim()).filter(Boolean) || [],
|
||||
siteUrl: process.env.SITE_URL || "https://manoonoils.com",
|
||||
dashboardUrl: process.env.DASHBOARD_URL || "https://dashboard.manoonoils.com",
|
||||
},
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
class SettingsStore {
|
||||
private filePath: string;
|
||||
private settings: AppSettings | null = null;
|
||||
|
||||
constructor() {
|
||||
this.filePath = process.env.SETTINGS_FILE_PATH || "/tmp/.app-settings.json";
|
||||
}
|
||||
|
||||
private async ensureFileExists(): Promise<void> {
|
||||
try {
|
||||
await fs.access(this.filePath);
|
||||
} catch {
|
||||
const dir = path.dirname(this.filePath);
|
||||
await fs.mkdir(dir, { recursive: true });
|
||||
await fs.writeFile(this.filePath, JSON.stringify(DEFAULT_SETTINGS, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
async get(): Promise<AppSettings> {
|
||||
if (this.settings) {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.ensureFileExists();
|
||||
const data = await fs.readFile(this.filePath, "utf-8");
|
||||
this.settings = JSON.parse(data) as AppSettings;
|
||||
return this.settings!;
|
||||
} catch (error) {
|
||||
console.error("Error reading settings:", error);
|
||||
this.settings = DEFAULT_SETTINGS;
|
||||
return this.settings;
|
||||
}
|
||||
}
|
||||
|
||||
async set(newSettings: Partial<AppSettings>): Promise<AppSettings> {
|
||||
const current = await this.get();
|
||||
const updated: AppSettings = {
|
||||
...current,
|
||||
...newSettings,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
try {
|
||||
await fs.writeFile(this.filePath, JSON.stringify(updated, null, 2));
|
||||
this.settings = updated;
|
||||
return updated;
|
||||
} catch (error) {
|
||||
console.error("Error writing settings:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async isWebhookEnabled(webhook: keyof WebhookSettings): Promise<boolean> {
|
||||
const settings = await this.get();
|
||||
return settings.webhooks[webhook].enabled;
|
||||
}
|
||||
|
||||
async shouldSendAdminNotification(webhook: keyof WebhookSettings): Promise<boolean> {
|
||||
const settings = await this.get();
|
||||
return settings.webhooks[webhook].sendAdminNotification;
|
||||
}
|
||||
|
||||
async shouldSendCustomerNotification(webhook: keyof WebhookSettings): Promise<boolean> {
|
||||
const settings = await this.get();
|
||||
return settings.webhooks[webhook].sendCustomerNotification;
|
||||
}
|
||||
}
|
||||
|
||||
export const settingsStore = new SettingsStore();
|
||||
Reference in New Issue
Block a user