- Run record
- loading
Loading this Run…
Loading the Revisions of this Run…
A published source file of Revision 0 of Boardly — Website Relaunch 1.1.0, shown as text in the browser.
import boardRaw from "../public/data/board.json";
import membersRaw from "../public/data/members.json";
export type LabelDef = { id: string; name: string };
export type ChecklistItem = { id: string; text: string; done: boolean };
export type Card = {
id: string;
title: string;
description: string;
assignee: string | null;
labels: string[];
priority: string;
due: string | null;
checklist: ChecklistItem[];
};
export type Column = { id: string; title: string; wip_limit: number | null; card_ids: string[] };
export type BoardState = { columns: Column[]; cards: Record<string, Card> };
export type Member = { id: string; name: string; role: string };
type RawBoard = {
product: string;
workspace: string;
board: string;
today: string;
fictional_notice: string;
labels: LabelDef[];
priorities: string[];
columns: Column[];
cards: Card[];
};
const raw = boardRaw as unknown as RawBoard;
const rawMembers = membersRaw as unknown as { members: Member[] };
export const WORKSPACE = raw.workspace;
export const BOARD_NAME = raw.board;
export const TODAY = raw.today;
export const FICTIONAL_NOTICE = raw.fictional_notice;
export const LABELS = raw.labels;
export const PRIORITIES = raw.priorities;
export const MEMBERS = rawMembers.members;
export const DONE_COLUMN_ID = "done";
export const INITIAL_BOARD: BoardState = {
columns: raw.columns.map(c => ({ id: c.id, title: c.title, wip_limit: c.wip_limit, card_ids: [...c.card_ids] })),
cards: Object.fromEntries(
raw.cards.map(c => [c.id, { ...c, labels: [...c.labels], checklist: c.checklist.map(i => ({ ...i })) }]),
),
};
export const LABEL_STYLES: Record<string, { bg: string; fg: string; bd: string }> = {
design: { bg: "#EDEAF9", fg: "#5346B5", bd: "#D8D2F0" },
frontend: { bg: "#E2EDF7", fg: "#27619E", bd: "#C7DBEE" },
backend: { bg: "#E3F2E7", fg: "#2E7A43", bd: "#C9E8D1" },
content: { bg: "#FBF1DB", fg: "#8A6412", bd: "#F0E2BC" },
research: { bg: "#F8E6F1", fg: "#96417C", bd: "#EFCCE2" },
bug: { bg: "#FAE5E4", fg: "#A83232", bd: "#F1CCCA" },
};
export const PRIORITY_META: Record<string, { label: string; color: string }> = {
low: { label: "Low", color: "#8A8F98" },
medium: { label: "Medium", color: "#2E6EA6" },
high: { label: "High", color: "#C2710E" },
urgent: { label: "Urgent", color: "#B3372F" },
};
export const MEMBER_COLORS: Record<string, string> = {
maya: "#5C5AA8",
tomas: "#A8603C",
aiko: "#A85D82",
jonah: "#3D77A8",
priya: "#6E8A3A",
};
export const COLUMN_ACCENT: Record<string, string> = {
backlog: "#8A8F98",
todo: "#3D77A8",
"in-progress": "#2C6E63",
review: "#B07C1F",
done: "#4E8D5E",
};
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
export function formatDue(iso: string): string {
const [, m, d] = iso.split("-");
return `${MONTHS[Number(m) - 1]} ${Number(d)}`;
}
export function formatDueLong(iso: string): string {
const [y, m, d] = iso.split("-");
return `${MONTHS[Number(m) - 1]} ${Number(d)}, ${y}`;
}
export function initials(name: string): string {
const parts = name.trim().split(/\s+/);
return ((parts[0]?.[0] ?? "") + (parts[1]?.[0] ?? "")).toUpperCase();
}
export function memberById(id: string | null): Member | undefined {
return id ? MEMBERS.find(m => m.id === id) : undefined;
}
export function labelById(id: string): LabelDef | undefined {
return LABELS.find(l => l.id === id);
}
export function isOverdue(card: Card, colId: string): boolean {
return card.due !== null && card.due < TODAY && colId !== DONE_COLUMN_ID;
}
export function checklistCounts(card: Card): { done: number; total: number } {
return { done: card.checklist.filter(i => i.done).length, total: card.checklist.length };
}Source is browser-viewable only. There is no download or archive endpoint, and no additional license is granted beyond inspection and research.