208 lines
6.8 KiB
TypeScript
208 lines
6.8 KiB
TypeScript
"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>
|
||
);
|
||
}
|