31 lines
2.3 KiB
JavaScript
31 lines
2.3 KiB
JavaScript
// Calendar dates are derived from event timestamps, never from the last edit time.
|
|
export async function activityFor(db, userId, month, timeZone) {
|
|
const formatter = new Intl.DateTimeFormat("en-CA", {timeZone, year:"numeric",month:"2-digit",day:"2-digit"});
|
|
const dateKey = (value, fallback) => {
|
|
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(value))) return value;
|
|
const parsed = value && Number.isFinite(Date.parse(value)) ? new Date(value) : new Date(fallback);
|
|
const parts = Object.fromEntries(formatter.formatToParts(parsed).map(p=>[p.type,p.value]));
|
|
return `${parts.year}-${parts.month}-${parts.day}`;
|
|
};
|
|
const [roasts, cups, brews, plans] = await Promise.all([
|
|
db.query("SELECT id,roast_plan_id,filename,parsed->'roast' AS roast,created_at FROM actual_roasts WHERE user_id=$1", [userId]),
|
|
db.query("SELECT id,roast_plan_id,data->>'ritual_started_at_iso' AS started_at,created_at FROM cupping_sessions WHERE user_id=$1", [userId]),
|
|
db.query("SELECT b.id,b.method,b.brewed_at,r.name FROM brews b LEFT JOIN roasted_beans r ON r.id=b.bean_id AND r.user_id=b.user_id WHERE b.user_id=$1", [userId]),
|
|
db.query("SELECT id,name,plan->'fields'->>'0.1' AS coffee,created_at FROM roast_plans WHERE user_id=$1", [userId]),
|
|
]);
|
|
const names = new Map(plans.rows.map(p=>[p.id,p.name || p.coffee || "Untitled plan"]));
|
|
const events = [];
|
|
const add = (kind, row, title, timestamp, fallback, href) => {
|
|
const date = dateKey(timestamp,fallback);
|
|
if (date.startsWith(month + "-")) events.push({id:row.id,kind,title,date,href,
|
|
planHref: row.roast_plan_id && names.has(row.roast_plan_id) ? "/app?plan="+row.roast_plan_id : null,
|
|
dateSource: timestamp && Number.isFinite(Date.parse(timestamp)) ? "event" : "logged",
|
|
});
|
|
};
|
|
for (const r of roasts.rows) add("roast",r,r.roast?.title || r.filename,r.roast?.roastDate,r.created_at,"/roasts?roast="+r.id);
|
|
for (const c of cups.rows) add("cupping",c,names.get(c.roast_plan_id) || "Cupping session",c.started_at,c.created_at,"/cupping?session="+c.id);
|
|
for (const b of brews.rows) add("brew",b,[b.name,b.method].filter(Boolean).join(" · "),b.brewed_at,b.brewed_at,"/brews?brew="+b.id);
|
|
for (const p of plans.rows) add("plan",p,names.get(p.id),p.created_at,p.created_at,"/app?plan="+p.id);
|
|
return events.sort((a,b)=>a.date.localeCompare(b.date) || a.title.localeCompare(b.title));
|
|
}
|