-
+ {back ? (
+
- {subtitle ? (
-
- {subtitle}
-
+ {back}
+
+ ) : null}
+
+
+
+ {title}
+
+ {subtitle ? (
+
+ {subtitle}
+
+ ) : null}
+
+ {actions ? (
+
{actions}
) : null}
- {actions ? (
-
{actions}
- ) : null}
);
};
diff --git a/src/equipments/components/equipment-actions-menu.tsx b/src/shared/components/resource-actions-menu.tsx
similarity index 72%
rename from src/equipments/components/equipment-actions-menu.tsx
rename to src/shared/components/resource-actions-menu.tsx
index 3e18fe0..bd1c7a5 100644
--- a/src/equipments/components/equipment-actions-menu.tsx
+++ b/src/shared/components/resource-actions-menu.tsx
@@ -4,14 +4,15 @@ import { Button, Dropdown, type MenuProps, Modal } from 'antd';
import type { FC } from 'react';
import { useCurrentBoat } from '@/boats/hooks/use-current-boat';
-import type { Equipment } from '@/shared/types/models';
-interface EquipmentActionsMenuProps {
- equipment: Equipment;
+interface ResourceActionsMenuProps {
+ resource: string;
+ resourceId: string;
}
-export const EquipmentActionsMenu: FC
= ({
- equipment,
+const ResourceActionsMenu: FC = ({
+ resource,
+ resourceId,
}) => {
const translate = useTranslate();
const { data: boat } = useCurrentBoat();
@@ -21,15 +22,17 @@ export const EquipmentActionsMenu: FC = ({
const handleDelete = () => {
Modal.confirm({
- title: translate('equipments.delete.confirmTitle'),
- content: translate('equipments.delete.confirmContent'),
+ title: translate('shared.actions_menu.delete.confirm.title'),
+ content: translate('shared.actions_menu.delete.confirm.content', {
+ resource: translate(`${resource}.single`),
+ }),
okText: translate('common.delete'),
cancelText: translate('common.cancel'),
okType: 'danger',
onOk: () => {
deleteEquipment({
- resource: 'equipments',
- id: equipment.id,
+ resource,
+ id: resourceId,
});
},
});
@@ -38,7 +41,7 @@ export const EquipmentActionsMenu: FC = ({
const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
if (key === 'edit') {
go({
- to: `/boats/${boat?.data?.id}/equipments/${equipment.id}/edit`,
+ to: `/boats/${boat?.data?.id}/${resource}/${resourceId}/edit`,
});
} else if (key === 'delete') {
handleDelete();
@@ -70,3 +73,5 @@ export const EquipmentActionsMenu: FC = ({
);
};
+
+export { ResourceActionsMenu };
diff --git a/src/shared/types/models.ts b/src/shared/types/models.ts
index 4668429..34d971c 100644
--- a/src/shared/types/models.ts
+++ b/src/shared/types/models.ts
@@ -12,4 +12,6 @@ export type EquipmentAttachment = Tables<'equipment_attachments'>;
export type Access = Tables<'accesses'>;
+export type Intervention = Tables<'interventions'>;
+export type InsertIntervention = TablesInsert<'interventions'>;
export type UpdateIntervention = TablesUpdate<'interventions'>;
diff --git a/supabase/migrations/20250731064112_add_cost_to_intervention_table.sql b/supabase/migrations/20250731064112_add_cost_to_intervention_table.sql
new file mode 100644
index 0000000..1043887
--- /dev/null
+++ b/supabase/migrations/20250731064112_add_cost_to_intervention_table.sql
@@ -0,0 +1,7 @@
+alter table "public"."interventions" add column "labor_cost" numeric;
+
+alter table "public"."interventions" add column "supply_cost" numeric;
+
+alter table "public"."interventions" add column "total_cost" numeric;
+
+
diff --git a/supabase/migrations/20250731093745_create_intervention_attachments_table.sql b/supabase/migrations/20250731093745_create_intervention_attachments_table.sql
new file mode 100644
index 0000000..ec15369
--- /dev/null
+++ b/supabase/migrations/20250731093745_create_intervention_attachments_table.sql
@@ -0,0 +1,106 @@
+alter table "public"."equipment_attachments" drop constraint "attachments_equipment_id_fkey";
+
+alter table "public"."equipment_attachments" drop constraint "attachments_pkey";
+
+drop index if exists "public"."attachments_pkey";
+
+create table "public"."intervention_attachments" (
+ "id" uuid not null default gen_random_uuid(),
+ "intervention_id" uuid not null,
+ "file_path" text not null,
+ "file_name" text not null,
+ "file_type" text,
+ "description" text,
+ "uploaded_at" timestamp with time zone not null default now()
+);
+
+
+alter table "public"."intervention_attachments" enable row level security;
+
+CREATE UNIQUE INDEX equipment_attachments_pkey ON public.equipment_attachments USING btree (id);
+
+CREATE INDEX idx_intervention_attachments_intervention_id ON public.intervention_attachments USING btree (intervention_id);
+
+CREATE UNIQUE INDEX intervention_attachments_pkey ON public.intervention_attachments USING btree (id);
+
+alter table "public"."equipment_attachments" add constraint "equipment_attachments_pkey" PRIMARY KEY using index "equipment_attachments_pkey";
+
+alter table "public"."intervention_attachments" add constraint "intervention_attachments_pkey" PRIMARY KEY using index "intervention_attachments_pkey";
+
+alter table "public"."equipment_attachments" add constraint "equipment_attachments_equipment_id_fkey" FOREIGN KEY (equipment_id) REFERENCES equipments(id) ON DELETE CASCADE not valid;
+
+alter table "public"."equipment_attachments" validate constraint "equipment_attachments_equipment_id_fkey";
+
+alter table "public"."intervention_attachments" add constraint "intervention_attachments_intervention_id_fkey" FOREIGN KEY (intervention_id) REFERENCES interventions(id) ON DELETE CASCADE not valid;
+
+alter table "public"."intervention_attachments" validate constraint "intervention_attachments_intervention_id_fkey";
+
+set check_function_bodies = off;
+
+CREATE OR REPLACE FUNCTION public.check_intervention_access(intervention_id uuid)
+ RETURNS boolean
+ LANGUAGE sql
+ SET search_path TO ''
+AS $function$
+ SELECT EXISTS (
+ SELECT 1
+ FROM public.interventions e
+ JOIN public.accesses a ON e.boat_id = a.boat_id
+ WHERE e.id = intervention_id
+ AND a.user_id = (SELECT auth.uid())
+ );
+$function$
+;
+
+grant delete on table "public"."intervention_attachments" to "anon";
+
+grant insert on table "public"."intervention_attachments" to "anon";
+
+grant references on table "public"."intervention_attachments" to "anon";
+
+grant select on table "public"."intervention_attachments" to "anon";
+
+grant trigger on table "public"."intervention_attachments" to "anon";
+
+grant truncate on table "public"."intervention_attachments" to "anon";
+
+grant update on table "public"."intervention_attachments" to "anon";
+
+grant delete on table "public"."intervention_attachments" to "authenticated";
+
+grant insert on table "public"."intervention_attachments" to "authenticated";
+
+grant references on table "public"."intervention_attachments" to "authenticated";
+
+grant select on table "public"."intervention_attachments" to "authenticated";
+
+grant trigger on table "public"."intervention_attachments" to "authenticated";
+
+grant truncate on table "public"."intervention_attachments" to "authenticated";
+
+grant update on table "public"."intervention_attachments" to "authenticated";
+
+grant delete on table "public"."intervention_attachments" to "service_role";
+
+grant insert on table "public"."intervention_attachments" to "service_role";
+
+grant references on table "public"."intervention_attachments" to "service_role";
+
+grant select on table "public"."intervention_attachments" to "service_role";
+
+grant trigger on table "public"."intervention_attachments" to "service_role";
+
+grant truncate on table "public"."intervention_attachments" to "service_role";
+
+grant update on table "public"."intervention_attachments" to "service_role";
+
+create policy "Users can manage attachments of interventions to which they hav"
+on "public"."intervention_attachments"
+as permissive
+for all
+to authenticated
+using (check_intervention_access(intervention_id))
+with check (check_intervention_access(intervention_id));
+
+
+
diff --git a/supabase/schemas/equipment_attachments.sql b/supabase/schemas/equipment_attachments.sql
index 2cd22db..2df4baf 100644
--- a/supabase/schemas/equipment_attachments.sql
+++ b/supabase/schemas/equipment_attachments.sql
@@ -6,8 +6,8 @@ create table public.equipment_attachments (
file_type text,
description text,
uploaded_at timestamp with time zone not null default now(),
- constraint attachments_pkey primary key (id),
- constraint attachments_equipment_id_fkey foreign key (equipment_id) references public.equipments(id) on delete cascade
+ constraint equipment_attachments_pkey primary key (id),
+ constraint equipment_attachments_equipment_id_fkey foreign key (equipment_id) references public.equipments(id) on delete cascade
);
alter table public.equipment_attachments enable row level security;
diff --git a/supabase/schemas/intervention_attachments.sql b/supabase/schemas/intervention_attachments.sql
new file mode 100644
index 0000000..733e66d
--- /dev/null
+++ b/supabase/schemas/intervention_attachments.sql
@@ -0,0 +1,38 @@
+create table public.intervention_attachments (
+ id uuid not null default gen_random_uuid(),
+ intervention_id uuid not null,
+ file_path text not null,
+ file_name text not null,
+ file_type text,
+ description text,
+ uploaded_at timestamp with time zone not null default now(),
+ constraint intervention_attachments_pkey primary key (id),
+ constraint intervention_attachments_intervention_id_fkey foreign key (intervention_id) references public.interventions(id) on delete cascade
+);
+
+alter table public.intervention_attachments enable row level security;
+
+CREATE OR REPLACE FUNCTION check_intervention_access(intervention_id uuid)
+returns boolean
+language sql
+set search_path = ''
+as $$
+ SELECT EXISTS (
+ SELECT 1
+ FROM public.interventions e
+ JOIN public.accesses a ON e.boat_id = a.boat_id
+ WHERE e.id = intervention_id
+ AND a.user_id = (SELECT auth.uid())
+ );
+$$;
+
+create policy "Users can manage attachments of interventions to which they have access"
+on public.intervention_attachments
+to authenticated
+using (
+ check_intervention_access(intervention_id)
+) with check (
+ check_intervention_access(intervention_id)
+);
+
+create index if not exists idx_intervention_attachments_intervention_id on public.intervention_attachments(intervention_id);
diff --git a/supabase/schemas/interventions.sql b/supabase/schemas/interventions.sql
index b7fad5c..cb5b6ff 100644
--- a/supabase/schemas/interventions.sql
+++ b/supabase/schemas/interventions.sql
@@ -4,6 +4,9 @@ CREATE TABLE public.interventions (
description text,
title text NOT NULL,
date timestamp with time zone NOT NULL,
+ total_cost numeric,
+ labor_cost numeric,
+ supply_cost numeric,
created_at timestamp with time zone NOT NULL DEFAULT now(),
constraint interventions_pkey primary key (id),
constraint interventions_boat_id_fkey foreign key (boat_id) references public.boats(id)