8be7d5aad2
- Remove 'Flotte ansehen' button from hero section - Remove '24/7 Support' stat from hero section - Remove 'Unsere Flotte' eyebrow from fleet section - Remove ALL 'Warum wir' / 'Why us' references from nav links, i18n keys, and legal pages - Update reviews: Ferrari references only (removed GT3 mentions) - Update Impressum with correct company data (MC Cars GmbH) - Add multi-photo gallery: DB migration (17-vehicle-photos.sql), admin UI for photo management, frontend carousel on cards and dialog - Update SEO: Ferrari-focused meta tags, title, keywords, JSON-LD - Clean up dead i18n keys (viewFleet, statSupport, fleetEyebrow, navWhy, why* keys) - Fix legal page issues: add config.js script, fix logo references to SVG - Add Playwright E2E tests (26/26 passing) - Update footer tagline across all pages
92 lines
3.4 KiB
PL/PgSQL
92 lines
3.4 KiB
PL/PgSQL
-- 17-vehicle-photos.sql
|
|
-- Idempotent migration: add vehicle_photos table for multiple photos per vehicle.
|
|
-- Each vehicle can have multiple photos with ordering support.
|
|
|
|
-- Create vehicle_photos table
|
|
create table if not exists public.vehicle_photos (
|
|
id uuid primary key default gen_random_uuid(),
|
|
vehicle_id uuid not null references public.vehicles(id) on delete cascade,
|
|
photo_url text not null default '',
|
|
photo_path text not null,
|
|
display_order integer not null default 0,
|
|
is_primary boolean not null default false,
|
|
created_at timestamptz not null default now()
|
|
);
|
|
|
|
create index if not exists vehicle_photos_vehicle_id_idx
|
|
on public.vehicle_photos(vehicle_id, display_order);
|
|
|
|
-- Enable RLS
|
|
alter table public.vehicle_photos enable row level security;
|
|
|
|
-- Drop existing policies to ensure idempotency
|
|
drop policy if exists "vehicle_photos_public_read" on public.vehicle_photos;
|
|
drop policy if exists "vehicle_photos_admin_read" on public.vehicle_photos;
|
|
drop policy if exists "vehicle_photos_admin_insert" on public.vehicle_photos;
|
|
drop policy if exists "vehicle_photos_admin_delete" on public.vehicle_photos;
|
|
drop policy if exists "vehicle_photos_admin_update" on public.vehicle_photos;
|
|
|
|
-- Public can read all photos
|
|
create policy "vehicle_photos_public_read"
|
|
on public.vehicle_photos for select
|
|
to anon using (true);
|
|
|
|
-- Authenticated (admin) full access
|
|
create policy "vehicle_photos_admin_read"
|
|
on public.vehicle_photos for select
|
|
to authenticated using (true);
|
|
|
|
create policy "vehicle_photos_admin_insert"
|
|
on public.vehicle_photos for insert
|
|
to authenticated with check (true);
|
|
|
|
create policy "vehicle_photos_admin_update"
|
|
on public.vehicle_photos for update
|
|
to authenticated using (true) with check (true);
|
|
|
|
create policy "vehicle_photos_admin_delete"
|
|
on public.vehicle_photos for delete
|
|
to authenticated using (true);
|
|
|
|
-- Grants
|
|
grant select on public.vehicle_photos to anon, authenticated;
|
|
grant insert, update, delete on public.vehicle_photos to authenticated;
|
|
grant all on public.vehicle_photos to service_role;
|
|
|
|
-- Migrate existing vehicle photo_url/photo_path to vehicle_photos table
|
|
-- This ensures existing vehicles get their photo into the new table
|
|
insert into public.vehicle_photos (vehicle_id, photo_url, photo_path, display_order, is_primary)
|
|
select id, photo_url, coalesce(photo_path, 'legacy'), 0, true
|
|
from public.vehicles
|
|
where photo_url != '' and photo_path is not null
|
|
on conflict do nothing;
|
|
|
|
-- RPC: set primary photo for a vehicle (unsets others)
|
|
create or replace function public.set_primary_vehicle_photo(
|
|
p_vehicle_id uuid,
|
|
p_photo_id uuid
|
|
) returns void
|
|
language plpgsql security invoker as $$
|
|
begin
|
|
update public.vehicle_photos set is_primary = false where vehicle_id = p_vehicle_id;
|
|
update public.vehicle_photos set is_primary = true where id = p_photo_id and vehicle_id = p_vehicle_id;
|
|
end;
|
|
$$;
|
|
|
|
-- RPC: re-order photos for a vehicle
|
|
create or replace function public.reorder_vehicle_photos(
|
|
p_vehicle_id uuid,
|
|
p_photo_orders jsonb -- [{id: uuid, order: int}, ...]
|
|
) returns void
|
|
language plpgsql security invoker as $$
|
|
declare
|
|
rec jsonb;
|
|
begin
|
|
for rec in select * from jsonb_array_elements(p_photo_orders) loop
|
|
update public.vehicle_photos
|
|
set display_order = (rec->>'order')::int
|
|
where id = (rec->>'id')::uuid and vehicle_id = p_vehicle_id;
|
|
end loop;
|
|
end;
|
|
$$;
|