Compare commits

..
2 Commits
Author SHA1 Message Date
Z User 17ceefe32a feat: auth system (middleware + login) + remove .env from git + fix hardcoded token
CRITICAL SECURITY FIXES:
- src/middleware.ts: protects all routes except public ones (health, license check, seed-prod)
  Redirects unauthenticated users to /login, returns 401 for API routes
- src/app/login/page.tsx: login page with password input
- src/app/api/auth/login: HMAC-signed session cookie (7-day expiry)
- src/app/api/auth/logout: clears session cookie
- Top bar: Abmelden (logout) button now functional
- .env removed from git tracking (secrets no longer in repo)
- seed-prod: hardcoded admin token replaced with env MCP_API_TOKEN or random UUID
- ADMIN_PASSWORD env var required for login (set in Dokploy env)

Public routes (no auth needed):
  /api/health, /api/aos/seed-prod, /api/aos/licenses/check, /api/aos/licenses/validate
  /api/v1/* (token-auth'd), /api/mcp (token-auth'd), /login
2026-10-28 22:38:39 +00:00
Z User e7185103f5 f6acc620-0a4c-41b3-9763-6681634541c0 2026-10-28 22:14:58 +00:00
11 changed files with 1909 additions and 100 deletions

No files matched your search

-95
View File
@@ -1,95 +0,0 @@
# AOS — Agency Operating System Environment (dev)
# --- Database ---
DATABASE_URL=file:/home/z/my-project/db/custom.db
# --- Encryption (AES-256-GCM for secrets at rest) ---
ENCRYPTION_KEY=UrEE757ABMzqcME/AQfef9XDPSaBlgIhVDOy8BIpbSY=
# --- Auth ---
AUTH_SECRET=zB7wxxn7xDnClPUlwoKG4VwHDaIqvtAz3DW3Bn43GlM=
# --- Leads Finder Providers ---
TAVILY_API_KEY=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
FIRECRAWL_API_KEY=fc-2ddabe84274a44b39da31a49d1624700
SERPAPI_API_KEY=5e1d045575cc29b705c53e8303b6ada506e8a3ef382fca78a2964c7e25751ba1
APIFY_API_TOKEN=apify_api_YUsr1w7L0qFpvzwDirjv1oWHToT2xu3lhJt7
# --- App ---
NODE_ENV=development
PORT=3000
# ── Stripe ──
STRIPE_PUBLISHABLE_KEY=pk_test_51TWfTxDGcQIOgPxeHVZh5ilWEc61bK7MBuBez4fGV5XrjRGwRXsXJp5rm1eAsWHGzQ20NBXRG7Nmp0pJRJfUflImA003OoDaSQt
STRIPE_SECRET_KEY=sk_test_51TWfTxDGcQIOgPxej8AvcfLMt6a7IEgZk3L34WLnOCNw2AAAyqORQtgJLjEaj3Ygm014ZAo3oByvDSdJVFwYLHmk0048mdLZH4
RESTRICTED_KEY=rk_test_51TWfTxDGcQIOgPxeGPSfA6ske0A6xPde23jfOJKbUfFOrEWl4bTIHv4MSOBwlQpravXk4mxKAjKdmkGb3asZqOVJ0048mdLZH4
# ── License Server (B2B SaaS) ──
LICENSE_PRICE_STARTER_CENTS=2900
LICENSE_PRICE_PRO_CENTS=5000
LICENSE_PRICE_ENTERPRISE_CENTS=15000
LICENSE_TRIAL_DAYS=14
LICENSE_NOTICE_PERIOD_DAYS=90
LICENSE_YEARLY_DISCOUNT_PCT=10
LICENSE_OFFLINE_GRACE_HOURS=72
# ── Agency / Reseller ──
AGENCY_DISCOUNT_MIN_PCT=0
AGENCY_DISCOUNT_MAX_PCT=20
AGENCY_DISCOUNT_DEFAULT_PCT=10
# ── Platform Domain ──
# The domain AOS runs on. Tenant instances get subdomains of this domain.
PLATFORM_DOMAIN=dfmpanel.eu
# Public URL of the AOS instance (used by license-server SDK + email links)
AOS_PUBLIC_URL=https://dfmpanel.eu
# ── Dokploy (tenant instance provisioning) ──
# Dokploy server URL + API key for managing tenant instances.
DOKPLOY_URL=https://cp.project-url.eu
DOKPLOY_API_KEY=CEIqJlWVtmSNgffNWywTJmEeuvUJBndinBzudretwiuzVWPxuvUNmoQaHUwRwUBy
# The Dokploy server ID to deploy to (default "default" if not set)
# DOKPLOY_SERVER_ID=default
# The Dokploy project to group tenant applications under
# DOKPLOY_PROJECT_ID=default
# The IP of the Dokploy server (used for Hetzner DNS A records)
# DOKPLOY_SERVER_IP=123.456.789.012
# ── Hetzner Cloud DNS ──
# DNS is managed via the Hetzner Cloud API (api.hetzner.cloud/v1/zones).
# The legacy dns.hetzner.com API was shut down in May 2026.
HETZNER_DNS_TOKEN=JhZMOBTMeWvXz91KVPxRh0U4UMFqkSNCMHJKiQS9kUjHIwCkWCc8ViZTm64MyaOp
# Zone ID of dfmpanel.eu (found via: GET https://api.hetzner.cloud/v1/zones)
HETZNER_ZONE_ID=1669672
# If true, a single *.dfmpanel.eu wildcard A record handles all subdomains.
# If false, a per-instance A record is created/deleted with each instance.
USE_WILDCARD_DNS=false
# ── Dokploy Server ──
# IP of the Dokploy server (A record target for instance subdomains).
# Found from the existing @ and www A records of dfmpanel.eu.
DOKPLOY_SERVER_IP=92.206.22.59
# ── Cron Job ──
# Shared secret for the cleanup cron job (POST /api/aos/instances/cleanup)
# The cron job (Dokploy cron or GitHub Action) must send this as:
# Authorization: Bearer <CRON_SECRET>
# CRON_SECRET=your-cron-secret
# ── Instance Defaults ──
# Default Git repo + branch for new tenant instances
INSTANCE_GIT_REPO=https://github.com/cetinmustafa83/restov1
INSTANCE_GIT_BRANCH=main
# Demo instance duration in days
INSTANCE_DEMO_DAYS=14
# Grace period after demo expiry or subscription cancellation (days)
INSTANCE_GRACE_DAYS=7
# ── Graphify (tenant codebase knowledge graph) ──
# Graphify MCP HTTP service (Docker container). When configured, new tenant
# instances trigger a background graph build, and the support ticket AI
# queries the codebase before generating a summary.
# Run: docker run -p 8080:8080 -v ./data/graphify:/data graphify serve
# --transport http --host 0.0.0.0 --api-key <secret>
# GRAPHIFY_URL=http://localhost:8080
# GRAPHIFY_API_KEY=your-graphify-api-key
+1
View File
@@ -59,3 +59,4 @@ aos-verify*.sh
.dev.pid .dev.pid
.zscripts/dev.pid .zscripts/dev.pid
db/backups/ db/backups/
.env
+6 -4
View File
@@ -206,18 +206,20 @@ export async function POST(req: Request) {
const existingTokens = await db.apiToken.count() const existingTokens = await db.apiToken.count()
if (existingTokens === 0) { if (existingTokens === 0) {
const adminScopes = ['mcp:read', 'mcp:write', 'crm.company:read', 'crm.deal:read', 'finance.invoice:read', 'leads:read', 'leads:write', 'support:read', 'support:write', 'licenses.license:read', 'licenses.license:write'] const adminScopes = ['mcp:read', 'mcp:write', 'crm.company:read', 'crm.deal:read', 'finance.invoice:read', 'leads:read', 'leads:write', 'support:read', 'support:write', 'licenses.license:read', 'licenses.license:write']
const token = 'aos_admin_seed_token_for_claude_code_2026' // Use MCP_API_TOKEN env var if set, otherwise generate a random one
const hash = crypto.createHash('sha256').update(token).digest('hex') const tokenValue = process.env.MCP_API_TOKEN || ('aos_' + crypto.randomUUID())
const hash = crypto.createHash('sha256').update(tokenValue).digest('hex')
await db.apiToken.create({ await db.apiToken.create({
data: { data: {
name: 'Claude Code Admin (seeded)', name: 'MCP Admin Token (seeded)',
tokenHash: hash, tokenHash: hash,
tokenPrefix: token.slice(0, 12) + '…', tokenPrefix: tokenValue.slice(0, 12) + '…',
scopes: adminScopes.join(','), scopes: adminScopes.join(','),
expiresAt: null, expiresAt: null,
}, },
}) })
stats.apiTokens = 1 stats.apiTokens = 1
stats.mcpToken = tokenValue === process.env.MCP_API_TOKEN ? '(from env)' : tokenValue
} else { } else {
stats.apiTokens = 0 stats.apiTokens = 0
} }
+64
View File
@@ -0,0 +1,64 @@
import { NextResponse } from 'next/server'
import { z } from 'zod'
export const dynamic = 'force-dynamic'
const schema = z.object({
password: z.string().min(1),
redirect: z.string().optional(),
})
// POST /api/auth/login
// Simple password-based auth. Password is set via ADMIN_PASSWORD env var.
// Returns a session cookie (HMAC-signed, 7-day expiry).
export async function POST(req: Request) {
try {
const parsed = schema.safeParse(await req.json())
if (!parsed.success) {
return NextResponse.json({ error: 'invalid request' }, { status: 400 })
}
const { password, redirect } = parsed.data
const adminPassword = process.env.ADMIN_PASSWORD
if (!adminPassword) {
return NextResponse.json(
{ error: 'ADMIN_PASSWORD env not configured. Set it in Dokploy environment variables.' },
{ status: 503 }
)
}
if (password !== adminPassword) {
return NextResponse.json({ error: 'Falsches Passwort' }, { status: 401 })
}
// Create session token: base64(payload).hmac
const crypto = await import('crypto')
const payload = {
sub: 'admin',
iat: Date.now(),
exp: Date.now() + 7 * 24 * 3600 * 1000, // 7 days
}
const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url')
const key = process.env.AUTH_SECRET || adminPassword
const signature = crypto
.createHmac('sha256', key)
.update(payloadB64)
.digest('base64url')
const token = `${payloadB64}.${signature}`
const res = NextResponse.json({
ok: true,
redirect: redirect || '/',
})
res.cookies.set('aos-session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 7 * 24 * 3600, // 7 days
})
return res
} catch {
return NextResponse.json({ error: 'login failed' }, { status: 500 })
}
}
+10
View File
@@ -0,0 +1,10 @@
import { NextResponse } from 'next/server'
export const dynamic = 'force-dynamic'
// POST /api/auth/logout
export async function POST() {
const res = NextResponse.json({ ok: true })
res.cookies.delete('aos-session')
return res
}
+84
View File
@@ -0,0 +1,84 @@
'use client'
import { useState } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Loader2, Lock } from 'lucide-react'
export default function LoginPage() {
const router = useRouter()
const searchParams = useSearchParams()
const redirect = searchParams.get('redirect') || '/'
const [password, setPassword] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!password) return
setLoading(true)
setError('')
try {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ password, redirect }),
})
const data = await res.json()
if (!res.ok) {
setError(data.error || 'Login fehlgeschlagen')
return
}
router.push(data.redirect || '/')
router.refresh()
} catch {
setError('Netzwerkfehler')
} finally {
setLoading(false)
}
}
return (
<div className="flex min-h-screen items-center justify-center bg-background p-4">
<div className="w-full max-w-sm space-y-6">
<div className="text-center space-y-2">
<div className="mx-auto flex size-14 items-center justify-center rounded-xl bg-foreground text-background">
<Lock className="size-7" />
</div>
<h1 className="text-2xl font-semibold tracking-tight">AOS Login</h1>
<p className="text-sm text-muted-foreground">
Agency Operating System — dfmpanel.eu
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="password">Passwort</Label>
<Input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Admin-Passwort eingeben"
autoFocus
autoComplete="current-password"
/>
</div>
{error && (
<p className="text-sm text-red-600 dark:text-red-400">{error}</p>
)}
<Button type="submit" className="w-full gap-2" disabled={loading || !password}>
{loading && <Loader2 className="size-4 animate-spin" />}
Anmelden
</Button>
</form>
<p className="text-center text-xs text-muted-foreground">
Geschützter Bereich — nur für autorisierte Benutzer.
</p>
</div>
</div>
)
}
+10 -1
View File
@@ -110,7 +110,16 @@ export function TopBar() {
<DropdownMenuItem>Profil</DropdownMenuItem> <DropdownMenuItem>Profil</DropdownMenuItem>
<DropdownMenuItem>Sitzungen</DropdownMenuItem> <DropdownMenuItem>Sitzungen</DropdownMenuItem>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem className="text-muted-foreground">Abmelden</DropdownMenuItem> <DropdownMenuItem
className="text-muted-foreground"
onSelect={async (e) => {
e.preventDefault()
await fetch('/api/auth/logout', { method: 'POST' })
window.location.href = '/login'
}}
>
Abmelden
</DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
</div> </div>
+102
View File
@@ -0,0 +1,102 @@
import { NextRequest, NextResponse } from 'next/server'
// Middleware: protects all routes except public ones.
// Uses a simple session cookie (HMAC-signed) for auth.
// Password is set via ADMIN_PASSWORD env var.
const PUBLIC_PATHS = [
'/api/health',
'/api/aos/seed-prod',
'/api/aos/licenses/check',
'/api/aos/licenses/validate',
'/login',
'/_next',
'/favicon.ico',
'/manifest.json',
'/icons/',
'/apple-touch-icon',
]
const PUBLIC_API_PREFIXES = [
'/api/health',
'/api/aos/seed-prod',
'/api/aos/licenses/check',
'/api/aos/licenses/validate',
'/api/v1/', // public REST API (token-auth'd separately)
'/api/mcp', // MCP (token-auth'd)
]
function isPublic(pathname: string): boolean {
// Exact matches
if (PUBLIC_PATHS.includes(pathname)) return true
// Prefix matches
for (const prefix of PUBLIC_API_PREFIXES) {
if (pathname.startsWith(prefix)) return true
}
// Static assets
if (pathname.startsWith('/_next/') || pathname.startsWith('/icons/')) return true
return false
}
async function verifySession(token: string | undefined): Promise<boolean> {
if (!token) return false
const adminPassword = process.env.ADMIN_PASSWORD
if (!adminPassword) return false
try {
// Session token format: base64(payload).hmac
const [payloadB64, signature] = token.split('.')
if (!payloadB64 || !signature) return false
const payload = JSON.parse(Buffer.from(payloadB64, 'base64').toString())
if (payload.exp && Date.now() > payload.exp) return false
// Verify HMAC
const crypto = await import('crypto')
const key = process.env.AUTH_SECRET || adminPassword
const expectedSig = crypto
.createHmac('sha256', key)
.update(payloadB64)
.digest('base64url')
return signature === expectedSig
} catch {
return false
}
}
export async function middleware(req: NextRequest) {
const { pathname } = req.nextUrl
// Allow public paths
if (isPublic(pathname)) {
return NextResponse.next()
}
// Check session cookie
const sessionToken = req.cookies.get('aos-session')?.value
const isAuthenticated = await verifySession(sessionToken)
if (!isAuthenticated) {
// For API routes, return 401
if (pathname.startsWith('/api/')) {
return NextResponse.json(
{ error: 'unauthorized', message: 'Authentication required' },
{ status: 401 }
)
}
// For pages, redirect to login
const loginUrl = new URL('/login', req.url)
loginUrl.searchParams.set('redirect', pathname)
return NextResponse.redirect(loginUrl)
}
return NextResponse.next()
}
export const config = {
matcher: [
/*
* Match all request paths except:
* - _next/static, _next/image (static files)
* - favicon.ico, icons, manifest (public assets)
*/
'/((?!_next/static|_next/image|favicon.ico|icons|manifest.json|apple-touch-icon).*)',
],
}
@@ -0,0 +1,73 @@
/home/z/my-project/worklog.md:180: - `src/app/api/aos/recurring/run/route.ts` — POST handler takes no `req` param at all; it's a pure cron-style trigger.
/home/z/my-project/src/lib/graphify.ts:220:// Dokploy cron). Here we provide the command that should be executed.
/home/z/my-project/src/components/aos/views/recurring.tsx:227: <Badge variant="outline" className="text-[10px]">Cron: 1. des Monats, 06:00</Badge>
/home/z/my-project/src/components/aos/views/data.tsx:252: <p>Automatische Lösch-Jobs (cron) nach Ablauf der Frist. GoBD: Daten sind unveränderlich, Korrekturen als Storno.</p>
/home/z/my-project/src/app/api/aos/instances/[id]/graph-build/route.ts:12:// 2. An external worker (cron job) that polls for queued graphs
/home/z/my-project/src/app/api/aos/instances/[id]/graph-build/route.ts:91: // cron job) can execute it.
/home/z/my-project/src/app/api/aos/instances/cleanup/route.ts:10:// Cron job: run daily. Finds instances whose grace period has elapsed and
/home/z/my-project/src/app/api/aos/instances/cleanup/route.ts:14:// In production, this is triggered by a cron job (e.g. via Dokploy's cron
/home/z/my-project/src/app/api/aos/instances/cleanup/route.ts:18: // Simple auth: shared secret in header (cron job includes it)
/home/z/my-project/src/app/api/aos/instances/cleanup/route.ts:20: const expectedSecret = process.env.CRON_SECRET
/home/z/my-project/src/app/api/aos/instances/route.ts:279: // In production: enqueue to a worker (BullMQ, Dokploy cron, etc.)
/home/z/my-project/src/app/api/aos/recurring/run/route.ts:104: actor: 'system:cron',
/home/z/my-project/skills/design/design-templates/digital-eguide/social-carousel.html:631: const IMAGES = {"01-golden-dunes-sunrise-31415631.jpg": "data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/riso-product/reference.html:15::root{--n01:url(data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/riso-product/reference.html:736: <div class="mega__thumb"><img src="data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/waitlist-page/层云-waitlist.html:561: <video src="data:video/mp4;base64,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 truncated
/home/z/my-project/skills/design/design-templates/waitlist-page/层云-waitlist.html:567: <video src="data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAAAAG1wNDJtcDQxaXNvbWF2YzEAABUQbW9vdgAAAGxtdmhkAAAAANzRPOTc0TzkAAAAGQAAAWIAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAACFpb2RzAAAAABCAgIAQAE////9//w6AgIAEAAAAAQAAFHt0cmFrAAAAXHRraGQAAAAH3NE85NzRPOQAAAABAAAAAAAAAWIAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAhwAAAPAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAFiAAAAAgABAAAAABPzbWRpYQAAACBtZGhkAAAAANzRPOTc0TzkAAAAGQAAAWJVxAAAAAAANmhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABMLVNNQVNIIFZpZGVvIEhhbmRsZXIAAAATlW1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAE1VzdGJsAAAAs3N0c2QAAAAAAAAAAQAAAKNhdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAhwDwABIAAAASAAAAAAAAAABCkFWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAOmF2Y0MBZAAf/+EAHWdkAB+sViQIgee+agwMDIAAAAMAgAAAGQeMGMTAAQAGaOiOyyLA/fj4AAAAABNjb2xybmNseAAGAAYABgAAAAAYc3R0cwAAAAAAAAABAAABYgAAAAEAAAp4Y3R0cwAAAAAAAAFNAAAAAQAAAAIAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABAAAAAIAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAEAAAAAgAAAAEAAAABAAAAAwAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAEAAAAAgAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAwAAAAEAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAACAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAwAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAEAAAAAgAAAAEAAAABAAAABAAAAAIAAAABAAAAAQAAAAIAAAABAAAABAAAAAIAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABAAAAAIAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAEAAAAAgAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAEAAAAAgAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAEAAAAAgAAAAEAAAABAAAABAAAAAIAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAgAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAQAAAACAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAIAAAACAAAAAQAAAAMAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABQAAAAEAAAACAAAAAQAAAAAAAAABAAAAAQAAAAEAAAAFAAAAAQAAAAIAAAABAAAAAAAAAAEAAAABAAAAAQAAAAUAAAABAAAAAgAAAAEAAAAAAAAAAQAAAAEAAAABAAAABAAAAAIAAAABAAAAJHN0c3MAAAAAAAAABQAAAAEAAABNAAAAmQAAAOUAAAExAAABbnNkdHAAAAAAppaWmpqWlpqalpaampaWmpaWmpqWlpqalpaalpqWlpqalpaampaWmpaWmpqWlpqalpaalpaampaWmpqWmpaWmpaWmpqWlpqalpaamqaWlpqalpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqWlpqWlpqmlpaalpaalpaampaWmpqWlpqWlpqWlpqWlpqalpaalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqWlpqWlpqWlpqappaWmpqWlpqWlpLine truncated
/home/z/my-project/skills/design/design-templates/waitlist-page/层云-waitlist.html:570: <video src="data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAAAAG1wNDJtcDQxaXNvbWF2YzEAABSwbW9vdgAAAGxtdmhkAAAAANzTDdfc0w3XAAB1MAAFMXQAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAACFpb2RzAAAAABCAgIAQAE////9//w6AgIAEAAAAAQAAFBt0cmFrAAAAXHRraGQAAAAH3NMN19zTDdcAAAABAAAAAAAFMXQAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAtAAAAVWAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEABTF0AAAH0gABAAAAABOTbWRpYQAAACBtZGhkAAAAANzTDdfc0w3XAAB1MAAFMXRVxAAAAAAANmhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABMLVNNQVNIIFZpZGVvIEhhbmRsZXIAAAATNW1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAEvVzdGJsAAAAsXN0c2QAAAAAAAAAAQAAAKFhdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAtAFVgBIAAAASAAAAAAAAAABCkFWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAOGF2Y0MBZAAg/+EAHGdkACCs2YC0Ct+aagICAoAAAAMAgAB1MAeMGM0BAAVo6Xssi/34+AAAAAATY29scm5jbHgAAQABAAEAAAAAGHN0dHMAAAAAAAAAAQAAAVQAAAPpAAAKeGN0dHMAAAAAAAABTQAAAAEAAAfSAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAH0gAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAH0gAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAA+kAAAAAgAAA+kAAAACAAAH0gAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAAfSAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAAfSAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAD6QAAAACAAAD6QAAAAEAAA+kAAAAAgAAA+kAAAABAAAH0gAAAAEAAAu7AAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAH0gAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAAfSAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAPpAAAAAIAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAALuwAAAAEAAAPpAAAAAgAAB9IAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAD6QAAAACAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAAfSAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAACBzdHNzAAAAAAAAAAQAAAABAAAAWwAAALUAAAEPAAABYHNkdHAAAAAAppaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpaampaWmpqWlpqalpaampaWmpqWlpqalpaappaWlpqalpaampaWmpqWlpqalpaampaWmpqWlpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpaampaWmpqWlpqalpaampaWmpqWlpqalpaalpaappaalpaampaWmpqWlpqalpaampaWmpqWlpqalpaWmpqWlpqalpaampaWmpqWlpqalpaampaWlpqalpaampaWmpLine truncated
/home/z/my-project/skills/design/design-templates/waitlist-page/层云-waitlist.html:573: <video src="data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAAAAG1wNDJtcDQxaXNvbWF2YzEAAA+ObW9vdgAAAGxtdmhkAAAAANwOU8XcDlPFAABdwAADqnAAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAACFpb2RzAAAAABCAgIAQAE////9//w6AgIAEAAAAAQAADvl0cmFrAAAAXHRraGQAAAAH3A5TxdwOU8UAAAABAAAAAAADqnAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAhwAAAPAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAA6pwAAAH0gABAAAAAA5xbWRpYQAAACBtZGhkAAAAANwOU8XcDlPFAABdwAADqnBVxAAAAAAANmhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABMLVNNQVNIIFZpZGVvIEhhbmRsZXIAAAAOE21pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAADdNzdGJsAAAAs3N0c2QAAAAAAAAAAQAAAKNhdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAhwDwABIAAAASAAAAAAAAAABCkFWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAAAOmF2Y0MBZAAf/+EAHWdkAB+sViQIgee+agwMDIAAAAMAgABdwAeMGMTAAQAGaOiOyyLA/fj4AAAAABNjb2xybmNseAAGAAYABgAAAAAYc3R0cwAAAAAAAAABAAAA8AAAA+kAAAdgY3R0cwAAAAAAAADqAAAAAQAAB9IAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAD6QAAAACAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAAfSAAAAAQAAD6QAAAACAAAD6QAAAAEAAAu7AAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAC7sAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAH0gAAAAEAAAu7AAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAPpAAAAAIAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAA+kAAAAAgAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAAA+kAAAAAgAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAAH0gAAAAEAAA+kAAAAAgAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAAQAAE40AAAABAAAH0gAAAAEAAAAAAAAAAQAAA+kAAAABAAATjQAAAAEAAAfSAAAAAQAAAAAAAAABAAAD6QAAAAEAABONAAAAAQAAB9IAAAABAAAAAAAAAAEAAAPpAAAAIHN0c3MAAAAAAAAABAAAAAEAAABJAAAAkQAAANkAAAD8c2R0cAAAAACmlpaampaWmpqWlpqalpaampaWmpqWlpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqmlpaalpqWlpqalpaampaWmpqWlpqalpaampaalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqWlpqalpaampaWmpqmlpqWlpqalpaampaWmpqWlpqWlpqalpaampaWmpqWlpqalpaampaWmpaWmpqWlpqalpaampaWmpqWlpqWlpqalpaampaWmpqmlpaalpaampaWmpqWlpqalpaampaWmpoAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAwAAAABAAAD1HN0c3oAAAAAAAAAAAAAAPAAAZS+AABB6AAACs0AAANQAAAB8wAARL0AAAh+AAAEKwAAAb8AAEJUAAAIfQAAA/UAAAHjAAA0OQAABd8AAAP/AAABzgAALUIAAAWOAAADkwAAAZ4AADDMAAADRAAAAf4AACjqAAAEbgAAAygAAAGnAAArswAABF0AAAMoAAABYQAALzAAAAMSAAABcAAAAXAAADcMAAADtQAAAYEAAAFTAAA6dQAAA0wAAAFoAAABigAARR4AAARnAAABywAAAcQAAEDOAAAFMAAAAbsAAAHLAABDFQAABa8AAAGxAAAB9gAAQb8AAAWbAAAB8wAAAioAAEA9AAAF0QAAAc4AAAI7AAA/JgAABt8AAAJ0AAACVwAASoYAAAbjAAACvgAAAfIAAekZAABW4gAABd4AAAQdAABRoQAAAfsAAFEvAAAMvQAAAocAAAKQAABNAwAACqYAAAKVAAACUAAARUcAAAnCAAACfwAAAn4AAENOAAAJBQAAAqcAAAMQAAA+2QAAB6YAAAJJAAACqAAAPScAAAHzAAA5IQAABc4AAAKqAAAChAAAOjAAAAVaAAAC6QAAAo8AADqNAAAFxgAAAtQAAAKiAABIGgAABVwAAAM5AAACjwAAO78AAAUzAAAC0AAAAfYAAD2SAAAGewAAApwAAAKGAAA54wAABMkAAAJmAAACBwAAO94AAAYSAAACxwAAAfYAADhBAAAFmgAAAp8AAAJ5AABBfwAAB5YAAAKEAAACngAAQEcAAAkrAAAC1wAAAtAAAcF4AABQEAAAAfUAAEvWAAAKVQAAAo4AAAMvAABSeAAADOwAAANDAAAC4AAAWm4AAA2PAAAD/gAAAuIAAFHkAAAEugAAA0cAAE0qAAALtAAAAbwAAAIYAABNcQAACoQAAAIQAAAB8AAAStwAAAggAAABzwAAAdgAAEXJAAAGoQAAAaQAAAF7AABDdQAABEwAAAGEAAABqAAARcQAAAKiAAABrgAARfAAAALine truncated
/home/z/my-project/skills/design/design-templates/waitlist-page/层云-waitlist.html:576: <video src="data:video/mp4;base64,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 truncated
/home/z/my-project/skills/design/design-templates/waitlist-page/层云-waitlist.html:582: <video src="data:video/mp4;base64,AAAAHGZ0eXBtcDQyAAAAAG1wNDJpc29tYXZjMQAADsltb292AAAAeG12aGQBAAAAAAAAAN776DMAAAAA3vvoMwAAAlgAAAAAAAAXdgABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAOSXRyYWsAAABodGtoZAEAAAcAAAAA3vvoMwAAAADe++gzAAAAAQAAAAAAAAAAAAAXdgAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAACHAAAA8AAAAAAACxlZHRzAAAAJGVsc3QBAAAAAAAAAQAAAAAAABd2AAAAAAAAC7sAAQAAAAANrW1kaWEAAAAsbWRoZAEAAAAAAAAA3vvoMwAAAADe++gzAABdwAAAAAAAA6pwVcQAAAAAADpoZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmltZW8gQXJ0YXggVmlkZW8gSGFuZGxlcgAAAA0/bWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAM/3N0YmwAAACzc3RzZAAAAAAAAAABAAAAo2F2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAACHAPAAEgAAABIAAAAAAAAAAEKQVZDIENvZGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAAA6YXZjQwFkAB//4QAdZ2QAH6xWJAiB575qDAwMgAAAAwCAAF3AB4wYxMABAAZo6I7LIsD9+PgAAAAAE2NvbHJuY2x4AAYABgAGAAAAABhzdHRzAAAAAAAAAAEAAADwAAAD6QAABzhjdHRzAAAAAAAAAOUAAAABAAALuwAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAD6QAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAATjQAAAAIAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAAAu7AAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAPpAAAAAEAAAfSAAAAAQAAE40AAAACAAAH0gAAAAIAAAu7AAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAE40AAAACAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAE40AAAACAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAXdgAAAAEAAAu7AAAAAQAAA+kAAAABAAAH0gAAAAEAABd2AAAAAQAAC7sAAAABAAAD6QAAAAEAAAfSAAAAAQAAF3YAAAABAAALuwAAAAEAAAPpAAAAAQAAB9IAAAABAAAX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 truncated
/home/z/my-project/skills/design/design-templates/blog-post/肌肤专题|关于屏障的一次重读.html:74: <img src="data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:55:@font-face{font-family:MiSans;src:local(MiSans),url("data:font/woff2;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:77:@font-face{font-family:MiSans Semibold;src:local(MiSans Semibold),url("data:font/woff2;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:83:@font-face{font-family:MiSans Semibold;src:local(MiSans Semibold),url("data:font/woff2;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:161:@font-face{font-family:"FlyFlowerSong";src:local("FlyFlowerSong"),url("data:font/woff2;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:814: <div class="thumb"><img src="data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:819: <div class="thumb"><img src="data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:824: <div class="thumb"><img src="data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:829: <div class="thumb"><img src="data:image/jpeg;base64,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rSC3I0yjeueq3049K3rG66dOW8rm5kmbnUnPeDJF1IRILEEQQSZ1mJnWTOdZzIM6iiLAAAAQqFssKgoAAEsCABYLYKhKFAorqTEELBCCgWAUAoAFEUUAgWCoKgqBZUiwAzLlZjWSQAUEAKIFBERSJCABZRqWrZbdWWksECSyEsIsQChQCEsIELAKEogIACLIBABVCqlAEolgAAWDpvnq67b49LetxK6c+fJLzTMAQQICqFAAqUASiAQQUWVaqgoAWmpaASjMsiSyIJNazrVtlqipKjM1mIsi6zqtXNtS5CJNaxpd6xqumsW3bIqSNMjpcU6dOPXU3vG66bxrBllGWdmUJGYszmTTA0yNySqzIskLM5kuYzQlAAAgEAFABAUKogCAiyggoALCpUCgOqMEEACFloBZQCgWUBKhQAAABSKJQQRLlZm5JmwRSAAFAUCSwREQgABZS2WrrNt1YoQQhKJKJLAEWCwBIqUgFlCy0ESyIoSwAiogFAKAoAIsAAANaxq3e+Vt65xkuSSASiKSAACAALZbQAJLEFJRbZqlLQSSwtlqpRYqyBCJnUiFi6zrS6mqC2SpMywksytlq3NtuUgJNaxqtazu3VyrTKNTI0zTdxpd9OWrO/Tj01OrmjUxLNTOTWZBkjM1mBCoCQZTMRJUSUAlKlAEACKIsUAABYqoKlhKIEFIACgSqSwoOkOcSygipRZQKURZVAWBYShQQFAAWUABICZ1lc51kkAQAAWUSy0IksRLCCAAFlLZaus6toqEESKCwqSohUBUpIsIsgsFlLCgEIWBLAAAAQoFlAUBBALAAtlpYUQsAAABLJFQKqCALZbQpLISxAi2attl0otSxJLIqDQogqCwJLIlJLrOtXdzqqi2EkksJKhQELEhc01qa0us6tsBIiso1c03carprnuze+VrtOazcyXSAEksJnWYkshELERmyITNSpZKJQqCwCLKllAASlgAAAKKCAQCCgiopQCgNk5wIAWC2KoFlRYKABYKQpCgABalCVASSxZnWFmdZIABLBYFlEFSwSkksIsgABZS2a0tltpCSyISSpaEUEWChQsggQsqJYLAAEKgACAJUAKKWCkWwQAABZqhbYoysklAFAEFlQFASkgi2W0KCJLEWWLZrVtmtIoksJKiAtlIqosgqpKjKwusaNXGtNIECAFgoksJLIlVNazrVtltLkkSQjLdzbdaxTprnbOtxbNoqpVqStSVBBmxJnWYiiTUJNZiSLine truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:914: feather: 'data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:915: aurora: 'data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:916: spirit: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/4gIcSUNDX1BST0ZJTEUAAQEAAAIMbGNtcwIQAABtbnRyUkdCIFhZWiAH3AABABkAAwApADlhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA/AAAAF5jcHJ0AAABXAAAAAt3dHB0AAABaAAAABRia3B0AAABfAAAABRyWFlaAAABkAAAABRnWFlaAAABpAAAABRiWFlaAAABuAAAABRyVFJDAAABzAAAAEBnVFJDAAABzAAAAEBiVFJDAAABzAAAAEBkZXNjAAAAAAAAAANjMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXh0AAAAAElYAABYWVogAAAAAAAA9tYAAQAAAADTLVhZWiAAAAAAAAADFgAAAzMAAAKkWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPY3VydgAAAAAAAAAaAAAAywHJA2MFkghrC/YQPxVRGzQh8SmQMhg7kkYFUXdd7WtwegWJsZp8rGm/fdPD6TD////bAEMACQYGCAYFCQgHCAoJCQoNFg4NDAwNGhMUEBYfHCEgHxweHiMnMiojJS8lHh4rOywvMzU4ODghKj1BPDZBMjc4Nf/bAEMBCQoKDQsNGQ4OGTUkHiQ1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1Nf/CABEIDhAJYAMBIgACEQEDEQH/xAAbAAADAQEBAQEAAAAAAAAAAAAAAQIDBAUGB//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/aAAwDAQACEQMRAAAB8hOfRyBCNyxtMaBRCAQAmMRKxNRqkGUiKCSlLIIYMQyxTU1IIaAQAAIOWMTVsYMYk0SqmhNSIECaoBhcXGuuOmbZIrEKDprNaSZTc3KB6y2hGggQaIECaoacVLUQmpQAblqJoASO4pXIkE0CaGANNCAABAYqAAKN+jLRqM7iyALl1NWMZQmQmnKNCvXK5e7u4O7h6O240xqmmjaaACKblcufp57cOffn3nGLnrykDWBgjB0NUDAq40h0rhDIlUllUqE1STEAYVNS21cKhwJpBAJNKJoQCioWWyWFc1KpWSmkgZYgErSLloAiLgmaVhSqLBqppS5zcVM0rJGkbTGAAnDaAVIlMhDa5zrC5lKyQLAAFSVJqiaVSqSJpo6moupvNRSms5uKiaSO4abPOpVnUS5zU6IYJMqU0gmoBlhcWtpzAIRgStoG0AmhAgEVQiViauppLuNLEqkSFLIA2mMZZM6SZzcKgEBMECDQraZVTUMASaqU0IECBEMpAQXLNLycbGYulZ3N6VNTSm4MouNYBVcg0AIE1YIWgCG04aGTGkZsjFQ0jQhuWU5pZGkBAAAJgCAAABgAhBpm19A59VmKi5QhHcUWS6aABMYmpcuXs7vN7uPf0teffnu6ls00WMHCTRnzdHK1z4bYdMZzUdOYg1htOxiY2mNpjqaLuKyoAQCpAqVKpGrkqaUpma7ipLcsaZEq5skYJUlkbVMc1IxZVIhXNkTSuZGrEFI7VSg1ETU1KpBSoppwk0uc3NRNTYgEAAAgEynLGhA0RTmlibhZTVkq1UtiJNWoYJNUk1YhqR1NRo5c1RJKoqBS1YORLcEVJLSQKAyVckqkkjLENDqaipaECRtEtORKSChIYgQK1tOVgK3LS9MnZpKQ5JlbQlVNUNOhOZZzuSQSAACEGmrqaKpVAMSVU2zNSJNIk1QBAIpuWUS4txReuWk3rUPO3DhJio1kc1csAJaBNUk1YAA0xgBFzLIKVppEANiCpZSBUmoTFYAAAAEA0MTqRgJovo5tSpc0A0bVSjHYgKE1DaFoTjbt4O7n39Dq5erj1upq4bTRtMSqTHl6uW65sdsd4zzuOnMEay2nY2mjaChMqoou4qLQQgFBpUMWZtWKlQ6VZoNomnJQgaTExiVszVjUqkqGlSpExc2ZqlZIxmbVJdLTNidIM40jSU1TuKigIJqVmaVRNTZI0gmAmIAxMEYE1IIpw1qWSzNokqkhaqsp0myUykmqSaEmkbmoppzTAlmakhVNgmQgKScgIWnNStMlhVNyk1YADaY5qYQANMGOEMEAghABa2qlASsSSyBLJBgDcspw6twxyIUuVQhAAAAaCrjSLpXCVoibms5ualNEjViAEwAGAOHU0aXnc1ZLmiXJMi1ltNG0ACCWVI1YJgCY2mEXEsg4FUiAG5YDUrEACAQjQUwAaYJqBoGCoQ4ek3QmqHNSOppW0AAgCtGgbSjfu4e/n27+rl6uXW6imaaaNpimpXHl6eWufHXHec4uOnME9ZKmkbQNp2MTKqKjSpcU0xJoYm2wcsqlYrmwoeaFJE00AQNNKZYiwyWstZqlLIxVNyRNzqZqlcyBYXNyXRWUxpBnNxqyqmwqWUJytClU0qibiyUxE0wTBADEFJkSrlUNgrU0mNFRUhO0GMa56ZprUSapJiSqQUnDZU0ilmwrms1SsQ3Eq0Zq4pJqVtNaEKpqWUmrAAbmgTUIAKVQMcoqRKpJIyxDAAaaBUhWNy0oHIAhiFYgoRTQgloQAAAAABWuOsa6Z6ZOakmLi2JqdSZpCTVgmCGhiYMcNqlq5uaBkszUVKC5KTRg4QFJUiRqxJqgAppwTcywxSuaRIFhUuViATQJiIAAdAAAQAAAAFJpl1FgmINMKllOQYkUk7WJgBLr6Hn93Pp6fTydPPrpU1DqaZYIJJXLl6MNOfHfn1nPPSOnNAXFOXTaYwBtNHU0XcXDEAmDaqbbdTUTrJnSpKaY01Ccu5ctiotHotZZrRmGXTiuU3M0hombipm51ImlcyBYXNSa3neRFyZxpFTNTok0NoikhQEqmpslNCYWMCEMExgDhTcrNK5WU2oKSJpzNpBGWuWmc3GoIBAWJMhtMpqpWmppTSM05sYnAMJi5IVJQKVACTLJVJJGCpACIBIus6iqhrQlDQkALBpgmNJNCTSNzSNoAEMQMBQAALEmlE0AKmBAAO87ja8rjRSlcOaUtUppWSNIhqBNUNVBSY6VLbmpqkCznpmkgWOlSMCEMEmVCpVKasACqlxU0pc1UygmCYS2ElITTBiRKkJgCaBoGAAgYgARpUXTAQYA00AQwYmCjBQZLp3cHdjp6PXxdvPrbTimhGhCzuFzx2x1OfDo594yi53zQPWRoKaYMAYx3FpVzUMAEwdKpqrVZ2lpMuTosQFg0Eply6m0q1pLesbQ3Tlww6Ma55qZoTRM1NTNTqTNK5lMsKVSXcXk5uVzz1is1U2JMpDIQwSatSaJVTYmAwcJUlTTRtECaFc1NWA0k1E0mxSoM8ts7MZuNJGqQAhpC4oqpcrAlU1KzFKxAQ2mKWqlVM0MapUiU1cgJBNA0yU5gEDctKcuG5BiChCMErAUTTSTTLE7GJyAIYmrEDE6E0CYqQAAIAaGFSzSsriyQpItJqRJzYIEQCACqk4pprTly1UNbJAhxYnLSqiixENACapJzSTkGmOpoqWolNKhkIQMcFCAAGgBNInDGghiBgUCCkIYmVpnoAOwABggDBjVFEsjKAJb7uDszv0ezg7OXfdxUU0IwEmblcsd8dTn5+nn3jGNM94TT1gaY2mMAbQlXFGlTUMQjacrubmrqam2qUuauLGhWNAiB2VUtnW8rl325tY6JRLGOuN1iglSaJmlUzS1IVK5lMRUUjtaZqKJcY2zrKbnUgYgDRFNc41zVJqkmrE0wY5UMJVKQBiGgaJbJS0QynNpbTiMdsqyz0z1EmUkykNINOHU3KDJqZuTNOLGhgxpKpLM1M02qmhUozVxrKBXIAAmKamEmhiaNpjBQNMABiYwFQDUgMjRYwIAEABgAwoTSgJUAIAAKAIYmlVFFOXKwKJcqk0iAsQCJoG01pzUrQinCXQzCpBBpjaZQnAAAKkmhTSpNBTTkaaWRzKwCRoctA0wAUAEmSSNAAAANFgmoYANMupqmBTaaAEDTsoCaoQCaUQD6+Xpzvu7eHs59umprNppowLFNRLnleWplz7YbxnFxvEtPWBp0NMbRDaY6lppUuG00dSy6ipvS4vO2NSxNTcpC1GIRgJTllvNprpzVL2PkqXbJS0DUqTRKa1JVKyVSSVRYtJ0iqLyStS556xbhGuepA1Y2mjByxOitynSSFSslgNpwACmkiYhgKMcTNxSaZV52aEmSyuLM4udJVTSABNIUmO4uW5tTpnNymc1NymMVJiVJYm5lVTcrG5rKNYuc1U3IAAFilqEgAGNqkEyEwAGJgANpDSyNINNkGCGAMRDFTQjTVomlQ0CYIAAAaY6mkbVKIAlpUmrEAiARDBNC1UEtpAAhiBiY2mNpjAGBKJqxKpJTVAA2iKBClqUcuWppBNIlyWUS4oRQggABMAZSTmGJg0wAKuLsbToYQDBNDNORaEloRTE5X08/TnXb1cvXz7dF53nVOKSxAZ3nWOOuFmeO2O8ZzUbwCesDQNpjaYNCOpotzcDTSmmVeek3Wmd53QiVRUazIlcty7KFUDABuRDFHLWhOaYiCamlLVICxKlZLGlXN5Vc3mipGcaRblnpGpmrmxMaOhzUqyXKdY0ynSEgpWA2IqYQwkaAGMblmdJM1U2Ny00cOFFTUTU0pqaSpCLine truncated
/home/z/my-project/skills/design/design-templates/xianying-tool/index.standalone.html:917: veil: 'data:image/jpeg;base64,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rSC3I0yjeueq3049K3rG66dOW8rm5kmbnUnPeDJF1IRILEEQQSZ1mJnWTOdZzIM6iiLAAAAQqFssKgoAAEsCABYLYKhKFAorqTEELBCCgWAUAoAFEUUAgWCoKgqBZUiwAzLlZjWSQAUEAKIFBERSJCABZRqWrZbdWWksECSyEsIsQChQCEsIELAKEogIACLIBABVCqlAEolgAAWDpvnq67b49LetxK6c+fJLzTMAQQICqFAAqUASiAQQUWVaqgoAWmpaASjMsiSyIJNazrVtlqipKjM1mIsi6zqtXNtS5CJNaxpd6xqumsW3bIqSNMjpcU6dOPXU3vG66bxrBllGWdmUJGYszmTTA0yNySqzIskLM5kuYzQlAAAgEAFABAUKogCAiyggoALCpUCgOqMEEACFloBZQCgWUBKhQAAABSKJQQRLlZm5JmwRSAAFAUCSwREQgABZS2WrrNt1YoQQhKJKJLAEWCwBIqUgFlCy0ESyIoSwAiogFAKAoAIsAAANaxq3e+Vt65xkuSSASiKSAACAALZbQAJLEFJRbZqlLQSSwtlqpRYqyBCJnUiFi6zrS6mqC2SpMywksytlq3NtuUgJNaxqtazu3VyrTKNTI0zTdxpd9OWrO/Tj01OrmjUxLNTOTWZBkjM1mBCoCQZTMRJUSUAlKlAEACKIsUAABYqoKlhKIEFIACgSqSwoOkOcSygipRZQKURZVAWBYShQQFAAWUABICZ1lc51kkAQAAWUSy0IksRLCCAAFlLZaus6toqEESKCwqSohUBUpIsIsgsFlLCgEIWBLAAAAQoFlAUBBALAAtlpYUQsAAABLJFQKqCALZbQpLISxAi2attl0otSxJLIqDQogqCwJLIlJLrOtXdzqqi2EkksJKhQELEhc01qa0us6tsBIiso1c03carprnuze+VrtOazcyXSAEksJnWYkshELERmyITNSpZKJQqCwCLKllAASlgAAAKKCAQCCgiopQCgNk5wIAWC2KoFlRYKABYKQpCgABalCVASSxZnWFmdZIABLBYFlEFSwSkksIsgABZS2a0tltpCSyISSpaEUEWChQsggQsqJYLAAEKgACAJUAKKWCkWwQAABZqhbYoysklAFAEFlQFASkgi2W0KCJLEWWLZrVtmtIoksJKiAtlIqosgqpKjKwusaNXGtNIECAFgoksJLIlVNazrVtltLkkSQjLdzbdaxTprnbOtxbNoqpVqStSVBBmxJnWYiiTUJNZiSyJLILIEWoAAAKJQAUBKqKILine truncated
/home/z/my-project/skills/design/design-templates/dashboard/stack-dashboard-zh.html:383: background-image: url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4gIcSUNDX1BST0ZJTEUAAQEAAAIMbGNtcwIQAABtbnRyUkdCIFhZWiAH3AABABkAAwApADlhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA/AAAAF5jcHJ0AAABXAAAAAt3dHB0AAABaAAAABRia3B0AAABfAAAABRyWFlaAAABkAAAABRnWFlaAAABpAAAABRiWFlaAAABuAAAABRyVFJDAAABzAAAAEBnVFJDAAABzAAAAEBiVFJDAAABzAAAAEBkZXNjAAAAAAAAAANjMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXh0AAAAAElYAABYWVogAAAAAAAA9tYAAQAAAADTLVhZWiAAAAAAAAADFgAAAzMAAAKkWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPY3VydgAAAAAAAAAaAAAAywHJA2MFkghrC/YQPxVRGzQh8SmQMhg7kkYFUXdd7WtwegWJsZp8rGm/fdPD6TD////bAIQABQYGBwkHCgsLCg0ODQ4NExIQEBITHRUWFRYVHSsbIBsbIBsrJi4mIyYuJkQ2MDA2RE9CP0JPX1VVX3hyeJyc0gEFBgYHCQcKCwsKDQ4NDg0TEhAQEhMdFRYVFhUdKxsgGxsgGysmLiYjJi4mRDYwMDZET0I/Qk9fVVVfeHJ4nJzS/8IAEQgBkAGQAwEiAAIRAQMRAf/EADUAAAAHAQEBAAAAAAAAAAAAAAECAwQFBgcIAAkBAAMBAQEBAAAAAAAAAAAAAAABAgMEBQb/2gAMAwEAAhADEAAAANfH3ufTwgYAE3gL4Sh4AKgxCkA5EkgXIxahKJwzVqfSrjUVnRqrdlqb1ZFqyM4RMJFkgVoG7tVqJJYFwrKlrWHVHNoURW3E+ccEvMCiMPI+BiD1EEPEIwjOQ8FeZ23wtTHwRqJQKBvEMAh7yAASgCYpoK3OkDNrJFah0Z3wq+Ww+arpbJ4K2axeCvesPgr3rGIVwbEDK8FhAK6FhKEB6dKyFNMCiINKgOM9JECOaSrBqPDzCpepxCIpdWClEbKBvRsmVUATFQwJiqYEfL+BAVxBv5x5CAOABuC5UIgqVpPxgAoCUADyYKFSSBdBsxaeMmEc1JIZ3MtWk1SVatS1Zdp2EYQg5aPYx7l7GxsJcz7GqM6mynqajLy+ps1FdLeEcdyGOIFMIh4BAADxQH3jAAKCFamqJjyvp0hHihmDsAaA7AGZXhAZJP0xR7OXaCr0TaY+lTq3omZ3OI6rj223MeZ+i0Mi0k0HVXdpxbeaaNQkbM125R9FpMssjVJBO7S1LtMVv5vDjv7wmAphMAAcAIU5QL4fAAiZBeK+187axno/hTZM+vpYtctz52ZXoOWJHxQYJyJRRUfYkwpcToTJrM8H6V5O0mNulPvFyoy06Dc010/TY2WfKCancpOWkbIosSmWc+DqcLYM9EpVeWi76PhjQRAweMBg8A+AoKeBPyngKJjAU/jI4wrnXHDrve9C561fl9Hoc2O6ztwOAMW8g94A8UQBJB2VGGc67PlptXXsnWtcOwIySsMzmUHqUJc521vERUVZKYbUjPjSoMZ6Mk5qWkGUpFqOkjzV8MAqhMAgIh4B8AgHjeAvjAHjEFChkzgfiPtvnxVznOtgnfcn+K6Vz9nRD7nvdujgfeRLWK4Nig6I2gQ5tr8hG49ySE4zrO69HcZ9d6c6zJwxrMrUzUG6YJ1K6zVUPHQKOUXiDpyy0OYNGMAqhEBA3veD3veAwFADFIQFPIIIkDRgIlKLZGqOM3zKVjrfR1luvJ1xNj5o6D2z2smaX3fgdItGbiQpktnrKBFAgbSqrMyJDSImjc+/UDVFbq4GqL9FkeWRM1HrOzJsU37dgi1bCkEIeMa3cQGdDCBg973gADeAgKACRFmqICh021F6um/IoYJyJUcmDem/L6K7KYb+f6GMe1znX0/L6TuuFXZXpERLxfV5sNQr/ndzQ1oqdbfspRHPWw0ay1bLbpFeMkt+NwcHKaHnogyO6MDVrMNmRLZ9FVLKHdV2p6oMA5biYBDw+8HvD4C+EADPLhy6XR+teP8At2omfH9mEExgqOCdVc4cnfPLJXPxPcq/IXXHMnqeXGa3kE16XmbxoPPmoPKYyey5vedLsdbv6uJfGlMd3VWkm+XRu1tzPROvz3plHU0xCUEIk8kcItrOswrjCdgqmPgT0bTPrgxTZbiIGDxgEPD4QAp6gGa4itAGp+6OD++ayeh4IBEvkHznRElWDNbC6+c+oZY1vOY9XHgzlFT3/n7fbsxuMvash17CVNH1LK94x6awjr0j5vq5d7WTY7RGlZ3p/vfOoGW8hLyvkJA48Nk0k2jUHW7XWKmoVOz0fTPsYxTZbiYBAwgYAEfAlzJuHHLpMicnSuvW3O3RkyQqpYaRFyggVwUKLVLxVvnPp3FY0SAqOQfHN9L82a7UqZip6q3zOmRmzYxrGWuhXORL839JQ5K7zLWc3ivWf6T5ePYyqF5xKj4jCqkMCMVLMwq9Xu9auKJA22r3HaRimx6DCAgYxTAJD08MWyh8k9YqFsNVF2NrNB0BZgAggpTkQUPAEPn+hUfw/fmqxZy8vVx41uFQ+o+aUMuEXo1CtNay2qV0p8l1cXbUhVGHyf1U1WbfDzpPvY9L6b5ZZlHxm3PMtq9G1NyGjrhZIhg1YSDXh6ltCPo4XbRijl0GMUwGMUwBzD0BxPQqeEbFzcE7NF9pXyh3oyN4pBKgiUFqHdcSK0qByub8f3Nar8i387t56pWgRP1PzFSFOUjRyDZaLpj1u66+HpK58+7n859I/dwQ83TaG8An9F8y5g2tY6eaxx9Jr1xrEhgjgN3jsdENEg62uDlNZ2jrgxTZdBjFEDiVsGLc2XaAuoBw4cTbSXjbVjr1hamb3TmAp/JIgt4G8LOcxl5zruaXPHq1thC+8D3aEpTLv9H87QvWmpaZIIzNammRnzbbnV6P5t2jzvRthHBvL9aooaA3+h+ZzGu6LV98KS3skbSijyL4IteySMuoOLa6Tq8vOyc1uJimz2ExTAbPdA5jZk9ijLDO8bGy0Lnq9u1tuvD16oBPen5B/FFHvezlXC1Ruvw+y2wqPgO7yu5YLEq55XqQe6ZJfPV8i1Z/sOa50xrNkhdcnUfMtXLRRBOp1OxZN0Vz9OdxGnVvq480j9BY3FSNZZEKYtoUuqywNfQTzGS098nn9hsqkO7GKZaGEBCI423jnuqnpBzCYdcFIxNxldAP28V8/wC7qgoq/TfLGEpAisImHHL6SfN01Rd+Zs8kg35oq6alU6mLdzheTpt1x5q6E4+vLqpq+T9PJd6pMLXnS7nS+kdcpWfihRJMyI0KNW8U5ct6+NK0PYuflkSlUVTNdfweXbnC4mKYozR1lzMNbxFynob1NuWSRsVdfY7dWwyy/wA59BYZGLffT/KuM1t2Mmkxj92wBaIPErN08be8w3XcVLwkqCnmdDSKDyd2S3ilvujmv9Asz3HSuP4CW154jS87uN56XKU6WCzPqui3a2dUa1NlTgHITizGSTMm/INIxFwTOsoFtMUxSfJvSHINVOPJHL894C/Z7qFYoR8pN5b63a7LQ+Hq0RyVj6PmUau16g5ddKYOHnRyuJZXZQ0G5xgRMj6NKFTrNppfB6fOUX1vzh6nk1TSMvcFahXLzG8XZXp2lyHTw7P6uphaVKWjU3VjV0qVgbV6OaujjPTs05xmi4aatm0knoLmnSie7GL6NcoxC8xxrE4Za6fectotO0THZt0NhfSElr8PrwLlmqYJc0fNbnV53b2s1kE/3FmpObjzUGOwZpiTz3Qss5uzVHUeG3Ph2J9vZ30YY1rGSbF5fsY89ttR9Dy9UZv27zjWElGUmqHmFSWPVaNeTQZBJjXyhaX9NeMvEvRZpnZce/zvHoyOvS+UTvX0VQ6OS8aTnO9eJ7lA6KyDYujltAFierhleZ+hOCKdks1a1idIfYVUVmoi1QcvSMxacJFBoKvZozLaQ84ICZlDa4o16zjNZ1l+w0rLrtfpB70cNUj7DBNRke7j6ls1VbNIMXbQGxFkwRUTKE7P0NZn0JwLd+a8umr5raICiEOqe4nt/wAP3fxfbLr2H7nWeUWDn22el5kxCWPomWxTkikRDecKFeRshRVoLKUK2WygFZiryLM4sNm8qrQ2UXNaGyiGW0HWcY5e+0zkfqnXwYxWtcoDzocZLQtwg1ct2NEHSINUXaANk10gIPhD6B8xdQckZ9NSbTDa1XvSb1OwaVWOgufoyu4wcLz9GM9cZV0f3eeURFIvjiCRV/A3BwANwc+BlX7VxXF9YT2X60m285DTNDy4AiKoBT8C6P515e2d3Xnrozp46hneuUp54bDaNS9Mods8bsZouUAbpOUgbEdFBmR4mH0E5b6kyCdsCLAW2dmDvVaLnptTHVuSUuuuQuu+Hby67vETKuTeL6QwAACUpQOCQMW8gIL8+b5WU8G2nm91h09ghS7ZvyuAb+BcEABtyz1dyRn0SnU/I/V2mSdcnK08qzSrdV7zo8Xa4O5hkXTNhQAUFTVTAhFCo76y7Q80nflftLIekKmlYDvnP3H6HX+L7Cr0cWGYXdnq16nH3jL3hECgcLine truncated
/home/z/my-project/skills/design/design-templates/dashboard/stack-dashboard-zh.html:813: .av-5 { background-image: url('data:image/jpeg;base64,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 truncated
/home/z/my-project/skills/study-buddy/SKILL.md:100:## 模块1:定时提醒(Cron)
/home/z/my-project/skills/study-buddy/SKILL.md:102:**所有定时提醒统一用 `create_cron_job`,不用 HEARTBEAT.md。**
/home/z/my-project/skills/study-buddy/SKILL.md:104:### 晨间推送 cron
/home/z/my-project/skills/study-buddy/SKILL.md:113:### 晚间复盘 cron
/home/z/my-project/skills/study-buddy/SKILL.md:128: **不要主动问删 cron**——所有项目完成 ≠ 用户要停学,下个项目可能马上来。
/home/z/my-project/skills/study-buddy/SKILL.md:129: cron 默认保留。只有用户明确表达"不学了 / 暂停一下 / 休息" 等停学意图时,
/home/z/my-project/skills/study-buddy/SKILL.md:130: 才主动建议:"要不要把每日提醒 cron 也关掉?" 用户同意 →
/home/z/my-project/skills/study-buddy/SKILL.md:131: 调 `list_cron_jobs` 列出所有 cron → 按任务名 `StudyBuddy 晨间推送` /
/home/z/my-project/skills/study-buddy/SKILL.md:132: `StudyBuddy 晚间复盘` 找到对应 cron 的 ID → 调 `delete_cron_job` 删除。
/home/z/my-project/skills/study-buddy/SKILL.md:137:- 计划调整 / 删除提醒时,同步更新对应 cron
/home/z/my-project/skills/study-buddy/SKILL.md:138:- 修改晚间复盘的软性规则需同步更新 cron message
/home/z/my-project/skills/study-buddy/SKILL.md:171:2. 调用 `create_cron_job` 创建 10 分钟后的一次性任务(**任务类型:`at`**,**任务名:`StudyBuddy 项目生成回查`**),message:
/home/z/my-project/skills/study-buddy/SKILL.md:178: - **cron 建失败** → 告诉用户:"任务排期出点小状况,没法及时喊你啦~你可随时咨询进度,或点击链接查看生成状态。" 然后继续第 3 步
/home/z/my-project/skills/study-buddy/SKILL.md:188:4. 当前会话**不继续进入步骤3**,等 cron 触发
/home/z/my-project/skills/study-buddy/SKILL.md:190:**步骤2 回查**(10 分钟后 `at` cron 触发,新会话):
/home/z/my-project/skills/study-buddy/SKILL.md:203: - **成功** → 正常输出 + 继续走步骤3、4,同时调 `delete_cron_job`(按任务名 `StudyBuddy 项目生成回查` 定位)删除回查 cron,避免重复执行
/home/z/my-project/skills/study-buddy/SKILL.md:204: - **失败/未完成** → 告诉用户当前状态,cron 保留,等 10 分钟回查
/home/z/my-project/skills/study-buddy/SKILL.md:227:> 多项目场景下:**所有项目的叶子合并成一张总表**统一排 DAY;**只建一套提醒 cron**(晨/晚各一个),服务全部进行中的项目(用户精力有限,不并行学多个项目)
/home/z/my-project/skills/study-buddy/SKILL.md:233: - 不建 cron
/home/z/my-project/skills/study-buddy/SKILL.md:237: - 按模块1 建 2 个 cron(晨间/晚间各一个,服务所有进行中的项目)
/home/z/my-project/skills/study-buddy/SKILL.md:260:> 晨间/晚间由模块1 cron 自动触发;本模块描述触发后的输出格式。
/home/z/my-project/skills/study-buddy/SKILL.md:265:白天(cron 触发起点 + 用户互动):
/home/z/my-project/skills/study-buddy/SKILL.md:266: 晨间推送(cron 触发) → 用户学 → 用户表达"学完了"的意图(凭语境判断,不限措辞)
/home/z/my-project/skills/study-buddy/SKILL.md:279:晚间(cron 触发):
/home/z/my-project/skills/study-buddy/SKILL.md:313:3. 按 cron message 中的 3 条软性规则逐条执行(命中才介入:项目完成检查等)
/home/z/my-project/skills/study-buddy/SKILL.md:382:> 用户主动询问任意时间段的学习报告时执行(日报/周报/月报/项目总结/自定义范围)。晨间/晚间 cron 走各自模块,不走这里。
/home/z/my-project/skills/study-buddy/SKILL.md:414:全程**不写 USER.md**(练过、打勾、DAY 调整、薄弱知识点、答对 X/Y 都不动)——这些写动作由晚间复盘 cron 独占。
/home/z/my-project/skills/study-buddy/SKILL.md:498:- **计划太难/太轻松**:重新评估 → 调整计划 → 更新 USER.md → 同步修改 cron
/home/z/my-project/skills/study-buddy/SKILL.md:499:- **用户换项目/学新东西**:回到模块2 完整跑一遍 → 更新 USER.md → 同步修改 cron
/home/z/my-project/skills/market-research-reports/scripts/generate_market_visuals.py:50: "Obtainable Market. Each labeled with acronym, full name. "
/home/z/my-project/skills/market-research-reports/SKILL.md:519: "TAM SAM SOM concentric circles diagram. Outer circle TAM Total Addressable Market, middle circle SAM Serviceable Addressable Market, inner circle SOM Serviceable Obtainable Market. Each labeled with acronym and description. Blue gradient" \
/home/z/my-project/skills/market-research-reports/references/visual_generation_guide.md:113: "TAM SAM SOM concentric circles. Outer circle TAM Total Addressable Market. Middle circle SAM Serviceable Addressable Market. Inner circle SOM Serviceable Obtainable Market. Each labeled with acronym, full name, placeholder for dollar value. Arrows pointing to each with descriptions. Blue gradient darkest outer to lightest inner. White background professional appearance" \
/home/z/my-project/skills/market-research-reports/references/visual_generation_guide.md:323:- Acronym in bold
/home/z/my-project/skills/market-research-reports/references/visual_generation_guide.md:336: "TAM SAM SOM concentric circles. Outer circle TAM Total Addressable Market [VALUE]B. Middle circle SAM Serviceable Addressable Market [VALUE]B. Inner circle SOM Serviceable Obtainable Market [VALUE]B. Each labeled with acronym, full name, dollar value. Arrows pointing to each with descriptions. Blue gradient darkest outer to lightest inner. White background professional" \
/home/z/my-project/skills/aminer-academic-search/references/api-catalog.md:729:| acronyms | Abbreviation |
/home/z/my-project/skills/aminer-daily-paper/prompts/enrich.md:8:2. **keywords** — 2-4 Chinese keywords. Keep well-known English acronyms as-is.
/home/z/my-project/skills/literature-survey/references/01-bibliography-expansion.md:124:**Acronyms in titles**: wrap with `{}` to preserve case — `{T}ransformers`, `{FED}former`, `{N-BEATS}`. Escape `&`, `%`, `$`, `_`, `#`.
@@ -0,0 +1,683 @@
1→'use client'
2→
3→import { useEffect, useState } from 'react'
4→import { db as _db } from '@/lib/db' // not used — placeholder for type alignment
5→import { useAos } from '@/store/aos'
6→import { useFetch } from '@/hooks/use-fetch'
7→import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
8→import { Badge } from '@/components/ui/badge'
9→import { Button } from '@/components/ui/button'
10→import { Input } from '@/components/ui/input'
11→import { Label } from '@/components/ui/label'
12→import { Skeleton } from '@/components/ui/skeleton'
13→import { ScrollArea } from '@/components/ui/scroll-area'
14→import { Progress } from '@/components/ui/progress'
15→import {
16→ Dialog,
17→ DialogContent,
18→ DialogHeader,
19→ DialogTitle,
20→ DialogFooter,
21→ DialogDescription,
22→} from '@/components/ui/dialog'
23→import { Textarea } from '@/components/ui/textarea'
24→import {
25→ Building2,
26→ ArrowLeft,
27→ FolderKanban,
28→ Receipt,
29→ LifeBuoy,
30→ CheckCircle2,
31→ Clock,
32→ ShieldCheck,
33→ Check,
34→ X,
35→ Loader2,
36→ KeyRound,
37→ AlertTriangle,
38→ Bell,
39→ Info,
40→} from 'lucide-react'
41→import { formatEuro, formatDate, formatRelative, daysUntil } from '@/lib/format'
42→import { cn } from '@/lib/utils'
43→import { toast } from 'sonner'
44→import {
45→ Popover,
46→ PopoverContent,
47→ PopoverTrigger,
48→} from '@/components/ui/popover'
49→import { Footer } from './footer'
50→
51→void _db
52→
53→interface PortalCompany {
54→ id: string
55→ name: string
56→ legalForm: string | null
57→ city: string | null
58→ projectCount: number
59→ invoiceCount: number
60→ licenseCount: number
61→ contactName: string | null
62→ contactEmail: string | null
63→}
64→
65→interface PortalData {
66→ company: { id: string; name: string; legalForm: string | null; city: string | null }
67→ kpis: {
68→ openProjects: number
69→ unpaidCents: number
70→ unpaidInvoiceCount: number
71→ openTickets: number
72→ pendingApprovals: number
73→ activeLicenses: number
74→ }
75→ projects: {
76→ id: string; name: string; type: string; status: string; progress: number
77→ budgetType: string; spentHours: number; budgetHours: number | null
78→ dueDate: string | null; taskCount: number; doneTasks: number
79→ }[]
80→ invoices: {
81→ id: string; number: string; status: string; type: string
82→ issueDate: string; dueDate: string; grossCents: number
83→ zugferd: boolean; xrechnung: boolean; lineCount: number
84→ }[]
85→ tickets: {
86→ id: string; number: string; subject: string; status: string; priority: string
87→ messageCount: number; lastMessageAt: string
88→ }[]
89→ approvals: {
90→ id: string; title: string; description: string | null; status: string
91→ decidedAt: string | null; decidedBy: string | null; decidedIp: string | null
92→ decision: string | null; createdAt: string
93→ }[]
94→ licenses: {
95→ id: string; key: string; product: string; plan: string; status: string
96→ validUntil: string | null; activations: { domain: string; environment: string }[]
97→ }[]
98→}
99→
100→export function PortalShell() {
101→ const { portalMode, portalCompanyId, setPortalMode, setPortalCompany } = useAos()
102→ const [tab, setTab] = useState<'overview' | 'approvals' | 'invoices' | 'tickets' | 'licenses'>('overview')
103→
104→ // If portal mode is on but no company selected, show the login/selection screen
105→ if (portalMode && !portalCompanyId) {
106→ return <PortalLogin onBack={() => setPortalMode(false)} onSelect={(id) => setPortalCompany(id)} />
107→ }
108→
109→ if (portalMode && portalCompanyId) {
110→ return (
111→ <PortalApp
112→ companyId={portalCompanyId}
113→ tab={tab}
114→ setTab={setTab}
115→ onExit={() => { setPortalMode(false); setPortalCompany(null) }}
116→ />
117→ )
118→ }
119→
120→ return null
121→}
122→
123→function PortalLogin({ onBack, onSelect }: { onBack: () => void; onSelect: (id: string) => void }) {
124→ const { data, loading } = useFetch<{ companies: PortalCompany[] }>('/api/aos/portal/companies')
125→ const [q, setQ] = useState('')
126→
127→ return (
128→ <div className="flex min-h-screen flex-col bg-muted/30">
129→ <header className="flex h-16 items-center gap-3 border-b border-border bg-background px-4 md:px-6">
130→ <Button variant="ghost" size="sm" className="gap-1.5" onClick={onBack}>
131→ <ArrowLeft className="size-4" />Zur Agentur-Ansicht
132→ </Button>
133→ <div className="ml-auto flex items-center gap-2 text-xs text-muted-foreground">
134→ <ShieldCheck className="size-3.5" />Sichere Verbindung
135→ </div>
136→ </header>
137→ <main className="mx-auto w-full max-w-3xl flex-1 p-4 md:p-8">
138→ <div className="mb-6 space-y-1.5">
139→ <h1 className="text-2xl font-semibold tracking-tight">Client-Portal</h1>
140→ <p className="text-sm text-muted-foreground">
141→ Wähle dein Unternehmen. Du siehst ausschließlich deine eigenen Projekte, Rechnungen, Tickets und Freigaben.
142→ </p>
143→ </div>
144→ <div className="mb-4">
145→ <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Firma suchen…" className="max-w-sm" />
146→ </div>
147→ {loading || !data ? (
148→ <div className="space-y-2">
149→ {Array.from({ length: 4 }).map((_, i) => <Skeleton key={i} className="h-20 w-full" />)}
150→ </div>
151→ ) : (
152→ <div className="space-y-2">
153→ {data.companies
154→ .filter((c) => c.name.toLowerCase().includes(q.toLowerCase()))
155→ .map((c) => (
156→ <button
157→ key={c.id}
158→ onClick={() => onSelect(c.id)}
159→ className="flex w-full items-center gap-4 rounded-lg border border-border bg-background p-4 text-left transition hover:border-foreground/40 hover:shadow-sm"
160→ >
161→ <div className="flex size-12 items-center justify-center rounded-md bg-muted">
162→ <Building2 className="size-5 text-muted-foreground" />
163→ </div>
164→ <div className="min-w-0 flex-1">
165→ <div className="flex items-center gap-2">
166→ <span className="truncate text-sm font-semibold">{c.name}</span>
167→ {c.legalForm && <Badge variant="outline" className="text-[10px]">{c.legalForm}</Badge>}
168→ </div>
169→ <p className="mt-0.5 truncate text-xs text-muted-foreground">{c.contactName ?? '—'} · {c.contactEmail ?? '—'}</p>
170→ <div className="mt-1.5 flex items-center gap-3 text-[11px] text-muted-foreground">
171→ <span className="flex items-center gap-1"><FolderKanban className="size-3" />{c.projectCount} Projekte</span>
172→ <span className="flex items-center gap-1"><Receipt className="size-3" />{c.invoiceCount} Rechnungen</span>
173→ <span className="flex items-center gap-1"><KeyRound className="size-3" />{c.licenseCount} Lizenzen</span>
174→ </div>
175→ </div>
176→ <ArrowLeft className="size-4 rotate-180 text-muted-foreground" />
177→ </button>
178→ ))}
179→ </div>
180→ )}
181→ </main>
182→ <Footer />
183→ </div>
184→ )
185→}
186→
187→function PortalApp({ companyId, tab, setTab, onExit }: {
188→ companyId: string
189→ tab: 'overview' | 'approvals' | 'invoices' | 'tickets' | 'licenses'
190→ setTab: (t: 'overview' | 'approvals' | 'invoices' | 'tickets' | 'licenses') => void
191→ onExit: () => void
192→}) {
193→ const { data, loading, refetch } = useFetch<PortalData>(`/api/aos/portal/companies/${companyId}`)
194→
195→ if (loading || !data) {
196→ return (
197→ <div className="flex min-h-screen flex-col bg-muted/30">
198→ <header className="flex h-16 items-center gap-3 border-b border-border bg-background px-4 md:px-6">
199→ <Skeleton className="h-8 w-32" />
200→ </header>
201→ <main className="flex-1 p-6"><Skeleton className="h-96 w-full" /></main>
202→ </div>
203→ )
204→ }
205→
206→ return (
207→ <div className="flex min-h-screen flex-col bg-muted/30">
208→ {/* Portal header */}
209→ <header className="flex h-16 items-center gap-3 border-b border-border bg-background px-4 md:px-6">
210→ <Button variant="ghost" size="sm" className="gap-1.5" onClick={onExit}>
211→ <ArrowLeft className="size-4" />Agentur-Ansicht
212→ </Button>
213→ <div className="ml-2 flex items-center gap-2">
214→ <div className="flex size-9 items-center justify-center rounded-md bg-primary text-primary-foreground">
215→ <Building2 className="size-4" />
216→ </div>
217→ <div className="leading-tight">
218→ <p className="text-sm font-semibold">{data.company.name}</p>
219→ <p className="text-[10px] text-muted-foreground">Client-Portal · {data.company.legalForm ?? ''} {data.company.city ?? ''}</p>
220→ </div>
221→ </div>
222→ <div className="ml-auto flex items-center gap-2">
223→ <PortalNotificationsBell companyId={data.company.id} />
224→ <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
225→ <ShieldCheck className="size-3.5" />Sicher geschützt
226→ </div>
227→ </div>
228→ </header>
229→
230→ {/* Tab nav */}
231→ <div className="border-b border-border bg-background px-4 md:px-6">
232→ <div className="flex gap-1 overflow-x-auto py-2">
233→ {([
234→ { id: 'overview', label: 'Übersicht', icon: Building2 },
235→ { id: 'approvals', label: `Freigaben${data.kpis.pendingApprovals > 0 ? ` (${data.kpis.pendingApprovals})` : ''}`, icon: CheckCircle2 },
236→ { id: 'invoices', label: 'Rechnungen', icon: Receipt },
237→ { id: 'tickets', label: 'Tickets', icon: LifeBuoy },
238→ { id: 'licenses', label: 'Lizenzen', icon: KeyRound },
239→ ] as const).map((t) => {
240→ const Icon = t.icon
241→ const active = tab === t.id
242→ return (
243→ <button
244→ key={t.id}
245→ onClick={() => setTab(t.id)}
246→ className={cn(
247→ 'flex shrink-0 items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition',
248→ active ? 'bg-muted text-foreground' : 'text-muted-foreground hover:bg-muted/50'
249→ )}
250→ >
251→ <Icon className="size-3.5" />
252→ {t.label}
253→ </button>
254→ )
255→ })}
256→ </div>
257→ </div>
258→
259→ {/* Content */}
260→ <main className="flex-1 p-4 md:p-6">
261→ {tab === 'overview' && <PortalOverview data={data} setTab={setTab} />}
262→ {tab === 'approvals' && <PortalApprovals data={data} refetch={refetch} />}
263→ {tab === 'invoices' && <PortalInvoices data={data} />}
264→ {tab === 'tickets' && <PortalTickets data={data} />}
265→ {tab === 'licenses' && <PortalLicenses data={data} />}
266→ </main>
267→ <Footer />
268→ </div>
269→ )
270→}
271→
272→function PortalOverview({ data, setTab }: { data: PortalData; setTab: (t: 'overview' | 'approvals' | 'invoices' | 'tickets' | 'licenses') => void }) {
273→ return (
274→ <div className="space-y-6">
275→ {/* Welcome banner */}
276→ <Card className="border-foreground/20 bg-gradient-to-br from-foreground/5 to-transparent">
277→ <CardContent className="flex items-center gap-4 p-5">
278→ <div className="flex size-12 items-center justify-center rounded-xl bg-foreground text-background">
279→ <Building2 className="size-6" />
280→ </div>
281→ <div className="flex-1">
282→ <h2 className="text-lg font-semibold">Willkommen, {data.company.name}</h2>
283→ <p className="text-xs text-muted-foreground">
284→ Du siehst ausschließlich deine eigenen Daten — sicher und geschützt.
285→ {data.kpis.pendingApprovals > 0 && <span className="font-medium text-foreground"> {data.kpis.pendingApprovals} Freigabe(n) warten auf dich.</span>}
286→ </p>
287→ </div>
288→ {data.kpis.pendingApprovals > 0 && (
289→ <Button size="sm" className="gap-1.5" onClick={() => setTab('approvals')}>
290→ <CheckCircle2 className="size-4" />
291→ Freigaben ({data.kpis.pendingApprovals})
292→ </Button>
293→ )}
294→ </CardContent>
295→ </Card>
296→
297→ <div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6">
298→ <Card className="p-4"><p className="text-xs text-muted-foreground">Offene Projekte</p><p className="mt-1 text-2xl font-semibold tabular-nums">{data.kpis.openProjects}</p></Card>
299→ <Card className="p-4"><p className="text-xs text-muted-foreground">Offene Freigaben</p><p className="mt-1 text-2xl font-semibold tabular-nums">{data.kpis.pendingApprovals}</p></Card>
300→ <Card className="p-4"><p className="text-xs text-muted-foreground">Offene Rechnungen</p><p className="mt-1 text-2xl font-semibold tabular-nums">{data.kpis.unpaidInvoiceCount}</p><p className="text-[10px] text-muted-foreground">{formatEuro(data.kpis.unpaidCents)}</p></Card>
301→ <Card className="p-4"><p className="text-xs text-muted-foreground">Offene Tickets</p><p className="mt-1 text-2xl font-semibold tabular-nums">{data.kpis.openTickets}</p></Card>
302→ <Card className="p-4"><p className="text-xs text-muted-foreground">Aktive Lizenzen</p><p className="mt-1 text-2xl font-semibold tabular-nums">{data.kpis.activeLicenses}</p></Card>
303→ </div>
304→
305→ <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
306→ {/* Pending approvals */}
307→ <Card>
308→ <CardHeader className="flex flex-row items-center justify-between pb-2">
309→ <CardTitle className="flex items-center gap-2 text-sm"><Clock className="size-3.5 text-muted-foreground" />Wartende Freigaben</CardTitle>
310→ <Button variant="ghost" size="sm" className="h-7 text-xs" onClick={() => setTab('approvals')}>Alle</Button>
311→ </CardHeader>
312→ <CardContent className="space-y-2">
313→ {data.approvals.filter((a) => a.status === 'pending').slice(0, 4).map((a) => (
314→ <div key={a.id} className="rounded-md border border-border p-3">
315→ <p className="text-xs font-medium">{a.title}</p>
316→ {a.description && <p className="mt-0.5 text-[11px] text-muted-foreground">{a.description}</p>}
317→ <p className="mt-1 text-[10px] text-muted-foreground">Eingereicht {formatRelative(a.createdAt)}</p>
318→ </div>
319→ ))}
320→ {data.approvals.filter((a) => a.status === 'pending').length === 0 && (
321→ <p className="py-4 text-center text-xs text-muted-foreground">Keine offenen Freigaben.</p>
322→ )}
323→ </CardContent>
324→ </Card>
325→
326→ {/* Projects */}
327→ <Card>
328→ <CardHeader className="pb-2"><CardTitle className="text-sm">Meine Projekte ({data.projects.length})</CardTitle></CardHeader>
329→ <CardContent className="space-y-2">
330→ {data.projects.slice(0, 4).map((p) => (
331→ <div key={p.id} className="rounded-md border border-border p-3">
332→ <div className="flex items-center justify-between">
333→ <p className="truncate text-xs font-medium">{p.name}</p>
334→ <Badge variant="outline" className="text-[10px] capitalize">{p.status}</Badge>
335→ </div>
336→ <div className="mt-2 flex items-center justify-between text-[10px] text-muted-foreground">
337→ <span>{p.doneTasks}/{p.taskCount} Aufgaben</span>
338→ <span>{p.progress}%</span>
339→ </div>
340→ <Progress value={p.progress} className="mt-1 h-1" />
341→ </div>
342→ ))}
343→ </CardContent>
344→ </Card>
345→ </div>
346→
347→ {/* Recent invoices */}
348→ <Card>
349→ <CardHeader className="pb-2"><CardTitle className="text-sm">Letzte Rechnungen</CardTitle></CardHeader>
350→ <CardContent className="p-0">
351→ <div className="overflow-x-auto">
352→ <table className="w-full text-sm">
353→ <thead className="border-y border-border bg-muted/40 text-left text-[11px] uppercase tracking-wide text-muted-foreground">
354→ <tr><th className="px-4 py-2 font-medium">Nr.</th><th className="px-4 py-2 font-medium">Datum</th><th className="px-4 py-2 font-medium">Fällig</th><th className="px-4 py-2 font-medium text-right">Betrag</th><th className="px-4 py-2 font-medium">Status</th></tr>
355→ </thead>
356→ <tbody className="divide-y divide-border">
357→ {data.invoices.slice(0, 5).map((i) => (
358→ <tr key={i.id}>
359→ <td className="px-4 py-2.5"><code className="font-mono text-[11px]">{i.number}</code></td>
360→ <td className="px-4 py-2.5 text-xs">{formatDate(i.issueDate)}</td>
361→ <td className="px-4 py-2.5 text-xs">{formatDate(i.dueDate)}</td>
362→ <td className="px-4 py-2.5 text-right text-xs font-semibold tabular-nums">{formatEuro(i.grossCents)}</td>
363→ <td className="px-4 py-2.5"><Badge variant="outline" className="text-[10px] capitalize">{i.status}</Badge></td>
364→ </tr>
365→ ))}
366→ </tbody>
367→ </table>
368→ </div>
369→ </CardContent>
370→ </Card>
371→ </div>
372→ )
373→}
374→
375→function PortalApprovals({ data, refetch }: { data: PortalData; refetch: () => void }) {
376→ const [deciding, setDeciding] = useState<string | null>(null)
377→ const [decision, setDecision] = useState<'approved' | 'rejected' | 'changes-requested'>('approved')
378→ const [feedback, setFeedback] = useState('')
379→ const [dialogOpen, setDialogOpen] = useState(false)
380→ const [busy, setBusy] = useState(false)
381→
382→ const openDecision = (approvalId: string, dec: 'approved' | 'rejected' | 'changes-requested') => {
383→ setDeciding(approvalId)
384→ setDecision(dec)
385→ setFeedback('')
386→ setDialogOpen(true)
387→ }
388→
389→ const submit = async () => {
390→ if (!deciding) return
391→ setBusy(true)
392→ const t = toast.loading('Freigabe wird gespeichert (IP + Zeitstempel)…')
393→ try {
394→ const r = await fetch(`/api/aos/portal/approvals/${deciding}/decide`, {
395→ method: 'PATCH',
396→ headers: { 'content-type': 'application/json' },
397→ body: JSON.stringify({ decision, decidedBy: data.company.name, feedback }),
398→ })
399→ const res = await r.json()
400→ if (!r.ok) throw new Error(res.error || 'decide failed')
401→ toast.success(`Freigabe ${decision === 'approved' ? 'akzeptiert' : decision === 'rejected' ? 'abgelehnt' : 'mit Änderungswunsch'} (IP: ${res.evidence.decidedIp})`, { id: t })
402→ setDialogOpen(false)
403→ refetch()
404→ } catch (err) {
405→ toast.error(err instanceof Error ? err.message : 'Speichern fehlgeschlagen', { id: t })
406→ } finally {
407→ setBusy(false)
408→ }
409→ }
410→
411→ const statusMeta: Record<string, { label: string; cls: string }> = {
412→ pending: { label: 'Wartend', cls: 'bg-foreground/50 text-background' },
413→ approved: { label: 'Freigegeben', cls: 'bg-foreground text-background' },
414→ rejected: { label: 'Abgelehnt', cls: 'bg-muted text-muted-foreground' },
415→ 'changes-requested': { label: 'Änderung gewünscht', cls: 'bg-muted text-foreground' },
416→ }
417→
418→ return (
419→ <div className="space-y-4">
420→ <div className="flex items-center gap-2">
421→ <CheckCircle2 className="size-5 text-muted-foreground" />
422→ <div>
423→ <h1 className="text-lg font-semibold">Freigaben</h1>
424→ <p className="text-xs text-muted-foreground">Meilenstein-Freigaben mit Zeitstempel- und IP-Evidenz.</p>
425→ </div>
426→ </div>
427→
428→ <div className="space-y-2">
429→ {data.approvals.map((a) => {
430→ const meta = statusMeta[a.status] ?? statusMeta.pending
431→ return (
432→ <Card key={a.id} className="p-4">
433→ <div className="flex items-start justify-between gap-3">
434→ <div className="min-w-0 flex-1">
435→ <div className="flex items-center gap-2">
436→ <p className="text-sm font-medium">{a.title}</p>
437→ <Badge variant="outline" className={cn('text-[10px]', meta.cls)}>{meta.label}</Badge>
438→ </div>
439→ {a.description && <p className="mt-1 text-xs text-muted-foreground">{a.description}</p>}
440→ {a.status !== 'pending' && (
441→ <div className="mt-2 space-y-0.5 text-[10px] text-muted-foreground">
442→ <p>Entschieden: {formatDate(a.decidedAt!)} von {a.decidedBy}</p>
443→ <p>IP-Evidenz: <code className="font-mono">{a.decidedIp}</code></p>
444→ {a.decision && <p className="italic">„{a.decision}"</p>}
445→ </div>
446→ )}
447→ {a.status === 'pending' && (
448→ <p className="mt-1 text-[10px] text-muted-foreground">Eingereicht {formatRelative(a.createdAt)}</p>
449→ )}
450→ </div>
451→ {a.status === 'pending' && (
452→ <div className="flex shrink-0 gap-1.5">
453→ <Button size="sm" className="h-8 gap-1 text-xs" onClick={() => openDecision(a.id, 'approved')}>
454→ <Check className="size-3.5" />Freigeben
455→ </Button>
456→ <Button size="sm" variant="outline" className="h-8 gap-1 text-xs" onClick={() => openDecision(a.id, 'changes-requested')}>
457→ <AlertTriangle className="size-3.5" />Änderung
458→ </Button>
459→ <Button size="sm" variant="ghost" className="h-8 gap-1 text-xs text-muted-foreground" onClick={() => openDecision(a.id, 'rejected')}>
460→ <X className="size-3.5" />Ablehnen
461→ </Button>
462→ </div>
463→ )}
464→ </div>
465→ </Card>
466→ )
467→ })}
468→ {data.approvals.length === 0 && <p className="py-8 text-center text-xs text-muted-foreground">Keine Freigaben.</p>}
469→ </div>
470→
471→ <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
472→ <DialogContent className="sm:max-w-md">
473→ <DialogHeader>
474→ <DialogTitle>
475→ {decision === 'approved' && 'Freigabe bestätigen'}
476→ {decision === 'rejected' && 'Freigabe ablehnen'}
477→ {decision === 'changes-requested' && 'Änderungswunsch senden'}
478→ </DialogTitle>
479→ <DialogDescription>
480→ Deine Entscheidung wird mit Zeitstempel und IP-Adresse gespeichert (eIDAS Art. 25 AdES).
481→ </DialogDescription>
482→ </DialogHeader>
483→ <div className="space-y-3">
484→ <div className="space-y-1.5">
485→ <Label className="text-xs">Kommentar / Feedback (optional)</Label>
486→ <Textarea value={feedback} onChange={(e) => setFeedback(e.target.value)} placeholder="z.B. Bitte Kontrast erhöhen…" className="min-h-[80px] text-sm" />
487→ </div>
488→ <div className="rounded-md border border-dashed border-border p-2.5 text-[10px] text-muted-foreground">
489→ <p className="flex items-center gap-1.5"><ShieldCheck className="size-3" />Evidenz: {new Date().toLocaleString('de-DE')} · IP wird erfasst</p>
490→ </div>
491→ </div>
492→ <DialogFooter>
493→ <Button variant="outline" onClick={() => setDialogOpen(false)}>Abbrechen</Button>
494→ <Button onClick={submit} disabled={busy} className="gap-1.5">
495→ {busy && <Loader2 className="size-3.5 animate-spin" />}
496→ {decision === 'approved' ? 'Freigeben' : decision === 'rejected' ? 'Ablehnen' : 'Senden'}
497→ </Button>
498→ </DialogFooter>
499→ </DialogContent>
500→ </Dialog>
501→ </div>
502→ )
503→}
504→
505→function PortalInvoices({ data }: { data: PortalData }) {
506→ return (
507→ <div className="space-y-4">
508→ <div className="flex items-center gap-2">
509→ <Receipt className="size-5 text-muted-foreground" />
510→ <div>
511→ <h1 className="text-lg font-semibold">Rechnungen ({data.invoices.length})</h1>
512→ <p className="text-xs text-muted-foreground">Deine Rechnungen — Ansicht nur für dein Unternehmen.</p>
513→ </div>
514→ </div>
515→ <Card>
516→ <CardContent className="p-0">
517→ <div className="overflow-x-auto">
518→ <table className="w-full text-sm">
519→ <thead className="border-y border-border bg-muted/40 text-left text-[11px] uppercase tracking-wide text-muted-foreground">
520→ <tr>
521→ <th className="px-4 py-2 font-medium">Nr.</th>
522→ <th className="px-4 py-2 font-medium">Typ</th>
523→ <th className="px-4 py-2 font-medium">Datum</th>
524→ <th className="px-4 py-2 font-medium">Fällig</th>
525→ <th className="px-4 py-2 font-medium text-right">Betrag</th>
526→ <th className="px-4 py-2 font-medium">E-Rechnung</th>
527→ <th className="px-4 py-2 font-medium">Status</th>
528→ </tr>
529→ </thead>
530→ <tbody className="divide-y divide-border">
531→ {data.invoices.map((i) => {
532→ const due = daysUntil(i.dueDate)
533→ return (
534→ <tr key={i.id}>
535→ <td className="px-4 py-2.5"><code className="font-mono text-[11px]">{i.number}</code></td>
536→ <td className="px-4 py-2.5 text-xs text-muted-foreground">{i.type}</td>
537→ <td className="px-4 py-2.5 text-xs">{formatDate(i.issueDate)}</td>
538→ <td className="px-4 py-2.5 text-xs">{formatDate(i.dueDate)}{i.status === 'sent' && due < 0 && <span className="ml-1 text-[10px] text-foreground">({Math.abs(due)} d)</span>}</td>
539→ <td className="px-4 py-2.5 text-right text-xs font-semibold tabular-nums">{formatEuro(i.grossCents)}</td>
540→ <td className="px-4 py-2.5">
541→ <div className="flex gap-1">
542→ {i.zugferd && <Badge variant="outline" className="text-[9px]">ZUGFeRD</Badge>}
543→ {i.xrechnung && <Badge variant="outline" className="text-[9px]">XRechnung</Badge>}
544→ </div>
545→ </td>
546→ <td className="px-4 py-2.5"><Badge variant="outline" className="text-[10px] capitalize">{i.status}</Badge></td>
547→ </tr>
548→ )
549→ })}
550→ </tbody>
551→ </table>
552→ </div>
553→ </CardContent>
554→ </Card>
555→ </div>
556→ )
557→}
558→
559→function PortalTickets({ data }: { data: PortalData }) {
560→ return (
561→ <div className="space-y-4">
562→ <div className="flex items-center justify-between">
563→ <div className="flex items-center gap-2">
564→ <LifeBuoy className="size-5 text-muted-foreground" />
565→ <div>
566→ <h1 className="text-lg font-semibold">Tickets ({data.tickets.length})</h1>
567→ <p className="text-xs text-muted-foreground">Support-Anfragen und Konversationen.</p>
568→ </div>
569→ </div>
570→ <Button size="sm"><LifeBuoy className="size-4" />Neues Ticket</Button>
571→ </div>
572→ <div className="space-y-2">
573→ {data.tickets.map((t) => (
574→ <Card key={t.id} className="p-4">
575→ <div className="flex items-start justify-between gap-3">
576→ <div className="min-w-0 flex-1">
577→ <div className="flex items-center gap-2">
578→ <code className="text-[10px] font-mono text-muted-foreground">{t.number}</code>
579→ {t.priority === 'urgent' && <Badge variant="outline" className="text-[9px]">DRINGEND</Badge>}
580→ </div>
581→ <p className="mt-0.5 truncate text-sm font-medium">{t.subject}</p>
582→ <p className="mt-1 text-[10px] text-muted-foreground">{t.messageCount} Nachrichten · letzte {formatRelative(t.lastMessageAt)}</p>
583→ </div>
584→ <Badge variant="outline" className="text-[10px] capitalize">{t.status}</Badge>
585→ </div>
586→ </Card>
587→ ))}
588→ {data.tickets.length === 0 && <p className="py-8 text-center text-xs text-muted-foreground">Keine Tickets.</p>}
589→ </div>
590→ </div>
591→ )
592→}
593→
594→function PortalLicenses({ data }: { data: PortalData }) {
595→ return (
596→ <div className="space-y-4">
597→ <div className="flex items-center gap-2">
598→ <KeyRound className="size-5 text-muted-foreground" />
599→ <div>
600→ <h1 className="text-lg font-semibold">Lizenzen ({data.licenses.length})</h1>
601→ <p className="text-xs text-muted-foreground">Deine Produkt-Lizenzen und Aktivierungen.</p>
602→ </div>
603→ </div>
604→ <div className="space-y-2">
605→ {data.licenses.map((l) => (
606→ <Card key={l.id} className="p-4">
607→ <div className="flex items-start justify-between gap-3">
608→ <div className="min-w-0 flex-1">
609→ <div className="flex items-center gap-2">
610→ <p className="text-sm font-medium">{l.product}</p>
611→ <Badge variant="outline" className="text-[10px] capitalize">{l.plan}</Badge>
612→ </div>
613→ <code className="mt-1 block text-[10px] font-mono text-muted-foreground">{l.key}</code>
614→ <div className="mt-1.5 space-y-0.5 text-[10px] text-muted-foreground">
615→ {l.activations.map((a, i) => <p key={i}>↳ {a.domain} ({a.environment})</p>)}
616→ {l.validUntil && <p>Gültig bis: {formatDate(l.validUntil)}</p>}
617→ </div>
618→ </div>
619→ <Badge variant="outline" className="text-[10px] capitalize">{l.status}</Badge>
620→ </div>
621→ </Card>
622→ ))}
623→ </div>
624→ </div>
625→ )
626→}
627→
628→// Portal notifications bell — client-scoped
629→function PortalNotificationsBell({ companyId }: { companyId: string }) {
630→ const [open, setOpen] = useState(false)
631→ const { data } = useFetch<{ notifications: { id: string; type: string; title: string; detail: string; module: string; daysUntil: number }[]; stats: { total: number; urgent: number; warning: number; info: number } }>(`/api/aos/portal/companies/${companyId}/notifications`)
632→
633→ const notifs = data?.notifications ?? []
634→ const urgent = data?.stats.urgent ?? 0
635→
636→ return (
637→ <Popover open={open} onOpenChange={setOpen}>
638→ <PopoverTrigger asChild>
639→ <Button variant="ghost" size="icon" className="relative" aria-label="Benachrichtigungen">
640→ <Bell className="size-4" />
641→ {urgent > 0 && (
642→ <span className="absolute right-1 top-1 flex size-4 items-center justify-center rounded-full bg-foreground text-[9px] font-bold text-background">
643→ {urgent}
644→ </span>
645→ )}
646→ {urgent === 0 && notifs.length > 0 && (
647→ <span className="absolute right-1.5 top-1.5 size-1.5 rounded-full bg-foreground/50" />
648→ )}
649→ </Button>
650→ </PopoverTrigger>
651→ <PopoverContent align="end" className="w-72 p-0">
652→ <div className="flex items-center justify-between border-b border-border px-3 py-2.5">
653→ <span className="text-xs font-semibold">Deine Benachrichtigungen</span>
654→ {notifs.length > 0 && <Badge variant="outline" className="text-[10px]">{notifs.length}</Badge>}
655→ </div>
656→ <ScrollArea className="h-72">
657→ {notifs.length === 0 ? (
658→ <div className="flex flex-col items-center justify-center gap-2 py-10 text-center">
659→ <CheckCircle2 className="size-7 text-muted-foreground/50" />
660→ <p className="text-xs text-muted-foreground">Keine offenen Benachrichtigungen.</p>
661→ </div>
662→ ) : (
663→ <div className="divide-y divide-border">
664→ {notifs.map((n) => {
665→ const Icon = n.type === 'urgent' ? AlertTriangle : n.type === 'warning' ? Clock : Info
666→ return (
667→ <div key={n.id} className="flex items-start gap-2.5 px-3 py-2.5">
668→ <Icon className={cn('mt-0.5 size-3.5 shrink-0', n.type === 'urgent' ? 'text-foreground' : n.type === 'warning' ? 'text-foreground/70' : 'text-muted-foreground')} />
669→ <div className="min-w-0 flex-1">
670→ <p className="truncate text-xs font-medium">{n.title}</p>
671→ <p className="mt-0.5 text-[10px] text-muted-foreground">{n.detail}</p>
672→ </div>
673→ </div>
674→ )
675→ })}
676→ </div>
677→ )}
678→ </ScrollArea>
679→ </PopoverContent>
680→ </Popover>
681→ )
682→}
683→
@@ -0,0 +1,876 @@
1→'use client'
2→
3→import { useMemo, useState } from 'react'
4→import {
5→ Users,
6→ Building2,
7→ Globe,
8→ MapPin,
9→ Clock,
10→ Percent,
11→ CheckCircle2,
12→ XCircle,
13→ History,
14→ Inbox,
15→ Mail,
16→ Loader2,
17→ ChevronRight,
18→ ShoppingBag,
19→} from 'lucide-react'
20→import { useFetch } from '@/hooks/use-fetch'
21→import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
22→import { Badge } from '@/components/ui/badge'
23→import { Button } from '@/components/ui/button'
24→import { Input } from '@/components/ui/input'
25→import { Label } from '@/components/ui/label'
26→import { Textarea } from '@/components/ui/textarea'
27→import { Skeleton } from '@/components/ui/skeleton'
28→import {
29→ Dialog,
30→ DialogContent,
31→ DialogDescription,
32→ DialogFooter,
33→ DialogHeader,
34→ DialogTitle,
35→} from '@/components/ui/dialog'
36→import {
37→ Sheet,
38→ SheetContent,
39→ SheetDescription,
40→ SheetHeader,
41→ SheetTitle,
42→} from '@/components/ui/sheet'
43→import {
44→ Collapsible,
45→ CollapsibleContent,
46→ CollapsibleTrigger,
47→} from '@/components/ui/collapsible'
48→import { PageHeader } from '../primitives'
49→import { FuseButton } from '@/components/FuseButton'
50→import { formatRelative, formatDate, formatDateTime } from '@/lib/format'
51→import { cn } from '@/lib/utils'
52→import { toast } from 'sonner'
53→
54→/* ----------------------------- types ----------------------------- */
55→
56→interface AgencyCompany {
57→ id: string
58→ name: string
59→ email: string | null
60→ website: string | null
61→ city: string | null
62→ isAgency: boolean
63→ agencyStatus: string | null
64→ agencyDiscountPct: number | null
65→}
66→
67→interface AgencyApplication {
68→ id: string
69→ companyId: string
70→ status: 'pending' | 'approved' | 'rejected'
71→ discountPct: number
72→ businessModel?: string | null
73→ expectedClientVolume?: string | null
74→ referredBy?: string | null
75→ reviewedBy?: string | null
76→ reviewedAt?: string | null
77→ rejectReason?: string | null
78→ appliedAt: string
79→ createdAt: string
80→ updatedAt: string
81→ company: AgencyCompany
82→}
83→
84→interface AgencyClient {
85→ id: string
86→ name: string
87→ email: string | null
88→}
89→
90→interface ApprovedAgency extends AgencyCompany {
91→ agencyDiscountPct: number
92→ agencyApprovedAt: string
93→ agencyClients: AgencyClient[]
94→ _count: { agencyClients: number; licenses: number }
95→}
96→
97→interface AgencyData {
98→ applications: {
99→ pending: AgencyApplication[]
100→ reviewed: AgencyApplication[]
101→ }
102→ agencies: ApprovedAgency[]
103→ stats: { pending: number; approved: number; totalApplications: number }
104→}
105→
106→const BASE_PRICE_EUR = 50 // 50 €/Monat base price for preview
107→
108→/* ----------------------------- view ----------------------------- */
109→
110→export function AgencyView() {
111→ const { data, loading, refetch } = useFetch<AgencyData>('/api/aos/agency')
112→
113→ if (loading || !data) {
114→ return (
115→ <div className="space-y-6 p-4 md:p-6">
116→ <Skeleton className="h-9 w-32" />
117→ <div className="grid grid-cols-2 gap-4 sm:grid-cols-4">
118→ {Array.from({ length: 4 }).map((_, i) => (
119→ <Skeleton key={i} className="h-24" />
120→ ))}
121→ </div>
122→ <Skeleton className="h-64" />
123→ </div>
124→ )
125→ }
126→
127→ const { applications, agencies, stats } = data
128→ const avgDiscount =
129→ agencies.length > 0
130→ ? Math.round(
131→ agencies.reduce((sum, a) => sum + (a.agencyDiscountPct ?? 0), 0) / agencies.length,
132→ )
133→ : 0
134→
135→ return (
136→ <div className="space-y-6 p-4 md:p-6">
137→ <PageHeader
138→ title="Reseller"
139→ description="Reseller-Verwaltung: Bewerbungen prüfen, Rabatt-Sätze festlegen (0–20 %) und genehmigte Reseller mit ihren Kunden einsehen."
140→ />
141→
142→ {/* Stats */}
143→ <div className="grid grid-cols-2 gap-4 sm:grid-cols-4">
144→ <StatCard
145→ label="Offene Bewerbungen"
146→ value={stats.pending}
147→ icon={Inbox}
148→ hint="wartet auf Freigabe"
149→ />
150→ <StatCard
151→ label="Genehmigte Reseller"
152→ value={stats.approved}
153→ icon={Users}
154→ hint="aktiv im System"
155→ />
156→ <StatCard
157→ label="Bewerbungen gesamt"
158→ value={stats.totalApplications}
159→ icon={History}
160→ hint="inkl. Verlauf"
161→ />
162→ <StatCard
163→ label="Ø Rabatt"
164→ value={`${avgDiscount}%`}
165→ icon={Percent}
166→ hint={agencies.length ? `über ${agencies.length} Reseller` : '—'}
167→ />
168→ </div>
169→
170→ <PendingApplicationsSection applications={applications.pending} onChanged={refetch} />
171→ <ApprovedAgenciesSection agencies={agencies} />
172→ <ReviewedSection applications={applications.reviewed} />
173→ </div>
174→ )
175→}
176→
177→/* ----------------------------- stats card ----------------------------- */
178→
179→function StatCard({
180→ label,
181→ value,
182→ icon: Icon,
183→ hint,
184→}: {
185→ label: string
186→ value: number | string
187→ icon: typeof Inbox
188→ hint?: string
189→}) {
190→ return (
191→ <Card className="p-4">
192→ <div className="flex items-center justify-between">
193→ <p className="text-xs text-muted-foreground">{label}</p>
194→ <Icon className="size-3.5 text-muted-foreground" />
195→ </div>
196→ <p className="mt-1 text-2xl font-semibold tabular-nums">{value}</p>
197→ {hint && <p className="text-[10px] text-muted-foreground">{hint}</p>}
198→ </Card>
199→ )
200→}
201→
202→/* ----------------------------- pending applications ----------------------------- */
203→
204→function PendingApplicationsSection({
205→ applications,
206→ onChanged,
207→}: {
208→ applications: AgencyApplication[]
209→ onChanged: () => void
210→}) {
211→ const [approveTarget, setApproveTarget] = useState<AgencyApplication | null>(null)
212→ const [rejectTarget, setRejectTarget] = useState<AgencyApplication | null>(null)
213→
214→ return (
215→ <section className="space-y-3">
216→ <div className="flex items-center justify-between">
217→ <h2 className="text-sm font-semibold tracking-tight">
218→ Bewerbende Reseller
219→ <span className="ml-2 text-xs font-normal text-muted-foreground">
220→ {applications.length} offen
221→ </span>
222→ </h2>
223→ </div>
224→
225→ {applications.length === 0 ? (
226→ <div className="flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-border bg-muted/20 px-6 py-14 text-center">
227→ <div className="flex size-12 items-center justify-center rounded-full border border-border bg-background">
228→ <Inbox className="size-5 text-muted-foreground" />
229→ </div>
230→ <div className="space-y-1">
231→ <p className="text-sm font-medium">Keine bewerbenden Anfragen</p>
232→ <p className="max-w-sm text-xs text-muted-foreground">
233→ Neue Reseller-Bewerbungen erscheinen hier.
234→ </p>
235→ </div>
236→ </div>
237→ ) : (
238→ <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
239→ {applications.map((app) => (
240→ <Card key={app.id} className="flex flex-col">
241→ <CardContent className="flex flex-1 flex-col gap-3 p-4">
242→ {/* header */}
243→ <div className="flex items-start justify-between gap-3">
244→ <div className="min-w-0 space-y-1">
245→ <p className="truncate text-sm font-semibold">{app.company.name}</p>
246→ <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground">
247→ {app.company.email && (
248→ <span className="inline-flex items-center gap-1">
249→ <Mail className="size-3" />
250→ {app.company.email}
251→ </span>
252→ )}
253→ {app.company.website && (
254→ <span className="inline-flex items-center gap-1">
255→ <Globe className="size-3" />
256→ {app.company.website}
257→ </span>
258→ )}
259→ {app.company.city && (
260→ <span className="inline-flex items-center gap-1">
261→ <MapPin className="size-3" />
262→ {app.company.city}
263→ </span>
264→ )}
265→ </div>
266→ </div>
267→ <Badge variant="outline" className="gap-1 border-foreground/40 text-[10px]">
268→ <Clock className="size-2.5" />
269→ {formatRelative(app.appliedAt)}
270→ </Badge>
271→ </div>
272→
273→ {/* application details */}
274→ {(app.businessModel || app.expectedClientVolume || app.referredBy) && (
275→ <div className="grid grid-cols-1 gap-2 rounded-md border border-border bg-muted/30 p-3 text-xs sm:grid-cols-3">
276→ {app.businessModel && (
277→ <Meta label="Geschäftsmodell" value={app.businessModel} />
278→ )}
279→ {app.expectedClientVolume && (
280→ <Meta label="Erw. Kundenvolumen" value={app.expectedClientVolume} />
281→ )}
282→ {app.referredBy && (
283→ <Meta label="Empfohlen von" value={app.referredBy} />
284→ )}
285→ </div>
286→ )}
287→
288→ {/* actions */}
289→ <div className="mt-auto flex items-center justify-end gap-2 pt-1">
290→ <Button
291→ size="sm"
292→ variant="outline"
293→ onClick={() => setRejectTarget(app)}
294→ >
295→ <XCircle className="size-3.5" />
296→ Ablehnen
297→ </Button>
298→ <Button
299→ size="sm"
300→ onClick={() => setApproveTarget(app)}
301→ >
302→ <CheckCircle2 className="size-3.5" />
303→ Genehmigen
304→ </Button>
305→ </div>
306→ </CardContent>
307→ </Card>
308→ ))}
309→ </div>
310→ )}
311→
312→ <ApproveDialog
313→ application={approveTarget}
314→ onClose={() => setApproveTarget(null)}
315→ onChanged={onChanged}
316→ />
317→ <RejectDialog
318→ application={rejectTarget}
319→ onClose={() => setRejectTarget(null)}
320→ onChanged={onChanged}
321→ />
322→ </section>
323→ )
324→}
325→
326→function Meta({ label, value }: { label: string; value: string }) {
327→ return (
328→ <div className="min-w-0">
329→ <p className="text-[10px] uppercase tracking-wide text-muted-foreground">{label}</p>
330→ <p className="mt-0.5 truncate text-xs font-medium">{value}</p>
331→ </div>
332→ )
333→}
334→
335→/* ----------------------------- approve dialog ----------------------------- */
336→
337→function ApproveDialog({
338→ application,
339→ onClose,
340→ onChanged,
341→}: {
342→ application: AgencyApplication | null
343→ onClose: () => void
344→ onChanged: () => void
345→}) {
346→ const [discount, setDiscount] = useState(10)
347→ const [committing, setCommitting] = useState(false)
348→
349→ // Reset state when dialog opens for a new application
350→ const handleOpenChange = (open: boolean) => {
351→ if (open) setDiscount(10)
352→ if (!open) {
353→ if (!committing) onClose()
354→ }
355→ }
356→
357→ const net = useMemo(() => {
358→ const netEur = BASE_PRICE_EUR * (1 - discount / 100)
359→ return netEur.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
360→ }, [discount])
361→
362→ const handleCommit = async () => {
363→ if (!application) return
364→ setCommitting(true)
365→ try {
366→ const r = await fetch(`/api/aos/agency/${application.id}/approve`, {
367→ method: 'PATCH',
368→ headers: { 'content-type': 'application/json' },
369→ body: JSON.stringify({ discountPct: discount }),
370→ })
371→ if (!r.ok) {
372→ const err = await r.json().catch(() => ({}))
373→ throw new Error(err.error || 'approve failed')
374→ }
375→ // Defer close + refetch so the FuseButton's done-state + toast can render.
376→ setTimeout(() => {
377→ onClose()
378→ onChanged()
379→ }, 350)
380→ } catch (err) {
381→ setCommitting(false)
382→ throw err
383→ }
384→ // Note: setCommitting(false) intentionally skipped on success — dialog will
385→ // close via the setTimeout above and the button's doneLabel will be shown.
386→ }
387→
388→ return (
389→ <Dialog open={!!application} onOpenChange={handleOpenChange}>
390→ <DialogContent className="sm:max-w-md">
391→ {application && (
392→ <>
393→ <DialogHeader>
394→ <DialogTitle className="flex items-center gap-2">
395→ <CheckCircle2 className="size-4" />
396→ Reseller-Bewerbung genehmigen
397→ </DialogTitle>
398→ <DialogDescription>
399→ <span className="font-medium text-foreground">{application.company.name}</span> wird
400→ als Reseller freigeschaltet. Der Rabatt wird auf alle vom Reseller angelegten Kundenlizenzierungen
401→ angewendet.
402→ </DialogDescription>
403→ </DialogHeader>
404→
405→ <div className="space-y-3">
406→ <div className="space-y-1.5">
407→ <div className="flex items-center justify-between">
408→ <Label htmlFor="discount-pct">Rabatt (%)</Label>
409→ <span className="text-[10px] text-muted-foreground">0 – 20</span>
410→ </div>
411→ <Input
412→ id="discount-pct"
413→ type="number"
414→ min={0}
415→ max={20}
416→ step={1}
417→ value={discount}
418→ onChange={(e) => {
419→ const raw = parseInt(e.target.value, 10)
420→ if (Number.isNaN(raw)) {
421→ setDiscount(0)
422→ return
423→ }
424→ setDiscount(Math.min(20, Math.max(0, raw)))
425→ }}
426→ className="tabular-nums"
427→ />
428→ </div>
429→
430→ {/* live preview */}
431→ <div className="rounded-md border border-border bg-muted/40 p-3 text-xs">
432→ <p className="text-[10px] uppercase tracking-wide text-muted-foreground">
433→ Preisvorschau
434→ </p>
435→ <p className="mt-1 tabular-nums">
436→ <span className="font-medium">{BASE_PRICE_EUR} €/Monat</span>
437→ <span className="mx-1.5 text-muted-foreground">Basis</span>
438→ <span className="mx-1 text-muted-foreground">→</span>
439→ <span className="text-muted-foreground">mit {discount}% Rabatt</span>
440→ <span className="mx-1.5 text-muted-foreground">=</span>
441→ <span className="font-semibold border-foreground/40 px-1.5 py-0.5 rounded border">
442→ {net} €
443→ </span>
444→ </p>
445→ </div>
446→ </div>
447→
448→ <DialogFooter className="gap-2">
449→ <Button variant="outline" onClick={onClose} disabled={committing}>
450→ Abbrechen
451→ </Button>
452→ <FuseButton
453→ label="Genehmigen"
454→ doneLabel="Genehmigt"
455→ onCommit={handleCommit}
456→ disabled={committing}
457→ variant="default"
458→ />
459→ </DialogFooter>
460→ </>
461→ )}
462→ </DialogContent>
463→ </Dialog>
464→ )
465→}
466→
467→/* ----------------------------- reject dialog ----------------------------- */
468→
469→function RejectDialog({
470→ application,
471→ onClose,
472→ onChanged,
473→}: {
474→ application: AgencyApplication | null
475→ onClose: () => void
476→ onChanged: () => void
477→}) {
478→ const [reason, setReason] = useState('')
479→ const [submitting, setSubmitting] = useState(false)
480→
481→ const handleOpenChange = (open: boolean) => {
482→ if (!open) {
483→ if (!submitting) {
484→ setReason('')
485→ onClose()
486→ }
487→ }
488→ }
489→
490→ const submit = async () => {
491→ if (!application) return
492→ if (!reason.trim()) {
493→ toast.error('Bitte gib einen Ablehnungsgrund an.')
494→ return
495→ }
496→ setSubmitting(true)
497→ const t = toast.loading('Ablehnung wird gespeichert…')
498→ try {
499→ const r = await fetch(`/api/aos/agency/${application.id}/reject`, {
500→ method: 'PATCH',
501→ headers: { 'content-type': 'application/json' },
502→ body: JSON.stringify({ reason: reason.trim() }),
503→ })
504→ if (!r.ok) {
505→ const err = await r.json().catch(() => ({}))
506→ throw new Error(err.error || 'reject failed')
507→ }
508→ toast.success(`${application.company.name} abgelehnt`, { id: t })
509→ setReason('')
510→ onClose()
511→ onChanged()
512→ } catch (err) {
513→ toast.error(err instanceof Error ? err.message : 'Ablehnung fehlgeschlagen', { id: t })
514→ } finally {
515→ setSubmitting(false)
516→ }
517→ }
518→
519→ return (
520→ <Dialog open={!!application} onOpenChange={handleOpenChange}>
521→ <DialogContent className="sm:max-w-md">
522→ {application && (
523→ <>
524→ <DialogHeader>
525→ <DialogTitle className="flex items-center gap-2">
526→ <XCircle className="size-4" />
527→ Reseller-Bewerbung ablehnen
528→ </DialogTitle>
529→ <DialogDescription>
530→ <span className="font-medium text-foreground">{application.company.name}</span>
531→ {' '}wird abgelehnt. Der Grund wird für den Bewerber sichtbar protokolliert.
532→ </DialogDescription>
533→ </DialogHeader>
534→
535→ <div className="space-y-1.5">
536→ <Label htmlFor="reject-reason">Ablehnungsgrund</Label>
537→ <Textarea
538→ id="reject-reason"
539→ placeholder="z. B. Unvollständige Angaben, kein passendes Geschäftsmodell…"
540→ value={reason}
541→ onChange={(e) => setReason(e.target.value)}
542→ rows={4}
543→ maxLength={500}
544→ disabled={submitting}
545→ />
546→ <p className="text-right text-[10px] text-muted-foreground">
547→ {reason.length} / 500
548→ </p>
549→ </div>
550→
551→ <DialogFooter className="gap-2">
552→ <Button variant="outline" onClick={onClose} disabled={submitting}>
553→ Abbrechen
554→ </Button>
555→ <Button variant="destructive" onClick={submit} disabled={submitting}>
556→ {submitting ? (
557→ <Loader2 className="size-3.5 animate-spin" />
558→ ) : (
559→ <XCircle className="size-3.5" />
560→ )}
561→ Ablehnen
562→ </Button>
563→ </DialogFooter>
564→ </>
565→ )}
566→ </DialogContent>
567→ </Dialog>
568→ )
569→}
570→
571→/* ----------------------------- approved agencies ----------------------------- */
572→
573→function ApprovedAgenciesSection({ agencies }: { agencies: ApprovedAgency[] }) {
574→ const [openAgency, setOpenAgency] = useState<ApprovedAgency | null>(null)
575→
576→ return (
577→ <section className="space-y-3">
578→ <div className="flex items-center justify-between">
579→ <h2 className="text-sm font-semibold tracking-tight">
580→ Genehmigte Reseller
581→ <span className="ml-2 text-xs font-normal text-muted-foreground">
582→ {agencies.length} aktiv
583→ </span>
584→ </h2>
585→ </div>
586→
587→ {agencies.length === 0 ? (
588→ <div className="flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-border bg-muted/20 px-6 py-14 text-center">
589→ <div className="flex size-12 items-center justify-center rounded-full border border-border bg-background">
590→ <Users className="size-5 text-muted-foreground" />
591→ </div>
592→ <div className="space-y-1">
593→ <p className="text-sm font-medium">Noch keine Reseller genehmigt</p>
594→ <p className="max-w-sm text-xs text-muted-foreground">
595→ Genehmigte Reseller-Bewerbungen erscheinen hier mit ihren Kunden und Lizenzen.
596→ </p>
597→ </div>
598→ </div>
599→ ) : (
600→ <Card>
601→ <CardHeader className="pb-2">
602→ <CardTitle className="text-sm">Reseller ({agencies.length})</CardTitle>
603→ </CardHeader>
604→ <CardContent className="p-0">
605→ <div className="overflow-x-auto">
606→ <table className="w-full text-sm">
607→ <thead className="border-y border-border bg-muted/40 text-left text-[11px] uppercase tracking-wide text-muted-foreground">
608→ <tr>
609→ <th className="px-4 py-2 font-medium">Reseller</th>
610→ <th className="px-4 py-2 font-medium">Rabatt</th>
611→ <th className="px-4 py-2 font-medium text-right">Kunden</th>
612→ <th className="px-4 py-2 font-medium text-right">Lizenzen</th>
613→ <th className="px-4 py-2 font-medium">Genehmigt am</th>
614→ <th className="px-4 py-2 font-medium text-right">Aktion</th>
615→ </tr>
616→ </thead>
617→ <tbody className="divide-y divide-border">
618→ {agencies.map((a) => (
619→ <tr key={a.id} className="transition hover:bg-muted/40">
620→ <td className="px-4 py-2.5">
621→ <div className="flex items-center gap-2">
622→ <div className="flex size-7 shrink-0 items-center justify-center rounded-md border border-border">
623→ <Building2 className="size-3.5 text-muted-foreground" />
624→ </div>
625→ <div className="min-w-0">
626→ <p className="truncate text-xs font-medium">{a.name}</p>
627→ {a.email && (
628→ <p className="truncate text-[10px] text-muted-foreground">{a.email}</p>
629→ )}
630→ </div>
631→ </div>
632→ </td>
633→ <td className="px-4 py-2.5">
634→ <Badge
635→ variant="outline"
636→ className="border-foreground/40 text-[10px] tabular-nums"
637→ >
638→ <Percent className="size-2.5" />
639→ {a.agencyDiscountPct}%
640→ </Badge>
641→ </td>
642→ <td className="px-4 py-2.5 text-right text-xs tabular-nums">
643→ {a._count.agencyClients}
644→ </td>
645→ <td className="px-4 py-2.5 text-right text-xs tabular-nums">
646→ {a._count.licenses}
647→ </td>
648→ <td className="px-4 py-2.5 text-xs">
649→ {formatDate(a.agencyApprovedAt)}
650→ </td>
651→ <td className="px-4 py-2.5 text-right">
652→ <Button
653→ size="sm"
654→ variant="ghost"
655→ onClick={() => setOpenAgency(a)}
656→ className="gap-1"
657→ >
658→ <ShoppingBag className="size-3.5" />
659→ Kunden ansehen
660→ <ChevronRight className="size-3" />
661→ </Button>
662→ </td>
663→ </tr>
664→ ))}
665→ </tbody>
666→ </table>
667→ </div>
668→ </CardContent>
669→ </Card>
670→ )}
671→
672→ <ClientsSheet agency={openAgency} onClose={() => setOpenAgency(null)} />
673→ </section>
674→ )
675→}
676→
677→function ClientsSheet({
678→ agency,
679→ onClose,
680→}: {
681→ agency: ApprovedAgency | null
682→ onClose: () => void
683→}) {
684→ return (
685→ <Sheet open={!!agency} onOpenChange={(o) => !o && onClose()}>
686→ <SheetContent side="right" className="w-full gap-0 sm:max-w-md">
687→ {agency && (
688→ <>
689→ <SheetHeader className="border-b border-border">
690→ <SheetTitle className="flex items-center gap-2">
691→ <Building2 className="size-4 text-muted-foreground" />
692→ {agency.name}
693→ </SheetTitle>
694→ <SheetDescription>
695→ Reseller-Kundenverwaltung — {agency._count.agencyClients} Kunde(n),{' '}
696→ {agency._count.licenses} Lizenz(en).
697→ </SheetDescription>
698→ </SheetHeader>
699→
700→ <div className="flex-1 overflow-y-auto px-4 py-3">
701→ {/* routing note */}
702→ <div className="mb-3 flex items-start gap-2 rounded-md border border-border bg-muted/40 p-3 text-[11px]">
703→ <Mail className="mt-0.5 size-3.5 shrink-0 text-muted-foreground" />
704→ <p className="text-muted-foreground">
705→ Reseller kann eigene Kunden anlegen und lizenzieren. Tickets von dessen Kunden werden
706→ an den Reseller geroutet, nicht an uns.
707→ </p>
708→ </div>
709→
710→ {/* meta */}
711→ <dl className="mb-3 grid grid-cols-2 gap-2 text-xs">
712→ <MetaItem label="Rabatt" value={`${agency.agencyDiscountPct}%`} />
713→ <MetaItem label="Genehmigt" value={formatDate(agency.agencyApprovedAt)} />
714→ {agency.email && (
715→ <MetaItem label="E-Mail" value={agency.email} full />
716→ )}
717→ {agency.city && <MetaItem label="Stadt" value={agency.city} />}
718→ {agency.website && <MetaItem label="Website" value={agency.website} />}
719→ </dl>
720→
721→ {/* clients list */}
722→ <p className="mb-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
723→ Kunden ({agency.agencyClients.length})
724→ </p>
725→ {agency.agencyClients.length === 0 ? (
726→ <div className="rounded-md border border-dashed border-border bg-muted/20 px-4 py-8 text-center">
727→ <p className="text-xs text-muted-foreground">
728→ Noch keine Kunden angelegt.
729→ </p>
730→ </div>
731→ ) : (
732→ <ul className="space-y-1">
733→ {agency.agencyClients.map((c) => (
734→ <li
735→ key={c.id}
736→ className="flex items-center gap-3 rounded-md border border-border bg-background px-3 py-2"
737→ >
738→ <div className="flex size-7 shrink-0 items-center justify-center rounded-full bg-muted text-[10px] font-semibold">
739→ {c.name.slice(0, 2).toUpperCase()}
740→ </div>
741→ <div className="min-w-0 flex-1">
742→ <p className="truncate text-xs font-medium">{c.name}</p>
743→ {c.email && (
744→ <p className="truncate text-[10px] text-muted-foreground">{c.email}</p>
745→ )}
746→ </div>
747→ </li>
748→ ))}
749→ </ul>
750→ )}
751→ </div>
752→ </>
753→ )}
754→ </SheetContent>
755→ </Sheet>
756→ )
757→}
758→
759→function MetaItem({
760→ label,
761→ value,
762→ full,
763→}: {
764→ label: string
765→ value: string
766→ full?: boolean
767→}) {
768→ return (
769→ <div className={cn('min-w-0', full && 'col-span-2')}>
770→ <dt className="text-[10px] uppercase tracking-wide text-muted-foreground">{label}</dt>
771→ <dd className="mt-0.5 truncate text-xs font-medium">{value}</dd>
772→ </div>
773→ )
774→}
775→
776→/* ----------------------------- reviewed (history) ----------------------------- */
777→
778→function ReviewedSection({ applications }: { applications: AgencyApplication[] }) {
779→ const [open, setOpen] = useState(false)
780→
781→ return (
782→ <section className="space-y-2">
783→ <Collapsible open={open} onOpenChange={setOpen}>
784→ <Card className="bg-muted/30">
785→ <CollapsibleTrigger asChild>
786→ <button
787→ type="button"
788→ className="flex w-full items-center justify-between p-3 text-left"
789→ >
790→ <div className="flex items-center gap-2">
791→ <History className="size-3.5 text-muted-foreground" />
792→ <span className="text-xs font-semibold">Verlauf</span>
793→ <Badge variant="secondary" className="text-[10px] tabular-nums">
794→ {applications.length}
795→ </Badge>
796→ </div>
797→ <span className="text-[10px] text-muted-foreground">
798→ {open ? 'ausblenden' : 'einblenden'}
799→ </span>
800→ </button>
801→ </CollapsibleTrigger>
802→
803→ <CollapsibleContent>
804→ {applications.length === 0 ? (
805→ <div className="border-t border-border px-4 py-6 text-center text-xs text-muted-foreground">
806→ Noch keine bewerteten Bewerbungen.
807→ </div>
808→ ) : (
809→ <div className="border-t border-border">
810→ <ul className="divide-y divide-border">
811→ {applications.map((a) => (
812→ <li
813→ key={a.id}
814→ className="flex flex-col gap-1 px-4 py-2.5 sm:flex-row sm:items-center sm:justify-between"
815→ >
816→ <div className="min-w-0 space-y-0.5">
817→ <div className="flex items-center gap-2">
818→ <span className="truncate text-xs font-medium">{a.company.name}</span>
819→ <StatusBadge status={a.status} />
820→ </div>
821→ {a.status === 'rejected' && a.rejectReason && (
822→ <p className="truncate text-[11px] text-muted-foreground">
823→ Grund: {a.rejectReason}
824→ </p>
825→ )}
826→ {a.status === 'approved' && (
827→ <p className="text-[11px] text-muted-foreground">
828→ Rabatt: <span className="tabular-nums">{a.discountPct}%</span>
829→ </p>
830→ )}
831→ </div>
832→ <div className="shrink-0 text-right text-[10px] text-muted-foreground">
833→ {a.reviewedBy && <p>reviewed by {a.reviewedBy}</p>}
834→ {a.reviewedAt && (
835→ <p className="tabular-nums">{formatDateTime(a.reviewedAt)}</p>
836→ )}
837→ </div>
838→ </li>
839→ ))}
840→ </ul>
841→ </div>
842→ )}
843→ </CollapsibleContent>
844→ </Card>
845→ </Collapsible>
846→ </section>
847→ )
848→}
849→
850→function StatusBadge({ status }: { status: 'approved' | 'rejected' | 'pending' }) {
851→ if (status === 'approved') {
852→ return (
853→ <Badge
854→ variant="outline"
855→ className="gap-1 border-foreground/40 text-[10px]"
856→ >
857→ <CheckCircle2 className="size-2.5" />
858→ Genehmigt
859→ </Badge>
860→ )
861→ }
862→ if (status === 'rejected') {
863→ return (
864→ <Badge variant="outline" className="gap-1 text-[10px] text-muted-foreground">
865→ <XCircle className="size-2.5" />
866→ Abgelehnt
867→ </Badge>
868→ )
869→ }
870→ return (
871→ <Badge variant="outline" className="text-[10px] text-muted-foreground">
872→ Offen
873→ </Badge>
874→ )
875→}
876→