on the admin dashboard create a tab called "Flows" and add the estimate
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
|
||||
'use server';
|
||||
|
||||
import db from '@/lib/db';
|
||||
import { z } from 'zod';
|
||||
import { revalidatePath } from 'next/cache';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export type Flow = {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string | null;
|
||||
path: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
const flowSchema = z.object({
|
||||
id: z.coerce.number().optional(),
|
||||
name: z.string().min(1, 'Name is required'),
|
||||
description: z.string().optional(),
|
||||
path: z.string().min(1, 'Path is required').startsWith('/', { message: 'Path must start with /' }),
|
||||
});
|
||||
|
||||
export async function getFlows(): Promise<Flow[]> {
|
||||
try {
|
||||
const stmt = db.prepare(
|
||||
'SELECT id, name, description, path, createdAt, updatedAt FROM flows ORDER BY createdAt DESC'
|
||||
);
|
||||
const flows = stmt.all() as Flow[];
|
||||
return flows;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch flows:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFlow(id: number): Promise<Flow | null> {
|
||||
try {
|
||||
const stmt = db.prepare('SELECT * FROM flows WHERE id = ?');
|
||||
const flow = stmt.get(id) as Flow | undefined;
|
||||
return flow || null;
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch flow with id ${id}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveFlow(formData: FormData) {
|
||||
const validatedFields = flowSchema.safeParse(Object.fromEntries(formData.entries()));
|
||||
|
||||
if (!validatedFields.success) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Invalid fields.',
|
||||
errors: validatedFields.error.flatten().fieldErrors,
|
||||
};
|
||||
}
|
||||
|
||||
const { id, name, description, path } = validatedFields.data;
|
||||
|
||||
try {
|
||||
if (id) {
|
||||
// Update existing flow
|
||||
const stmt = db.prepare(
|
||||
'UPDATE flows SET name = ?, description = ?, path = ?, updatedAt = CURRENT_TIMESTAMP WHERE id = ?'
|
||||
);
|
||||
stmt.run(name, description || null, path, id);
|
||||
} else {
|
||||
// Create new flow
|
||||
const stmt = db.prepare(
|
||||
'INSERT INTO flows (name, description, path) VALUES (?, ?, ?)'
|
||||
);
|
||||
stmt.run(name, description || null, path);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Failed to save flow:', error);
|
||||
return {
|
||||
success: false,
|
||||
message: error.code === 'SQLITE_CONSTRAINT_UNIQUE' ? 'A flow with this path already exists.' : 'An internal error occurred.',
|
||||
errors: null,
|
||||
};
|
||||
}
|
||||
|
||||
revalidatePath('/admin/flows');
|
||||
redirect('/admin/flows');
|
||||
}
|
||||
|
||||
export async function deleteFlow(id: number): Promise<{ success: boolean, message: string }> {
|
||||
try {
|
||||
const stmt = db.prepare('DELETE FROM flows WHERE id = ?');
|
||||
stmt.run(id);
|
||||
revalidatePath('/admin/flows');
|
||||
return { success: true, message: 'Flow deleted successfully.' };
|
||||
} catch (error) {
|
||||
console.error('Failed to delete flow:', error);
|
||||
return { success: false, message: 'An internal error occurred.' };
|
||||
}
|
||||
}
|
||||
@@ -39,5 +39,16 @@ db.exec(`
|
||||
)
|
||||
`);
|
||||
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS flows (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
path TEXT NOT NULL,
|
||||
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
|
||||
|
||||
export default db;
|
||||
|
||||
Reference in New Issue
Block a user