feat: Introduce reusable AppLogo component and update project activity timestamp to UTC.
This commit is contained in:
parent
a29f57d119
commit
7a3bb08d48
|
|
@ -11,7 +11,7 @@ import subprocess
|
|||
import json
|
||||
from typing import Dict, Any, List, Optional
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
import asyncio
|
||||
import httpx
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ class CIService:
|
|||
self.db.add(review_record)
|
||||
|
||||
# Update project activity
|
||||
project.latest_pr_activity = datetime.utcnow()
|
||||
project.latest_pr_activity = datetime.now(timezone.utc)
|
||||
await self.db.commit()
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -300,6 +300,9 @@ class CIService:
|
|||
context_used=json.dumps([r.file_path for r in context_results])
|
||||
)
|
||||
self.db.add(review_record)
|
||||
|
||||
# Update project activity
|
||||
project.latest_pr_activity = datetime.now(timezone.utc)
|
||||
await self.db.commit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
import React from 'react';
|
||||
|
||||
/**
|
||||
* AppLogo Component
|
||||
* A professional SVG-based logo representing an AI Code Review Bot.
|
||||
* Supports theme switching and various sizes.
|
||||
*/
|
||||
|
||||
interface AppLogoProps {
|
||||
className?: string;
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
||||
showText?: boolean;
|
||||
collapsed?: boolean;
|
||||
theme?: 'dark' | 'light'; // Optional override
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
const AppLogo: React.FC<AppLogoProps> = ({
|
||||
className = "",
|
||||
size = 'md',
|
||||
showText = true,
|
||||
collapsed = false,
|
||||
subtitle = "AI Code Review Bot"
|
||||
}) => {
|
||||
// Size mapping for both icon and text
|
||||
const sizeMap = {
|
||||
sm: { icon: 'w-6 h-6', text: 'text-lg', sub: 'text-[8px]', gap: 'gap-2' },
|
||||
md: { icon: 'w-10 h-10', text: 'text-xl', sub: 'text-[10px]', gap: 'gap-3' },
|
||||
lg: { icon: 'w-14 h-14', text: 'text-3xl', sub: 'text-sm', gap: 'gap-4' },
|
||||
xl: { icon: 'w-20 h-20', text: 'text-4xl', sub: 'text-base', gap: 'gap-5' },
|
||||
'2xl': { icon: 'w-24 h-24', text: 'text-5xl', sub: 'text-lg', gap: 'gap-6' }
|
||||
};
|
||||
|
||||
const currentSize = sizeMap[size];
|
||||
|
||||
return (
|
||||
<div className={`flex items-center ${currentSize.gap} transition-all duration-300 ${className} ${collapsed ? 'justify-center' : ''}`}>
|
||||
{/* Logo Icon Container */}
|
||||
<div className={`relative flex-shrink-0 ${currentSize.icon} transition-transform duration-300 hover:scale-110 group`}>
|
||||
{/* SVG Logo */}
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-full h-full drop-shadow-[0_0_15px_rgba(255,107,44,0.3)]"
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="logo-grad-primary" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stopColor="hsl(var(--primary))" />
|
||||
<stop offset="100%" stopColor="hsl(var(--primary) / 0.7)" />
|
||||
</linearGradient>
|
||||
<filter id="logo-glow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur stdDeviation="3" result="blur" />
|
||||
<feComposite in="SourceGraphic" in2="blur" operator="over" />
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
{/* Outer Hexagon Frame */}
|
||||
<path
|
||||
d="M50 5 L90 28 L90 72 L50 95 L10 72 L10 28 Z"
|
||||
stroke="url(#logo-grad-primary)"
|
||||
strokeWidth="4"
|
||||
fill="currentColor"
|
||||
className="text-primary/10 transition-colors duration-300"
|
||||
/>
|
||||
|
||||
{/* Circuit Like Lines */}
|
||||
<path
|
||||
d="M30 15 L50 5 L70 15"
|
||||
stroke="url(#logo-grad-primary)"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeOpacity="0.5"
|
||||
/>
|
||||
<path
|
||||
d="M30 85 L50 95 L70 85"
|
||||
stroke="url(#logo-grad-primary)"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeOpacity="0.5"
|
||||
/>
|
||||
|
||||
{/* Brackets < > */}
|
||||
<path
|
||||
d="M32 35 L18 50 L32 65"
|
||||
stroke="url(#logo-grad-primary)"
|
||||
strokeWidth="7"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
filter="url(#logo-glow)"
|
||||
className="group-hover:translate-x-[-2px] transition-transform duration-300"
|
||||
/>
|
||||
<path
|
||||
d="M68 35 L82 50 L68 65"
|
||||
stroke="url(#logo-grad-primary)"
|
||||
strokeWidth="7"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
filter="url(#logo-glow)"
|
||||
className="group-hover:translate-x-[2px] transition-transform duration-300"
|
||||
/>
|
||||
|
||||
{/* Central AI Eye Entity */}
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="20"
|
||||
stroke="url(#logo-grad-primary)"
|
||||
strokeWidth="2"
|
||||
fill="var(--cyber-bg-elevated)"
|
||||
className="transition-colors duration-300"
|
||||
/>
|
||||
|
||||
{/* Glowing Core */}
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="12"
|
||||
fill="url(#logo-grad-primary)"
|
||||
className="animate-pulse"
|
||||
filter="url(#logo-glow)"
|
||||
/>
|
||||
|
||||
{/* Lens Highlight */}
|
||||
<circle
|
||||
cx="46"
|
||||
cy="46"
|
||||
r="4"
|
||||
fill="white"
|
||||
fillOpacity="0.8"
|
||||
/>
|
||||
|
||||
{/* Scanline Effect across the icon */}
|
||||
<rect
|
||||
x="15"
|
||||
y="48"
|
||||
width="70"
|
||||
height="4"
|
||||
fill="url(#logo-grad-primary)"
|
||||
fillOpacity="0.2"
|
||||
className="animate-[scan_3s_ease-in-out_infinite]"
|
||||
>
|
||||
<animate
|
||||
attributeName="y"
|
||||
values="25;75;25"
|
||||
dur="3s"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
</rect>
|
||||
</svg>
|
||||
|
||||
{/* Outer Glow for Hover */}
|
||||
<div className="absolute inset-0 bg-primary/20 rounded-xl blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none" />
|
||||
</div>
|
||||
|
||||
{/* Text Section */}
|
||||
{showText && !collapsed && (
|
||||
<div className="flex flex-col transition-all duration-300">
|
||||
<div
|
||||
className={`${currentSize.text} font-bold tracking-wider font-mono leading-tight`}
|
||||
style={{
|
||||
textShadow: '0 0 25px rgba(255,107,44,0.4)',
|
||||
color: 'var(--cyber-text)'
|
||||
}}
|
||||
>
|
||||
<span className="text-primary">DEEP</span>
|
||||
<span>AUDIT</span>
|
||||
</div>
|
||||
<div className={`${currentSize.sub} text-muted-foreground font-mono tracking-[0.2em] uppercase mt-0.5 whitespace-nowrap`}>
|
||||
{subtitle}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppLogo;
|
||||
|
|
@ -26,6 +26,7 @@ import {
|
|||
ExternalLink,
|
||||
GitGraph,
|
||||
} from "lucide-react";
|
||||
import AppLogo from "@/components/common/AppLogo";
|
||||
import routes from "@/app/routes";
|
||||
import { version } from "../../../package.json";
|
||||
|
||||
|
|
@ -123,41 +124,14 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
|
||||
<Link
|
||||
to="/"
|
||||
className={`flex items-center gap-3 group transition-all duration-300 ${collapsed ? 'justify-center' : 'flex-1 min-w-0'}`}
|
||||
className={`flex items-center group transition-all duration-300 ${collapsed ? 'justify-center' : 'flex-1 min-w-0'}`}
|
||||
onClick={() => setMobileOpen(false)}
|
||||
>
|
||||
{/* Logo Icon with enhanced styling */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<div
|
||||
className="w-11 h-11 rounded-xl flex items-center justify-center overflow-hidden transition-all duration-300 group-hover:shadow-[0_0_20px_rgba(255,107,44,0.3)]"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, hsl(var(--primary) / 0.15), hsl(var(--primary) / 0.05))',
|
||||
border: '1px solid hsl(var(--primary) / 0.4)'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src="/logo_deepaudit.png"
|
||||
alt="DeepAudit"
|
||||
className="w-7 h-7 object-contain transition-transform duration-300 group-hover:scale-110"
|
||||
<AppLogo
|
||||
collapsed={collapsed}
|
||||
size="md"
|
||||
subtitle="AI Code Review Bot"
|
||||
/>
|
||||
</div>
|
||||
{/* Glow effect */}
|
||||
<div className="absolute inset-0 bg-primary/30 rounded-xl blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
</div>
|
||||
|
||||
{/* Logo Text with enhanced styling */}
|
||||
<div className={`transition-all duration-300 ${collapsed ? 'w-0 opacity-0 overflow-hidden' : 'flex-1 min-w-0 opacity-100'}`}>
|
||||
<div
|
||||
className="text-xl font-bold tracking-wider font-mono leading-tight"
|
||||
style={{ textShadow: '0 0 25px rgba(255,107,44,0.4)' }}
|
||||
>
|
||||
<span className="text-primary">DEEP</span>
|
||||
<span style={{ color: 'var(--cyber-text)' }}>AUDIT</span>
|
||||
</div>
|
||||
<div className="text-[10px] text-muted-foreground tracking-[0.15em] uppercase mt-0.5">
|
||||
Security Agent
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{/* Collapse button with enhanced styling */}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Square, Download, Play, Loader2, Radio, Cpu, Sparkles } from "lucide-react";
|
||||
import AppLogo from "@/components/common/AppLogo";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { StatusBadge } from "./StatusBadge";
|
||||
import type { HeaderProps } from "../types";
|
||||
|
|
@ -26,28 +27,15 @@ export function Header({
|
|||
|
||||
{/* Left side - Brand and task info */}
|
||||
<div className="flex items-center gap-5 relative z-10">
|
||||
{/* Logo section with enhanced styling */}
|
||||
<div className="flex items-center gap-3 pr-5 border-r border-border/50">
|
||||
<div className="relative group">
|
||||
{/* Logo background glow */}
|
||||
<div className="absolute inset-0 bg-primary/20 rounded-lg blur-lg opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="relative p-2 rounded-lg bg-gradient-to-br from-primary/20 to-primary/5 border border-primary/30">
|
||||
<Cpu className="w-5 h-5 text-primary" />
|
||||
<AppLogo size="sm" subtitle="AI Code Review Bot" />
|
||||
{isRunning && (
|
||||
<>
|
||||
<span className="absolute -top-1 -right-1 w-2.5 h-2.5 bg-emerald-400 rounded-full animate-pulse shadow-[0_0_10px_rgba(52,211,153,0.6)]" />
|
||||
<span className="absolute -top-1 -right-1 w-2.5 h-2.5 bg-emerald-400 rounded-full animate-ping opacity-75" />
|
||||
</>
|
||||
<div className="relative ml-[-12px] mt-[-20px]">
|
||||
<span className="absolute w-2 h-2 bg-emerald-400 rounded-full animate-pulse shadow-[0_0_10px_rgba(52,211,153,0.6)]" />
|
||||
<span className="absolute w-2 h-2 bg-emerald-400 rounded-full animate-ping opacity-75" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-bold text-foreground tracking-wider text-base leading-tight">
|
||||
DEEP<span className="text-primary">AUDIT</span>
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground tracking-[0.2em] uppercase">Security Agent</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Task info with enhanced styling */}
|
||||
{task && (
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { useState, useEffect, useRef, useCallback } from "react";
|
||||
import { Shield, Zap } from "lucide-react";
|
||||
import AppLogo from "@/components/common/AppLogo";
|
||||
|
||||
interface SplashScreenProps {
|
||||
onComplete: () => void;
|
||||
|
|
@ -14,7 +15,7 @@ interface SplashScreenProps {
|
|||
// Enhanced boot sequence messages with icons
|
||||
const BOOT_SEQUENCE = [
|
||||
{ text: "[INIT] Loading DeepAudit Core...", delay: 0, type: 'init' },
|
||||
{ text: "[SCAN] Neural Analysis Engine v3.0", delay: 200, type: 'scan' },
|
||||
{ text: "[SCAN] AI Code Review Engine v3.0", delay: 200, type: 'scan' },
|
||||
{ text: "[LOAD] Vulnerability Pattern Database", delay: 400, type: 'load' },
|
||||
{ text: "[SYNC] Agent Orchestration Module", delay: 600, type: 'sync' },
|
||||
{ text: "[READY] System Online", delay: 800, type: 'ready' },
|
||||
|
|
@ -229,31 +230,9 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
<div className="w-full max-w-2xl">
|
||||
{/* Logo with adaptive styling */}
|
||||
<div className={`text-center mb-10 transition-all duration-1000 ${showLogo ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-8"}`}>
|
||||
{/* Logo text - light mode: clean, dark mode: neon glow */}
|
||||
<div className="logo-glitch relative inline-block">
|
||||
<div
|
||||
className="text-5xl sm:text-6xl md:text-7xl font-bold tracking-wider mb-3 font-mono relative logo-text"
|
||||
>
|
||||
<span className="text-primary">DEEP</span>
|
||||
<span className="text-gray-800 dark:text-white">AUDIT</span>
|
||||
<div className="flex justify-center mb-6">
|
||||
<AppLogo size="xl" subtitle="AI Code Review Bot" />
|
||||
</div>
|
||||
{/* Glitch layers - dark mode only, opacity controlled by CSS */}
|
||||
<div className="glitch-layer glitch-layer-1 text-5xl sm:text-6xl md:text-7xl font-bold tracking-wider font-mono absolute top-0 left-0 w-full opacity-0 dark:opacity-0">
|
||||
<span className="text-cyan-500">DEEP</span>
|
||||
<span className="text-white">AUDIT</span>
|
||||
</div>
|
||||
<div className="glitch-layer glitch-layer-2 text-5xl sm:text-6xl md:text-7xl font-bold tracking-wider font-mono absolute top-0 left-0 w-full opacity-0 dark:opacity-0">
|
||||
<span className="text-red-500">DEEP</span>
|
||||
<span className="text-white">AUDIT</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* Subtitle - adaptive styling */}
|
||||
<div className="flex items-center justify-center gap-3 text-gray-500 dark:text-gray-400 text-sm tracking-[0.3em] uppercase mt-4">
|
||||
<div className="w-12 h-px bg-gradient-to-r from-transparent via-primary/40 dark:via-cyan-500/50 to-transparent" />
|
||||
<Shield className="w-4 h-4 text-primary/70 dark:text-cyan-500/70" />
|
||||
<span className="dark:cyber-text">Autonomous Security Agent</span>
|
||||
<Shield className="w-4 h-4 text-primary/70 dark:text-cyan-500/70" />
|
||||
<div className="w-12 h-px bg-gradient-to-r from-transparent via-primary/40 dark:via-cyan-500/50 to-transparent" />
|
||||
</div>
|
||||
{/* Version tag */}
|
||||
<div className="mt-2 text-[10px] font-mono text-primary/50 tracking-widest">
|
||||
|
|
@ -302,8 +281,7 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
{bootLogs.map((log, i) => (
|
||||
<div
|
||||
key={`boot-${i}`}
|
||||
className={`mb-2 flex items-center gap-2 ${
|
||||
log.includes("[READY]") ? "text-emerald-600 dark:text-emerald-400" :
|
||||
className={`mb-2 flex items-center gap-2 ${log.includes("[READY]") ? "text-emerald-600 dark:text-emerald-400" :
|
||||
log.includes("[INIT]") ? "text-primary" :
|
||||
log.includes("[SCAN]") ? "text-violet-600 dark:text-violet-400" :
|
||||
log.includes("[LOAD]") ? "text-amber-600 dark:text-amber-400" :
|
||||
|
|
@ -317,8 +295,7 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
}}
|
||||
>
|
||||
<span className="text-emerald-600 dark:text-emerald-500/60">$</span>
|
||||
<span className={`w-1.5 h-1.5 rounded-full ${
|
||||
log.includes("[READY]") ? "bg-emerald-500 dark:shadow-[0_0_8px_rgba(52,211,153,0.8)]" :
|
||||
<span className={`w-1.5 h-1.5 rounded-full ${log.includes("[READY]") ? "bg-emerald-500 dark:shadow-[0_0_8px_rgba(52,211,153,0.8)]" :
|
||||
log.includes("[INIT]") ? "bg-primary dark:shadow-[0_0_8px_rgba(255,107,44,0.8)]" :
|
||||
log.includes("[SCAN]") ? "bg-violet-500 dark:shadow-[0_0_8px_rgba(167,139,250,0.8)]" :
|
||||
log.includes("[LOAD]") ? "bg-amber-500 dark:shadow-[0_0_8px_rgba(251,191,36,0.8)]" :
|
||||
|
|
@ -353,8 +330,7 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
<span>{entry.input}</span>
|
||||
</div>
|
||||
{entry.output && (
|
||||
<div className={`ml-4 mt-1 whitespace-pre-wrap text-xs ${
|
||||
entry.isError ? "text-red-400" : "text-muted-foreground"
|
||||
<div className={`ml-4 mt-1 whitespace-pre-wrap text-xs ${entry.isError ? "text-red-400" : "text-muted-foreground"
|
||||
}`}>
|
||||
{entry.output}
|
||||
</div>
|
||||
|
|
@ -381,8 +357,7 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
/>
|
||||
<span className="text-foreground">{currentInput}</span>
|
||||
<span
|
||||
className={`inline-block w-2 h-4 bg-emerald-400 ml-0.5 align-middle transition-opacity ${
|
||||
cursorBlink ? "opacity-100" : "opacity-0"
|
||||
className={`inline-block w-2 h-4 bg-emerald-400 ml-0.5 align-middle transition-opacity ${cursorBlink ? "opacity-100" : "opacity-0"
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -400,7 +375,6 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Cyberpunk Animation Styles */}
|
||||
<style>{`
|
||||
|
|
@ -572,7 +546,7 @@ export function SplashScreen({ onComplete }: SplashScreenProps) {
|
|||
text-shadow: 0 0 10px rgba(52,211,153,0.8), 0 0 20px rgba(52,211,153,0.4);
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -241,6 +241,6 @@ export const DEEPAUDIT_ASCII = `
|
|||
║ | |_| | |___| |___| __/ ___ \\ |_| | |_| | | | | ║
|
||||
║ |____/|_____|_____|_| /_/ \\_\\___/|____/___| |_| ║
|
||||
║ ║
|
||||
║ [ Autonomous Security Agent ] ║
|
||||
║ [ AI Code Review Bot ] ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════╝`;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { Label } from "@/components/ui/label";
|
|||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { toast } from "sonner";
|
||||
import { Lock, Mail, Terminal, Shield, Fingerprint, Cpu } from "lucide-react";
|
||||
import AppLogo from "@/components/common/AppLogo";
|
||||
import { version } from "../../package.json";
|
||||
|
||||
export default function Login() {
|
||||
|
|
@ -143,24 +144,9 @@ export default function Login() {
|
|||
<div className="w-full max-w-md relative z-30 px-4">
|
||||
{/* Logo & Title */}
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center justify-center p-3 cyber-dialog border border-border/60 rounded-lg mb-6"
|
||||
style={{ boxShadow: '0 0 30px rgba(255,107,44,0.1)' }}>
|
||||
<img
|
||||
src="/logo_deepaudit.png"
|
||||
alt="DeepAudit"
|
||||
className="w-14 h-14 object-contain"
|
||||
/>
|
||||
<div className="flex flex-col items-center justify-center mb-6">
|
||||
<AppLogo size="lg" subtitle="AI Code Review Bot" />
|
||||
</div>
|
||||
<div
|
||||
className="text-3xl font-bold tracking-wider mb-2 font-mono"
|
||||
style={{ textShadow: "0 0 30px rgba(255,107,44,0.5), 0 0 60px rgba(255,107,44,0.3)" }}
|
||||
>
|
||||
<span className="text-primary">DEEP</span>
|
||||
<span className="text-foreground">AUDIT</span>
|
||||
</div>
|
||||
<p className="text-base font-mono text-muted-foreground">
|
||||
// Autonomous Security Agent
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Login Form Card */}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { Input } from '@/components/ui/input';
|
|||
import { Label } from '@/components/ui/label';
|
||||
import { toast } from 'sonner';
|
||||
import { User, Mail, Lock, Terminal, Shield, Cpu } from 'lucide-react';
|
||||
import AppLogo from '@/components/common/AppLogo';
|
||||
import { version } from '../../package.json';
|
||||
|
||||
export default function Register() {
|
||||
|
|
@ -112,24 +113,9 @@ export default function Register() {
|
|||
<div className="w-full max-w-md relative z-30 px-4">
|
||||
{/* Logo & Title */}
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center justify-center p-3 cyber-dialog border border-border/60 rounded-lg mb-6"
|
||||
style={{ boxShadow: '0 0 30px rgba(255,107,44,0.1)' }}>
|
||||
<img
|
||||
src="/logo_deepaudit.png"
|
||||
alt="DeepAudit"
|
||||
className="w-14 h-14 object-contain"
|
||||
/>
|
||||
<div className="flex flex-col items-center justify-center mb-6">
|
||||
<AppLogo size="lg" subtitle="Create New Account" />
|
||||
</div>
|
||||
<div
|
||||
className="text-3xl font-bold tracking-wider mb-2 font-mono"
|
||||
style={{ textShadow: "0 0 30px rgba(255,107,44,0.5), 0 0 60px rgba(255,107,44,0.3)" }}
|
||||
>
|
||||
<span className="text-primary">DEEP</span>
|
||||
<span className="text-foreground">AUDIT</span>
|
||||
</div>
|
||||
<p className="text-sm font-mono text-muted-foreground">
|
||||
// Create New Account
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Register Form Card */}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/com
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { GitGraph, ArrowRight, Trash2, Clock } from "lucide-react";
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { formatDistanceToNowStrict } from 'date-fns';
|
||||
import { zhCN } from 'date-fns/locale';
|
||||
|
||||
interface CIProject {
|
||||
|
|
@ -102,7 +102,7 @@ const CIProjects: React.FC = () => {
|
|||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Clock className="w-4 h-4" />
|
||||
<span>
|
||||
Latest: {project.latest_pr_activity ? formatDistanceToNow(new Date(project.latest_pr_activity), { addSuffix: true, locale: zhCN }) : 'Never'}
|
||||
AI 最后回复: {project.latest_pr_activity ? formatDistanceToNowStrict(new Date(project.latest_pr_activity), { addSuffix: true, locale: zhCN }) : '从无回复'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue