diff --git a/frontend/src/lib/palette.ts b/frontend/src/lib/palette.ts new file mode 100644 index 0000000..d33626e --- /dev/null +++ b/frontend/src/lib/palette.ts @@ -0,0 +1,102 @@ +import type React from 'react' + +export type CategoryType = + | 'income' + | 'bill' + | 'variable_expense' + | 'debt' + | 'saving' + | 'investment' + | 'carryover' + +export interface CategoryShades { + light: string + medium: string + base: string +} + +export const palette: Record = { + income: { + light: 'oklch(0.96 0.04 145)', + medium: 'oklch(0.88 0.08 145)', + base: 'oklch(0.76 0.14 145)', + }, + bill: { + light: 'oklch(0.96 0.03 250)', + medium: 'oklch(0.88 0.07 250)', + base: 'oklch(0.76 0.12 250)', + }, + variable_expense: { + light: 'oklch(0.97 0.04 85)', + medium: 'oklch(0.90 0.08 85)', + base: 'oklch(0.80 0.14 85)', + }, + debt: { + light: 'oklch(0.96 0.04 15)', + medium: 'oklch(0.88 0.08 15)', + base: 'oklch(0.76 0.13 15)', + }, + saving: { + light: 'oklch(0.95 0.04 280)', + medium: 'oklch(0.87 0.08 280)', + base: 'oklch(0.75 0.13 280)', + }, + investment: { + light: 'oklch(0.96 0.04 320)', + medium: 'oklch(0.88 0.07 320)', + base: 'oklch(0.76 0.12 320)', + }, + carryover: { + light: 'oklch(0.96 0.03 210)', + medium: 'oklch(0.88 0.06 210)', + base: 'oklch(0.76 0.11 210)', + }, +} + +/** + * Returns a CSSProperties object with a linear-gradient background + * using the light and medium shades of the given category type. + */ +export function headerGradient(type: CategoryType): React.CSSProperties { + const shades = palette[type] + return { + background: `linear-gradient(to right, ${shades.light}, ${shades.medium})`, + } +} + +/** + * Returns a CSSProperties object with a multi-stop linear-gradient + * for the FinancialOverview header (sky via lavender to green). + */ +export function overviewHeaderGradient(): React.CSSProperties { + return { + background: `linear-gradient(to right, ${palette.carryover.light}, ${palette.saving.light}, ${palette.income.light})`, + } +} + +export interface AmountColorClassOpts { + type: CategoryType + actual: number + budgeted: number + isIncome?: boolean + isAvailable?: boolean +} + +/** + * Returns a Tailwind utility class for coloring a monetary amount: + * - isIncome or isAvailable: positive → 'text-success', negative → 'text-destructive', zero → '' + * - Expense: actual > budgeted → 'text-warning', else → '' + */ +export function amountColorClass(opts: AmountColorClassOpts): string { + const { actual, budgeted, isIncome, isAvailable } = opts + + if (isIncome || isAvailable) { + if (actual > 0) return 'text-success' + if (actual < 0) return 'text-destructive' + return '' + } + + // Expense path + if (actual > budgeted) return 'text-warning' + return '' +}