refactor(settings): split into tabs (paperclip + 3 stubs)
Extracts Paperclip companies + tag-mappings UI into PaperclipTab component, adds stub tabs for Environment / Tools / Registrations, and replaces the flat page.tsx with a shadcn Tabs layout to make room for Tasks 8-10. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1
web-ui/src/app/settings/_components/environment-tab.tsx
Normal file
1
web-ui/src/app/settings/_components/environment-tab.tsx
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export function EnvironmentTab() { return <div>Environment tab — coming soon</div>; }
|
||||||
225
web-ui/src/app/settings/_components/paperclip-tab.tsx
Normal file
225
web-ui/src/app/settings/_components/paperclip-tab.tsx
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Plus, Trash2, Tags, Building2 } from "lucide-react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import {
|
||||||
|
useTagMappings,
|
||||||
|
usePaperclipCompanies,
|
||||||
|
useAddTagMapping,
|
||||||
|
useDeleteTagMapping,
|
||||||
|
} from "@/lib/api/settings";
|
||||||
|
import { APPEAL_SUBTYPES } from "@/lib/practice-area";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
const TAG_SUGGESTIONS = APPEAL_SUBTYPES.filter((s) => s.value !== "unknown");
|
||||||
|
|
||||||
|
export function PaperclipTab() {
|
||||||
|
const { data: mappings, isPending: loadingMappings } = useTagMappings();
|
||||||
|
const { data: companies, isPending: loadingCompanies } = usePaperclipCompanies();
|
||||||
|
const addMapping = useAddTagMapping();
|
||||||
|
const deleteMapping = useDeleteTagMapping();
|
||||||
|
|
||||||
|
const [tag, setTag] = useState("");
|
||||||
|
const [tagLabel, setTagLabel] = useState("");
|
||||||
|
const [companyId, setCompanyId] = useState("");
|
||||||
|
|
||||||
|
function handleTagInput(value: string) {
|
||||||
|
setTag(value);
|
||||||
|
const match = TAG_SUGGESTIONS.find((s) => s.value === value);
|
||||||
|
if (match) setTagLabel(match.label);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
if (!tag || !companyId) {
|
||||||
|
toast.error("יש לבחור תגית וחברה");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const company = companies?.find((c) => c.id === companyId);
|
||||||
|
addMapping.mutate(
|
||||||
|
{
|
||||||
|
tag,
|
||||||
|
tag_label: tagLabel,
|
||||||
|
company_id: companyId,
|
||||||
|
company_name: company?.name ?? "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success("מיפוי נוסף בהצלחה");
|
||||||
|
setTag("");
|
||||||
|
setTagLabel("");
|
||||||
|
setCompanyId("");
|
||||||
|
},
|
||||||
|
onError: (err) => toast.error(`שגיאה: ${err.message}`),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDelete(id: string, tag: string) {
|
||||||
|
deleteMapping.mutate(id, {
|
||||||
|
onSuccess: () => toast.success(`מיפוי "${tag}" נמחק`),
|
||||||
|
onError: (err) => toast.error(`שגיאה: ${err.message}`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="bg-surface border-rule shadow-sm">
|
||||||
|
<CardContent className="px-6 py-5">
|
||||||
|
<h2 className="text-navy text-lg mb-3 flex items-center gap-2">
|
||||||
|
<Building2 className="w-4 h-4" />
|
||||||
|
חברות ב-Paperclip
|
||||||
|
</h2>
|
||||||
|
{loadingCompanies ? (
|
||||||
|
<Skeleton className="h-12 w-full" />
|
||||||
|
) : !companies?.length ? (
|
||||||
|
<p className="text-ink-muted text-sm">לא נמצאו חברות</p>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-wrap gap-3">
|
||||||
|
{companies.map((c) => (
|
||||||
|
<div
|
||||||
|
key={c.id}
|
||||||
|
className="flex items-center gap-2 rounded-md bg-rule-soft/60 border border-rule px-4 py-2.5"
|
||||||
|
>
|
||||||
|
<span className="text-sm font-medium text-ink">{c.name}</span>
|
||||||
|
<Badge variant="outline" className="text-[0.7rem] tabular-nums">
|
||||||
|
{c.prefix}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="bg-surface border-rule shadow-sm">
|
||||||
|
<CardContent className="px-6 py-5">
|
||||||
|
<h2 className="text-navy text-lg mb-4 flex items-center gap-2">
|
||||||
|
<Tags className="w-4 h-4" />
|
||||||
|
מיפוי תגיות
|
||||||
|
<Badge variant="outline" className="text-[0.7rem] tabular-nums">
|
||||||
|
{mappings?.length ?? 0}
|
||||||
|
</Badge>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap items-end gap-3 mb-5 p-4 rounded-md bg-rule-soft/40 border border-rule">
|
||||||
|
<div className="flex flex-col gap-1.5 min-w-[180px]">
|
||||||
|
<label className="text-[0.72rem] text-ink-muted">תגית</label>
|
||||||
|
<Input
|
||||||
|
list="tag-suggestions"
|
||||||
|
value={tag}
|
||||||
|
onChange={(e) => handleTagInput(e.target.value)}
|
||||||
|
placeholder="סוג ערר או תגית חופשית"
|
||||||
|
className="w-[220px]"
|
||||||
|
/>
|
||||||
|
<datalist id="tag-suggestions">
|
||||||
|
{TAG_SUGGESTIONS.map((s) => (
|
||||||
|
<option key={s.value} value={s.value}>
|
||||||
|
{s.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</datalist>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-1.5 min-w-[140px]">
|
||||||
|
<label className="text-[0.72rem] text-ink-muted">תווית</label>
|
||||||
|
<Input
|
||||||
|
value={tagLabel}
|
||||||
|
onChange={(e) => setTagLabel(e.target.value)}
|
||||||
|
placeholder="שם לתצוגה"
|
||||||
|
className="w-[160px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-1.5 min-w-[200px]">
|
||||||
|
<label className="text-[0.72rem] text-ink-muted">
|
||||||
|
חברה ב-Paperclip
|
||||||
|
</label>
|
||||||
|
<Select value={companyId} onValueChange={setCompanyId}>
|
||||||
|
<SelectTrigger className="w-[240px]">
|
||||||
|
<SelectValue placeholder="בחר חברה" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{companies?.map((c) => (
|
||||||
|
<SelectItem key={c.id} value={c.id}>
|
||||||
|
{c.name} ({c.prefix})
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={handleAdd}
|
||||||
|
disabled={addMapping.isPending || !tag || !companyId}
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
<Plus className="w-4 h-4" data-icon="inline-start" />
|
||||||
|
{addMapping.isPending ? "שומר..." : "הוסף מיפוי"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{loadingMappings ? (
|
||||||
|
<Skeleton className="h-32 w-full" />
|
||||||
|
) : !mappings?.length ? (
|
||||||
|
<p className="text-ink-muted text-sm">
|
||||||
|
אין מיפויים. הוסף מיפוי כדי שתיקים חדשים ישויכו אוטומטית
|
||||||
|
לפרויקט בחברה הנכונה.
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-rule text-ink-muted text-[0.72rem] uppercase tracking-wider">
|
||||||
|
<th className="text-start py-2 px-3 font-medium">Tag</th>
|
||||||
|
<th className="text-start py-2 px-3 font-medium">Label</th>
|
||||||
|
<th className="text-start py-2 px-3 font-medium">Company</th>
|
||||||
|
<th className="py-2 px-3 w-12" />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{mappings.map((m) => (
|
||||||
|
<tr
|
||||||
|
key={m.id}
|
||||||
|
className="border-b border-rule/60 hover:bg-rule-soft/40 transition-colors"
|
||||||
|
>
|
||||||
|
<td className="py-2.5 px-3">
|
||||||
|
<Badge variant="outline" className="text-[0.75rem] font-mono">
|
||||||
|
{m.tag}
|
||||||
|
</Badge>
|
||||||
|
</td>
|
||||||
|
<td className="py-2.5 px-3 text-ink">{m.tag_label}</td>
|
||||||
|
<td className="py-2.5 px-3 text-ink">{m.company_name}</td>
|
||||||
|
<td className="py-2.5 px-3">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-xs"
|
||||||
|
onClick={() => handleDelete(m.id, m.tag)}
|
||||||
|
disabled={deleteMapping.isPending}
|
||||||
|
title="מחק מיפוי"
|
||||||
|
>
|
||||||
|
<Trash2 className="w-3.5 h-3.5 text-danger" />
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export function RegistrationsTab() { return <div>Registrations tab — coming soon</div>; }
|
||||||
1
web-ui/src/app/settings/_components/tools-tab.tsx
Normal file
1
web-ui/src/app/settings/_components/tools-tab.tsx
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export function ToolsTab() { return <div>Tools tab — coming soon</div>; }
|
||||||
@@ -1,80 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Plus, Trash2, Tags, Building2 } from "lucide-react";
|
import { Server, Wrench, Plug, Building2 } from "lucide-react";
|
||||||
import { AppShell } from "@/components/app-shell";
|
import { AppShell } from "@/components/app-shell";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { PaperclipTab } from "./_components/paperclip-tab";
|
||||||
import { Button } from "@/components/ui/button";
|
import { EnvironmentTab } from "./_components/environment-tab";
|
||||||
import { Input } from "@/components/ui/input";
|
import { ToolsTab } from "./_components/tools-tab";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { RegistrationsTab } from "./_components/registrations-tab";
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
import {
|
|
||||||
useTagMappings,
|
|
||||||
usePaperclipCompanies,
|
|
||||||
useAddTagMapping,
|
|
||||||
useDeleteTagMapping,
|
|
||||||
} from "@/lib/api/settings";
|
|
||||||
import { APPEAL_SUBTYPES } from "@/lib/practice-area";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
const TAG_SUGGESTIONS = APPEAL_SUBTYPES.filter((s) => s.value !== "unknown");
|
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
const { data: mappings, isPending: loadingMappings } = useTagMappings();
|
|
||||||
const { data: companies, isPending: loadingCompanies } = usePaperclipCompanies();
|
|
||||||
const addMapping = useAddTagMapping();
|
|
||||||
const deleteMapping = useDeleteTagMapping();
|
|
||||||
|
|
||||||
const [tag, setTag] = useState("");
|
|
||||||
const [tagLabel, setTagLabel] = useState("");
|
|
||||||
const [companyId, setCompanyId] = useState("");
|
|
||||||
|
|
||||||
function handleTagInput(value: string) {
|
|
||||||
setTag(value);
|
|
||||||
const match = TAG_SUGGESTIONS.find((s) => s.value === value);
|
|
||||||
if (match) setTagLabel(match.label);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleAdd() {
|
|
||||||
if (!tag || !companyId) {
|
|
||||||
toast.error("יש לבחור תגית וחברה");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const company = companies?.find((c) => c.id === companyId);
|
|
||||||
addMapping.mutate(
|
|
||||||
{
|
|
||||||
tag,
|
|
||||||
tag_label: tagLabel,
|
|
||||||
company_id: companyId,
|
|
||||||
company_name: company?.name ?? "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
onSuccess: () => {
|
|
||||||
toast.success("מיפוי נוסף בהצלחה");
|
|
||||||
setTag("");
|
|
||||||
setTagLabel("");
|
|
||||||
setCompanyId("");
|
|
||||||
},
|
|
||||||
onError: (err) => toast.error(`שגיאה: ${err.message}`),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDelete(id: string, tag: string) {
|
|
||||||
deleteMapping.mutate(id, {
|
|
||||||
onSuccess: () => toast.success(`מיפוי "${tag}" נמחק`),
|
|
||||||
onError: (err) => toast.error(`שגיאה: ${err.message}`),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppShell>
|
<AppShell>
|
||||||
<section className="space-y-6">
|
<section className="space-y-6">
|
||||||
@@ -88,164 +23,37 @@ export default function SettingsPage() {
|
|||||||
</nav>
|
</nav>
|
||||||
<h1 className="text-navy mb-0">הגדרות</h1>
|
<h1 className="text-navy mb-0">הגדרות</h1>
|
||||||
<p className="text-ink-muted text-sm mt-1 max-w-2xl">
|
<p className="text-ink-muted text-sm mt-1 max-w-2xl">
|
||||||
ניהול מיפוי תגיות ערר לחברות ב-Paperclip. כל תיק חדש ישויך
|
תצורת המערכת, MCP server, ו-Paperclip integration.
|
||||||
אוטומטית לפרויקט בחברה הנכונה לפי סוג הערר.
|
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
|
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
|
||||||
|
|
||||||
{/* Companies overview */}
|
<Tabs defaultValue="paperclip" className="space-y-4">
|
||||||
<Card className="bg-surface border-rule shadow-sm">
|
<TabsList>
|
||||||
<CardContent className="px-6 py-5">
|
<TabsTrigger value="paperclip">
|
||||||
<h2 className="text-navy text-lg mb-3 flex items-center gap-2">
|
<Building2 className="w-4 h-4" data-icon="inline-start" />
|
||||||
<Building2 className="w-4 h-4" />
|
Paperclip
|
||||||
חברות ב-Paperclip
|
</TabsTrigger>
|
||||||
</h2>
|
<TabsTrigger value="environment">
|
||||||
{loadingCompanies ? (
|
<Server className="w-4 h-4" data-icon="inline-start" />
|
||||||
<Skeleton className="h-12 w-full" />
|
Environment
|
||||||
) : !companies?.length ? (
|
</TabsTrigger>
|
||||||
<p className="text-ink-muted text-sm">לא נמצאו חברות</p>
|
<TabsTrigger value="tools">
|
||||||
) : (
|
<Wrench className="w-4 h-4" data-icon="inline-start" />
|
||||||
<div className="flex flex-wrap gap-3">
|
Tools
|
||||||
{companies.map((c) => (
|
</TabsTrigger>
|
||||||
<div
|
<TabsTrigger value="registrations">
|
||||||
key={c.id}
|
<Plug className="w-4 h-4" data-icon="inline-start" />
|
||||||
className="flex items-center gap-2 rounded-md bg-rule-soft/60 border border-rule px-4 py-2.5"
|
Registrations
|
||||||
>
|
</TabsTrigger>
|
||||||
<span className="text-sm font-medium text-ink">{c.name}</span>
|
</TabsList>
|
||||||
<Badge variant="outline" className="text-[0.7rem] tabular-nums">
|
|
||||||
{c.prefix}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* Tag mappings */}
|
<TabsContent value="paperclip"><PaperclipTab /></TabsContent>
|
||||||
<Card className="bg-surface border-rule shadow-sm">
|
<TabsContent value="environment"><EnvironmentTab /></TabsContent>
|
||||||
<CardContent className="px-6 py-5">
|
<TabsContent value="tools"><ToolsTab /></TabsContent>
|
||||||
<h2 className="text-navy text-lg mb-4 flex items-center gap-2">
|
<TabsContent value="registrations"><RegistrationsTab /></TabsContent>
|
||||||
<Tags className="w-4 h-4" />
|
</Tabs>
|
||||||
מיפוי תגיות
|
|
||||||
<Badge variant="outline" className="text-[0.7rem] tabular-nums">
|
|
||||||
{mappings?.length ?? 0}
|
|
||||||
</Badge>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{/* Add form */}
|
|
||||||
<div className="flex flex-wrap items-end gap-3 mb-5 p-4 rounded-md bg-rule-soft/40 border border-rule">
|
|
||||||
<div className="flex flex-col gap-1.5 min-w-[180px]">
|
|
||||||
<label className="text-[0.72rem] text-ink-muted">
|
|
||||||
תגית
|
|
||||||
</label>
|
|
||||||
<Input
|
|
||||||
list="tag-suggestions"
|
|
||||||
value={tag}
|
|
||||||
onChange={(e) => handleTagInput(e.target.value)}
|
|
||||||
placeholder="סוג ערר או תגית חופשית"
|
|
||||||
className="w-[220px]"
|
|
||||||
/>
|
|
||||||
<datalist id="tag-suggestions">
|
|
||||||
{TAG_SUGGESTIONS.map((s) => (
|
|
||||||
<option key={s.value} value={s.value}>
|
|
||||||
{s.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</datalist>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-1.5 min-w-[140px]">
|
|
||||||
<label className="text-[0.72rem] text-ink-muted">תווית</label>
|
|
||||||
<Input
|
|
||||||
value={tagLabel}
|
|
||||||
onChange={(e) => setTagLabel(e.target.value)}
|
|
||||||
placeholder="שם לתצוגה"
|
|
||||||
className="w-[160px]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-1.5 min-w-[200px]">
|
|
||||||
<label className="text-[0.72rem] text-ink-muted">
|
|
||||||
חברה ב-Paperclip
|
|
||||||
</label>
|
|
||||||
<Select value={companyId} onValueChange={setCompanyId}>
|
|
||||||
<SelectTrigger className="w-[240px]">
|
|
||||||
<SelectValue placeholder="בחר חברה" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{companies?.map((c) => (
|
|
||||||
<SelectItem key={c.id} value={c.id}>
|
|
||||||
{c.name} ({c.prefix})
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
onClick={handleAdd}
|
|
||||||
disabled={addMapping.isPending || !tag || !companyId}
|
|
||||||
size="default"
|
|
||||||
>
|
|
||||||
<Plus className="w-4 h-4" data-icon="inline-start" />
|
|
||||||
{addMapping.isPending ? "שומר..." : "הוסף מיפוי"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Table */}
|
|
||||||
{loadingMappings ? (
|
|
||||||
<Skeleton className="h-32 w-full" />
|
|
||||||
) : !mappings?.length ? (
|
|
||||||
<p className="text-ink-muted text-sm">
|
|
||||||
אין מיפויים. הוסף מיפוי כדי שתיקים חדשים ישויכו אוטומטית
|
|
||||||
לפרויקט בחברה הנכונה.
|
|
||||||
</p>
|
|
||||||
) : (
|
|
||||||
<div className="overflow-x-auto">
|
|
||||||
<table className="w-full text-sm">
|
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-rule text-ink-muted text-[0.72rem] uppercase tracking-wider">
|
|
||||||
<th className="text-start py-2 px-3 font-medium">Tag</th>
|
|
||||||
<th className="text-start py-2 px-3 font-medium">Label</th>
|
|
||||||
<th className="text-start py-2 px-3 font-medium">Company</th>
|
|
||||||
<th className="py-2 px-3 w-12" />
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{mappings.map((m) => (
|
|
||||||
<tr
|
|
||||||
key={m.id}
|
|
||||||
className="border-b border-rule/60 hover:bg-rule-soft/40 transition-colors"
|
|
||||||
>
|
|
||||||
<td className="py-2.5 px-3">
|
|
||||||
<Badge variant="outline" className="text-[0.75rem] font-mono">
|
|
||||||
{m.tag}
|
|
||||||
</Badge>
|
|
||||||
</td>
|
|
||||||
<td className="py-2.5 px-3 text-ink">{m.tag_label}</td>
|
|
||||||
<td className="py-2.5 px-3 text-ink">{m.company_name}</td>
|
|
||||||
<td className="py-2.5 px-3">
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon-xs"
|
|
||||||
onClick={() => handleDelete(m.id, m.tag)}
|
|
||||||
disabled={deleteMapping.isPending}
|
|
||||||
title="מחק מיפוי"
|
|
||||||
>
|
|
||||||
<Trash2 className="w-3.5 h-3.5 text-danger" />
|
|
||||||
</Button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</section>
|
</section>
|
||||||
</AppShell>
|
</AppShell>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user