- Fix VAT declaration ruta mappings to match SKV 4700 form correctly (ruta 05 = total taxable sales, ruta 10/11/12 = output VAT per rate) - Add INK2 declaration report for aktiebolag with SRU export - Add full archive ZIP export for 7-year retention compliance - Add AI consent gate requiring user approval before AI extension API calls - Add DPA and privacy policy public pages - Add audit trail API routes - Update VAT registration threshold from 80k to 120k kr in onboarding - Update CLAUDE.md documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
103 lines
2.9 KiB
TypeScript
103 lines
2.9 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog'
|
|
import { Button } from '@/components/ui/button'
|
|
import { AI_DATA_DISCLOSURES, type AiExtensionId } from '@/lib/extensions/ai-consent'
|
|
import Link from 'next/link'
|
|
|
|
interface AiConsentDialogProps {
|
|
extensionId: AiExtensionId
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
onConsented: () => void
|
|
}
|
|
|
|
export function AiConsentDialog({
|
|
extensionId,
|
|
open,
|
|
onOpenChange,
|
|
onConsented,
|
|
}: AiConsentDialogProps) {
|
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
|
|
|
const disclosure = AI_DATA_DISCLOSURES[extensionId]
|
|
|
|
async function handleAccept() {
|
|
setIsSubmitting(true)
|
|
try {
|
|
const res = await fetch('/api/ai-consent', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ extension_id: extensionId }),
|
|
})
|
|
|
|
if (res.ok) {
|
|
onOpenChange(false)
|
|
onConsented()
|
|
}
|
|
} finally {
|
|
setIsSubmitting(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>AI-samtycke kravs</DialogTitle>
|
|
<DialogDescription>
|
|
Denna funktion anvander AI-tjanster fran externa leverantorer.
|
|
Granska informationen nedan innan du fortsatter.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="space-y-4 py-4">
|
|
<div>
|
|
<p className="text-sm font-medium mb-1">Leverantor</p>
|
|
<p className="text-sm text-muted-foreground">{disclosure.provider}</p>
|
|
</div>
|
|
|
|
<div>
|
|
<p className="text-sm font-medium mb-1">Data som skickas</p>
|
|
<ul className="text-sm text-muted-foreground list-disc pl-5 space-y-1">
|
|
{disclosure.dataTypes.map((dt) => (
|
|
<li key={dt}>{dt}</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<div>
|
|
<p className="text-sm font-medium mb-1">Syfte</p>
|
|
<p className="text-sm text-muted-foreground">{disclosure.purpose}</p>
|
|
</div>
|
|
|
|
<p className="text-xs text-muted-foreground">
|
|
Las mer i var{' '}
|
|
<Link href="/privacy" className="underline underline-offset-4" target="_blank">
|
|
integritetspolicy
|
|
</Link>
|
|
. Du kan nar som helst aterkalla ditt samtycke i installningarna.
|
|
</p>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button variant="outline" onClick={() => onOpenChange(false)} disabled={isSubmitting}>
|
|
Avbryt
|
|
</Button>
|
|
<Button onClick={handleAccept} disabled={isSubmitting}>
|
|
{isSubmitting ? 'Sparar...' : 'Jag samtycker'}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|