feat(plan): resolveCell/resolveGrid return arrays; dashboard shows up to 3
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -150,16 +150,16 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
key: readonly unknown[],
|
||||
userId: number,
|
||||
dates: string[],
|
||||
mutator: (prev: ResolvedCell | null) => ResolvedCell | null,
|
||||
): Record<string, ResolvedCell | null> | null {
|
||||
mutator: (prev: ResolvedCell[]) => ResolvedCell[],
|
||||
): Record<string, ResolvedCell[]> | null {
|
||||
const prev = snapshotGrid(key);
|
||||
if (!prev) return null;
|
||||
const userPrev = prev.cells[userId] ?? {};
|
||||
const rolled: Record<string, ResolvedCell | null> = {};
|
||||
const userNext: Record<string, ResolvedCell | null> = { ...userPrev };
|
||||
const rolled: Record<string, ResolvedCell[]> = {};
|
||||
const userNext: Record<string, ResolvedCell[]> = { ...userPrev };
|
||||
for (const date of dates) {
|
||||
rolled[date] = userPrev[date] ?? null;
|
||||
userNext[date] = mutator(rolled[date]);
|
||||
rolled[date] = userPrev[date] ?? [];
|
||||
userNext[date] = mutator(rolled[date]).slice(0, 3);
|
||||
}
|
||||
qc.setQueryData(key, {
|
||||
...prev,
|
||||
@@ -244,7 +244,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// the ResolvedCell mirrors the request body.
|
||||
const days = eachDay(body.date_from, body.date_to);
|
||||
const id = data && typeof data.id === "number" ? data.id : null;
|
||||
const rolled = patchCells(currentGridKey, body.user_id, days, () =>
|
||||
const rolled = patchCells(currentGridKey, body.user_id, days, (prev) => [
|
||||
makeEntryCell({
|
||||
userId: body.user_id,
|
||||
date: days[0],
|
||||
@@ -255,7 +255,8 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
rangeTo: body.date_to,
|
||||
entryId: id,
|
||||
}),
|
||||
);
|
||||
...prev,
|
||||
]);
|
||||
// Stash the rollback on the mutation object so PlanWork can call
|
||||
// it from onError.
|
||||
(createEntry as any)._rolled = rolled;
|
||||
@@ -294,8 +295,8 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
let ownerUserId: number | null = null;
|
||||
if (grid) {
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
for (const cell of Object.values(byDate)) {
|
||||
if (cell && cell.entryId === id) {
|
||||
for (const cells of Object.values(byDate)) {
|
||||
if (cells.some((c) => c.entryId === id)) {
|
||||
ownerUserId = Number(uidStr);
|
||||
break;
|
||||
}
|
||||
@@ -304,20 +305,27 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
}
|
||||
}
|
||||
if (ownerUserId !== null) {
|
||||
const rolled = patchCells(currentGridKey, ownerUserId, days, (prev) =>
|
||||
makeEntryCell({
|
||||
userId: ownerUserId!,
|
||||
date: days[0],
|
||||
projectId:
|
||||
body.project_id === undefined
|
||||
? (prev?.project_id ?? null)
|
||||
: body.project_id,
|
||||
category: body.category ?? prev?.category ?? "work",
|
||||
note: body.note ?? prev?.note ?? "",
|
||||
rangeFrom: body.date_from,
|
||||
rangeTo: body.date_to,
|
||||
entryId: id,
|
||||
}),
|
||||
const rolled = patchCells(
|
||||
currentGridKey,
|
||||
ownerUserId,
|
||||
days,
|
||||
(prev) => {
|
||||
const existing = prev.find((c) => c.entryId === id) ?? null;
|
||||
const updated = makeEntryCell({
|
||||
userId: ownerUserId!,
|
||||
date: days[0],
|
||||
projectId:
|
||||
body.project_id === undefined
|
||||
? (existing?.project_id ?? null)
|
||||
: body.project_id,
|
||||
category: body.category ?? existing?.category ?? "work",
|
||||
note: body.note ?? existing?.note ?? "",
|
||||
rangeFrom: body.date_from,
|
||||
rangeTo: body.date_to,
|
||||
entryId: id,
|
||||
});
|
||||
return [updated, ...prev.filter((c) => c.entryId !== id)];
|
||||
},
|
||||
);
|
||||
(updateEntry as any)._rolled = rolled;
|
||||
}
|
||||
@@ -338,24 +346,27 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
if (grid) {
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
for (const [, cell] of Object.entries(byDate)) {
|
||||
if (
|
||||
cell &&
|
||||
cell.entryId === vars.id &&
|
||||
cell.rangeFrom &&
|
||||
cell.rangeTo
|
||||
) {
|
||||
const days = eachDay(cell.rangeFrom, cell.rangeTo);
|
||||
const rolled = patchCells(
|
||||
currentGridKey,
|
||||
Number(uidStr),
|
||||
days,
|
||||
() => null,
|
||||
);
|
||||
(deleteEntry as any)._rolled = rolled;
|
||||
let range: { from: string; to: string } | null = null;
|
||||
for (const cells of Object.values(byDate)) {
|
||||
const hit = cells.find(
|
||||
(c) => c.entryId === vars.id && c.rangeFrom && c.rangeTo,
|
||||
);
|
||||
if (hit) {
|
||||
range = { from: hit.rangeFrom!, to: hit.rangeTo! };
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (range) {
|
||||
const days = eachDay(range.from, range.to);
|
||||
const rolled = patchCells(
|
||||
currentGridKey,
|
||||
Number(uidStr),
|
||||
days,
|
||||
(prev) => prev.filter((c) => c.entryId !== vars.id),
|
||||
);
|
||||
(deleteEntry as any)._rolled = rolled;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
@@ -375,7 +386,7 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
currentGridKey,
|
||||
vars.user_id,
|
||||
[vars.shift_date],
|
||||
() =>
|
||||
(prev) => [
|
||||
makeOverrideCell({
|
||||
userId: vars.user_id,
|
||||
date: vars.shift_date,
|
||||
@@ -384,6 +395,8 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
note: vars.note,
|
||||
overrideId: id,
|
||||
}),
|
||||
...prev,
|
||||
],
|
||||
);
|
||||
(createOverride as any)._rolled = rolled;
|
||||
invalidate();
|
||||
@@ -411,21 +424,30 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
if (grid) {
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
for (const [date, cell] of Object.entries(byDate)) {
|
||||
if (cell && cell.overrideId === vars.id) {
|
||||
for (const [date, cells] of Object.entries(byDate)) {
|
||||
if (cells.some((c) => c.overrideId === vars.id)) {
|
||||
const rolled = patchCells(
|
||||
currentGridKey,
|
||||
Number(uidStr),
|
||||
[date],
|
||||
(prev) =>
|
||||
makeOverrideCell({
|
||||
(prev) => {
|
||||
const existing =
|
||||
prev.find((c) => c.overrideId === vars.id) ?? null;
|
||||
const updated = makeOverrideCell({
|
||||
userId: Number(uidStr),
|
||||
date,
|
||||
projectId: vars.body.project_id ?? prev?.project_id ?? null,
|
||||
category: vars.body.category ?? prev?.category ?? "work",
|
||||
note: vars.body.note ?? prev?.note ?? "",
|
||||
projectId:
|
||||
vars.body.project_id ?? existing?.project_id ?? null,
|
||||
category:
|
||||
vars.body.category ?? existing?.category ?? "work",
|
||||
note: vars.body.note ?? existing?.note ?? "",
|
||||
overrideId: vars.id,
|
||||
}),
|
||||
});
|
||||
return [
|
||||
updated,
|
||||
...prev.filter((c) => c.overrideId !== vars.id),
|
||||
];
|
||||
},
|
||||
);
|
||||
(updateOverride as any)._rolled = rolled;
|
||||
break;
|
||||
@@ -446,13 +468,13 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
const grid = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
if (grid) {
|
||||
for (const [uidStr, byDate] of Object.entries(grid.cells)) {
|
||||
for (const [date, cell] of Object.entries(byDate)) {
|
||||
if (cell && cell.overrideId === vars.id) {
|
||||
for (const [date, cells] of Object.entries(byDate)) {
|
||||
if (cells.some((c) => c.overrideId === vars.id)) {
|
||||
const rolled = patchCells(
|
||||
currentGridKey,
|
||||
Number(uidStr),
|
||||
[date],
|
||||
() => null,
|
||||
(prev) => prev.filter((c) => c.overrideId !== vars.id),
|
||||
);
|
||||
(deleteOverride as any)._rolled = rolled;
|
||||
break;
|
||||
@@ -472,15 +494,15 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
// directly without the "weak type" mismatch a `{ _rolled? }` param causes.
|
||||
function rollbackMutation(mutation: unknown, userId: number) {
|
||||
const stash = mutation as {
|
||||
_rolled?: Record<string, ResolvedCell | null> | null;
|
||||
_rolled?: Record<string, ResolvedCell[]> | null;
|
||||
};
|
||||
if (!stash._rolled) return;
|
||||
const prev = qc.getQueryData<GridData>(currentGridKey as any);
|
||||
if (!prev) return;
|
||||
const userPrev = prev.cells[userId] ?? {};
|
||||
const userNext = { ...userPrev };
|
||||
for (const [date, cell] of Object.entries(stash._rolled)) {
|
||||
userNext[date] = cell;
|
||||
for (const [date, cells] of Object.entries(stash._rolled)) {
|
||||
userNext[date] = cells;
|
||||
}
|
||||
qc.setQueryData(currentGridKey, {
|
||||
...prev,
|
||||
@@ -518,10 +540,18 @@ export function usePlanWork({ initialDate, canEdit }: UsePlanWorkArgs) {
|
||||
};
|
||||
}
|
||||
|
||||
export function getCells(
|
||||
grid: GridData | undefined,
|
||||
userId: number,
|
||||
date: string,
|
||||
): ResolvedCell[] {
|
||||
return grid?.cells?.[userId]?.[date] ?? [];
|
||||
}
|
||||
|
||||
export function getCell(
|
||||
grid: GridData | undefined,
|
||||
userId: number,
|
||||
date: string,
|
||||
): ResolvedCell | null {
|
||||
return grid?.cells?.[userId]?.[date] ?? null;
|
||||
return getCells(grid, userId, date)[0] ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user