feat: customizable business branding (name, logo, colors) #63

Merged
ghost merged 5 commits from feat/business-branding into main 2026-03-19 11:07:07 +00:00
3 changed files with 5 additions and 4 deletions
Showing only changes of commit 5c3cc639ac - Show all commits
+1 -1
View File
@@ -13,6 +13,7 @@ import { reportsRouter } from "./routes/reports.js";
import { appointmentGroupsRouter } from "./routes/appointmentGroups.js";
import { groomingLogsRouter } from "./routes/groomingLogs.js";
import { settingsRouter } from "./routes/settings.js";
import { getDb, businessSettings } from "@groombook/db";
import { authMiddleware } from "./middleware/auth.js";
import { devRouter } from "./routes/dev.js";
import { startReminderScheduler } from "./services/reminders.js";
@@ -40,7 +41,6 @@ app.route("/api/dev", devRouter);
// Public branding endpoint — no auth required, returns business name/colors/logo
app.get("/api/branding", async (c) => {
const { getDb, businessSettings } = await import("@groombook/db");
const db = getDb();
const [row] = await db.select().from(businessSettings).limit(1);
const settings = row ?? { businessName: "GroomBook", primaryColor: "#4f8a6f", accentColor: "#8b7355", logoBase64: null, logoMimeType: null };
+3 -2
View File
@@ -44,8 +44,9 @@ settingsRouter.patch(
if (rows[0]) {
settingsId = rows[0].id;
} else {
const inserted = await db.insert(businessSettings).values({}).returning();
settingsId = inserted[0]!.id;
const [inserted] = await db.insert(businessSettings).values({}).returning();
if (!inserted) throw new Error("Failed to create default settings");
settingsId = inserted.id;
}
const [updated] = await db
+1 -1
View File
@@ -224,7 +224,7 @@ export function CustomerPortal() {
className={`
w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors
${active
? "text-stone-800 font-semibold"
? "bg-stone-100 text-stone-800 font-semibold"
: "text-stone-600 hover:bg-stone-50 hover:text-stone-900"
}
`}