Files
dezky/apps/portal/data/workspace.ts
T
Ronni Baslund 0bd4e5498e feat: portal redesign, pricing catalog, partner-staff invites
- portal: new admin/ and partner/ surfaces with full component library
  (AppLauncher, Avatar, Badge, Card, Modal, Tabs, etc.), composables,
  layouts, partner-routing middleware, and supporting server APIs
- pricing: Price schema/module with operator CRUD, pricing.vue catalog UI,
  Subscription extended with cycle/currency/perSeatAmount/seats snapshots
  for stable MRR aggregation
- partner staff: User.partnerId, invite-partner-user DTO and flow,
  /partners/:slug/users endpoints, InvitePartnerUserModal, shared
  dezky-partner-staff Authentik group
- /me: partner-aware endpoint returning user + partner context so portal
  can route between end-user and partner-admin surfaces
- tenant: seats field for portfolio displays and future MRR calculations
- operator: pricing page, signed-out page, useMe/useToast composables,
  ToastStack
2026-05-28 20:00:33 +02:00

257 lines
23 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The "current workspace" for prototype purposes. Replaced by platform-api
// lookup in production. Holds the brand identity that the BrandingScreen
// lives in front of.
export interface Workspace {
id: string
name: string
productName: string
domain: string
plan: 'starter' | 'business' | 'enterprise'
seats: { used: number; total: number }
storage: { usedGb: number; totalGb: number }
mailFlow: { deliveredPct: number; trend: 'up' | 'down' | 'flat' }
monthlySpendDkk: number
status: 'active' | 'trial' | 'past_due' | 'suspended'
}
export const workspace: Workspace = {
id: 'ws-baslund',
name: 'Baslund',
productName: 'Baslund Workspace',
domain: 'baslund.dk',
plan: 'business',
seats: { used: 11, total: 25 },
storage: { usedGb: 142, totalGb: 500 },
mailFlow: { deliveredPct: 99.4, trend: 'up' },
monthlySpendDkk: 1940,
status: 'active',
}
export const sampleUsers = [
{ id: 'u-1', name: 'Anne Hansen', email: 'anne@baslund.dk', role: 'owner', groups: ['Leadership', 'Finance'], mfa: 'totp', lastLogin: '2 min ago', status: 'active', storageMb: 8200, license: 'business' },
{ id: 'u-2', name: 'Mikkel Sørensen', email: 'mikkel@baslund.dk', role: 'admin', groups: ['Engineering'], mfa: 'webauthn', lastLogin: '14 min ago', status: 'active', storageMb: 14210, license: 'business' },
{ id: 'u-3', name: 'Sofie Lund', email: 'sofie@baslund.dk', role: 'admin', groups: ['Design'], mfa: 'totp', lastLogin: '1 hour ago', status: 'active', storageMb: 6804, license: 'business' },
{ id: 'u-4', name: 'Frederik Holm', email: 'frederik@baslund.dk', role: 'user', groups: ['Finance'], mfa: 'totp', lastLogin: '3 hours ago', status: 'active', storageMb: 2401, license: 'business' },
{ id: 'u-5', name: 'Caroline Bjerg', email: 'caroline@baslund.dk', role: 'user', groups: ['Sales'], mfa: 'none', lastLogin: 'Yesterday', status: 'active', storageMb: 1880, license: 'business' },
{ id: 'u-6', name: 'Johan Olesen', email: 'johan@baslund.dk', role: 'user', groups: ['Engineering'], mfa: 'webauthn', lastLogin: '2 days ago', status: 'active', storageMb: 4250, license: 'business' },
{ id: 'u-7', name: 'Maria Petersen', email: 'maria@baslund.dk', role: 'user', groups: ['Design'], mfa: 'totp', lastLogin: '5 days ago', status: 'active', storageMb: 3120, license: 'business' },
{ id: 'u-8', name: 'Henrik Schmidt', email: 'henrik@baslund.dk', role: 'user', groups: ['Engineering'], mfa: 'totp', lastLogin: '1 week ago', status: 'active', storageMb: 9540, license: 'business' },
{ id: 'u-9', name: 'Trine Madsen', email: 'trine@baslund.dk', role: 'user', groups: ['Sales'], mfa: 'none', lastLogin: 'never', status: 'invited', storageMb: 0, license: 'business' },
{ id: 'u-10', name: 'Lars Engelbrecht', email: 'lars@baslund.dk', role: 'user', groups: ['Engineering'], mfa: 'totp', lastLogin: '12 days ago', status: 'suspended', storageMb: 5102, license: 'business' },
{ id: 'u-11', name: 'Bo Christensen', email: 'bo@baslund.dk', role: 'user', groups: ['Sales'], mfa: 'totp', lastLogin: '3 hours ago', status: 'active', storageMb: 1242, license: 'starter' },
]
export const sampleGroups = [
{ id: 'g-1', name: 'Leadership', description: 'Owners + admins', members: 3, owner: 'Anne Hansen', resources: ['leadership@', 'Drev/Leadership'] },
{ id: 'g-2', name: 'Engineering', description: 'Backend, frontend, infrastructure', members: 4, owner: 'Mikkel Sørensen', resources: ['eng@', 'Drev/Engineering', '#eng'] },
{ id: 'g-3', name: 'Design', description: 'Brand, product, marketing visuals', members: 2, owner: 'Sofie Lund', resources: ['design@', 'Drev/Design', '#design'] },
{ id: 'g-4', name: 'Finance', description: 'Bookkeeping, AP/AR, payroll', members: 2, owner: 'Frederik Holm', resources: ['finance@', 'Drev/Finance'] },
{ id: 'g-5', name: 'Sales', description: 'Outbound + customer success', members: 3, owner: 'Bo Christensen', resources: ['sales@', 'Drev/Sales', '#sales'] },
]
export const sampleDomains = [
{
id: 'd-1',
domain: 'baslund.dk',
primary: true,
status: 'partial',
records: [
{ type: 'MX', status: 'ok', value: '10 mail.dezky.com' },
{ type: 'SPF', status: 'warn', value: 'v=spf1 ~all', expected: 'v=spf1 include:_spf.dezky.com ~all' },
{ type: 'DKIM', status: 'ok', value: 'k=rsa; p=MIGfMA0GCSq...' },
{ type: 'DMARC', status: 'bad', value: '— not found —', expected: 'v=DMARC1; p=quarantine; rua=mailto:dmarc@baslund.dk' },
],
addedOn: '2025-12-04',
},
{
id: 'd-2',
domain: 'baslund.shop',
primary: false,
status: 'healthy',
records: [
{ type: 'MX', status: 'ok', value: '10 mail.dezky.com' },
{ type: 'SPF', status: 'ok', value: 'v=spf1 include:_spf.dezky.com ~all' },
{ type: 'DKIM', status: 'ok', value: 'k=rsa; p=MIGfMA0G...' },
{ type: 'DMARC', status: 'ok', value: 'v=DMARC1; p=quarantine' },
],
addedOn: '2026-02-11',
},
{
id: 'd-3',
domain: 'baslund.io',
primary: false,
status: 'verifying',
records: [
{ type: 'TXT', status: 'warn', value: 'dezky-site-verification=…', hint: 'Awaiting propagation · ~10 min remaining' },
],
addedOn: '2026-05-22',
},
]
export const sampleInvoices = [
{ id: 'inv-2026-001247', date: '2026-05-01', period: '2026-05', amount: 1940, status: 'paid', method: 'MobilePay' },
{ id: 'inv-2026-001112', date: '2026-04-01', period: '2026-04', amount: 1940, status: 'paid', method: 'MobilePay' },
{ id: 'inv-2026-000984', date: '2026-03-01', period: '2026-03', amount: 1940, status: 'paid', method: 'MobilePay' },
{ id: 'inv-2026-000855', date: '2026-02-01', period: '2026-02', amount: 1940, status: 'paid', method: 'MobilePay' },
{ id: 'inv-2026-000721', date: '2026-01-01', period: '2026-01', amount: 1820, status: 'paid', method: 'Card · VISA 4242' },
]
// Audit events — strict port of project/platform-screens.jsx SAMPLE_AUDIT
// (line 29). Same 8 rows, same wording, same tones. The AdminDashboard slices
// the first 6, the SecurityScreen audit log uses all of them.
export const sampleAudit = [
{ id: 'a1', when: '14:02:11', actor: 'Anne Baslund', action: 'user.invited', target: 'magnus@dezky.com', ip: '92.43.118.4', tone: 'info' as const },
{ id: 'a2', when: '13:48:02', actor: 'Mikkel Nørgaard', action: 'billing.plan_changed', target: 'Team → Business', ip: '92.43.118.4', tone: 'info' as const },
{ id: 'a3', when: '13:21:55', actor: 'system', action: 'domain.dns_check', target: 'baslund.dk', ip: '—', tone: 'warn' as const },
{ id: 'a4', when: '12:09:30', actor: 'Sofie Lindberg', action: 'user.suspended', target: 'tina@dezky.com', ip: '78.110.4.92', tone: 'warn' as const },
{ id: 'a5', when: '11:44:00', actor: 'Anne Baslund', action: 'mfa.policy_updated', target: 'require for admins', ip: '92.43.118.4', tone: 'info' as const },
{ id: 'a6', when: '10:12:08', actor: 'Lars Holm', action: 'session.terminated', target: 'iPad — Safari', ip: '78.110.4.10', tone: 'info' as const },
{ id: 'a7', when: '09:55:41', actor: 'system', action: 'auth.failed_login', target: 'oliver@dezky.com', ip: '203.0.113.4', tone: 'bad' as const },
{ id: 'a8', when: '09:30:00', actor: 'Anne Baslund', action: 'branding.color_set', target: '#D4FF3A', ip: '92.43.118.4', tone: 'info' as const },
]
// Org-wide mail aliases — strict port of platform-admin.jsx ORG_ALIASES (line 9)
export const orgAliases = [
{ alias: 'info@dezky.com', dest: 'Distribution · Everyone', active: true, created: '14 Jan 2026' },
{ alias: 'sales@dezky.com', dest: 'frederik@dezky.com', active: true, created: '22 Jan 2026' },
{ alias: 'support@dezky.com', dest: 'sofie@dezky.com', active: true, created: '22 Jan 2026' },
{ alias: 'no-reply@dezky.com', dest: '(discard)', active: true, created: '14 Jan 2026' },
{ alias: 'careers@dezky.com', dest: 'anne@dezky.com', active: true, created: '04 Mar 2026' },
{ alias: 'legal@dezky.com', dest: 'mikkel@dezky.com', active: false, created: '12 Apr 2026' },
]
// Forwarding rules — strict port of platform-admin.jsx FORWARDING_RULES (line 18)
export const forwardingRules = [
{ name: 'Out-of-hours to on-call', match: 'support@dezky.com · 18:0008:00 CET', fwd: 'oncall@dezky.com', enabled: true },
{ name: 'Vendor invoices', match: 'subject: "invoice" · from: *@vendors', fwd: 'finance@dezky.com', enabled: true },
{ name: 'Legal threads', match: 'cc: legal@*', fwd: 'mikkel@dezky.com', enabled: false },
]
// Distribution lists — strict port of platform-admin.jsx DISTRIBUTION_LISTS (line 24)
export const distributionLists = [
{ name: 'Everyone', alias: 'everyone@dezky.com', members: 11, owner: 'Anne Baslund', moderation: 'open' as const, external: false },
{ name: 'Engineering', alias: 'eng@dezky.com', members: 4, owner: 'Anne Baslund', moderation: 'closed' as const, external: false },
{ name: 'Leadership', alias: 'leads@dezky.com', members: 3, owner: 'Anne Baslund', moderation: 'closed' as const, external: false },
{ name: 'Customers VIP', alias: 'vip-customers@dezky.com', members: 0, owner: 'Frederik Madsen', moderation: 'closed' as const, external: true },
]
// Anti-spam content filters — strict port of platform-admin.jsx ANTI_SPAM_FILTERS (line 31)
export const antiSpamFilters = [
{ name: 'Block executable attachments', match: 'attachment ext in (.exe, .scr, .bat, .cmd)', action: 'reject' as const, enabled: true },
{ name: 'Quarantine cryptocurrency mail', match: 'body contains "wallet address"', action: 'quarantine' as const, enabled: true },
{ name: 'Tag external mail', match: 'from outside @dezky.com', action: 'add tag' as const, enabled: true },
]
// Full groups list — strict port of platform-admin.jsx GROUPS_FULL (line 64)
export const groupsFull = [
{ id: 'g_eng', name: 'Engineering', alias: 'engineering@dezky.com', members: 4, description: 'Product engineering team', created: '14 Jan 2026', owner: 'Anne Baslund' },
{ id: 'g_des', name: 'Design', alias: 'design@dezky.com', members: 2, description: 'Brand and product designers', created: '02 Feb 2026', owner: 'Sofie Lindberg' },
{ id: 'g_ops', name: 'Operations', alias: 'ops@dezky.com', members: 2, description: 'Operations and on-call', created: '14 Jan 2026', owner: 'Mikkel Nørgaard' },
{ id: 'g_fin', name: 'Finance', alias: 'finance@dezky.com', members: 2, description: 'Finance and accounting', created: '22 Jan 2026', owner: 'Astrid Vinther' },
{ id: 'g_sales', name: 'Sales', alias: 'sales@dezky.com', members: 2, description: 'Customer sales', created: '14 Jan 2026', owner: 'Frederik Madsen' },
{ id: 'g_all', name: 'All-hands', alias: 'everyone@dezky.com', members: 11, description: 'Everyone in the workspace', created: '14 Jan 2026', owner: 'Anne Baslund' },
]
// Source-fidelity users (project/platform-screens.jsx SAMPLE_USERS line 8) —
// flat shape used by UsersScreen, BillingScreen seats math and StorageScreen
// "top users" list. Kept in sync with the visual mock — these have `last`,
// `group` (singular), `storage` (GB) rather than the multi-group `sampleUsers`
// above.
export const sampleUsersFlat = [
{ id: 'u_1ph2', name: 'Anne Baslund', email: 'anne@dezky.com', role: 'Owner', status: 'active', last: '2 min ago', group: 'Engineering', storage: 12.4 },
{ id: 'u_4kx9', name: 'Mikkel Nørgaard', email: 'mikkel@dezky.com', role: 'Admin', status: 'active', last: '14 min ago', group: 'Operations', storage: 8.1 },
{ id: 'u_88aw', name: 'Sofie Lindberg', email: 'sofie@dezky.com', role: 'Admin', status: 'active', last: '1 h ago', group: 'Finance', storage: 3.2 },
{ id: 'u_d12k', name: 'Lars Holm', email: 'lars@dezky.com', role: 'Member', status: 'active', last: '3 h ago', group: 'Engineering', storage: 22.7 },
{ id: 'u_9rqo', name: 'Emma Skov', email: 'emma@dezky.com', role: 'Member', status: 'invited', last: '—', group: 'Design', storage: 0 },
{ id: 'u_3vbn', name: 'Jonas Berg', email: 'jonas@dezky.com', role: 'Member', status: 'active', last: '2 d ago', group: 'Engineering', storage: 14.0 },
{ id: 'u_g51e', name: 'Tina Falkenberg', email: 'tina@dezky.com', role: 'Member', status: 'suspended', last: '11 d ago', group: 'Finance', storage: 5.6 },
{ id: 'u_kk7n', name: 'Oliver Schmidt', email: 'oliver@dezky.com', role: 'Member', status: 'active', last: '4 h ago', group: 'Design', storage: 9.3 },
{ id: 'u_pp01', name: 'Frederik Madsen', email: 'frederik@dezky.com', role: 'Member', status: 'active', last: 'Yesterday', group: 'Sales', storage: 6.8 },
{ id: 'u_qq22', name: 'Astrid Vinther', email: 'astrid@dezky.com', role: 'Admin', status: 'active', last: '32 min ago', group: 'Operations', storage: 4.1 },
{ id: 'u_rr44', name: 'Magnus Eriksen', email: 'magnus@dezky.com', role: 'Member', status: 'invited', last: '—', group: 'Engineering', storage: 0 },
{ id: 'u_tt55', name: 'Clara Bjerre', email: 'clara@dezky.com', role: 'Member', status: 'active', last: '5 d ago', group: 'Sales', storage: 2.0 },
]
// Source-fidelity domains (platform-screens.jsx SAMPLE_DOMAINS line 23) — flat
// shape with per-record-type status used by DomainsScreen / DomainCard.
export const sampleDomainsFlat = [
{ domain: 'dezky.com', status: 'ok' as const, mx: 'ok' as const, spf: 'ok' as const, dkim: 'ok' as const, dmarc: 'ok' as const, users: 11 },
{ domain: 'dezky.io', status: 'ok' as const, mx: 'ok' as const, spf: 'ok' as const, dkim: 'ok' as const, dmarc: 'warn' as const, users: 0 },
{ domain: 'baslund.dk', status: 'warn' as const, mx: 'ok' as const, spf: 'warn' as const, dkim: 'ok' as const, dmarc: 'bad' as const, users: 2 },
]
// Meeting rooms — strict port of platform-collab.jsx MEETING_ROOMS (line 8)
export const meetingRooms = [
{ id: 'r_eng', name: 'Engineering standup', alias: 'eng-standup', type: 'recurring' as const, when: 'Daily · 09:30', owner: 'Mikkel Nørgaard', members: 4, recording: 'auto' as const, protected: false },
{ id: 'r_lead', name: 'Leadership weekly', alias: 'leadership', type: 'recurring' as const, when: 'Mondays · 14:00', owner: 'Anne Baslund', members: 3, recording: 'manual' as const, protected: true },
{ id: 'r_allh', name: 'All-hands', alias: 'allhands', type: 'recurring' as const, when: '2nd Friday · 15:00', owner: 'Anne Baslund', members: 11, recording: 'auto' as const, protected: false },
{ id: 'r_inter', name: 'Interview room A', alias: 'interview-a', type: 'ad-hoc' as const, when: 'Persistent', owner: 'Sofie Lindberg', members: 2, recording: 'off' as const, protected: true },
{ id: 'r_cust', name: 'Customer demos', alias: 'demo', type: 'shared' as const, when: 'On-demand', owner: 'Frederik Madsen', members: 2, recording: 'manual' as const, protected: false },
{ id: 'r_focus', name: 'Focus · pair', alias: 'pair', type: 'ad-hoc' as const, when: 'Persistent', owner: 'Lars Holm', members: 1, recording: 'off' as const, protected: false },
]
// Meeting recordings — strict port of platform-collab.jsx MEETING_RECORDINGS (line 17)
export const meetingRecordings = [
{ id: 'rec1', title: 'All-hands · May edition', date: '12 May 2026', dur: '52 min', size: '184 MB', host: 'Anne Baslund', views: 11, retention: '365 d', legal: false },
{ id: 'rec2', title: 'Customer demo · Novo Holding', date: '11 May 2026', dur: '38 min', size: '142 MB', host: 'Frederik Madsen', views: 4, retention: '90 d', legal: false },
{ id: 'rec3', title: 'Engineering · Sprint review 24', date: '09 May 2026', dur: '46 min', size: '168 MB', host: 'Mikkel Nørgaard', views: 6, retention: '365 d', legal: false },
{ id: 'rec4', title: 'Board update · Q1 close', date: '02 May 2026', dur: '28 min', size: '102 MB', host: 'Anne Baslund', views: 3, retention: 'forever', legal: true },
{ id: 'rec5', title: 'New hire onboarding · Magnus', date: '29 Apr 2026', dur: '24 min', size: '88 MB', host: 'Sofie Lindberg', views: 2, retention: '90 d', legal: false },
{ id: 'rec6', title: 'Engineering · Sprint review 23', date: '25 Apr 2026', dur: '41 min', size: '154 MB', host: 'Mikkel Nørgaard', views: 5, retention: '365 d', legal: false },
{ id: 'rec7', title: 'Customer call · Aalborg Logistik', date: '22 Apr 2026', dur: '34 min', size: '128 MB', host: 'Frederik Madsen', views: 3, retention: '90 d', legal: false },
]
// Chat workspaces — strict port of platform-collab.jsx CHAT_WORKSPACES (line 27)
export const chatWorkspaces = [
{ id: 'cw_main', name: 'baslund · main', url: 'baslund.chat.dezky.com', members: 11, channels: 24, messages30d: 8420, status: 'active' as const, primary: true },
{ id: 'cw_eng', name: 'engineering', url: 'eng.chat.dezky.com', members: 4, channels: 11, messages30d: 12480, status: 'active' as const, primary: false },
]
// Chat channels — strict port of platform-collab.jsx CHAT_CHANNELS (line 32)
export const chatChannels = [
{ name: 'general', type: 'public' as const, members: 11, messages30d: 1840, owner: 'Anne Baslund', topic: 'Workspace-wide announcements' },
{ name: 'engineering', type: 'public' as const, members: 4, messages30d: 3220, owner: 'Mikkel Nørgaard', topic: 'Eng standups, deploys, code questions' },
{ name: 'design', type: 'public' as const, members: 2, messages30d: 480, owner: 'Sofie Lindberg', topic: 'Brand, product design, reviews' },
{ name: 'sales-customers', type: 'private' as const, members: 3, messages30d: 720, owner: 'Frederik Madsen', topic: 'Customer accounts and pipeline' },
{ name: 'random', type: 'public' as const, members: 9, messages30d: 1240, owner: 'Anne Baslund', topic: 'Off-topic' },
{ name: 'incidents', type: 'public' as const, members: 5, messages30d: 84, owner: 'Mikkel Nørgaard', topic: 'Service alerts and incident response' },
{ name: 'dezky-roadmap', type: 'private' as const, members: 4, messages30d: 410, owner: 'Anne Baslund', topic: 'Product planning, not for everyone' },
{ name: 'finance', type: 'private' as const, members: 2, messages30d: 96, owner: 'Astrid Vinther', topic: 'Invoicing, accounting' },
]
// Integrations marketplace — strict port of platform-collab.jsx INTEGRATIONS (line 43)
export interface Integration {
id: string
name: string
cat: 'Productivity' | 'Storage' | 'CRM' | 'Accounting' | 'Operations'
desc: string
connected: boolean
users?: number
kind: string
icon: string
color: string
accent: string
danish?: boolean
}
export const integrations: Integration[] = [
{ id: 'notion', name: 'Notion', cat: 'Productivity', desc: 'Docs and wikis. Sign in with dezky.', connected: true, users: 11, kind: 'SSO', icon: '◧', color: '#000000', accent: '#FFFFFF' },
{ id: 'figma', name: 'Figma', cat: 'Productivity', desc: 'Design files with single sign-on.', connected: true, users: 6, kind: 'SSO', icon: 'F', color: '#F24E1E', accent: '#FFFFFF' },
{ id: 'linear', name: 'Linear', cat: 'Productivity', desc: 'Issue tracking for engineering.', connected: true, users: 4, kind: 'SSO + provisioning', icon: 'L', color: '#5E6AD2', accent: '#FFFFFF' },
{ id: 'github', name: 'GitHub', cat: 'Productivity', desc: 'Source control. SAML enforcement.', connected: false, kind: 'SSO', icon: '⌬', color: '#181717', accent: '#FFFFFF' },
{ id: 'sketch', name: 'Sketch', cat: 'Productivity', desc: 'Design tool with team libraries.', connected: false, kind: 'SSO', icon: '◆', color: '#FDB300', accent: '#0A0A0A' },
{ id: 'gdrive', name: 'Google Drive', cat: 'Storage', desc: 'Mount Google Drive folders inside Drev.', connected: false, kind: 'OAuth', icon: 'G', color: '#1A73E8', accent: '#FFFFFF' },
{ id: 'dropbox', name: 'Dropbox', cat: 'Storage', desc: 'Mirror Dropbox into Drev. Read-only.', connected: false, kind: 'OAuth', icon: 'D', color: '#0061FF', accent: '#FFFFFF' },
{ id: 'hubspot', name: 'HubSpot', cat: 'CRM', desc: 'Customer pipeline + email sync.', connected: true, users: 3, kind: 'API', icon: 'H', color: '#FF7A59', accent: '#FFFFFF' },
{ id: 'pipedrive', name: 'Pipedrive', cat: 'CRM', desc: 'Sales CRM. Sign in with dezky.', connected: false, kind: 'SSO', icon: 'P', color: '#1A1A1A', accent: '#FFFFFF' },
{ id: 'economic', name: 'e-conomic', cat: 'Accounting', desc: 'Sync invoices to e-conomic. Danish CVR aware.', connected: true, users: 2, kind: 'API', icon: 'e', color: '#0091CD', accent: '#FFFFFF', danish: true },
{ id: 'billy', name: 'Billy', cat: 'Accounting', desc: 'Danish accounting platform. Auto-bookkeeping.', connected: false, kind: 'API', icon: 'B', color: '#0EBC81', accent: '#FFFFFF', danish: true },
{ id: 'dinero', name: 'Dinero', cat: 'Accounting', desc: 'Send invoices, sync ledger.', connected: false, kind: 'API', icon: 'D', color: '#FFCB05', accent: '#0A0A0A', danish: true },
{ id: 'pleo', name: 'Pleo', cat: 'Accounting', desc: 'Company cards. Auto-reconcile receipts.', connected: false, kind: 'API', icon: 'p', color: '#1B1B1B', accent: '#D4FF3A', danish: true },
{ id: 'pagerduty', name: 'PagerDuty', cat: 'Operations', desc: 'Page on-call from dezky incidents.', connected: false, kind: 'Webhook', icon: 'P', color: '#06AC38', accent: '#FFFFFF' },
{ id: 'slack', name: 'Slack', cat: 'Operations', desc: 'Mirror Chat to Slack (read-only).', connected: false, kind: 'OAuth', icon: 'S', color: '#4A154B', accent: '#FFFFFF' },
]
export const integrationCategories = ['All', 'Productivity', 'Storage', 'CRM', 'Accounting', 'Operations'] as const