import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Archive, ChevronDown, ChevronRight, FileType, Link, PlusCircle, Rss, Star, Tag, Trash2, } from "lucide-react"; import { useTranslation } from "react-i18next"; import type { RuleEngineCondition } from "@karakeep/shared/types/rules"; import { FeedSelector } from "../feeds/FeedSelector"; import { TagAutocomplete } from "../tags/TagAutocomplete"; interface ConditionBuilderProps { value: RuleEngineCondition; onChange: (condition: RuleEngineCondition) => void; level?: number; onRemove?: () => void; } export function ConditionBuilder({ value, onChange, level = 0, onRemove, }: ConditionBuilderProps) { const { t } = useTranslation(); const [isOpen, setIsOpen] = useState(true); const handleTypeChange = (type: RuleEngineCondition["type"]) => { switch (type) { case "urlContains": onChange({ type: "urlContains", str: "" }); break; case "importedFromFeed": onChange({ type: "importedFromFeed", feedId: "" }); break; case "bookmarkTypeIs": onChange({ type: "bookmarkTypeIs", bookmarkType: "link" }); break; case "hasTag": onChange({ type: "hasTag", tagId: "" }); break; case "isFavourited": onChange({ type: "isFavourited" }); break; case "isArchived": onChange({ type: "isArchived" }); break; case "and": onChange({ type: "and", conditions: [] }); break; case "or": onChange({ type: "or", conditions: [] }); break; case "alwaysTrue": onChange({ type: "alwaysTrue" }); break; default: { const _exhaustiveCheck: never = type; return null; } } }; const renderConditionIcon = (type: RuleEngineCondition["type"]) => { switch (type) { case "urlContains": return ; case "importedFromFeed": return ; case "bookmarkTypeIs": return ; case "hasTag": return ; case "isFavourited": return ; case "isArchived": return ; default: return null; } }; const renderConditionFields = () => { switch (value.type) { case "urlContains": return (
onChange({ ...value, str: e.target.value })} placeholder="URL contains..." className="w-full" />
); case "importedFromFeed": return (
onChange({ ...value, feedId: e })} className="w-full" />
); case "bookmarkTypeIs": return (
); case "hasTag": return (
onChange({ type: value.type, tagId: t })} />
); case "and": case "or": return (
{value.conditions.map((condition, index) => ( { const newConditions = [...value.conditions]; newConditions[index] = newCondition; onChange({ ...value, conditions: newConditions }); }} level={level + 1} onRemove={() => { const newConditions = [...value.conditions]; newConditions.splice(index, 1); onChange({ ...value, conditions: newConditions }); }} /> ))}
); default: return null; } }; const ConditionSelector = () => ( ); return ( {value.type === "and" || value.type === "or" ? (
{value.conditions.length} condition {value.conditions.length !== 1 ? "s" : ""}
{onRemove && ( )}
{renderConditionFields()}
) : (
{renderConditionIcon(value.type)}
{onRemove && ( )}
{renderConditionFields()}
)}
); }