added dashboard

This commit is contained in:
Rajpreet0 2026-09-29 15:20:50 +02:00
parent 29ea53a03d
commit 64b2c85f81
14 changed files with 1496 additions and 11 deletions

View file

@ -0,0 +1,37 @@
-- Info-Sektion: Produktstatus, laufende Vorgänge, interne Notizen
-- Hosting als eigene Kategorie (neben Webseite, E-Mail, SEO)
alter type public.product_category add value if not exists 'hosting';
-- Freitext zum Status, z. B. "Erreichbar, keine Störungen" oder "Wartung geplant am 12.10."
alter table public.client_products
add column if not exists status_message text;
-- Vorgänge müssen nicht zwingend an ein Produkt gebunden sein
alter table public.product_tasks
alter column product_id drop not null;
-- "zuletzt bearbeitet von ..." für interne Notizen
alter table public.internal_notes
add column if not exists updated_by uuid references public.profiles(id) on delete set null default auth.uid(),
add column if not exists updated_at timestamptz not null default now();
update public.internal_notes
set updated_by = created_by, updated_at = created_at
where updated_by is null;
create or replace function public.set_updated_by()
returns trigger language plpgsql set search_path = '' as $$
begin
new.updated_by = auth.uid();
return new;
end $$;
create trigger set_updated_at before update on public.internal_notes
for each row execute function public.set_updated_at();
create trigger set_updated_by before update on public.internal_notes
for each row execute function public.set_updated_by();
create index if not exists internal_notes_client_updated_idx
on public.internal_notes (client_id, updated_at desc);

View file

@ -0,0 +1,51 @@
-- Erreichbarkeitsprüfungen für Produkte (manuell per Button + beim Seitenaufruf)
create table public.product_checks (
id bigint generated always as identity primary key,
product_id uuid not null references public.client_products(id) on delete cascade,
client_id uuid not null references public.clients(id) on delete cascade,
checked_at timestamptz not null default now(),
ok boolean not null,
status_code int,
response_ms int,
error text
);
create index on public.product_checks (product_id, checked_at desc);
-- Lesen: Admin alles, Client nur eigene. Schreiben bewusst ohne Policy:
-- Ergebnisse schreibt nur der Server (Service Role), damit Clients ihre Uptime nicht fälschen können.
alter table public.product_checks enable row level security;
create policy admin_select on public.product_checks for select to authenticated
using ((select public.is_admin()));
create policy client_select on public.product_checks for select to authenticated
using (client_id = (select public.current_client_id()));
-- Letzte Prüfung + Uptime der letzten 30 Tage je Produkt
create view public.product_check_summary with (security_invoker = true) as
select
p.id as product_id,
last.checked_at,
last.ok,
last.status_code,
last.response_ms,
last.error,
stats.checks_30d,
stats.uptime_30d
from public.client_products p
left join lateral (
select c.checked_at, c.ok, c.status_code, c.response_ms, c.error
from public.product_checks c
where c.product_id = p.id
order by c.checked_at desc
limit 1
) last on true
left join lateral (
select
count(*)::int as checks_30d,
round(100.0 * count(*) filter (where c.ok) / nullif(count(*), 0), 2) as uptime_30d
from public.product_checks c
where c.product_id = p.id
and c.checked_at > now() - interval '30 days'
) stats on true;