mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 05:43:12 +00:00
Merge pull request #193 from Sea-Haven-Industries/fix/ab/sh-339-wizard-complete-image
Some checks failed
Some checks failed
SH-339: Allow completing Reactive/Emergency WOs from the side panel after photo upload
This commit is contained in:
commit
d6510b262e
2 changed files with 74 additions and 1 deletions
|
|
@ -269,6 +269,20 @@ export function boardMediaItemsToMediaFiles(items: WorkOrderBoardMediaItem[]): M
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* `GET workorders/{id}/detail` info serializes the board row's `MediaCount` as 0 — the detail
|
||||
* DTO inherits the field but the service never sets it — so trusting it verbatim would leave the
|
||||
* slide-over closability gate reporting "At least 1 photo" even after an upload. Take the larger
|
||||
* of the reported count and the stored (non-legacy) attachments: a positive API count still wins,
|
||||
* but a spurious (or omitted) 0 can no longer mask media that are actually present.
|
||||
*/
|
||||
function resolveDetailMediaCount(infoRaw: unknown, media: WorkOrderBoardMediaItem[]): number {
|
||||
const record = asRecord(infoRaw);
|
||||
const explicit = record.mediaCount ?? record.MediaCount;
|
||||
const nonLegacyCount = media.filter((item) => !item.isLegacy).length;
|
||||
return Math.max(typeof explicit === "number" ? explicit : 0, nonLegacyCount);
|
||||
}
|
||||
|
||||
export function mapWorkOrderBoardDetail(raw: unknown): WorkOrderBoardDetail {
|
||||
const root = asRecord(raw);
|
||||
const infoRaw = root.info ?? root.Info ?? root;
|
||||
|
|
@ -283,8 +297,10 @@ export function mapWorkOrderBoardDetail(raw: unknown): WorkOrderBoardDetail {
|
|||
: [];
|
||||
const media = Array.isArray(mediaRaw) ? mediaRaw.map(mapBoardDetailMediaItem) : [];
|
||||
|
||||
const info = mapWorkOrderTableRow(infoRaw);
|
||||
|
||||
return {
|
||||
info: mapWorkOrderTableRow(infoRaw),
|
||||
info: { ...info, mediaCount: resolveDetailMediaCount(infoRaw, media) },
|
||||
completion: mapCompletion(completionRaw ?? {}),
|
||||
comments,
|
||||
audit,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import {
|
|||
mapBoardDetailMediaItem,
|
||||
mapWorkOrderBoardDetail,
|
||||
} from "@/domain/work-orders/mappers/work-order-board-detail-mapper";
|
||||
import {
|
||||
getClosabilityGaps,
|
||||
tableRowToClosabilityInput,
|
||||
} from "@/domain/work-orders/utils/wo-closability";
|
||||
|
||||
const SAMPLE_DETAIL = {
|
||||
info: {
|
||||
|
|
@ -279,3 +283,56 @@ describe("mapWorkOrderBoardDetail", () => {
|
|||
expect(completionForm.get("file")).toBeInstanceOf(File);
|
||||
});
|
||||
});
|
||||
|
||||
describe("mapWorkOrderBoardDetail media count (SH-339)", () => {
|
||||
const reactiveInfo = { ...SAMPLE_DETAIL.info, workOrderType: 6 };
|
||||
|
||||
it("derives mediaCount from stored media when detail info omits it", () => {
|
||||
const detail = mapWorkOrderBoardDetail({ ...SAMPLE_DETAIL, info: reactiveInfo });
|
||||
|
||||
expect(detail.info.type).toBe("Reactive");
|
||||
expect(detail.info.mediaCount).toBe(2);
|
||||
expect(getClosabilityGaps(tableRowToClosabilityInput(detail.info))).not.toContain(
|
||||
"At least 1 photo",
|
||||
);
|
||||
});
|
||||
|
||||
it("prefers stored media when detail info reports an explicit zero", () => {
|
||||
const detail = mapWorkOrderBoardDetail({
|
||||
...SAMPLE_DETAIL,
|
||||
info: { ...reactiveInfo, mediaCount: 0 },
|
||||
});
|
||||
|
||||
expect(detail.info.mediaCount).toBe(2);
|
||||
expect(getClosabilityGaps(tableRowToClosabilityInput(detail.info))).not.toContain(
|
||||
"At least 1 photo",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not count legacy URL-column media, matching the board row count", () => {
|
||||
const detail = mapWorkOrderBoardDetail({
|
||||
...SAMPLE_DETAIL,
|
||||
info: reactiveInfo,
|
||||
media: [
|
||||
{
|
||||
id: -1,
|
||||
category: 1,
|
||||
url: "https://cdn.example.com/legacy.jpg",
|
||||
fileName: "legacy.jpg",
|
||||
isLegacy: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(detail.info.mediaCount).toBe(0);
|
||||
});
|
||||
|
||||
it("keeps an explicit info mediaCount", () => {
|
||||
const detail = mapWorkOrderBoardDetail({
|
||||
...SAMPLE_DETAIL,
|
||||
info: { ...reactiveInfo, mediaCount: 5 },
|
||||
});
|
||||
|
||||
expect(detail.info.mediaCount).toBe(5);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue