geo/frontend/app/(dashboard)/onboarding/Step3Platforms.tsx

208 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Check, ArrowRight, ArrowLeft, Monitor, Info } from "lucide-react";
import { PLATFORMS } from "@/lib/platforms";
interface Step3PlatformsProps {
brandName: string;
competitors: string[];
initialPlatforms?: string[];
onNext: (
platforms: string[],
frequency: "daily" | "weekly" | "monthly",
) => void;
onBack: () => void;
onSkip: () => void;
}
export function Step3Platforms({
brandName: _brandName,
competitors: _competitors,
initialPlatforms,
onNext,
onBack,
onSkip,
}: Step3PlatformsProps) {
// 默认全选所有平台
const allPlatformKeys = PLATFORMS.map((p) => p.key);
const [selectedPlatforms, setSelectedPlatforms] = useState<string[]>(
initialPlatforms || allPlatformKeys,
);
const [frequency, setFrequency] = useState<"daily" | "weekly" | "monthly">(
"weekly",
);
const togglePlatform = (platformKey: string) => {
setSelectedPlatforms((prev) =>
prev.includes(platformKey)
? prev.filter((p) => p !== platformKey)
: [...prev, platformKey],
);
};
const selectAll = () => {
setSelectedPlatforms(allPlatformKeys);
};
const selectNone = () => {
setSelectedPlatforms([]);
};
const handleNext = () => {
if (selectedPlatforms.length === 0) {
return;
}
onNext(selectedPlatforms, frequency);
};
const frequencyOptions = [
{ value: "daily", label: "每日", description: "每天更新数据,最及时" },
{ value: "weekly", label: "每周", description: "每周更新一次,推荐" },
{ value: "monthly", label: "每月", description: "每月更新一次,成本最低" },
] as const;
return (
<div className="flex flex-col items-center justify-center py-8">
<div className="mb-6 text-center">
<div className="mb-4 inline-flex h-16 w-16 items-center justify-center rounded-full bg-purple-50">
<Monitor className="h-8 w-8 text-purple-600" />
</div>
<h2 className="mb-2 text-2xl font-bold"></h2>
<p className="text-muted-foreground">
AI搜索平台
</p>
</div>
<Card className="w-full max-w-2xl">
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle className="text-lg">AI搜索平台</CardTitle>
<div className="flex gap-2">
<Button
type="button"
variant="ghost"
size="sm"
onClick={selectAll}
className="h-7 text-xs"
>
</Button>
<Button
type="button"
variant="ghost"
size="sm"
onClick={selectNone}
className="h-7 text-xs"
>
</Button>
</div>
</div>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
{PLATFORMS.map((platform) => {
const isSelected = selectedPlatforms.includes(platform.key);
return (
<button
key={platform.key}
type="button"
onClick={() => togglePlatform(platform.key)}
className={`flex items-center gap-3 rounded-lg border p-3 text-left transition-all hover:border-primary/50 ${
isSelected
? "border-primary bg-primary/5 ring-1 ring-primary"
: "border-border bg-card"
}`}
>
<div
className={`flex h-5 w-5 shrink-0 items-center justify-center rounded border ${
isSelected
? "border-primary bg-primary text-primary-foreground"
: "border-muted-foreground/30"
}`}
>
{isSelected && <Check className="h-3 w-3" />}
</div>
<span className="font-medium">{platform.label}</span>
</button>
);
})}
</div>
{selectedPlatforms.length === 0 && (
<div className="flex items-center gap-2 rounded-lg bg-amber-50 p-3 text-amber-700">
<Info className="h-4 w-4" />
<span className="text-sm"></span>
</div>
)}
<div className="text-sm text-muted-foreground text-center">
{selectedPlatforms.length}/{PLATFORMS.length}
</div>
</CardContent>
</Card>
{/* 查询频率选择 */}
<Card className="mt-4 w-full max-w-2xl">
<CardHeader className="pb-3">
<CardTitle className="text-lg"></CardTitle>
</CardHeader>
<CardContent>
<div className="grid gap-3 sm:grid-cols-3">
{frequencyOptions.map((option) => (
<button
key={option.value}
type="button"
onClick={() => setFrequency(option.value)}
className={`rounded-lg border p-3 text-left transition-all ${
frequency === option.value
? "border-primary bg-primary/5 ring-1 ring-primary"
: "border-border bg-card hover:border-primary/50"
}`}
>
<div className="font-medium">{option.label}</div>
<div className="text-xs text-muted-foreground mt-1">
{option.description}
</div>
</button>
))}
</div>
</CardContent>
</Card>
<div className="mt-6 flex flex-col gap-3 sm:flex-row">
<Button
type="button"
variant="outline"
onClick={onBack}
className="flex-1"
>
<ArrowLeft className="mr-2 h-4 w-4" />
</Button>
<Button
type="button"
onClick={handleNext}
disabled={selectedPlatforms.length === 0}
className="flex-1"
>
<ArrowRight className="ml-2 h-4 w-4" />
</Button>
</div>
<Button type="button" variant="ghost" onClick={onSkip} className="mt-2">
</Button>
<div className="mt-4 flex items-center gap-2 text-xs text-muted-foreground">
<Info className="h-3 w-3" />
<span>使 + </span>
</div>
</div>
);
}