{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "contractor-timesheet-approval",
  "title": "Contractor Timesheet Approval",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/contractor-timesheet-approval/ContractorTimesheetApproval.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport {\n  Calendar,\n  Check,\n  CheckCheck,\n  CheckCircle2,\n  Clock,\n  FileSpreadsheet,\n  Globe,\n  RotateCcw,\n  Search,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\nimport TimesheetDetailSheet from './TimesheetDetailSheet.vue'\nimport TimesheetKpiCards from './TimesheetKpiCards.vue'\nimport TimesheetTableRow from './TimesheetTableRow.vue'\nimport type { ApprovalStatus, ContractorSubmission, DailyTimesheetEntry, DeliverableType } from './timesheet-types'\nimport { initialSubmissions } from './timesheet-data'\n\nexport type { ApprovalStatus, ContractorSubmission, DailyTimesheetEntry, DeliverableType }\n\ninterface Props {\n  title?: string\n  subtitle?: string\n  payCycle?: string\n  initialData?: ContractorSubmission[]\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  title: 'Contractor Invoices & Timesheets',\n  subtitle:\n    'Review international contractor hours, verify commit logs & deliverables, and execute multi-currency invoice approvals.',\n  payCycle: 'August 2026 · Bi-Weekly #2',\n  initialData: () => initialSubmissions,\n})\n\nconst submissions = ref<ContractorSubmission[]>(JSON.parse(JSON.stringify(props.initialData)))\nconst searchQuery = ref('')\nconst selectedStatus = ref<'all' | 'pending' | 'approved' | 'disputed'>('all')\nconst currencyDisplay = ref<'both' | 'usd' | 'local'>('both')\nconst selectedContractorId = ref<string | null>(null)\nconst isDrawerOpen = ref(false)\nconst isApprovingAll = ref(false)\nconst bulkApprovalDone = ref(false)\n\nconst pendingSubmissions = computed(() => submissions.value.filter((s) => s.status === 'pending'))\nconst pendingCount = computed(() => pendingSubmissions.value.length)\nconst pendingAmountUsd = computed(() => pendingSubmissions.value.reduce((acc, curr) => acc + curr.grossAmountUsd, 0))\n\nconst approvedSubmissions = computed(() => submissions.value.filter((s) => s.status === 'approved'))\nconst approvedCount = computed(() => approvedSubmissions.value.length)\nconst approvedAmountUsd = computed(() => approvedSubmissions.value.reduce((acc, curr) => acc + curr.grossAmountUsd, 0))\n\nconst disputedSubmissions = computed(() => submissions.value.filter((s) => s.status === 'disputed'))\nconst disputedCount = computed(() => disputedSubmissions.value.length)\n\nconst totalHoursLogged = computed(() => submissions.value.reduce((acc, curr) => acc + curr.hoursLogged, 0))\n\nconst scheduledPayoutsTotal = computed(() => 42800.0)\n\nconst filteredSubmissions = computed(() => {\n  return submissions.value.filter((item) => {\n    const matchesStatus = selectedStatus.value === 'all' ? true : item.status === selectedStatus.value\n    const query = searchQuery.value.trim().toLowerCase()\n    if (!query) return matchesStatus\n\n    const matchesSearch =\n      item.name.toLowerCase().includes(query) ||\n      item.role.toLowerCase().includes(query) ||\n      item.country.toLowerCase().includes(query) ||\n      item.city.toLowerCase().includes(query) ||\n      item.invoiceNumber.toLowerCase().includes(query) ||\n      item.verificationBadge.label.toLowerCase().includes(query)\n\n    return matchesStatus && matchesSearch\n  })\n})\n\nconst selectedContractor = computed(() => submissions.value.find((c) => c.id === selectedContractorId.value))\n\nfunction formatUsd(val: number): string {\n  return new Intl.NumberFormat('en-US', {\n    style: 'currency',\n    currency: 'USD',\n    minimumFractionDigits: 2,\n    maximumFractionDigits: 2,\n  }).format(val)\n}\n\nfunction formatLocal(val: number, currencyCode: string, currencySymbol: string): string {\n  if (currencyCode === 'JPY') {\n    return `${currencySymbol}${new Intl.NumberFormat('ja-JP').format(val)}`\n  }\n  return `${currencySymbol}${new Intl.NumberFormat('en-US', {\n    minimumFractionDigits: 2,\n    maximumFractionDigits: 2,\n  }).format(val)} ${currencyCode}`\n}\n\nfunction openDrawer(contractor: ContractorSubmission) {\n  selectedContractorId.value = contractor.id\n  isDrawerOpen.value = true\n}\n\nfunction approveInvoice(id: string) {\n  const index = submissions.value.findIndex((s) => s.id === id)\n  if (index !== -1) {\n    submissions.value[index].status = 'approved'\n  }\n}\n\nfunction disputeInvoice(id: string) {\n  const index = submissions.value.findIndex((s) => s.id === id)\n  if (index !== -1) {\n    submissions.value[index].status = 'disputed'\n  }\n}\n\nfunction handleApproveDrawer() {\n  if (selectedContractorId.value) approveInvoice(selectedContractorId.value)\n  isDrawerOpen.value = false\n}\n\nfunction handleDisputeDrawer() {\n  if (selectedContractorId.value) disputeInvoice(selectedContractorId.value)\n  isDrawerOpen.value = false\n}\n\nfunction approveAllPending() {\n  if (pendingCount.value === 0) return\n  isApprovingAll.value = true\n  setTimeout(() => {\n    submissions.value.forEach((s) => {\n      if (s.status === 'pending') {\n        s.status = 'approved'\n      }\n    })\n    isApprovingAll.value = false\n    bulkApprovalDone.value = true\n    setTimeout(() => {\n      bulkApprovalDone.value = false\n    }, 3000)\n  }, 400)\n}\n\nfunction resetData() {\n  submissions.value = JSON.parse(JSON.stringify(props.initialData))\n  selectedStatus.value = 'all'\n  searchQuery.value = ''\n  bulkApprovalDone.value = false\n}\n</script>\n\n<template>\n  <div data-slot=\"contractor-timesheet-approval\" :class=\"cn('text-foreground w-full space-y-6', props.class)\">\n    <!-- Header Section -->\n    <div class=\"border-border/80 flex flex-col gap-4 border-b pb-6 lg:flex-row lg:items-center lg:justify-between\">\n      <div class=\"space-y-1.5\">\n        <div class=\"flex flex-wrap items-center gap-2\">\n          <Badge variant=\"outline\" class=\"border-border text-muted-foreground text-xs font-medium\">\n            <Globe class=\"text-primary mr-1 size-3\" />\n            Global Workforce · HRMS\n          </Badge>\n          <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n            <Calendar class=\"text-muted-foreground size-3.5\" />\n            <span>Pay Cycle:</span>\n            <span class=\"text-foreground font-semibold\">{{ payCycle }}</span>\n          </div>\n          <Badge\n            v-if=\"pendingCount > 0\"\n            variant=\"outline\"\n            class=\"border-warning/30 bg-warning/10 text-warning text-xs font-medium\"\n          >\n            <span class=\"bg-warning mr-1.5 size-1.5 animate-pulse rounded-full\" />\n            {{ pendingCount }} Invoices Pending Review\n          </Badge>\n          <Badge v-else variant=\"outline\" class=\"border-success/30 bg-success/10 text-success text-xs font-medium\">\n            <CheckCircle2 class=\"text-success mr-1 size-3\" />\n            All Invoices Reviewed\n          </Badge>\n        </div>\n        <h1 class=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl\">\n          {{ title }}\n        </h1>\n        <p class=\"text-muted-foreground max-w-3xl text-sm leading-relaxed\">\n          {{ subtitle }}\n        </p>\n      </div>\n\n      <!-- Action Buttons -->\n      <div class=\"flex flex-wrap items-center gap-2.5 pt-1 lg:pt-0\">\n        <Button\n          variant=\"outline\"\n          size=\"sm\"\n          class=\"border-border hover:bg-muted h-9 gap-1.5 text-xs font-medium shadow-xs\"\n          @click=\"resetData\"\n        >\n          <RotateCcw class=\"text-muted-foreground size-3.5\" />\n          Reset Demo\n        </Button>\n\n        <Button\n          variant=\"default\"\n          size=\"sm\"\n          :disabled=\"pendingCount === 0 || isApprovingAll\"\n          class=\"h-9 gap-2 text-xs font-medium shadow-xs\"\n          @click=\"approveAllPending\"\n        >\n          <template v-if=\"isApprovingAll\">\n            <Clock class=\"size-3.5 animate-spin\" />\n            Processing Batch...\n          </template>\n          <template v-else-if=\"bulkApprovalDone\">\n            <Check class=\"text-success size-3.5\" />\n            Batch Approved!\n          </template>\n          <template v-else>\n            <CheckCheck class=\"size-3.5\" />\n            <span>Approve All Pending ({{ formatUsd(pendingAmountUsd) }})</span>\n          </template>\n        </Button>\n      </div>\n    </div>\n\n    <!-- 4 Billing Overview KPI Cards -->\n    <TimesheetKpiCards\n      :pending-amount-usd=\"pendingAmountUsd\"\n      :pending-count=\"pendingCount\"\n      :total-hours-logged=\"totalHoursLogged\"\n      :scheduled-payouts-total=\"scheduledPayoutsTotal\"\n      :format-usd=\"formatUsd\"\n    />\n\n    <!-- Filter Toolbar -->\n    <Card class=\"border-border bg-card shadow-xs\">\n      <CardContent class=\"p-4\">\n        <div class=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n          <!-- Search input -->\n          <div class=\"relative max-w-md flex-1\">\n            <Search class=\"text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2\" />\n            <input\n              v-model=\"searchQuery\"\n              type=\"text\"\n              placeholder=\"Search contractor, role, country, or PR...\"\n              class=\"border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border py-1.5 pr-3 pl-9 text-xs focus-visible:ring-2 focus-visible:outline-hidden\"\n            />\n          </div>\n\n          <!-- Filter buttons & Currency Toggle -->\n          <div class=\"flex flex-wrap items-center gap-2\">\n            <!-- Status filter tabs -->\n            <div class=\"border-border bg-muted/40 inline-flex rounded-lg border p-0.5 text-xs\">\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2.5 py-1 font-medium transition-colors',\n                    selectedStatus === 'all'\n                      ? 'bg-background text-foreground shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"selectedStatus = 'all'\"\n              >\n                All ({{ submissions.length }})\n              </button>\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2.5 py-1 font-medium transition-colors',\n                    selectedStatus === 'pending'\n                      ? 'bg-background text-warning text-warning shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"selectedStatus = 'pending'\"\n              >\n                Pending ({{ pendingCount }})\n              </button>\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2.5 py-1 font-medium transition-colors',\n                    selectedStatus === 'approved'\n                      ? 'bg-background text-success text-success shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"selectedStatus = 'approved'\"\n              >\n                Approved ({{ approvedCount }})\n              </button>\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2.5 py-1 font-medium transition-colors',\n                    selectedStatus === 'disputed'\n                      ? 'bg-background text-destructive text-destructive shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"selectedStatus = 'disputed'\"\n              >\n                Disputed ({{ disputedCount }})\n              </button>\n            </div>\n\n            <Separator orientation=\"vertical\" class=\"hidden h-6 md:block\" />\n\n            <!-- Currency toggle selector -->\n            <div class=\"border-border bg-muted/40 inline-flex rounded-lg border p-0.5 text-xs\">\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2 py-1 font-medium transition-colors',\n                    currencyDisplay === 'both'\n                      ? 'bg-background text-foreground shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"currencyDisplay = 'both'\"\n              >\n                Dual FX\n              </button>\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2 py-1 font-medium transition-colors',\n                    currencyDisplay === 'usd'\n                      ? 'bg-background text-foreground shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"currencyDisplay = 'usd'\"\n              >\n                USD ($)\n              </button>\n              <button\n                type=\"button\"\n                :class=\"\n                  cn(\n                    'rounded-md px-2 py-1 font-medium transition-colors',\n                    currencyDisplay === 'local'\n                      ? 'bg-background text-foreground shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"currencyDisplay = 'local'\"\n              >\n                Local\n              </button>\n            </div>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Contractor Invoices & Timesheets Table -->\n    <Card class=\"border-border bg-card overflow-hidden shadow-xs\">\n      <div class=\"overflow-x-auto\">\n        <Table>\n          <TableHeader class=\"bg-muted/40\">\n            <TableRow class=\"border-border hover:bg-transparent\">\n              <TableHead class=\"text-muted-foreground min-w-[240px] text-xs font-semibold tracking-wider uppercase\">\n                Contractor & Location\n              </TableHead>\n              <TableHead class=\"text-muted-foreground min-w-[180px] text-xs font-semibold tracking-wider uppercase\">\n                Role & Rate\n              </TableHead>\n              <TableHead class=\"text-muted-foreground min-w-[140px] text-xs font-semibold tracking-wider uppercase\">\n                Hours Logged\n              </TableHead>\n              <TableHead class=\"text-muted-foreground min-w-[200px] text-xs font-semibold tracking-wider uppercase\">\n                Invoice Gross Amount\n              </TableHead>\n              <TableHead class=\"text-muted-foreground min-w-[220px] text-xs font-semibold tracking-wider uppercase\">\n                Timesheet Verification\n              </TableHead>\n              <TableHead class=\"text-muted-foreground min-w-[120px] text-xs font-semibold tracking-wider uppercase\">\n                Status\n              </TableHead>\n              <TableHead\n                class=\"text-muted-foreground min-w-[180px] text-right text-xs font-semibold tracking-wider uppercase\"\n              >\n                Actions\n              </TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            <template v-if=\"filteredSubmissions.length > 0\">\n              <TimesheetTableRow\n                v-for=\"contractor in filteredSubmissions\"\n                :key=\"contractor.id\"\n                :contractor=\"contractor\"\n                :currency-display=\"currencyDisplay\"\n                :format-usd=\"formatUsd\"\n                :format-local=\"formatLocal\"\n                @open-drawer=\"openDrawer\"\n                @approve-invoice=\"approveInvoice\"\n                @dispute-invoice=\"disputeInvoice\"\n              />\n            </template>\n\n            <template v-else>\n              <TableRow>\n                <TableCell colspan=\"7\" class=\"h-36 text-center\">\n                  <div class=\"flex flex-col items-center justify-center gap-1.5\">\n                    <FileSpreadsheet class=\"text-muted-foreground/50 size-8\" />\n                    <p class=\"text-foreground text-sm font-medium\">No invoices match your filter</p>\n                    <p class=\"text-muted-foreground text-xs\">\n                      Try adjusting your search query or switching the status filter tab.\n                    </p>\n                  </div>\n                </TableCell>\n              </TableRow>\n            </template>\n          </TableBody>\n        </Table>\n      </div>\n    </Card>\n\n    <!-- Timesheet Detail Drawer / Slide-Over Component -->\n    <TimesheetDetailSheet\n      :open=\"isDrawerOpen\"\n      :selected-contractor=\"selectedContractor\"\n      :format-usd=\"formatUsd\"\n      :format-local=\"formatLocal\"\n      @update:open=\"isDrawerOpen = $event\"\n      @approve=\"handleApproveDrawer\"\n      @dispute=\"handleDisputeDrawer\"\n    />\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/ContractorTimesheetApproval.vue"
    },
    {
      "path": "packages/registry-vue/blocks/contractor-timesheet-approval/TimesheetDetailSheet.vue",
      "content": "<script setup lang=\"ts\">\nimport { Check, CheckCircle2, FileCheck, FileCode, GitPullRequest, ShieldCheck, XCircle } from 'lucide-vue-next'\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n  Sheet,\n  SheetClose,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n} from '@/components/ui/sheet'\nimport type { ContractorSubmission } from './timesheet-types'\n\ninterface Props {\n  open: boolean\n  selectedContractor: ContractorSubmission | undefined\n  formatUsd: (val: number) => string\n  formatLocal: (val: number, currencyCode: string, currencySymbol: string) => string\n}\n\ndefineProps<Props>()\n\ndefineEmits<{\n  'update:open': [value: boolean]\n  approve: []\n  dispute: []\n}>()\n</script>\n\n<template>\n  <Sheet :open=\"open\" @update:open=\"$emit('update:open', $event)\">\n    <SheetContent\n      side=\"right\"\n      class=\"bg-background text-foreground flex w-full flex-col overflow-y-auto p-0 sm:max-w-xl md:max-w-2xl\"\n    >\n      <template v-if=\"selectedContractor\">\n        <!-- Drawer Header -->\n        <SheetHeader class=\"border-border/80 space-y-3 border-b px-6 py-5 text-left\">\n          <div class=\"flex items-start justify-between gap-4\">\n            <div class=\"flex items-center gap-3\">\n              <Avatar class=\"border-border size-12 border\">\n                <AvatarFallback class=\"bg-primary/10 text-primary text-sm font-bold\">\n                  {{ selectedContractor.initials }}\n                </AvatarFallback>\n              </Avatar>\n              <div>\n                <div class=\"flex items-center gap-2\">\n                  <SheetTitle class=\"text-foreground text-lg font-bold\">\n                    {{ selectedContractor.name }}\n                  </SheetTitle>\n                  <span class=\"text-base\" :title=\"selectedContractor.country\">\n                    {{ selectedContractor.flag }}\n                  </span>\n                </div>\n                <SheetDescription class=\"text-muted-foreground text-xs\">\n                  {{ selectedContractor.role }} · {{ selectedContractor.city }}\n                </SheetDescription>\n              </div>\n            </div>\n\n            <!-- Status Badge in Header -->\n            <Badge\n              v-if=\"selectedContractor.status === 'pending'\"\n              variant=\"outline\"\n              class=\"border-warning/30 bg-warning/10 text-warning shrink-0 text-xs font-medium\"\n            >\n              <span class=\"bg-warning mr-1.5 size-1.5 rounded-full\" />\n              Pending Review\n            </Badge>\n            <Badge\n              v-else-if=\"selectedContractor.status === 'approved'\"\n              variant=\"outline\"\n              class=\"border-success/30 bg-success/10 text-success shrink-0 text-xs font-medium\"\n            >\n              <Check class=\"text-success mr-1 size-3\" />\n              Approved\n            </Badge>\n            <Badge\n              v-else\n              variant=\"outline\"\n              class=\"border-destructive/30 bg-destructive/10 text-destructive shrink-0 text-xs font-medium\"\n            >\n              <XCircle class=\"text-destructive mr-1 size-3\" />\n              Disputed\n            </Badge>\n          </div>\n\n          <!-- Header Quick Stats Grid -->\n          <div class=\"grid grid-cols-3 gap-2 pt-2 text-xs\">\n            <div class=\"border-border bg-muted/40 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground block\">Invoice Gross</span>\n              <span class=\"text-foreground text-sm font-bold tabular-nums\">\n                {{ formatUsd(selectedContractor.grossAmountUsd) }}\n              </span>\n              <span class=\"text-muted-foreground/70 block text-xs tabular-nums\">\n                {{\n                  formatLocal(\n                    selectedContractor.grossAmountLocal,\n                    selectedContractor.currencyCode,\n                    selectedContractor.currencySymbol,\n                  )\n                }}\n              </span>\n            </div>\n            <div class=\"border-border bg-muted/40 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground block\">Total Hours</span>\n              <span class=\"text-foreground text-sm font-bold tabular-nums\">\n                {{ selectedContractor.hoursLogged.toFixed(1) }} hrs\n              </span>\n              <span class=\"text-success text-success block text-xs font-medium tabular-nums\">\n                {{ selectedContractor.regularHours.toFixed(0) }}h reg ·\n                {{ selectedContractor.overtimeHours.toFixed(0) }}h ot\n              </span>\n            </div>\n            <div class=\"border-border bg-muted/40 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground block\">Contract Rate</span>\n              <span class=\"text-foreground text-sm font-bold tabular-nums\">\n                {{ formatUsd(selectedContractor.hourlyRateUsd) }}/hr\n              </span>\n              <span class=\"text-muted-foreground/70 block truncate text-xs\">\n                {{ selectedContractor.taxCompliance.jurisdiction }}\n              </span>\n            </div>\n          </div>\n        </SheetHeader>\n\n        <!-- Drawer Body: Timesheet Breakdown -->\n        <div class=\"flex-1 space-y-6 overflow-y-auto px-6 py-5\">\n          <!-- Verification Callout Banner -->\n          <div\n            class=\"border-success/20 bg-success/10 text-success flex items-start gap-3 rounded-lg border p-3.5 text-xs\"\n          >\n            <ShieldCheck class=\"text-success mt-0.5 size-4 shrink-0\" />\n            <div class=\"space-y-0.5\">\n              <p class=\"text-success font-semibold\">\n                {{ selectedContractor.verificationBadge.label }}\n              </p>\n              <p class=\"text-success leading-normal\">\n                {{ selectedContractor.verificationBadge.subtext }}. Automated hash verification confirmed timestamps\n                match developer activity during the billing window.\n              </p>\n            </div>\n          </div>\n\n          <!-- Daily Task Itemization -->\n          <div class=\"space-y-3\">\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <h2 class=\"text-muted-foreground text-xs font-semibold\">\n                Daily Itemized Activity Log ({{ selectedContractor.dailyEntries.length }} Work Days)\n              </h2>\n              <span class=\"text-muted-foreground font-mono text-xs\">\n                {{ selectedContractor.payPeriod }}\n              </span>\n            </div>\n\n            <div class=\"space-y-2.5\">\n              <div\n                v-for=\"entry in selectedContractor.dailyEntries\"\n                :key=\"entry.id\"\n                class=\"border-border bg-card hover:border-border/80 space-y-2 rounded-lg border p-3.5 transition-colors\"\n              >\n                <div class=\"flex items-center justify-between gap-x-2\">\n                  <div class=\"flex items-center gap-2\">\n                    <span class=\"text-foreground text-xs font-semibold\">{{ entry.day }}</span>\n                    <Badge variant=\"outline\" class=\"border-border text-muted-foreground h-4 py-0 text-xs\">\n                      {{ entry.date }}\n                    </Badge>\n                  </div>\n                  <div class=\"flex items-center gap-2\">\n                    <span class=\"text-foreground text-xs font-bold tabular-nums\">\n                      {{ entry.hours.toFixed(1) }} hrs\n                    </span>\n                    <span class=\"text-muted-foreground text-xs tabular-nums\">\n                      ({{ formatUsd(entry.hours * selectedContractor.hourlyRateUsd) }})\n                    </span>\n                  </div>\n                </div>\n\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  {{ entry.task }}\n                </p>\n\n                <!-- Linked Deliverables (PR / Commit / Figma / CI) -->\n                <div class=\"flex flex-wrap items-center gap-2 pt-1\">\n                  <div\n                    class=\"border-border bg-muted/50 text-foreground inline-flex items-center gap-1.5 rounded-md border px-2 py-0.5 font-mono text-xs\"\n                  >\n                    <template v-if=\"entry.deliverableType === 'github_pr'\">\n                      <GitPullRequest class=\"text-chart-1 size-3\" />\n                      <span>{{ entry.referenceId }}</span>\n                      <span class=\"text-muted-foreground\">({{ entry.referenceLabel }})</span>\n                      <span v-if=\"entry.commitCount\" class=\"text-muted-foreground\"\n                        >· {{ entry.commitCount }} commits</span\n                      >\n                    </template>\n                    <template v-else-if=\"entry.deliverableType === 'figma'\">\n                      <FileCode class=\"text-chart-2 size-3\" />\n                      <span>{{ entry.referenceId }}</span>\n                      <span class=\"text-muted-foreground\">({{ entry.referenceLabel }})</span>\n                    </template>\n                    <template v-else>\n                      <CheckCircle2 class=\"text-success size-3\" />\n                      <span>{{ entry.referenceId }}</span>\n                      <span class=\"text-muted-foreground\">({{ entry.referenceLabel }})</span>\n                    </template>\n                  </div>\n\n                  <Badge variant=\"outline\" class=\"border-success/20 bg-success/10 text-success h-5 gap-1 py-0 text-xs\">\n                    <Check class=\"size-2.5\" />\n                    Verified\n                  </Badge>\n                </div>\n              </div>\n            </div>\n          </div>\n\n          <!-- Tax & Bank Payout Compliance Box -->\n          <div class=\"border-border bg-muted/20 space-y-2.5 rounded-lg border p-4 text-xs\">\n            <h3 class=\"text-foreground flex items-center gap-1.5 font-bold\">\n              <FileCheck class=\"text-primary size-3.5\" />\n              Compliance & Disbursement Routing\n            </h3>\n            <div class=\"grid grid-cols-2 gap-3 pt-1\">\n              <div>\n                <span class=\"text-muted-foreground block\">Tax Form Status:</span>\n                <span class=\"text-foreground font-medium\">\n                  Form W-8BEN ({{ selectedContractor.taxCompliance.w8benStatus.toUpperCase() }})\n                </span>\n                <span class=\"text-muted-foreground block font-mono text-xs\">{{\n                  selectedContractor.taxCompliance.taxIdMasked\n                }}</span>\n              </div>\n              <div>\n                <span class=\"text-muted-foreground block\">Disbursement Route:</span>\n                <span class=\"text-foreground font-medium\"> {{ selectedContractor.paymentMethod.type }} Payout </span>\n                <span class=\"text-muted-foreground block text-xs\">{{ selectedContractor.paymentMethod.bankName }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Drawer Footer Actions -->\n        <SheetFooter\n          class=\"border-border/80 bg-muted/20 flex flex-row items-center justify-between gap-3 border-t px-6 py-4\"\n        >\n          <SheetClose as-child>\n            <Button variant=\"outline\" size=\"sm\" class=\"text-xs\"> Close </Button>\n          </SheetClose>\n\n          <div class=\"flex items-center gap-2\">\n            <Button\n              v-if=\"selectedContractor.status !== 'disputed'\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"border-destructive/30 text-destructive hover:bg-destructive/10 text-destructive text-xs\"\n              @click=\"$emit('dispute')\"\n            >\n              <XCircle class=\"mr-1.5 size-3.5\" />\n              Dispute Invoice\n            </Button>\n\n            <Button\n              v-if=\"selectedContractor.status !== 'approved'\"\n              variant=\"default\"\n              size=\"sm\"\n              class=\"text-xs shadow-xs\"\n              @click=\"$emit('approve')\"\n            >\n              <Check class=\"mr-1.5 size-3.5\" />\n              Approve ({{ formatUsd(selectedContractor.grossAmountUsd) }})\n            </Button>\n            <span v-else class=\"text-success flex items-center gap-1 text-xs font-semibold\">\n              <CheckCircle2 class=\"size-4\" />\n              Approved & Queued\n            </span>\n          </div>\n        </SheetFooter>\n      </template>\n    </SheetContent>\n  </Sheet>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/TimesheetDetailSheet.vue"
    },
    {
      "path": "packages/registry-vue/blocks/contractor-timesheet-approval/TimesheetKpiCards.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { Clock, ShieldCheck, Timer, Users } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\n\ninterface Props {\n  pendingAmountUsd: number\n  pendingCount: number\n  totalHoursLogged: number\n  scheduledPayoutsTotal: number\n  formatUsd: (val: number) => string\n  class?: HTMLAttributes['class']\n}\n\ndefineProps<Props>()\n</script>\n\n<template>\n  <div :class=\"cn('grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4', $props.class)\">\n    <!-- Card 1: Pending Approval Amount -->\n    <Card class=\"border-border bg-card shadow-xs transition-colors\">\n      <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n        <CardTitle class=\"text-muted-foreground text-xs font-medium\"> Pending Approval Amount </CardTitle>\n        <div\n          class=\"border-warning/20 bg-warning/10 text-warning flex size-8 items-center justify-center rounded-lg border\"\n        >\n          <Clock class=\"size-4\" />\n        </div>\n      </CardHeader>\n      <CardContent class=\"space-y-1\">\n        <div class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">\n          {{ formatUsd(pendingAmountUsd) }}\n        </div>\n        <p class=\"text-muted-foreground text-xs\">\n          <span class=\"text-warning text-warning font-semibold tabular-nums\"> {{ pendingCount }} invoices </span>\n          awaiting your approval\n        </p>\n        <div class=\"pt-2\">\n          <span\n            class=\"bg-muted text-muted-foreground inline-flex items-center rounded-md px-2 py-0.5 text-xs tabular-nums\"\n          >\n            £3,800 · ¥810k · R$41k\n          </span>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Card 2: Total Contractor Hours -->\n    <Card class=\"border-border bg-card shadow-xs transition-colors\">\n      <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n        <CardTitle class=\"text-muted-foreground text-xs font-medium\"> Total Contractor Hours </CardTitle>\n        <div class=\"border-info/20 bg-info/10 text-info flex size-8 items-center justify-center rounded-lg border\">\n          <Timer class=\"size-4\" />\n        </div>\n      </CardHeader>\n      <CardContent class=\"space-y-1\">\n        <div class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">\n          {{ totalHoursLogged.toFixed(1) }} hrs\n        </div>\n        <p class=\"text-muted-foreground text-xs\">\n          <span class=\"text-foreground font-medium tabular-nums\">160.0 regular</span>\n          · 80.0 overtime / project\n        </p>\n        <div class=\"pt-2\">\n          <span class=\"bg-info/10 text-info inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium\">\n            100% Timesheets submitted\n          </span>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Card 3: Approved & Scheduled Payouts -->\n    <Card class=\"border-border bg-card shadow-xs transition-colors\">\n      <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n        <CardTitle class=\"text-muted-foreground text-xs font-medium\"> Approved & Scheduled </CardTitle>\n        <div\n          class=\"border-success/20 bg-success/10 text-success flex size-8 items-center justify-center rounded-lg border\"\n        >\n          <ShieldCheck class=\"size-4\" />\n        </div>\n      </CardHeader>\n      <CardContent class=\"space-y-1\">\n        <div class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">\n          {{ formatUsd(scheduledPayoutsTotal) }}\n        </div>\n        <p class=\"text-muted-foreground text-xs\">\n          <span class=\"text-success text-success font-medium tabular-nums\"> 5 invoices </span>\n          batched for Aug 25 payout\n        </p>\n        <div class=\"pt-2\">\n          <span class=\"bg-muted text-muted-foreground inline-flex items-center rounded-md px-2 py-0.5 text-xs\">\n            Direct SEPA · ACH · SWIFT\n          </span>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Card 4: Active International Contractors -->\n    <Card class=\"border-border bg-card shadow-xs transition-colors\">\n      <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n        <CardTitle class=\"text-muted-foreground text-xs font-medium\"> Active Contractors </CardTitle>\n        <div\n          class=\"border-chart-1/20 bg-chart-1/10 text-chart-1 flex size-8 items-center justify-center rounded-lg border\"\n        >\n          <Users class=\"size-4\" />\n        </div>\n      </CardHeader>\n      <CardContent class=\"space-y-1\">\n        <div class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">8 Contractors</div>\n        <p class=\"text-muted-foreground text-xs\">Across 5 countries (UK, JP, BR, FR, CA)</p>\n        <div class=\"pt-2\">\n          <span class=\"bg-chart-1/10 text-chart-1 inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium\">\n            100% W-8BEN Tax Valid\n          </span>\n        </div>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/TimesheetKpiCards.vue"
    },
    {
      "path": "packages/registry-vue/blocks/contractor-timesheet-approval/TimesheetTableRow.vue",
      "content": "<script setup lang=\"ts\">\nimport {\n  AlertCircle,\n  Check,\n  CheckCircle2,\n  Download,\n  Eye,\n  FileText,\n  MoreHorizontal,\n  ShieldCheck,\n  XCircle,\n} from 'lucide-vue-next'\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { TableCell, TableRow } from '@/components/ui/table'\nimport type { ContractorSubmission } from './timesheet-types'\n\ninterface Props {\n  contractor: ContractorSubmission\n  currencyDisplay: 'both' | 'usd' | 'local'\n  formatUsd: (val: number) => string\n  formatLocal: (val: number, currencyCode: string, currencySymbol: string) => string\n}\n\ndefineProps<Props>()\n\nconst emit = defineEmits<{\n  openDrawer: [contractor: ContractorSubmission]\n  approveInvoice: [id: string]\n  disputeInvoice: [id: string]\n}>()\n</script>\n\n<template>\n  <TableRow class=\"border-border hover:bg-muted/30 transition-colors\">\n    <!-- Contractor & Location -->\n    <TableCell class=\"py-4\">\n      <div class=\"flex items-center gap-3\">\n        <Avatar class=\"border-border size-10 shrink-0 border\">\n          <AvatarFallback class=\"bg-primary/10 text-primary text-xs font-semibold\">\n            {{ contractor.initials }}\n          </AvatarFallback>\n        </Avatar>\n        <div class=\"space-y-0.5\">\n          <div class=\"flex items-center gap-1.5\">\n            <button\n              type=\"button\"\n              class=\"text-foreground focus-visible:ring-ring cursor-pointer rounded-xs text-left text-sm font-semibold hover:underline focus-visible:ring-2 focus-visible:outline-none\"\n              @click=\"emit('openDrawer', contractor)\"\n            >\n              {{ contractor.name }}\n            </button>\n            <span class=\"text-sm\" :title=\"contractor.country\">{{ contractor.flag }}</span>\n          </div>\n          <p class=\"text-muted-foreground flex items-center gap-1 text-xs\">\n            <span>{{ contractor.city }}</span>\n            <span>•</span>\n            <span class=\"text-muted-foreground/80 font-mono\">{{ contractor.invoiceNumber }}</span>\n          </p>\n        </div>\n      </div>\n    </TableCell>\n\n    <!-- Role & Rate -->\n    <TableCell class=\"py-4\">\n      <div class=\"space-y-0.5\">\n        <p class=\"text-foreground text-xs font-medium\">{{ contractor.role }}</p>\n        <p class=\"text-muted-foreground text-xs tabular-nums\">\n          {{ formatUsd(contractor.hourlyRateUsd) }}/hr\n          <span class=\"text-muted-foreground/70\">\n            ({{ formatLocal(contractor.hourlyRateLocal, contractor.currencyCode, contractor.currencySymbol) }}/hr)\n          </span>\n        </p>\n      </div>\n    </TableCell>\n\n    <!-- Hours Logged with daily breakdown expander button -->\n    <TableCell class=\"py-4\">\n      <div class=\"space-y-1\">\n        <div class=\"flex items-center gap-1.5\">\n          <span class=\"text-foreground text-sm font-bold tabular-nums\">\n            {{ contractor.hoursLogged.toFixed(1) }} hrs\n          </span>\n        </div>\n        <div class=\"text-muted-foreground flex items-center gap-1 text-xs tabular-nums\">\n          <span class=\"text-success font-medium\"> {{ contractor.regularHours.toFixed(0) }}h reg </span>\n          <template v-if=\"contractor.overtimeHours > 0\">\n            <span>+</span>\n            <span class=\"text-info font-medium\"> {{ contractor.overtimeHours.toFixed(0) }}h ot </span>\n          </template>\n        </div>\n      </div>\n    </TableCell>\n\n    <!-- Invoice Gross (Local & USD) -->\n    <TableCell class=\"py-4\">\n      <div class=\"space-y-1\">\n        <template v-if=\"currencyDisplay === 'both'\">\n          <div class=\"flex items-baseline gap-1.5\">\n            <span class=\"text-foreground text-sm font-bold tabular-nums\">\n              {{ formatUsd(contractor.grossAmountUsd) }}\n            </span>\n            <span class=\"text-muted-foreground text-xs font-normal\">USD</span>\n          </div>\n          <p class=\"text-muted-foreground text-xs tabular-nums\">\n            {{ formatLocal(contractor.grossAmountLocal, contractor.currencyCode, contractor.currencySymbol) }}\n            <span class=\"text-muted-foreground/60 text-xs\">(FX: {{ contractor.fxRate.toFixed(4) }})</span>\n          </p>\n        </template>\n        <template v-else-if=\"currencyDisplay === 'usd'\">\n          <div class=\"text-foreground text-sm font-bold tabular-nums\">\n            {{ formatUsd(contractor.grossAmountUsd) }} USD\n          </div>\n          <p class=\"text-muted-foreground text-xs tabular-nums\">Rate: {{ formatUsd(contractor.hourlyRateUsd) }}/hr</p>\n        </template>\n        <template v-else>\n          <div class=\"text-foreground text-sm font-bold tabular-nums\">\n            {{ formatLocal(contractor.grossAmountLocal, contractor.currencyCode, contractor.currencySymbol) }}\n          </div>\n          <p class=\"text-muted-foreground text-xs tabular-nums\">Conv: {{ formatUsd(contractor.grossAmountUsd) }} USD</p>\n        </template>\n      </div>\n    </TableCell>\n\n    <!-- Timesheet Verification Status -->\n    <TableCell class=\"py-4\">\n      <div class=\"space-y-1\">\n        <Badge variant=\"outline\" class=\"border-success/25 bg-success/10 text-success gap-1 text-xs font-medium\">\n          <CheckCircle2 class=\"text-success size-3\" />\n          {{ contractor.verificationBadge.label }}\n        </Badge>\n        <p class=\"text-muted-foreground max-w-[200px] truncate text-xs\" :title=\"contractor.verificationBadge.subtext\">\n          {{ contractor.verificationBadge.subtext }}\n        </p>\n      </div>\n    </TableCell>\n\n    <!-- Approval Status -->\n    <TableCell class=\"py-4\">\n      <Badge\n        v-if=\"contractor.status === 'pending'\"\n        variant=\"outline\"\n        class=\"border-warning/30 bg-warning/10 text-warning text-xs font-medium\"\n      >\n        <span class=\"bg-warning mr-1.5 size-1.5 rounded-full\" />\n        Pending Review\n      </Badge>\n      <Badge\n        v-else-if=\"contractor.status === 'approved'\"\n        variant=\"outline\"\n        class=\"border-success/30 bg-success/10 text-success text-xs font-medium\"\n      >\n        <Check class=\"text-success mr-1 size-3\" />\n        Approved\n      </Badge>\n      <Badge\n        v-else\n        variant=\"outline\"\n        class=\"border-destructive/30 bg-destructive/10 text-destructive text-xs font-medium\"\n      >\n        <XCircle class=\"text-destructive mr-1 size-3\" />\n        Disputed\n      </Badge>\n    </TableCell>\n\n    <!-- Action Buttons -->\n    <TableCell class=\"py-4 text-right\">\n      <div class=\"flex items-center justify-end gap-1.5\">\n        <Button\n          variant=\"outline\"\n          size=\"sm\"\n          class=\"border-border hover:bg-muted h-8 gap-1 px-2.5 text-xs font-medium\"\n          @click=\"emit('openDrawer', contractor)\"\n        >\n          <Eye class=\"text-muted-foreground size-3.5\" />\n          Timesheet\n        </Button>\n\n        <template v-if=\"contractor.status === 'pending'\">\n          <Button\n            variant=\"default\"\n            size=\"sm\"\n            class=\"h-8 px-2.5 text-xs font-medium shadow-xs\"\n            @click=\"emit('approveInvoice', contractor.id)\"\n          >\n            <Check class=\"mr-1 size-3.5\" />\n            Approve\n          </Button>\n        </template>\n\n        <!-- Dropdown Menu for Secondary Actions -->\n        <DropdownMenu>\n          <DropdownMenuTrigger as-child>\n            <Button variant=\"ghost\" size=\"icon\" class=\"text-muted-foreground hover:text-foreground size-8\">\n              <MoreHorizontal class=\"size-4\" />\n              <span class=\"sr-only\">Open contractor menu</span>\n            </Button>\n          </DropdownMenuTrigger>\n          <DropdownMenuContent align=\"end\" class=\"w-48\">\n            <DropdownMenuLabel class=\"text-muted-foreground text-xs\">\n              Invoice {{ contractor.invoiceNumber }}\n            </DropdownMenuLabel>\n            <DropdownMenuItem class=\"cursor-pointer text-xs\" @click=\"emit('openDrawer', contractor)\">\n              <FileText class=\"text-muted-foreground mr-2 size-3.5\" />\n              Itemized Timesheet\n            </DropdownMenuItem>\n            <DropdownMenuItem\n              v-if=\"contractor.status !== 'approved'\"\n              class=\"text-success cursor-pointer text-xs\"\n              @click=\"emit('approveInvoice', contractor.id)\"\n            >\n              <Check class=\"mr-2 size-3.5\" />\n              Approve Invoice\n            </DropdownMenuItem>\n            <DropdownMenuItem\n              v-if=\"contractor.status !== 'disputed'\"\n              class=\"text-destructive cursor-pointer text-xs\"\n              @click=\"emit('disputeInvoice', contractor.id)\"\n            >\n              <AlertCircle class=\"mr-2 size-3.5\" />\n              Dispute / Reject\n            </DropdownMenuItem>\n            <DropdownMenuSeparator />\n            <DropdownMenuItem class=\"cursor-pointer text-xs\">\n              <Download class=\"text-muted-foreground mr-2 size-3.5\" />\n              Download Invoice PDF\n            </DropdownMenuItem>\n            <DropdownMenuItem class=\"cursor-pointer text-xs\">\n              <ShieldCheck class=\"text-muted-foreground mr-2 size-3.5\" />\n              View W-8BEN Form\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </div>\n    </TableCell>\n  </TableRow>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/TimesheetTableRow.vue"
    },
    {
      "path": "packages/registry-vue/blocks/contractor-timesheet-approval/timesheet-types.ts",
      "content": "export type ApprovalStatus = 'pending' | 'approved' | 'disputed'\nexport type DeliverableType = 'github_pr' | 'figma' | 'ci_pipeline' | 'code_review'\n\nexport interface DailyTimesheetEntry {\n  id: string\n  date: string\n  day: string\n  hours: number\n  regularHours: number\n  overtimeHours: number\n  task: string\n  deliverableType: DeliverableType\n  referenceId: string\n  referenceLabel: string\n  commitCount?: number\n  verified: boolean\n}\n\nexport interface ContractorSubmission {\n  id: string\n  name: string\n  initials: string\n  avatarUrl?: string\n  role: string\n  country: string\n  countryCode: string\n  flag: string\n  city: string\n  contractType: string\n  hourlyRateUsd: number\n  hourlyRateLocal: number\n  currencyCode: string\n  currencySymbol: string\n  fxRate: number\n  hoursLogged: number\n  regularHours: number\n  overtimeHours: number\n  grossAmountLocal: number\n  grossAmountUsd: number\n  verificationBadge: {\n    label: string\n    subtext: string\n    status: 'verified' | 'manual'\n  }\n  status: ApprovalStatus\n  invoiceNumber: string\n  submittedAt: string\n  payPeriod: string\n  taxCompliance: {\n    w8benStatus: 'valid' | 'pending' | 'exempt'\n    taxIdMasked: string\n    jurisdiction: string\n  }\n  paymentMethod: {\n    type: 'SWIFT' | 'SEPA' | 'Local Wire' | 'ACH'\n    accountMasked: string\n    bankName: string\n  }\n  dailyEntries: DailyTimesheetEntry[]\n}\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/timesheet-types.ts"
    },
    {
      "path": "packages/registry-vue/blocks/contractor-timesheet-approval/timesheet-data.ts",
      "content": "import type { ContractorSubmission } from './timesheet-types'\n\nexport const initialSubmissions: ContractorSubmission[] = [\n  {\n    id: 'ctr-1',\n    name: \"Liam O'Connor\",\n    initials: 'LO',\n    role: 'Senior React Engineer',\n    country: 'United Kingdom',\n    countryCode: 'GB',\n    flag: '🇬🇧',\n    city: 'London, UK',\n    contractType: 'Hourly Contract · $97.00/hr',\n    hourlyRateUsd: 97.0,\n    hourlyRateLocal: 76.0,\n    currencyCode: 'GBP',\n    currencySymbol: '£',\n    fxRate: 1.2763,\n    hoursLogged: 50.0,\n    regularHours: 40.0,\n    overtimeHours: 10.0,\n    grossAmountLocal: 3800.0,\n    grossAmountUsd: 4850.0,\n    verificationBadge: {\n      label: 'Verified with GitHub PRs',\n      subtext: '14 PRs merged · 46 verified commits',\n      status: 'verified',\n    },\n    status: 'pending',\n    invoiceNumber: 'INV-2026-UK-0841',\n    submittedAt: 'Aug 21, 2026 · 17:45 UTC',\n    payPeriod: 'Aug 08 – Aug 21, 2026',\n    taxCompliance: {\n      w8benStatus: 'valid',\n      taxIdMasked: 'GB-UTR ••••••8912',\n      jurisdiction: 'HMRC UK (Non-US Source)',\n    },\n    paymentMethod: {\n      type: 'SWIFT',\n      accountMasked: 'Barclays •••• 4421',\n      bankName: 'Barclays Bank UK PLC',\n    },\n    dailyEntries: [\n      {\n        id: 'entry-1-1',\n        date: '2026-08-17',\n        day: 'Mon, Aug 17',\n        hours: 10.0,\n        regularHours: 8.0,\n        overtimeHours: 2.0,\n        task: 'Refactoring OKLCH Color Engine & AST Parser for sub-theme resolution',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #412',\n        referenceLabel: 'feature/v4-ast-parser',\n        commitCount: 12,\n        verified: true,\n      },\n      {\n        id: 'entry-1-2',\n        date: '2026-08-18',\n        day: 'Tue, Aug 18',\n        hours: 10.0,\n        regularHours: 8.0,\n        overtimeHours: 2.0,\n        task: 'SSR Hydration Mismatch Resolver for cross-framework Island Architectures',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #415',\n        referenceLabel: 'fix/island-hydration',\n        commitCount: 8,\n        verified: true,\n      },\n      {\n        id: 'entry-1-3',\n        date: '2026-08-19',\n        day: 'Wed, Aug 19',\n        hours: 10.0,\n        regularHours: 8.0,\n        overtimeHours: 2.0,\n        task: 'Design token runtime compilation and memoized theme class cache',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #418',\n        referenceLabel: 'perf/token-runtime',\n        commitCount: 7,\n        verified: true,\n      },\n      {\n        id: 'entry-1-4',\n        date: '2026-08-20',\n        day: 'Thu, Aug 20',\n        hours: 10.0,\n        regularHours: 8.0,\n        overtimeHours: 2.0,\n        task: 'Figma token sync GitHub Action workflow optimization and schema tests',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #419',\n        referenceLabel: 'ci/figma-token-sync',\n        commitCount: 9,\n        verified: true,\n      },\n      {\n        id: 'entry-1-5',\n        date: '2026-08-21',\n        day: 'Fri, Aug 21',\n        hours: 10.0,\n        regularHours: 8.0,\n        overtimeHours: 2.0,\n        task: 'Reka UI combobox accessible keyboard navigation bridge and focus ring parity',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #423',\n        referenceLabel: 'feat/reka-combobox-a11y',\n        commitCount: 10,\n        verified: true,\n      },\n    ],\n  },\n  {\n    id: 'ctr-2',\n    name: 'Yuki Tanaka',\n    initials: 'YT',\n    role: 'UI/UX Designer',\n    country: 'Japan',\n    countryCode: 'JP',\n    flag: '🇯🇵',\n    city: 'Tokyo, JP',\n    contractType: 'Hourly Contract · $90.00/hr',\n    hourlyRateUsd: 90.0,\n    hourlyRateLocal: 13500,\n    currencyCode: 'JPY',\n    currencySymbol: '¥',\n    fxRate: 0.00667,\n    hoursLogged: 60.0,\n    regularHours: 40.0,\n    overtimeHours: 20.0,\n    grossAmountLocal: 810000,\n    grossAmountUsd: 5400.0,\n    verificationBadge: {\n      label: 'Figma Files & Handoff Verified',\n      subtext: '8 wireframes & design spec approved',\n      status: 'verified',\n    },\n    status: 'pending',\n    invoiceNumber: 'INV-2026-JP-0219',\n    submittedAt: 'Aug 21, 2026 · 14:10 UTC',\n    payPeriod: 'Aug 08 – Aug 21, 2026',\n    taxCompliance: {\n      w8benStatus: 'valid',\n      taxIdMasked: 'JP-NTA ••••••4401',\n      jurisdiction: 'National Tax Agency Japan',\n    },\n    paymentMethod: {\n      type: 'Local Wire',\n      accountMasked: 'MUFG •••• 9102',\n      bankName: 'Mitsubishi UFJ Financial Group',\n    },\n    dailyEntries: [\n      {\n        id: 'entry-2-1',\n        date: '2026-08-17',\n        day: 'Mon, Aug 17',\n        hours: 12.0,\n        regularHours: 8.0,\n        overtimeHours: 4.0,\n        task: 'Enterprise Multi-currency Invoicing Flow User Journey Map & Edge Cases',\n        deliverableType: 'figma',\n        referenceId: 'Node #492:102',\n        referenceLabel: 'figma.com/@uipkge/multi-currency-flow',\n        commitCount: 6,\n        verified: true,\n      },\n      {\n        id: 'entry-2-2',\n        date: '2026-08-18',\n        day: 'Tue, Aug 18',\n        hours: 12.0,\n        regularHours: 8.0,\n        overtimeHours: 4.0,\n        task: 'Contractor Compliance Document Verification UX Specs & Empty States',\n        deliverableType: 'figma',\n        referenceId: 'Node #495:88',\n        referenceLabel: 'figma.com/@uipkge/compliance-docs',\n        commitCount: 5,\n        verified: true,\n      },\n      {\n        id: 'entry-2-3',\n        date: '2026-08-19',\n        day: 'Wed, Aug 19',\n        hours: 12.0,\n        regularHours: 8.0,\n        overtimeHours: 4.0,\n        task: 'Mobile responsive Timesheet approval breakpoints, drawers, and gesture specs',\n        deliverableType: 'figma',\n        referenceId: 'Node #501:14',\n        referenceLabel: 'figma.com/@uipkge/mobile-timesheet',\n        commitCount: 8,\n        verified: true,\n      },\n      {\n        id: 'entry-2-4',\n        date: '2026-08-20',\n        day: 'Thu, Aug 20',\n        hours: 12.0,\n        regularHours: 8.0,\n        overtimeHours: 4.0,\n        task: 'Interactive Design System Token Library for Dark/Light Themes & High-Contrast',\n        deliverableType: 'figma',\n        referenceId: 'Node #510:33',\n        referenceLabel: 'figma.com/@uipkge/tokens-library',\n        commitCount: 11,\n        verified: true,\n      },\n      {\n        id: 'entry-2-5',\n        date: '2026-08-21',\n        day: 'Fri, Aug 21',\n        hours: 12.0,\n        regularHours: 8.0,\n        overtimeHours: 4.0,\n        task: 'Usability testing session synthesis, prototype refinements, and engineering handoff',\n        deliverableType: 'figma',\n        referenceId: 'Node #514:02',\n        referenceLabel: 'figma.com/@uipkge/handoff-v2',\n        commitCount: 4,\n        verified: true,\n      },\n    ],\n  },\n  {\n    id: 'ctr-3',\n    name: 'Mateo Silva',\n    initials: 'MS',\n    role: 'Go Backend Specialist',\n    country: 'Brazil',\n    countryCode: 'BR',\n    flag: '🇧🇷',\n    city: 'São Paulo, BR',\n    contractType: 'Hourly Contract · $91.11/hr',\n    hourlyRateUsd: 91.11,\n    hourlyRateLocal: 455.55,\n    currencyCode: 'BRL',\n    currencySymbol: 'R$',\n    fxRate: 0.2,\n    hoursLogged: 90.0,\n    regularHours: 40.0,\n    overtimeHours: 50.0,\n    grossAmountLocal: 41000.0,\n    grossAmountUsd: 8200.0,\n    verificationBadge: {\n      label: 'Verified with GitHub PRs',\n      subtext: 'Kafka partitioning & Redis idempotency engine',\n      status: 'verified',\n    },\n    status: 'pending',\n    invoiceNumber: 'INV-2026-BR-0572',\n    submittedAt: 'Aug 21, 2026 · 19:20 UTC',\n    payPeriod: 'Aug 08 – Aug 21, 2026',\n    taxCompliance: {\n      w8benStatus: 'valid',\n      taxIdMasked: 'BR-CNPJ ••••••7100',\n      jurisdiction: 'Receita Federal do Brasil',\n    },\n    paymentMethod: {\n      type: 'SWIFT',\n      accountMasked: 'Itaú Unibanco •••• 8831',\n      bankName: 'Banco Itaú S.A.',\n    },\n    dailyEntries: [\n      {\n        id: 'entry-3-1',\n        date: '2026-08-17',\n        day: 'Mon, Aug 17',\n        hours: 18.0,\n        regularHours: 8.0,\n        overtimeHours: 10.0,\n        task: 'Distributed transaction saga orchestrator for multi-currency payout reconciliation',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #289',\n        referenceLabel: 'feat/saga-orchestrator',\n        commitCount: 15,\n        verified: true,\n      },\n      {\n        id: 'entry-3-2',\n        date: '2026-08-18',\n        day: 'Tue, Aug 18',\n        hours: 18.0,\n        regularHours: 8.0,\n        overtimeHours: 10.0,\n        task: 'Zero-downtime PostgreSQL table partitioning for timesheet audit logs & retention',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #294',\n        referenceLabel: 'db/pg-partitioning',\n        commitCount: 7,\n        verified: true,\n      },\n      {\n        id: 'entry-3-3',\n        date: '2026-08-19',\n        day: 'Wed, Aug 19',\n        hours: 18.0,\n        regularHours: 8.0,\n        overtimeHours: 10.0,\n        task: 'Webhook delivery retry backoff with Kafka dead-letter queue & idempotency keys',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #298',\n        referenceLabel: 'feat/kafka-dlq-retries',\n        commitCount: 19,\n        verified: true,\n      },\n      {\n        id: 'entry-3-4',\n        date: '2026-08-20',\n        day: 'Thu, Aug 20',\n        hours: 18.0,\n        regularHours: 8.0,\n        overtimeHours: 10.0,\n        task: 'Prometheus latency metric instrumentation & Grafana alert rules for payment workers',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #302',\n        referenceLabel: 'obs/prometheus-metrics',\n        commitCount: 5,\n        verified: true,\n      },\n      {\n        id: 'entry-3-5',\n        date: '2026-08-21',\n        day: 'Fri, Aug 21',\n        hours: 18.0,\n        regularHours: 8.0,\n        overtimeHours: 10.0,\n        task: 'Payment gateway failover simulation & multi-region load testing at 25k req/s',\n        deliverableType: 'github_pr',\n        referenceId: 'PR #307',\n        referenceLabel: 'test/gateway-failover',\n        commitCount: 12,\n        verified: true,\n      },\n    ],\n  },\n  {\n    id: 'ctr-4',\n    name: 'Chloe Dubois',\n    initials: 'CD',\n    role: 'QA Automation Lead',\n    country: 'France',\n    countryCode: 'FR',\n    flag: '🇫🇷',\n    city: 'Paris, FR',\n    contractType: 'Hourly Contract · $92.00/hr',\n    hourlyRateUsd: 92.0,\n    hourlyRateLocal: 85.0,\n    currencyCode: 'EUR',\n    currencySymbol: '€',\n    fxRate: 1.0824,\n    hoursLogged: 40.0,\n    regularHours: 40.0,\n    overtimeHours: 0.0,\n    grossAmountLocal: 3400.0,\n    grossAmountUsd: 3680.0,\n    verificationBadge: {\n      label: 'Playwright E2E Suites 100% Pass',\n      subtext: 'CI Run #8821 verified · 342 browser tests green',\n      status: 'verified',\n    },\n    status: 'approved',\n    invoiceNumber: 'INV-2026-FR-1108',\n    submittedAt: 'Aug 20, 2026 · 16:30 UTC',\n    payPeriod: 'Aug 08 – Aug 21, 2026',\n    taxCompliance: {\n      w8benStatus: 'valid',\n      taxIdMasked: 'FR-SIRET ••••••3921',\n      jurisdiction: 'DGFiP France (EU VAT Reg)',\n    },\n    paymentMethod: {\n      type: 'SEPA',\n      accountMasked: 'BNP Paribas •••• 5590',\n      bankName: 'BNP Paribas S.A.',\n    },\n    dailyEntries: [\n      {\n        id: 'entry-4-1',\n        date: '2026-08-17',\n        day: 'Mon, Aug 17',\n        hours: 8.0,\n        regularHours: 8.0,\n        overtimeHours: 0.0,\n        task: 'Playwright end-to-end multi-currency payment checkout regression suite',\n        deliverableType: 'ci_pipeline',\n        referenceId: 'CI Run #8812',\n        referenceLabel: 'e2e-checkout-matrix',\n        commitCount: 8,\n        verified: true,\n      },\n      {\n        id: 'entry-4-2',\n        date: '2026-08-18',\n        day: 'Tue, Aug 18',\n        hours: 8.0,\n        regularHours: 8.0,\n        overtimeHours: 0.0,\n        task: 'Visual regression tests for dark mode and high-contrast accessibility across viewports',\n        deliverableType: 'ci_pipeline',\n        referenceId: 'CI Run #8815',\n        referenceLabel: 'visual-regression-a11y',\n        commitCount: 6,\n        verified: true,\n      },\n      {\n        id: 'entry-4-3',\n        date: '2026-08-19',\n        day: 'Wed, Aug 19',\n        hours: 8.0,\n        regularHours: 8.0,\n        overtimeHours: 0.0,\n        task: 'Automated timesheet submission stress testing & concurrent approval race conditions',\n        deliverableType: 'ci_pipeline',\n        referenceId: 'CI Run #8818',\n        referenceLabel: 'load-timesheet-concurrency',\n        commitCount: 14,\n        verified: true,\n      },\n      {\n        id: 'entry-4-4',\n        date: '2026-08-20',\n        day: 'Thu, Aug 20',\n        hours: 8.0,\n        regularHours: 8.0,\n        overtimeHours: 0.0,\n        task: 'Cross-browser matrix testing (Chromium, Firefox, WebKit) on macOS/Linux runners',\n        deliverableType: 'ci_pipeline',\n        referenceId: 'CI Run #8820',\n        referenceLabel: 'cross-browser-ci',\n        commitCount: 4,\n        verified: true,\n      },\n      {\n        id: 'entry-4-5',\n        date: '2026-08-21',\n        day: 'Fri, Aug 21',\n        hours: 8.0,\n        regularHours: 8.0,\n        overtimeHours: 0.0,\n        task: 'CI test sharding optimization reducing full regression duration from 18m to 3m 12s',\n        deliverableType: 'ci_pipeline',\n        referenceId: 'CI Run #8821',\n        referenceLabel: 'ci-sharding-speedup',\n        commitCount: 5,\n        verified: true,\n      },\n    ],\n  },\n]\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/timesheet-data.ts"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/avatar.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/dropdown-menu.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/sheet.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Deel/Remote style international contractor invoice approval, hourly timesheet verification against GitHub PRs & deliverables, multi-currency payout calculation, overview KPI metrics, and itemized daily timesheet slide-over drawer.",
  "categories": [
    "finance",
    "app",
    "billing",
    "productivity"
  ]
}