> = [
+ "Extra",
+ "Aveta",
+];
+
type SlideOverExtrasTabProps = {
uploads: MediaFile[];
isReadOnly: boolean;
@@ -36,6 +45,7 @@ type SlideOverExtrasTabProps = {
avetaRequired?: boolean;
onUpload: (files: File[]) => void;
onRemove: (id: string) => void;
+ onCategorize?: (id: string, category: UploadableMediaCategory) => void;
};
function ExtraDocRow({
@@ -43,16 +53,20 @@ function ExtraDocRow({
isReadOnly,
pending,
onRemove,
+ onCategorize,
}: {
file: MediaFile;
isReadOnly: boolean;
pending: boolean;
onRemove: (id: string) => void;
+ onCategorize?: (id: string, category: UploadableMediaCategory) => void;
}) {
const category = resolveExtraDocCategory(file);
const isAveta = category === "Aveta";
const ItemIcon = isAveta ? ShieldCheck : FILETYPE_ICON[file.fileType];
const showDelete = !isReadOnly && canDeleteWorkOrderMedia(file);
+ const showCategory = !isReadOnly && Boolean(onCategorize) && !file.isLegacy;
+ const purpose = file.purpose === "Aveta" || isAveta ? "Aveta" : "Extra";
return (
@@ -70,8 +84,34 @@ function ExtraDocRow({
>
{file.name}
- {isAveta && (
- Aveta
+ {showCategory ? (
+
+ ) : (
+ isAveta && (
+ Aveta
+ )
)}
{showDelete && (
diff --git a/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx b/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx
index ea2aafc1..2f497d10 100644
--- a/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx
+++ b/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx
@@ -102,6 +102,7 @@ export function SlideOverInfoTabDisplayView({
serviceNotes={source.serviceNotes}
extraServices={source.extraServices}
avetaRequired={source.avetaRequired}
+ avetaAttached={source.hasAvetaDocument}
woNumber={source.woNumber}
viewOnly
onSave={() => undefined}
@@ -110,7 +111,9 @@ export function SlideOverInfoTabDisplayView({
{source.pm}
- {Boolean(source.avetaRequired) && }
+ {Boolean(source.avetaRequired) && (
+
+ )}
) : (
—
diff --git a/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts b/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts
index 15e6765b..4940b81d 100644
--- a/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts
+++ b/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts
@@ -44,7 +44,9 @@ export function useSlideOverMediaState({
const extrasUploads = useMemo(
() =>
boardMediaItemsToMediaFiles(
- (detailForRow?.media ?? []).filter((item) => item.category === "Extra"),
+ (detailForRow?.media ?? []).filter(
+ (item) => item.category === "Extra" || item.category === "Aveta",
+ ),
),
[detailForRow?.media],
);
diff --git a/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx b/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx
index 3a653c78..ebd41392 100644
--- a/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx
+++ b/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx
@@ -158,6 +158,7 @@ export function WorkOrderSlideOverTabs({
void state.uploadExtraFiles(files);
}}
onRemove={state.removeMedia}
+ onCategorize={state.categorizeMedia}
/>
)}
diff --git a/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx b/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx
index 0f67b21c..d5993fc5 100644
--- a/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx
+++ b/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx
@@ -3,14 +3,21 @@ import { Tooltip } from "@mui/material";
type AvetaBadgeProps = {
size?: number;
+ attached?: boolean;
};
/** Per-WO Aveta shield — never a site-level flag. Color is paired with the icon. */
-export function AvetaBadge({ size = 11 }: AvetaBadgeProps) {
+export function AvetaBadge({ size = 11, attached = false }: AvetaBadgeProps) {
+ const color = attached ? "var(--success)" : "var(--warning)";
+ const title = attached
+ ? "Aveta documentation is attached"
+ : "This work order requires Aveta compliance documentation";
+ const label = attached ? "Aveta attached" : "Aveta required";
+
return (
-
-
-
+
+
+
);
diff --git a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx
index 5da468d2..be03e7fe 100644
--- a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx
+++ b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx
@@ -22,6 +22,7 @@ type PMTypeCellProps = {
serviceNotes?: string;
extraServices?: string[];
avetaRequired?: boolean;
+ avetaAttached?: boolean;
woNumber?: string;
onSaveDetails?: (details: ServiceNotesDetails) => void;
viewOnly?: boolean;
@@ -35,6 +36,7 @@ export function PMTypeCell({
serviceNotes = "",
extraServices = [],
avetaRequired = false,
+ avetaAttached = false,
woNumber,
onSaveDetails,
viewOnly = false,
@@ -99,7 +101,7 @@ export function PMTypeCell({
) : (
—
)}
- {Boolean(avetaRequired) && }
+ {Boolean(avetaRequired) && }
{modal}
>
@@ -115,6 +117,7 @@ export function PMTypeCell({
notePreview={notePreview}
extrasCount={extras.length}
avetaRequired={avetaRequired}
+ avetaAttached={avetaAttached}
onOpenDetails={() => setModalOpen(true)}
/>
{modal}
diff --git a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx
index 20b7708d..3bb7d5aa 100644
--- a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx
+++ b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx
@@ -8,6 +8,7 @@ type PmTypeDetailsTriggerProps = {
notePreview: string;
extrasCount: number;
avetaRequired?: boolean;
+ avetaAttached?: boolean;
onOpenDetails: () => void;
};
@@ -17,6 +18,7 @@ export function PmTypeDetailsTrigger({
notePreview,
extrasCount,
avetaRequired = false,
+ avetaAttached = false,
onOpenDetails,
}: PmTypeDetailsTriggerProps) {
return (
@@ -44,7 +46,7 @@ export function PmTypeDetailsTrigger({
>
{value ? : "Select …"}
- {Boolean(avetaRequired) && }
+ {Boolean(avetaRequired) && }