Files
remco-vermeer 53bf667f54 Voeg Module 4 experts, waardebepalingspagina en projectverbeteringen toe
Experts (Module 4)
- Pagina Experts (CRM): experts uitnodigen per e-mail (zonder SMTP wordt de
  link getoond), rondes koppelen, opnieuw uitnodigen, verwijderen en
  "Inloggen als" (alleen lezen) om mee te kijken
- Uitnodigingspagina waar een expert zijn wachtwoord instelt (token 7 dagen
  geldig, eenmalig, alleen als hash opgeslagen)
- Expertpagina: projecten in waardebepaling uit de eigen rondes, project plan
  lezen en eigen beoordeling geven (3 scores, advies Bonus/Malus, toelichting)
- Rollen admin/expert: alle beheerpagina's en -acties controleren de rol
- Rikx calculatie gebruikt de beoordelingen van de experts in plaats van de
  handmatige expertkolommen; experts koppelen ook vanaf de rondepagina

Waardebepaling projecten
- Nieuwe pagina met projecten in waardebepaling op kosten/impact (laag naar
  hoog), filter op ronde, Rikx Waarde-veld dat live doorrekent en opslaat in
  de ronde, en een 75%-lijn bij een gekozen ronde

Projecten
- Rikx calculatie als tab, zichtbaar vanaf status Waardebepaling, met keuze
  rekenmethode (Arbeid; Jeugd nog niet beschikbaar) en beoordeling
  goedgekeurd/afgekeurd met reden
- Impactmaker gekoppeld aan een sociaal ondernemer
- Opslaan-knop bovenaan; ongeldige velden op een verborgen tab worden getoond
- Project toevoegen maakt direct een project aan; aparte pagina verwijderd
- Waarderingssystematiek Rikx juni 2023 toegevoegd aan _doc

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:42:22 +02:00

33 lines
1.5 KiB
TypeScript

"use server";
import { getDb } from "../../lib/db";
import { getCurrentUser } from "../../lib/auth";
import { defaultRikxPrijs } from "../../lib/rikxCalculatie";
export type SaveRondeWaardeResult = { ok: true; labels: string[] } | { ok: false; error: string };
// Zet de Rikx waarde (en Rikx prijs = 10%) op de opgegeven Rikx rondes.
// Aangeroepen vanuit het Rikx Waarde-veld op de pagina Waardebepaling projecten.
export async function saveRondeWaarde(rondeIds: number[], rikxWaarde: number): Promise<SaveRondeWaardeResult> {
const user = await getCurrentUser();
if (!user || user.role !== "admin") return { ok: false, error: "Geen toegang" };
if (!Number.isFinite(rikxWaarde) || rikxWaarde < 0) return { ok: false, error: "Ongeldige Rikx waarde" };
const ids = [...new Set(rondeIds.map(Number))].filter((id) => Number.isInteger(id) && id > 0);
if (ids.length === 0) return { ok: false, error: "Geen ronde om bij te werken" };
const db = getDb();
const placeholders = ids.map(() => "?").join(",");
const rondes = db.prepare(`SELECT id, label FROM rikx_rondes WHERE id IN (${placeholders})`).all(...ids) as {
id: number;
label: string;
}[];
if (rondes.length === 0) return { ok: false, error: "Ronde niet gevonden" };
db.prepare(
`UPDATE rikx_rondes SET rikx_waarde = ?, rikx_prijs = ?, updated_at = datetime('now') WHERE id IN (${placeholders})`
).run(rikxWaarde, defaultRikxPrijs(rikxWaarde), ...ids);
return { ok: true, labels: rondes.map((r) => r.label) };
}