Clean up flag config code
- FlagSvg: remove redundant getDisplayFlagConfig call; config is already a valid FlagConfig by type, so the validation/fallback was dead code. Also replace the unreachable `?? "#adf661"` fallback with a non-null assertion. - team/user models: pre-generate ID before insert so flagConfig is persisted immediately on creation rather than relying on display-time generation. - auth.server.ts: add create.after hook so BetterAuth-created users also get a flagConfig written to the DB on signup. https://claude.ai/code/session_014RUwPfm1qc539xLxW4m9Uy
This commit is contained in:
parent
f8ae740085
commit
4480f2e9b6
4 changed files with 40 additions and 19 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import { getDisplayFlagConfig } from "~/lib/avatar-data";
|
|
||||||
import type { FlagConfig } from "~/lib/flag-types";
|
import type { FlagConfig } from "~/lib/flag-types";
|
||||||
|
|
||||||
interface FlagSvgProps {
|
interface FlagSvgProps {
|
||||||
|
|
@ -10,12 +9,11 @@ interface FlagSvgProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function colorAt(colors: string[], index: number): string {
|
function colorAt(colors: string[], index: number): string {
|
||||||
return colors[index % colors.length] ?? "#adf661";
|
return colors[index % colors.length]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
||||||
const safeConfig = getDisplayFlagConfig(`${config.pattern}:${config.colors.join("-")}`, config);
|
const colors = config.colors;
|
||||||
const colors = safeConfig.colors;
|
|
||||||
const c0 = colorAt(colors, 0);
|
const c0 = colorAt(colors, 0);
|
||||||
const c1 = colorAt(colors, 1);
|
const c1 = colorAt(colors, 1);
|
||||||
const c2 = colorAt(colors, 2);
|
const c2 = colorAt(colors, 2);
|
||||||
|
|
@ -30,28 +28,28 @@ export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
||||||
className={cn("block shrink-0 overflow-hidden", className)}
|
className={cn("block shrink-0 overflow-hidden", className)}
|
||||||
>
|
>
|
||||||
{title ? <title>{title}</title> : null}
|
{title ? <title>{title}</title> : null}
|
||||||
{safeConfig.pattern === "triband-h" && (
|
{config.pattern === "triband-h" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="34" fill={c0} />
|
<rect width="100" height="34" fill={c0} />
|
||||||
<rect y="33" width="100" height="34" fill={c1} />
|
<rect y="33" width="100" height="34" fill={c1} />
|
||||||
<rect y="66" width="100" height="34" fill={c2} />
|
<rect y="66" width="100" height="34" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "triband-v" && (
|
{config.pattern === "triband-v" && (
|
||||||
<>
|
<>
|
||||||
<rect width="34" height="100" fill={c0} />
|
<rect width="34" height="100" fill={c0} />
|
||||||
<rect x="33" width="34" height="100" fill={c1} />
|
<rect x="33" width="34" height="100" fill={c1} />
|
||||||
<rect x="66" width="34" height="100" fill={c2} />
|
<rect x="66" width="34" height="100" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "diagonal" && (
|
{config.pattern === "diagonal" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<polygon points="0,0 100,0 0,100" fill={c1} />
|
<polygon points="0,0 100,0 0,100" fill={c1} />
|
||||||
<polygon points="100,100 100,28 28,100" fill={c2} />
|
<polygon points="100,100 100,28 28,100" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "nordic-cross" && (
|
{config.pattern === "nordic-cross" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<rect x="30" width="18" height="100" fill={c1} />
|
<rect x="30" width="18" height="100" fill={c1} />
|
||||||
|
|
@ -60,7 +58,7 @@ export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
||||||
<rect y="46" width="100" height="6" fill={c2} />
|
<rect y="46" width="100" height="6" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "cross" && (
|
{config.pattern === "cross" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<rect x="40" width="20" height="100" fill={c1} />
|
<rect x="40" width="20" height="100" fill={c1} />
|
||||||
|
|
@ -69,28 +67,28 @@ export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
||||||
<rect y="46" width="100" height="8" fill={c2} />
|
<rect y="46" width="100" height="8" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "canton" && (
|
{config.pattern === "canton" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<rect width="50" height="50" fill={c1} />
|
<rect width="50" height="50" fill={c1} />
|
||||||
<rect x="12" y="12" width="26" height="26" fill={c2} />
|
<rect x="12" y="12" width="26" height="26" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "triangle" && (
|
{config.pattern === "triangle" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<polygon points="0,0 64,50 0,100" fill={c1} />
|
<polygon points="0,0 64,50 0,100" fill={c1} />
|
||||||
<polygon points="0,22 36,50 0,78" fill={c2} />
|
<polygon points="0,22 36,50 0,78" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "chevron" && (
|
{config.pattern === "chevron" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<polygon points="0,0 56,50 0,100 28,100 84,50 28,0" fill={c1} />
|
<polygon points="0,0 56,50 0,100 28,100 84,50 28,0" fill={c1} />
|
||||||
<polygon points="0,22 32,50 0,78 0,62 14,50 0,38" fill={c2} />
|
<polygon points="0,22 32,50 0,78 0,62 14,50 0,38" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "quartered" && (
|
{config.pattern === "quartered" && (
|
||||||
<>
|
<>
|
||||||
<rect width="50" height="50" fill={c0} />
|
<rect width="50" height="50" fill={c0} />
|
||||||
<rect x="50" width="50" height="50" fill={c1} />
|
<rect x="50" width="50" height="50" fill={c1} />
|
||||||
|
|
@ -98,21 +96,21 @@ export function FlagSvg({ config, size = 48, className, title }: FlagSvgProps) {
|
||||||
<rect x="50" y="50" width="50" height="50" fill={c2} />
|
<rect x="50" y="50" width="50" height="50" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "bordered" && (
|
{config.pattern === "bordered" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<rect x="12" y="12" width="76" height="76" fill={c1} />
|
<rect x="12" y="12" width="76" height="76" fill={c1} />
|
||||||
<rect x="24" y="24" width="52" height="52" fill={c2} />
|
<rect x="24" y="24" width="52" height="52" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "circle" && (
|
{config.pattern === "circle" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<circle cx="50" cy="50" r="30" fill={c1} />
|
<circle cx="50" cy="50" r="30" fill={c1} />
|
||||||
<circle cx="50" cy="50" r="15" fill={c2} />
|
<circle cx="50" cy="50" r="15" fill={c2} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{safeConfig.pattern === "star" && (
|
{config.pattern === "star" && (
|
||||||
<>
|
<>
|
||||||
<rect width="100" height="100" fill={c0} />
|
<rect width="100" height="100" fill={c0} />
|
||||||
<polygon
|
<polygon
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import bcrypt from "bcrypt";
|
||||||
import { Resend } from "resend";
|
import { Resend } from "resend";
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
import * as schema from "~/database/schema";
|
import * as schema from "~/database/schema";
|
||||||
|
import { generateFlagConfig } from "~/lib/flag-generator";
|
||||||
|
|
||||||
if (!process.env.BETTER_AUTH_SECRET) {
|
if (!process.env.BETTER_AUTH_SECRET) {
|
||||||
throw new Error("BETTER_AUTH_SECRET is required");
|
throw new Error("BETTER_AUTH_SECRET is required");
|
||||||
|
|
@ -30,6 +31,14 @@ export const auth = betterAuth({
|
||||||
}),
|
}),
|
||||||
databaseHooks: {
|
databaseHooks: {
|
||||||
user: {
|
user: {
|
||||||
|
create: {
|
||||||
|
after: async (user) => {
|
||||||
|
await db
|
||||||
|
.update(schema.users)
|
||||||
|
.set({ flagConfig: generateFlagConfig(user.id) })
|
||||||
|
.where(eq(schema.users.id, user.id));
|
||||||
|
},
|
||||||
|
},
|
||||||
update: {
|
update: {
|
||||||
before: async (data) => {
|
before: async (data) => {
|
||||||
const incomingImage =
|
const incomingImage =
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,28 @@
|
||||||
import { eq, and, isNull } from "drizzle-orm";
|
import { eq, and, isNull } from "drizzle-orm";
|
||||||
import { database } from "~/database/context";
|
import { database } from "~/database/context";
|
||||||
import * as schema from "~/database/schema";
|
import * as schema from "~/database/schema";
|
||||||
|
import { generateFlagConfig } from "~/lib/flag-generator";
|
||||||
|
|
||||||
export type Team = typeof schema.teams.$inferSelect;
|
export type Team = typeof schema.teams.$inferSelect;
|
||||||
export type NewTeam = typeof schema.teams.$inferInsert;
|
export type NewTeam = typeof schema.teams.$inferInsert;
|
||||||
|
|
||||||
export async function createTeam(data: NewTeam): Promise<Team> {
|
export async function createTeam(data: NewTeam): Promise<Team> {
|
||||||
const db = database();
|
const db = database();
|
||||||
const [team] = await db.insert(schema.teams).values(data).returning();
|
const id = data.id ?? crypto.randomUUID();
|
||||||
|
const [team] = await db
|
||||||
|
.insert(schema.teams)
|
||||||
|
.values({ ...data, id, flagConfig: data.flagConfig ?? generateFlagConfig(id) })
|
||||||
|
.returning();
|
||||||
return team;
|
return team;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createManyTeams(teams: NewTeam[]): Promise<Team[]> {
|
export async function createManyTeams(teams: NewTeam[]): Promise<Team[]> {
|
||||||
const db = database();
|
const db = database();
|
||||||
return await db.insert(schema.teams).values(teams).returning();
|
const withFlags = teams.map((team) => {
|
||||||
|
const id = team.id ?? crypto.randomUUID();
|
||||||
|
return { ...team, id, flagConfig: team.flagConfig ?? generateFlagConfig(id) };
|
||||||
|
});
|
||||||
|
return await db.insert(schema.teams).values(withFlags).returning();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function findTeamById(id: string): Promise<Team | undefined> {
|
export async function findTeamById(id: string): Promise<Team | undefined> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { eq, inArray, and } from "drizzle-orm";
|
import { eq, inArray, and } from "drizzle-orm";
|
||||||
import { database } from "~/database/context";
|
import { database } from "~/database/context";
|
||||||
import * as schema from "~/database/schema";
|
import * as schema from "~/database/schema";
|
||||||
|
import { generateFlagConfig } from "~/lib/flag-generator";
|
||||||
|
|
||||||
export type User = typeof schema.users.$inferSelect;
|
export type User = typeof schema.users.$inferSelect;
|
||||||
export type NewUser = typeof schema.users.$inferInsert;
|
export type NewUser = typeof schema.users.$inferInsert;
|
||||||
|
|
@ -13,7 +14,11 @@ export function getUserDisplayName(
|
||||||
|
|
||||||
export async function createUser(data: NewUser): Promise<User> {
|
export async function createUser(data: NewUser): Promise<User> {
|
||||||
const db = database();
|
const db = database();
|
||||||
const [user] = await db.insert(schema.users).values(data).returning();
|
const id = data.id ?? crypto.randomUUID();
|
||||||
|
const [user] = await db
|
||||||
|
.insert(schema.users)
|
||||||
|
.values({ ...data, id, flagConfig: data.flagConfig ?? generateFlagConfig(id) })
|
||||||
|
.returning();
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue