UI badge cleanup + /chart-of-accounts route + loop skills (#850)
Bundles three separable concerns: - style(ui): badge audit + cleanup across 45 files — real-status chips use Badge variants (raw Tailwind colors dropped), non-status count/type/label chips demoted to muted text, clustered badges consolidated; 20 unused imports removed. - feat(bookkeeping): Kontoplan moved to a dedicated /chart-of-accounts route (nav + command palette wired); /bookkeeping shows the journal list only. - chore(skills): loop-* automation skills + design-scan workflow under .claude/. fix(reports): restored the destructive count badge on blocking errors in the periodisk sammanställning (EC Sales List) — a genuine status cue the audit had wrongly flattened; flagged by the PR reviewer and Swedish compliance bot, now clean. All CI green; compliance bots report no findings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d63d2aecf0
commit
2da9c71eb3
@@ -72,7 +72,7 @@ export default function BankSyncSinceLastVisit() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="inline-flex items-center gap-2 rounded-md border border-success/30 bg-success/5 px-2.5 py-1 text-xs text-success">
|
||||
<div className="inline-flex items-center gap-2 rounded-md border border-border bg-secondary px-2.5 py-1 text-xs text-foreground">
|
||||
<span>
|
||||
{count === 1
|
||||
? t('bank_sync_new_since_last_visit_one')
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { useToast } from '@/components/ui/use-toast'
|
||||
@@ -463,9 +462,9 @@ export default function BulkBookDialog({
|
||||
<FileText className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
|
||||
<span className="text-sm font-medium truncate">{tpl.name}</span>
|
||||
{tpl.is_system && (
|
||||
<Badge variant="outline" className="text-[10px]">
|
||||
<span className="flex-shrink-0 text-[10px] text-muted-foreground">
|
||||
{t('system_badge')}
|
||||
</Badge>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{tpl.description && (
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'
|
||||
import { useToast } from '@/components/ui/use-toast'
|
||||
import { formatCurrency, formatDate } from '@/lib/utils'
|
||||
@@ -316,9 +315,9 @@ export default function QuickReviewDialog({
|
||||
{isCounterpartyTemplate ? t('label_counterparty_template') : template ? t('label_template') : t('label_category')}
|
||||
</label>
|
||||
<div className="mt-1 flex items-center gap-2">
|
||||
<Badge variant="outline" className="text-sm py-1 px-3">
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
{template ? template.name_sv : categoryLabel}
|
||||
</Badge>
|
||||
</span>
|
||||
{onChangeTemplate && !isCounterpartyTemplate && (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -151,10 +151,10 @@ export default function SkattekontoInboxCard({
|
||||
<DataListMeta>
|
||||
<span className="tabular-nums">{formatDate(row.transaktionsdatum)}</span>
|
||||
<DataListMetaSeparator />
|
||||
<Badge variant="outline" className="h-4 gap-1 px-1.5 py-0 text-[10px]">
|
||||
<span className="inline-flex items-center gap-1 text-muted-foreground">
|
||||
<Landmark className="h-3 w-3" />
|
||||
{t('skv_badge')}
|
||||
</Badge>
|
||||
</span>
|
||||
{matchSuggestion && (
|
||||
<>
|
||||
<DataListMetaSeparator />
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useTranslations } from 'next-intl'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Search, ChevronDown, ChevronUp, AlertTriangle, Info, Building2 } from 'lucide-react'
|
||||
import { Search, ChevronDown, ChevronUp, AlertTriangle, Info, Building2, PenLine } from 'lucide-react'
|
||||
import {
|
||||
getCommonTemplates,
|
||||
getAdvancedTemplates,
|
||||
@@ -60,6 +60,12 @@ function getVatLabelKey(template: BookingTemplate): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse charge (omvänd moms) carries the ochre emphasis via the sanctioned
|
||||
// `warning` variant; every other VAT treatment uses the neutral `secondary`.
|
||||
function getVatBadgeVariant(vatTreatment: string | null | undefined): 'secondary' | 'warning' {
|
||||
return vatTreatment === 'reverse_charge' ? 'warning' : 'secondary'
|
||||
}
|
||||
|
||||
function groupTemplates(templates: BookingTemplate[]): Map<TemplateGroup, BookingTemplate[]> {
|
||||
const grouped = new Map<TemplateGroup, BookingTemplate[]>()
|
||||
for (const t of templates) {
|
||||
@@ -117,20 +123,17 @@ function LibraryTemplateCard({ raw, converted, selected, onClick }: LibraryTempl
|
||||
)}
|
||||
{vatLabelKey && (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className={`text-[10px] px-1.5 py-0 ${
|
||||
converted?.vat_treatment === 'reverse_charge'
|
||||
? 'bg-warning/10 text-warning-foreground'
|
||||
: ''
|
||||
}`}
|
||||
variant={getVatBadgeVariant(converted?.vat_treatment)}
|
||||
className="text-[10px] px-1.5 py-0"
|
||||
>
|
||||
{t(vatLabelKey)}
|
||||
</Badge>
|
||||
)}
|
||||
{!converted && (
|
||||
<Badge variant="outline" className="text-[10px] px-1.5 py-0">
|
||||
<span className="inline-flex items-center gap-1 text-[10px] text-muted-foreground">
|
||||
<PenLine className="h-3 w-3" />
|
||||
{t('opens_editor_badge')}
|
||||
</Badge>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -169,18 +172,14 @@ function TemplateCard({ template, selected, onClick, compact }: TemplateCardProp
|
||||
</span>
|
||||
{vatLabelKey && (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className={`text-[10px] px-1.5 py-0 ${
|
||||
template.vat_treatment === 'reverse_charge'
|
||||
? 'bg-warning/10 text-warning-foreground'
|
||||
: ''
|
||||
}`}
|
||||
variant={getVatBadgeVariant(template.vat_treatment)}
|
||||
className="text-[10px] px-1.5 py-0"
|
||||
>
|
||||
{t(vatLabelKey)}
|
||||
</Badge>
|
||||
)}
|
||||
{template.requires_vat_registration_data && (
|
||||
<Badge variant="outline" className="text-[10px] px-1.5 py-0 border-warning/30 text-warning-foreground gap-0.5">
|
||||
<Badge variant="warning" className="text-[10px] px-1.5 py-0 gap-0.5">
|
||||
<AlertTriangle className="h-2.5 w-2.5" />
|
||||
{t('requires_vat_reg')}
|
||||
</Badge>
|
||||
|
||||
@@ -473,13 +473,12 @@ export default function TransactionInboxCard({
|
||||
{transaction.title_edited_at && (
|
||||
<>
|
||||
<DataListMetaSeparator />
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="h-4 px-1.5 py-0 text-[10px]"
|
||||
<span
|
||||
className="text-muted-foreground"
|
||||
title={originalName ? t('original_name_tooltip', { name: originalName }) : undefined}
|
||||
>
|
||||
{t('edited_badge')}
|
||||
</Badge>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{skvCounterpartDate && (
|
||||
|
||||
Reference in New Issue
Block a user