Makelore 2.0 initial clean snapshot

This commit is contained in:
inman
2026-07-29 17:22:35 +08:00
commit b8ca3f8eea
694 changed files with 139782 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
import { ArrowRight } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import logoSvg from '@/assets/logo.svg';
import { aiModules, type AiModuleId } from '@/lib/ai-modules';
import { getAuthUserDisplayName } from '@/lib/auth-user-display';
import { cn } from '@/lib/utils';
import { useAuthStore } from '@/stores/auth';
const moduleToneClasses: Record<AiModuleId, { icon: string; badge: string }> = {
programming: { icon: 'bg-[#E9EFF5] text-[#3A5578]', badge: 'bg-[#E9EFF5] text-[#3A5578]' },
painting: { icon: 'bg-[#FDE8E1] text-[#F26A3D]', badge: 'bg-[#FDE8E1] text-[#B94624]' },
};
export function ModuleSelection() {
const navigate = useNavigate();
const authUser = useAuthStore((state) => state.user);
const userDisplayName = getAuthUserDisplayName(authUser);
return (
<main data-testid="ai-module-selection-page" className="min-h-[100dvh] overflow-auto bg-white px-4 py-6 text-[#26384D] sm:px-8 sm:py-10">
<div className="mx-auto flex min-h-[calc(100dvh-3rem)] max-w-6xl flex-col">
<header className="flex items-center justify-between gap-4">
<div className="flex items-center gap-3">
<img src={logoSvg} alt="Makelore" className="h-9 w-12 object-contain" />
<div>
<p className="text-sm font-bold tracking-[-0.01em]">Makelore</p>
<p className="text-xs font-medium text-[#68788B]"></p>
</div>
</div>
<span className="rounded-full border border-[#D8E0E8] bg-[#F6F8FA] px-3 py-1 text-xs font-semibold text-[#68788B]">Makelore 2.0</span>
</header>
<div className="grid flex-1 items-center gap-8 py-12 lg:grid-cols-[1fr_1.4fr] lg:gap-16">
<section className="max-w-md">
<p className="text-sm font-semibold tracking-[0.08em] text-[#68788B]">
{userDisplayName ? `${userDisplayName},欢迎回来!` : '欢迎回来!'}
</p>
<h1 className="mt-3 text-4xl font-bold leading-tight tracking-[-0.04em]"></h1>
<p className="mt-4 max-w-sm text-sm leading-6 text-[#68788B]"></p>
</section>
<section aria-label="AI 模块列表" className="grid gap-3">
{aiModules.map((module) => {
const tone = moduleToneClasses[module.id];
const ModuleIcon = module.Icon;
return (
<button
key={module.id}
type="button"
data-testid={`ai-module-option-${module.id}`}
disabled={!module.enabled}
onClick={() => {
if (module.route) navigate(module.route);
}}
className={cn(
'group flex min-h-28 w-full items-center justify-between gap-5 rounded-2xl border border-[#D8E0E8] bg-white p-5 text-left shadow-[0_10px_30px_rgba(38,56,77,0.06)] transition-[border-color,background-color,transform,box-shadow,opacity] hover:-translate-y-0.5 hover:border-[#3A5578] hover:bg-[#FAFBFC] hover:shadow-[0_16px_40px_rgba(38,56,77,0.10)] active:translate-y-0 disabled:cursor-not-allowed disabled:bg-[#EEF3F7] disabled:text-[#8A98A8] disabled:opacity-75',
)}
>
<span className="flex min-w-0 items-center gap-4">
<span className={cn('flex h-14 w-14 shrink-0 items-center justify-center rounded-xl', tone.icon)}>
<ModuleIcon className="h-7 w-7" strokeWidth={2.4} />
</span>
<span className="min-w-0">
<span className="flex flex-wrap items-center gap-2">
<span className="text-xl font-bold tracking-[-0.02em]">{module.title}</span>
<span className={cn('rounded-full px-2.5 py-1 text-[11px] font-semibold', tone.badge)}>{module.subtitle}</span>
</span>
<span className="mt-2 block text-sm font-medium leading-6 text-[#68788B]">{module.description}</span>
</span>
</span>
{module.enabled ? (
<ArrowRight className="h-6 w-6 shrink-0 transition-transform group-hover:translate-x-1" strokeWidth={2.6} />
) : (
<span className="shrink-0 text-xs font-black"></span>
)}
</button>
);
})}
</section>
</div>
</div>
</main>
);
}
export default ModuleSelection;