@fayz-ai/plugin-reports 0.14.2 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/data/aggregate.ts","../src/data/analytics-supabase.ts","../src/data/analytics-mock.ts","../src/lib/tenant.ts","../src/locales/en.ts","../src/locales/pt-BR.ts","../src/locales/index.ts","../src/migrations/index.ts","../src/lib/legacy.ts","../src/lib/lastViewed.ts","../src/lib/preferences.ts","../src/views/AnalyticsSurface.tsx","../src/views/AnalyticsAssistant.tsx","../src/views/AnalyticsModule.tsx","../src/views/AnalyticsOverview.tsx","../src/views/ReportsListPage.tsx","../src/export/csv.ts","../src/components/ExportDropdown.tsx","../src/components/ReportPagination.tsx","../src/views/AnalyticsReportViewer.tsx","../src/views/LiveViewPage.tsx","../src/views/AnalyticsSettingsPage.tsx","../src/lib/engine.ts","../src/data/supabase.ts","../src/data/mock.ts","../src/index.ts"],"names":["db","data","error","React","KEY","read","write","listeners","React2","jsx","useTranslation","jsxs","useState","useEffect","exportToExcel","exportToPdf","page","Fragment","DataTable","Button","AnalyticsControls","ToolbarAction","SubpageHeader","Card","getSupabaseClientOptional","key","camelToSnake","snakeToCamel","mapRow"],"mappings":"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A;AAAA;AAAA;AAAA;;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA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","file":"index.js","sourcesContent":["import type {\n AnalyticsCardDef, AnalyticsGrain, AnalyticsQueryState, AnalyticsResult, AnalyticsRow,\n} from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Client-side aggregation.\n//\n// The SQL engine (analytics_run) is the real one; this exists for the two cases\n// that cannot reach it — the mock provider, and cards whose source is an app\n// function rather than a read model. It deliberately mirrors the SQL semantics\n// step for step, because a card must not change meaning depending on which\n// provider answered it.\n// ---------------------------------------------------------------------------\n\nfunction num(value: unknown): number {\n if (value == null) return 0\n const n = typeof value === 'number' ? value : Number(value)\n return Number.isFinite(n) ? n : 0\n}\n\n/** Truncate a timestamp to the start of its bucket — the JS date_trunc. */\nexport function truncate(value: unknown, grain: AnalyticsGrain): string | null {\n const d = new Date(String(value))\n if (Number.isNaN(d.getTime())) return null\n const out = new Date(d)\n switch (grain) {\n case 'hour': out.setMinutes(0, 0, 0); break\n case 'week': {\n // ISO weeks start Monday; getDay() calls Sunday 0, hence the shift.\n const day = (out.getDay() + 6) % 7\n out.setDate(out.getDate() - day)\n out.setHours(0, 0, 0, 0)\n break\n }\n case 'month': out.setDate(1); out.setHours(0, 0, 0, 0); break\n case 'quarter': out.setMonth(Math.floor(out.getMonth() / 3) * 3, 1); out.setHours(0, 0, 0, 0); break\n case 'year': out.setMonth(0, 1); out.setHours(0, 0, 0, 0); break\n default: out.setHours(0, 0, 0, 0); break\n }\n return out.toISOString()\n}\n\nfunction matchesFilters(row: AnalyticsRow, filters: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(filters)) {\n if (value == null || value === '') continue\n const actual = row[key]\n if (Array.isArray(value)) {\n if (value.length > 0 && !value.map(String).includes(String(actual))) return false\n } else if (String(actual) !== String(value)) {\n return false\n }\n }\n return true\n}\n\nfunction inRange(row: AnalyticsRow, dateColumn: string, from?: string, to?: string): boolean {\n const raw = row[dateColumn]\n if (raw == null) return true\n const t = new Date(String(raw)).getTime()\n if (Number.isNaN(t)) return true\n // `to` is an inclusive DAY, so the window closes at its final millisecond —\n // comparing against midnight would silently drop everything ordered that day.\n if (from && t < new Date(`${from}T00:00:00`).getTime()) return false\n if (to && t > new Date(`${to}T23:59:59.999`).getTime()) return false\n return true\n}\n\n/** Apply one measure over a bucket of rows. 'ratio' is resolved by the UI layer. */\nfunction applyMeasure(rows: AnalyticsRow[], agg: string, column: string): number | null {\n if (agg === 'count') return rows.length\n const values = rows.map((r) => r[column]).filter((v) => v != null)\n if (agg === 'count_distinct') return new Set(values.map(String)).size\n const numbers = values.map(num)\n if (numbers.length === 0) return agg === 'sum' ? 0 : null\n switch (agg) {\n case 'sum': return numbers.reduce((a, b) => a + b, 0)\n case 'avg': return numbers.reduce((a, b) => a + b, 0) / numbers.length\n case 'min': return Math.min(...numbers)\n case 'max': return Math.max(...numbers)\n default: return null\n }\n}\n\nexport interface AggregateOptions {\n /** Skip pagination and return every group (the export path). */\n all?: boolean\n}\n\n/**\n * Group, aggregate, sort and page a row set exactly as analytics_run does.\n * Returns the same {rows, total, summary} envelope so callers cannot tell which\n * engine answered.\n */\nexport function aggregateRows(\n source: AnalyticsRow[],\n card: AnalyticsCardDef,\n state: AnalyticsQueryState,\n options?: AggregateOptions,\n): AnalyticsResult {\n // dateColumn null ⇒ a snapshot: the range must not apply (see AnalyticsQuery).\n const snapshot = card.query.dateColumn === null\n const dateColumn = card.query.dateColumn ?? 'created_at'\n const dimensions = card.query.dimensions ?? []\n const measures = (card.query.measures ?? []).filter((m) => m.agg !== 'ratio')\n\n const filtered = source\n .filter((row) => snapshot || inRange(row, dateColumn, state.dateRange?.from, state.dateRange?.to))\n .filter((row) => matchesFilters(row, state.filters ?? {}))\n\n // The rollup: same rows, same filters, no grouping. Identical to SQL 8.11.\n const summary: Record<string, number> = {}\n for (const m of measures) {\n const value = applyMeasure(filtered, m.agg, m.column ?? m.key)\n summary[m.key] = value ?? 0\n }\n\n // No measures ⇒ a detail listing; the rows pass through untouched.\n if (measures.length === 0 && dimensions.length === 0) {\n const sorted = sortRows(filtered, state.sortBy ?? card.query.defaultSort, state.sortDir ?? card.query.defaultSortDir)\n return { rows: page(sorted, state, options), total: sorted.length, summary }\n }\n\n const buckets = new Map<string, { key: AnalyticsRow; rows: AnalyticsRow[] }>()\n for (const row of filtered) {\n const keyParts: AnalyticsRow = {}\n for (const d of dimensions) {\n const raw = row[d.key]\n keyParts[d.key] = d.grain && d.grain !== 'auto' ? truncate(raw, d.grain) : (raw ?? null)\n }\n const id = JSON.stringify(dimensions.map((d) => keyParts[d.key]))\n const existing = buckets.get(id)\n if (existing) existing.rows.push(row)\n else buckets.set(id, { key: keyParts, rows: [row] })\n }\n\n let grouped: AnalyticsRow[] = [...buckets.values()].map(({ key, rows }) => {\n const out: AnalyticsRow = { ...key }\n for (const m of measures) out[m.key] = applyMeasure(rows, m.agg, m.column ?? m.key)\n return out\n })\n\n grouped = sortRows(grouped, state.sortBy ?? card.query.defaultSort, state.sortDir ?? card.query.defaultSortDir)\n if (card.query.limit) grouped = grouped.slice(0, card.query.limit)\n\n return { rows: page(grouped, state, options), total: grouped.length, summary }\n}\n\nfunction sortRows(rows: AnalyticsRow[], sortBy?: string, dir?: 'asc' | 'desc'): AnalyticsRow[] {\n if (!sortBy) return rows\n const sign = dir === 'asc' ? 1 : -1\n return [...rows].sort((a, b) => {\n const av = a[sortBy]\n const bv = b[sortBy]\n // Nulls sort last in both directions — matching SQL's NULLS LAST, so a\n // never-shipped order does not top a \"fastest fulfillment\" report.\n if (av == null && bv == null) return 0\n if (av == null) return 1\n if (bv == null) return -1\n if (typeof av === 'number' || typeof bv === 'number') return (num(av) - num(bv)) * sign\n return String(av).localeCompare(String(bv)) * sign\n })\n}\n\nfunction page(rows: AnalyticsRow[], state: AnalyticsQueryState, options?: AggregateOptions): AnalyticsRow[] {\n if (options?.all) return rows\n const size = state.pageSize || 50\n const start = ((state.page || 1) - 1) * size\n return rows.slice(start, start + size)\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type {\n AnalyticsBatchRequest, AnalyticsCardDef, AnalyticsProvider, AnalyticsQueryState,\n AnalyticsResult, AnalyticsRow,\n} from '@fayz-ai/core'\nimport { aggregateRows } from './aggregate'\n\n// ---------------------------------------------------------------------------\n// The Supabase analytics provider.\n//\n// Everything a card asks for goes through ONE server function, analytics_run:\n// \"orders over time\" and \"sales by product\" are the same call with different\n// dimensions. That is what removes the per-report SQL that made adding a report\n// a database migration.\n//\n// kind 'view' → analytics_run over a registered read model (the normal path)\n// kind 'rpc' → a bespoke function, for the rare card the generic engine\n// cannot express (escape hatch, not the default)\n// kind 'fn' → an app-supplied async function, aggregated client-side\n// ---------------------------------------------------------------------------\n\nfunction snakeToCamel(s: string): string {\n return s.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())\n}\n\n/**\n * Map DB keys to JS keys. Measure and dimension keys are passed through\n * UNTOUCHED — the card named them, the SQL aliased them to exactly that, and\n * silently camelCasing `net_sales` into `netSales` would make every card whose\n * viz references `net_sales` render blank.\n */\nfunction mapRow(row: AnalyticsRow, reserved: Set<string>, columnMap?: Record<string, string>): AnalyticsRow {\n const out: AnalyticsRow = {}\n for (const [key, value] of Object.entries(row)) {\n if (reserved.has(key)) { out[key] = value; continue }\n out[columnMap?.[key] ?? snakeToCamel(key)] = value\n // Keep the raw key too: column definitions written against the read model's\n // snake_case still resolve, so adopting a card needs no rename pass.\n if (!(key in out)) out[key] = value\n }\n return out\n}\n\nfunction reservedKeys(card: AnalyticsCardDef): Set<string> {\n return new Set([\n ...(card.query.dimensions ?? []).map((d) => d.key),\n ...(card.query.measures ?? []).map((m) => m.key),\n ])\n}\n\n/** Text columns free-text search scans, taken from the card's own columns. */\nfunction searchColumns(card: AnalyticsCardDef): string[] | undefined {\n const cols = (card.columns ?? [])\n // 'person' is a text column with a richer cell — searching a customer list\n // by name has to keep working after the name became a link.\n .filter((c) => c.type === 'text' || c.type === 'email' || c.type === 'person')\n .map((c) => c.key)\n return cols.length ? cols : undefined\n}\n\nfunction camelToSnake(s: string): string {\n return s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`)\n}\n\n/**\n * Direct read of a view — the path every pre-existing ReportDef takes.\n *\n * Ports the semantics of the original report provider verbatim (tenant scope,\n * inclusive date window, equality/IN filters, ILIKE search over text columns,\n * sort, page) so adopting the analytics engine changed no existing report's\n * answer.\n */\nasync function selectFromView(\n card: AnalyticsCardDef,\n state: AnalyticsQueryState,\n db: any,\n tenantId: string | undefined,\n reserved: Set<string>,\n): Promise<AnalyticsResult> {\n const { source } = card.query\n const size = state.pageSize || 50\n let q = db.from(source.name!).select('*', { count: 'exact' })\n\n if (tenantId) q = q.eq(source.tenantColumn ?? 'tenant_id', tenantId)\n\n const snapshot = card.query.dateColumn === null\n const dateCol = card.query.dateColumn ?? 'created_at'\n if (!snapshot && state.dateRange?.from) q = q.gte(dateCol, state.dateRange.from)\n if (!snapshot && state.dateRange?.to) {\n // A timestamp column needs the whole final day; a plain date column does\n // not — appending a time to a `date` would compare against a cast and drop\n // the last day of every range.\n q = q.lte(dateCol, dateCol.endsWith('_at') ? `${state.dateRange.to}T23:59:59.999` : state.dateRange.to)\n }\n\n for (const [key, value] of Object.entries(state.filters ?? {})) {\n if (value == null || value === '') continue\n const col = camelToSnake(key)\n q = Array.isArray(value) ? q.in(col, value) : q.eq(col, value)\n }\n\n const searchable = searchColumns(card)\n if (state.search?.trim() && searchable?.length) {\n const term = `%${state.search.trim()}%`\n q = q.or(searchable.map((c) => `${camelToSnake(c)}.ilike.${term}`).join(','))\n }\n\n const sortBy = state.sortBy ?? card.query.defaultSort\n if (sortBy) {\n q = q.order(camelToSnake(sortBy), {\n ascending: (state.sortDir ?? card.query.defaultSortDir ?? 'desc') === 'asc',\n })\n }\n\n const from = ((state.page || 1) - 1) * size\n const { data, error, count } = await q.range(from, from + size - 1)\n if (error) throw error\n\n return {\n rows: (data ?? []).map((r: AnalyticsRow) => mapRow(r, reserved, source.columnMap)),\n total: count ?? 0,\n }\n}\n\n/**\n * A rejection the card can actually print.\n *\n * PostgREST rejects with a PLAIN OBJECT ({ message, details, hint, code }), not\n * an Error — so `new Error(String(err))` turned every failed card into the words\n * \"[object Object]\" and threw away the one sentence that says what broke.\n */\nfunction toError(err: unknown): Error {\n if (err instanceof Error) return err\n if (err && typeof err === 'object') {\n const e = err as Record<string, unknown>\n const message = [...new Set(\n [e.message, e.details, e.hint].filter(\n (part): part is string => typeof part === 'string' && part.trim().length > 0,\n ),\n )].join(' — ')\n if (message) return Object.assign(new Error(message), e.code ? { code: e.code } : {})\n }\n return new Error(String(err))\n}\n\n/**\n * True when the card is answered by the generic aggregate engine — the only\n * shape that can travel in a batch, because the batch function IS analytics_run\n * called in a loop. A detail listing is a plain PostgREST select and an 'fn'\n * card never touches the database at all.\n */\nfunction isAggregateCard(card: AnalyticsCardDef): boolean {\n const { source } = card.query\n if (source.kind !== 'view' || !source.name) return false\n return (card.query.dimensions?.length ?? 0) > 0 || (card.query.measures?.length ?? 0) > 0\n}\n\n/**\n * The arguments analytics_run wants, as a plain object. Named once so a single\n * call and a batched element cannot drift into asking different questions —\n * the bug that would show up as a KPI disagreeing with itself depending on how\n * many other cards happened to be on screen.\n */\nfunction runArgs(card: AnalyticsCardDef, state: AnalyticsQueryState, tenantId: string | undefined) {\n const size = state.pageSize || 50\n // A snapshot card (dateColumn: null) sends no window at all, so \"stock on\n // hand\" stays stock on hand no matter what the range picker says.\n const snapshot = card.query.dateColumn === null\n return {\n source: card.query.source.name!,\n tenant_id: tenantId ?? null,\n from: !snapshot && state.dateRange.from ? `${state.dateRange.from}T00:00:00` : null,\n // Inclusive end-of-day: the range picker speaks in days, the column is a\n // timestamp, and closing at midnight loses everything sold that day.\n to: !snapshot && state.dateRange.to ? `${state.dateRange.to}T23:59:59.999` : null,\n dimensions: (card.query.dimensions ?? []).map((d) => ({\n key: d.key,\n ...(d.grain && d.grain !== 'auto' ? { grain: d.grain } : {}),\n })),\n measures: (card.query.measures ?? [])\n .filter((m) => m.agg !== 'ratio')\n .map((m) => ({ key: m.key, agg: m.agg, ...(m.column ? { column: m.column } : {}) })),\n filters: state.filters ?? {},\n search: state.search ?? null,\n search_columns: searchColumns(card) ?? null,\n sort: state.sortBy ?? card.query.defaultSort ?? null,\n dir: state.sortDir ?? card.query.defaultSortDir ?? 'desc',\n limit: card.query.limit ?? size,\n offset: card.query.limit ? 0 : ((state.page || 1) - 1) * size,\n }\n}\n\n/** Shape analytics_run's envelope into a result, mapping row keys. */\nfunction toResult(data: any, card: AnalyticsCardDef, reserved: Set<string>): AnalyticsResult {\n const rows: AnalyticsRow[] = data?.rows ?? []\n return {\n rows: rows.map((r) => mapRow(r, reserved, card.query.source.columnMap)),\n total: data?.total ?? rows.length,\n summary: data?.summary ?? undefined,\n }\n}\n\n/** The batch function is missing on this project — 025 was never applied. */\nfunction batchUnavailable(err: any): boolean {\n const code = typeof err?.code === 'string' ? err.code : ''\n if (['42883', 'PGRST202'].includes(code)) return true\n return typeof err?.message === 'string' && err.message.includes('analytics_run_batch')\n}\n\nexport interface SupabaseAnalyticsProviderConfig {\n tenantId: string | (() => string | undefined)\n schema?: string\n}\n\nexport function createSupabaseAnalyticsProvider(config: SupabaseAnalyticsProviderConfig): AnalyticsProvider {\n const resolveTenantId = () =>\n (typeof config.tenantId === 'function' ? config.tenantId() : config.tenantId) || undefined\n\n function client() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase client not available')\n return config.schema && config.schema !== 'public' ? supabase.schema(config.schema) : supabase\n }\n\n // Flipped off for good on the first \"function does not exist\", so an older\n // pool degrades to one-request-per-card instead of failing every card.\n let batchSupported = true\n\n return {\n async run(card: AnalyticsCardDef, state: AnalyticsQueryState): Promise<AnalyticsResult> {\n const { source } = card.query\n const reserved = reservedKeys(card)\n\n if (source.kind === 'fn') {\n if (!source.run) throw new Error(`analytics: card ${card.id} declares kind 'fn' with no run()`)\n const rows = await source.run({\n tenantId: resolveTenantId(),\n dateRange: state.dateRange,\n filters: state.filters,\n })\n return aggregateRows(rows, card, state)\n }\n\n if (!source.name) throw new Error(`analytics: card ${card.id} has no source name`)\n\n // A card with neither dimensions nor measures is a flat listing, and a\n // flat listing has nothing to aggregate. It reads the view DIRECTLY.\n //\n // This is not an optimisation — it is what keeps the five apps that\n // already ship ReportDef catalogues working. Their views (rep_appointments\n // _by_period, plg_courses_rep_revenue, …) predate analytics_run and are\n // not in its allowlist, so sending a plain SELECT through the aggregate\n // engine turned every existing report into PGRST202. Registration is the\n // price of GROUP BY, not the price of reading rows.\n const isDetail = (card.query.dimensions?.length ?? 0) === 0\n && (card.query.measures?.length ?? 0) === 0\n if (source.kind === 'view' && isDetail) {\n return selectFromView(card, state, client(), resolveTenantId(), reserved)\n }\n\n if (source.kind === 'rpc') {\n const { data, error } = await client().rpc(source.name, {\n p_tenant_id: resolveTenantId(),\n p_from: state.dateRange.from,\n p_to: state.dateRange.to,\n ...Object.fromEntries(Object.entries(state.filters ?? {}).map(([k, v]) => [`p_${k}`, v])),\n })\n if (error) throw error\n const rows: AnalyticsRow[] = Array.isArray(data) ? data : (data?.rows ?? [])\n return {\n rows: rows.map((r) => mapRow(r, reserved, source.columnMap)),\n total: Array.isArray(data) ? rows.length : (data?.total ?? rows.length),\n summary: Array.isArray(data) ? undefined : data?.summary,\n }\n }\n\n // The standard path: the generic aggregate engine.\n const args = runArgs(card, state, resolveTenantId())\n const { data, error } = await client().rpc('analytics_run', {\n p_source: args.source,\n p_tenant_id: args.tenant_id,\n p_from: args.from,\n p_to: args.to,\n p_dimensions: args.dimensions,\n p_measures: args.measures,\n p_filters: args.filters,\n p_search: args.search,\n p_search_columns: args.search_columns,\n p_sort: args.sort,\n p_dir: args.dir,\n p_limit: args.limit,\n p_offset: args.offset,\n })\n if (error) throw error\n return toResult(data, card, reserved)\n },\n\n // -----------------------------------------------------------------------\n // The batched path.\n //\n // Every aggregate card in the batch becomes ONE analytics_run_batch call;\n // detail listings and 'fn' cards, which the batch function cannot express,\n // still go one by one — but a dashboard is all aggregates, so opening\n // /analytics went from forty-one requests to one.\n //\n // Results keep their INDEX. The caller matched a promise to a position, and\n // returning a compacted array would silently hand card 7 card 9's numbers.\n // -----------------------------------------------------------------------\n async runMany(requests: AnalyticsBatchRequest[]): Promise<Array<AnalyticsResult | Error>> {\n const out: Array<AnalyticsResult | Error> = new Array(requests.length)\n const batchable: number[] = []\n\n for (let i = 0; i < requests.length; i++) {\n if (batchSupported && isAggregateCard(requests[i]!.card)) batchable.push(i)\n }\n\n // Anything the batch cannot carry runs on its own, concurrently.\n const singles = requests\n .map((req, i) => ({ req, i }))\n .filter(({ i }) => !batchable.includes(i))\n .map(({ req, i }) =>\n this.run(req.card, req.state)\n .then((r) => { out[i] = r })\n .catch((e: unknown) => { out[i] = toError(e) }))\n\n if (batchable.length > 0) {\n const tenantId = resolveTenantId()\n const payload = batchable.map((i) => runArgs(requests[i]!.card, requests[i]!.state, tenantId))\n const { data, error } = await client().rpc('analytics_run_batch', { p_requests: payload })\n\n if (error && batchUnavailable(error)) {\n // A pool that has analytics_run but not 034 must keep working rather\n // than reporting \"engine not installed\" on every card. Latched, so\n // the fallback costs one failed call per session, not per fetch.\n batchSupported = false\n await Promise.all([\n ...singles,\n ...batchable.map((i) =>\n this.run(requests[i]!.card, requests[i]!.state)\n .then((r) => { out[i] = r })\n .catch((e: unknown) => { out[i] = toError(e) })),\n ])\n return out\n }\n if (error) throw error\n\n const results: any[] = Array.isArray(data) ? data : []\n batchable.forEach((cardIndex, slot) => {\n const entry = results[slot]\n const { card } = requests[cardIndex]!\n out[cardIndex] = entry?.error\n ? Object.assign(toError(entry.error), { code: entry.code })\n : toResult(entry, card, reservedKeys(card))\n })\n }\n\n await Promise.all(singles)\n return out\n },\n }\n}\n","import type {\n AnalyticsCardDef, AnalyticsProvider, AnalyticsQueryState, AnalyticsRow,\n} from '@fayz-ai/core'\nimport { aggregateRows } from './aggregate'\n\n// ---------------------------------------------------------------------------\n// Mock analytics provider — synthesises rows shaped by whatever the card asks\n// for, then runs them through the SAME aggregator the 'fn' source uses. The\n// numbers are invented; the grouping, bucketing and rollup behaviour is real,\n// so a card that looks right against the mock is not lying about its shape.\n//\n// Deterministic on purpose: a seeded generator means the dev dashboard does not\n// reshuffle on every keystroke, and a screenshot stays reproducible.\n// ---------------------------------------------------------------------------\n\nfunction seeded(seed: string): () => number {\n let h = 2166136261\n for (let i = 0; i < seed.length; i++) {\n h ^= seed.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n return () => {\n h += 0x6d2b79f5\n let t = h\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\nconst SAMPLE_LABELS: Record<string, string[]> = {\n product_name: ['Camiseta Preta', 'Caneca Fayz', 'Moletom', 'Boné', 'Adesivos'],\n category_name: ['Vestuário', 'Acessórios', 'Casa'],\n customer_name: ['Ana Souza', 'Bruno Lima', 'Carla Dias', 'Diego Alves'],\n status: ['open', 'archived', 'cancelled'],\n financial_status: ['paid', 'pending', 'refunded'],\n fulfillment_status: ['fulfilled', 'unfulfilled', 'partially_fulfilled'],\n}\n\nfunction labelsFor(key: string, rand: () => number): string[] {\n const known = SAMPLE_LABELS[key]\n if (known) return known\n const n = 3 + Math.floor(rand() * 3)\n return Array.from({ length: n }, (_, i) => `${key.replace(/_/g, ' ')} ${i + 1}`)\n}\n\nexport function createMockAnalyticsProvider(): AnalyticsProvider {\n return {\n async run(card: AnalyticsCardDef, state: AnalyticsQueryState) {\n const rand = seeded(card.id)\n const dateColumn = card.query.dateColumn ?? 'created_at'\n const dimensions = card.query.dimensions ?? []\n const measures = card.query.measures ?? []\n\n const from = new Date(`${state.dateRange.from}T12:00:00`).getTime()\n const to = new Date(`${state.dateRange.to}T12:00:00`).getTime()\n const span = Math.max(to - from, 86_400_000)\n\n // Enough rows that every bucket and every category is represented, capped\n // so a 90-day range does not synthesise thousands of throwaway objects.\n const rowCount = Math.min(400, Math.max(60, Math.round(span / 86_400_000) * 4))\n const categoricalDims = dimensions.filter((d) => !d.grain && d.key !== dateColumn)\n const labelPools = new Map(categoricalDims.map((d) => [d.key, labelsFor(d.key, rand)]))\n\n const rows: AnalyticsRow[] = Array.from({ length: rowCount }, () => {\n const row: AnalyticsRow = {\n [dateColumn]: new Date(from + rand() * span).toISOString(),\n }\n for (const [key, pool] of labelPools) {\n row[key] = pool[Math.floor(rand() * pool.length)]\n }\n for (const m of measures) {\n if (m.agg === 'count' || m.agg === 'ratio') continue\n const column = m.column ?? m.key\n row[column] = m.format === 'currency'\n ? Math.round(rand() * 40000) / 100\n : m.format === 'percent'\n ? Math.round(rand() * 10000) / 100\n : Math.round(rand() * 50)\n }\n for (const c of card.columns ?? []) {\n if (c.key in row) continue\n row[c.key] = c.type === 'currency' || c.type === 'number'\n ? Math.round(rand() * 10000) / 100\n : c.type === 'date'\n ? new Date(from + rand() * span).toISOString()\n : `${c.label} ${Math.ceil(rand() * 20)}`\n }\n return row\n })\n\n return aggregateRows(rows, card, state)\n },\n\n // There is no transport to save a round trip on, so this is just the loop.\n // It exists because the mock is reached through createSafeDataProvider,\n // whose Proxy answers EVERY property with a function — `provider.runMany`\n // is truthy even for a provider that never declared it, and the caller's\n // feature check therefore cannot detect its absence. Implementing it is how\n // the mock stops being a landmine behind that Proxy.\n async runMany(requests) {\n return Promise.all(requests.map((r) =>\n this.run(r.card, r.state).catch((e: unknown) => (e instanceof Error ? e : new Error(String(e))))))\n },\n }\n}\n","import { useOrganizationStore } from '@fayz-ai/admin'\n\n// ---------------------------------------------------------------------------\n// Which tenant the analytics surface is reporting on.\n//\n// Defaults to the organization the shell is currently switched to. Leaving it\n// undefined is NOT equivalent: with no tenant the engine sends no predicate and\n// falls back to RLS alone, and RLS on the shop tables admits every tenant the\n// user is a member of (`tenant_id IN user_tenant_ids()`). In a multi-org app\n// that is one page reporting the sum of every store the operator can see, while\n// every other screen beside it shows only the active one.\n// ---------------------------------------------------------------------------\n\nlet override: string | undefined\n\n/** Pin the surface to a tenant, overriding the active organization. */\nexport function setReportsTenantId(id: string | undefined): void {\n override = id\n}\n\nexport function getReportsTenantId(): string | undefined {\n if (override) return override\n try {\n return useOrganizationStore.getState().currentOrg?.id\n } catch {\n // No org store mounted (a bespoke host, a test): fall back to RLS rather\n // than throwing inside a data provider.\n return undefined\n }\n}\n","export const en: Record<string, string> = {\n 'reports.pageTitle': 'Reports',\n 'reports.pageSubtitle': 'Access complete reports for analysis and decision making',\n 'reports.overview': 'Overview',\n 'reports.allReports': 'All reports',\n 'reports.dateRange': 'Date Range',\n 'reports.from': 'From',\n 'reports.to': 'To',\n 'reports.export': 'Export',\n 'reports.exportCsv': 'Export CSV',\n 'reports.exportExcel': 'Export Excel',\n 'reports.exportPdf': 'Export PDF',\n 'reports.noResults': 'No results found.',\n 'reports.backToReports': 'Back',\n 'reports.reports': 'reports',\n 'reports.search': 'Search reports...',\n 'reports.today': 'Today',\n 'reports.yesterday': 'Yesterday',\n 'reports.last7Days': 'Last 7 days',\n 'reports.thisMonth': 'This month',\n 'reports.lastMonth': 'Last month',\n 'reports.thisQuarter': 'This quarter',\n 'reports.custom': 'Custom',\n 'reports.generate': 'Generate',\n 'reports.emptyStateTitle': 'Ready to generate',\n 'reports.emptyStateDescription': 'Select a date range and filters, then click Generate to view the report.',\n // The assistant's invitation on /analytics. It opens on a question, not on a\n // grid: the numbers are already downstairs, and what the owner actually wants\n // is to know what they mean.\n 'reports.assistant.persona': 'Growth Analyst',\n 'reports.assistant.headline': 'Hi {{name}}, what would you like to learn today?',\n 'reports.assistant.pitch': \"Let's find the opportunities hiding in your business\",\n 'reports.assistant.description':\n \"Tell me your goals and I'll help build a plan to hit them. I read the same data these reports do, and I'll point at what changed and what to do about it.\",\n 'reports.assistant.placeholder': 'Build a custom report...',\n 'reports.assistant.suggestion.0': 'How is my business doing this month?',\n 'reports.assistant.suggestion.1': \"What's growing and what's falling?\",\n 'reports.assistant.suggestion.2': 'Where am I losing money?',\n 'reports.print': 'Print',\n 'reports.pagination.range': '{{from}}–{{to}} of {{total}}',\n 'reports.pagination.empty': 'No results',\n 'reports.pagination.perPage': '{{size}} / page',\n 'reports.settings.nav': 'Configure reports',\n 'reports.settings.title': 'Configure reports',\n 'reports.settings.subtitle': 'Choose what appears on the overview, in what order, and what each report shows. Saved in this browser.',\n 'reports.settings.new': 'New report',\n 'reports.settings.newHint': 'A new report asks a different question of a source the app already exposes.',\n 'reports.settings.newWithAIHint': 'Describe what you want to see and I build it.',\n 'reports.settings.newByHand': 'Create by hand',\n 'reports.settings.newByHandHint': 'Pick the source, the grouping and the measures.',\n 'reports.settings.askPersona': 'Report analyst',\n 'reports.settings.askPitch': 'Tell me the report you want.',\n 'reports.settings.askDescription': 'I know this app\\'s data sources and the fields on each. Describe what you want to see — I pick the grouping, the measures and the format, build it and open it for you to check.',\n 'reports.settings.askSuggestion.0': 'Revenue by table, highest first',\n 'reports.settings.askSuggestion.1': 'How much each station produces per service',\n 'reports.settings.askSuggestion.2': 'Average ticket by channel, month by month',\n 'reports.settings.askPlaceholder': 'Describe the report…',\n 'reports.settings.orByHand': 'or build it by hand',\n 'reports.settings.reset': 'Reset to defaults',\n 'reports.settings.onOverview': 'On the overview',\n 'reports.settings.onOverviewHint': 'Drag to reorder. Width is in grid columns.',\n 'reports.settings.offOverview': 'Off the overview',\n 'reports.settings.offOverviewHint': 'Still in the list and still open full size — they just do not claim a tile.',\n 'reports.settings.hidden': 'Removed from the catalogue',\n 'reports.settings.empty': 'No reports on the overview.',\n 'reports.settings.custom': 'Yours',\n 'reports.settings.pin': 'Add to the overview',\n 'reports.settings.unpin': 'Remove from the overview',\n 'reports.settings.up': 'Move up',\n 'reports.settings.down': 'Move down',\n 'reports.settings.edit': 'Adjust',\n 'reports.settings.remove': 'Remove from the catalogue',\n 'reports.settings.restore': 'Restore',\n 'reports.settings.delete': 'Delete',\n 'reports.settings.width': 'Width',\n 'reports.settings.width.1': 'Quarter',\n 'reports.settings.width.2': 'Half',\n 'reports.settings.width.3': 'Three quarters',\n 'reports.settings.width.4': 'Full',\n 'reports.settings.name': 'Name',\n 'reports.settings.category': 'Category',\n 'reports.settings.source': 'Data source',\n 'reports.settings.sourceHint': 'Where the rows come from — it decides which fields you can use.',\n 'reports.settings.viz': 'Visualization',\n 'reports.settings.dimensions': 'Group by',\n 'reports.settings.measures': 'Measures',\n 'reports.settings.resetCard': 'Reset this report',\n 'reports.settings.needName': 'Give the report a name.',\n 'reports.settings.needMeasure': 'Pick at least one measure.',\n 'reports.settings.save': 'Create',\n 'reports.settings.cancel': 'Cancel',\n 'reports.settings.done': 'Done',\n 'reports.viz.kpi': 'Number',\n 'reports.viz.line': 'Line',\n 'reports.viz.bar': 'Bars',\n 'reports.viz.area': 'Area',\n 'reports.viz.donut': 'Donut',\n 'reports.viz.breakdown': 'Ranking',\n 'reports.viz.table': 'Table',\n 'reports.viz.funnel': 'Funnel',\n 'reports.unavailableTitle': 'Coming soon',\n 'reports.unavailableDescription': 'This report is not available yet. It will be enabled in a future update.',\n}\n","export const ptBR: Record<string, string> = {\n 'reports.pageTitle': 'Relatórios',\n 'reports.pageSubtitle': 'Acesse relatórios completos para análise e tomada de decisão',\n 'reports.overview': 'Visão geral',\n 'reports.allReports': 'Todos os relatórios',\n 'reports.dateRange': 'Período',\n 'reports.from': 'De',\n 'reports.to': 'Até',\n 'reports.export': 'Exportar',\n 'reports.exportCsv': 'Exportar CSV',\n 'reports.exportExcel': 'Exportar Excel',\n 'reports.exportPdf': 'Exportar PDF',\n 'reports.noResults': 'Nenhum resultado encontrado.',\n 'reports.backToReports': 'Voltar',\n 'reports.reports': 'relatórios',\n 'reports.search': 'Buscar relatórios...',\n 'reports.today': 'Hoje',\n 'reports.yesterday': 'Ontem',\n 'reports.last7Days': 'Últimos 7 dias',\n 'reports.thisMonth': 'Este mês',\n 'reports.lastMonth': 'Mês passado',\n 'reports.thisQuarter': 'Este trimestre',\n 'reports.custom': 'Personalizado',\n 'reports.generate': 'Gerar',\n 'reports.emptyStateTitle': 'Pronto para gerar',\n 'reports.emptyStateDescription': 'Selecione o período e os filtros desejados, depois clique em Gerar para visualizar o relatório.',\n 'reports.assistant.persona': 'Analista de Crescimento',\n 'reports.assistant.headline': 'Oi {{name}}, o que você quer entender hoje?',\n 'reports.assistant.pitch': 'Vamos achar as oportunidades escondidas no seu negócio',\n 'reports.assistant.description':\n 'Me conte sua meta e eu ajudo a montar o plano para bater. Leio os mesmos dados destes relatórios e aponto o que mudou e o que fazer a respeito.',\n 'reports.assistant.placeholder': 'Peça um relatório do seu jeito...',\n 'reports.assistant.suggestion.0': 'Como está meu negócio neste mês?',\n 'reports.assistant.suggestion.1': 'O que está crescendo e o que está caindo?',\n 'reports.assistant.suggestion.2': 'Onde estou perdendo dinheiro?',\n 'reports.print': 'Imprimir',\n 'reports.pagination.range': '{{from}}–{{to}} de {{total}}',\n 'reports.pagination.empty': 'Nenhum resultado',\n 'reports.pagination.perPage': '{{size}} / página',\n 'reports.settings.nav': 'Configurar relatórios',\n 'reports.settings.title': 'Configurar relatórios',\n 'reports.settings.subtitle': 'Escolha o que aparece no painel, em que ordem e o que cada relatório mostra. As escolhas ficam neste navegador.',\n 'reports.settings.new': 'Novo relatório',\n 'reports.settings.newHint': 'Um relatório novo pergunta outra coisa a uma fonte que o app já expõe.',\n 'reports.settings.newWithAIHint': 'Descreva o que quer ver e eu monto.',\n 'reports.settings.newByHand': 'Criar manualmente',\n 'reports.settings.newByHandHint': 'Escolher fonte, agrupamento e medidas.',\n 'reports.settings.askPersona': 'Analista de relatórios',\n 'reports.settings.askPitch': 'Diga o relatório que você quer.',\n 'reports.settings.askDescription': 'Conheço as fontes deste app e os campos de cada uma. Descreva o que quer ver — eu escolho o agrupamento, as medidas e o formato, monto e abro para você conferir.',\n 'reports.settings.askSuggestion.0': 'Receita por mesa, do maior para o menor',\n 'reports.settings.askSuggestion.1': 'Quanto cada praça produz por turno',\n 'reports.settings.askSuggestion.2': 'Ticket médio por canal, mês a mês',\n 'reports.settings.askPlaceholder': 'Descreva o relatório…',\n 'reports.settings.orByHand': 'ou monte à mão',\n 'reports.settings.reset': 'Restaurar padrões',\n 'reports.settings.onOverview': 'No painel',\n 'reports.settings.onOverviewHint': 'Arraste para reordenar. A largura é em colunas da grade.',\n 'reports.settings.offOverview': 'Fora do painel',\n 'reports.settings.offOverviewHint': 'Continuam na lista e abrem inteiros; só não ocupam um bloco do painel.',\n 'reports.settings.hidden': 'Removidos do catálogo',\n 'reports.settings.empty': 'Nenhum relatório no painel.',\n 'reports.settings.custom': 'Seu',\n 'reports.settings.pin': 'Pôr no painel',\n 'reports.settings.unpin': 'Tirar do painel',\n 'reports.settings.up': 'Subir',\n 'reports.settings.down': 'Descer',\n 'reports.settings.edit': 'Ajustar',\n 'reports.settings.remove': 'Remover do catálogo',\n 'reports.settings.restore': 'Devolver',\n 'reports.settings.delete': 'Excluir',\n 'reports.settings.width': 'Largura',\n 'reports.settings.width.1': 'Um quarto',\n 'reports.settings.width.2': 'Metade',\n 'reports.settings.width.3': 'Três quartos',\n 'reports.settings.width.4': 'Inteiro',\n 'reports.settings.name': 'Nome',\n 'reports.settings.category': 'Categoria',\n 'reports.settings.source': 'Fonte de dados',\n 'reports.settings.sourceHint': 'De onde vêm as linhas — é ela que decide quais campos você pode usar.',\n 'reports.settings.viz': 'Visualização',\n 'reports.settings.dimensions': 'Agrupar por',\n 'reports.settings.measures': 'Medidas',\n 'reports.settings.resetCard': 'Restaurar este relatório',\n 'reports.settings.needName': 'Dê um nome ao relatório.',\n 'reports.settings.needMeasure': 'Escolha ao menos uma medida.',\n 'reports.settings.save': 'Criar',\n 'reports.settings.cancel': 'Cancelar',\n 'reports.settings.done': 'Pronto',\n 'reports.viz.kpi': 'Número',\n 'reports.viz.line': 'Linha',\n 'reports.viz.bar': 'Barras',\n 'reports.viz.area': 'Área',\n 'reports.viz.donut': 'Rosca',\n 'reports.viz.breakdown': 'Ranking',\n 'reports.viz.table': 'Tabela',\n 'reports.viz.funnel': 'Funil',\n 'reports.unavailableTitle': 'Em breve',\n 'reports.unavailableDescription': 'Este relatório ainda não está disponível. Será habilitado em uma atualização futura.',\n}\n","import { en } from './en'\nimport { ptBR } from './pt-BR'\n\nexport const reportsLocales: Record<string, Record<string, string>> = {\n en,\n 'pt-BR': ptBR,\n}\n","// AUTO-GENERATED from 000_baseline.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000_BASELINE = `-- ============================================================================\n-- plugins/plugin-reports/src/migrations/000_baseline.sql — what installing this provisions, as one file.\n--\n-- GENERATED by scripts/emit-unit-baselines.mjs (#338). Do not edit by hand:\n-- change the schema, regenerate, and let scripts/check-chain-equivalence.mjs\n-- prove the result still matches.\n--\n-- This replaced 3 migration files. They are kept, unapplied, in\n-- migrations.archive/ — a year of decisions is worth reading even when it is no\n-- longer worth replaying.\n--\n-- Object order is fixed rather than dependency-sorted: schemas, types,\n-- sequences, tables, defaults, functions, constraints, views, indexes, foreign\n-- keys, triggers, row security, policies, grants. Dependencies BETWEEN units\n-- are carried by the order packages/db/chain.json declares.\n-- ============================================================================\n\n-- A LANGUAGE sql function binds its body at CREATE time, and 570 functions\n-- sorted by name are not sorted by who calls whom. This is what lets them load\n-- in any order; every body is still compiled on first call, so a genuinely\n-- broken reference surfaces then rather than never. Session-scoped.\nSET check_function_bodies = false;\n\n\n\n-- ── default privileges: reset ───────────────────────────────────────────\n-- Cleared BEFORE anything is created, so every object below gets the ACL the\n-- dump describes rather than the image's defaults on top of it. Restored at\n-- the end of this file.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\n\n-- ── table ───────────────────────────────────────────────────────────────\n\nCREATE TABLE public.plg_reports_definitions (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid,\n unit_id uuid,\n key text NOT NULL,\n version integer DEFAULT 1 NOT NULL,\n title text NOT NULL,\n description text,\n module text NOT NULL,\n source_view text NOT NULL,\n params jsonb DEFAULT '[]'::jsonb NOT NULL,\n columns jsonb DEFAULT '[]'::jsonb NOT NULL,\n default_order_by text,\n required_permission text NOT NULL,\n is_active boolean DEFAULT true NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_by uuid,\n owner_id uuid,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reports_definitions_required_permission_check CHECK ((btrim(required_permission) <> ''::text)),\n CONSTRAINT plg_reports_definitions_version_check CHECK ((version >= 1))\n);\n\nALTER TABLE ONLY public.plg_reports_definitions FORCE ROW LEVEL SECURITY;\n\nCREATE TABLE public.plg_reports_runs (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n unit_id uuid,\n definition_key text NOT NULL,\n definition_version integer DEFAULT 1 NOT NULL,\n params jsonb DEFAULT '{}'::jsonb NOT NULL,\n requested_by uuid,\n row_count bigint,\n duration_ms integer,\n status text DEFAULT 'ok'::text NOT NULL,\n error text,\n format text,\n owner_id uuid,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reports_runs_status_check CHECK ((status = ANY (ARRAY['ok'::text, 'refused'::text, 'error'::text])))\n);\n\nALTER TABLE ONLY public.plg_reports_runs FORCE ROW LEVEL SECURITY;\n\nCREATE TABLE public.plg_reports_schedules (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n unit_id uuid,\n definition_key text NOT NULL,\n cron text NOT NULL,\n params jsonb DEFAULT '{}'::jsonb NOT NULL,\n recipients jsonb DEFAULT '[]'::jsonb NOT NULL,\n format text DEFAULT 'csv'::text NOT NULL,\n template_key text DEFAULT 'report.delivered'::text NOT NULL,\n is_active boolean DEFAULT true NOT NULL,\n last_run_at timestamp with time zone,\n next_run_at timestamp with time zone,\n owner_id uuid,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reports_schedules_format_check CHECK ((format = ANY (ARRAY['csv'::text, 'xlsx'::text, 'pdf'::text])))\n);\n\nALTER TABLE ONLY public.plg_reports_schedules FORCE ROW LEVEL SECURITY;\n\n\n-- ── function ────────────────────────────────────────────────────────────\n\nCREATE FUNCTION public.reports_definition(p_key text, p_tenant uuid DEFAULT NULL::uuid) RETURNS public.plg_reports_definitions\n LANGUAGE sql STABLE SECURITY DEFINER\n SET search_path TO ''\n AS $$\n SELECT d.* FROM public.plg_reports_definitions d\n WHERE d.key = p_key AND d.is_active\n AND (d.tenant_id = coalesce(p_tenant, app.current_tenant_id()) OR d.tenant_id IS NULL)\n -- A tenant's own definition beats the platform one, and the newest version\n -- beats an older one.\n ORDER BY (d.tenant_id IS NOT NULL) DESC, d.version DESC\n LIMIT 1\n$$;\n\nCREATE FUNCTION public.reports_deliver_due(p_limit integer DEFAULT 50) RETURNS jsonb\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $$\nDECLARE\n s public.plg_reports_schedules%ROWTYPE;\n v_recipient jsonb;\n v_res jsonb;\n v_sent integer := 0;\n v_runs integer := 0;\nBEGIN\n IF to_regprocedure('public.notifications_enqueue(uuid, text, uuid, jsonb, text, timestamptz, text, text, uuid, uuid)') IS NULL THEN\n RETURN jsonb_build_object('skipped', 'plugin-notifications is not installed');\n END IF;\n\n FOR s IN\n SELECT * FROM public.plg_reports_schedules\n WHERE is_active AND (next_run_at IS NULL OR next_run_at <= now())\n ORDER BY next_run_at NULLS FIRST\n LIMIT greatest(p_limit, 0)\n FOR UPDATE SKIP LOCKED\n LOOP\n v_runs := v_runs + 1;\n FOR v_recipient IN SELECT * FROM jsonb_array_elements(coalesce(s.recipients, '[]'::jsonb)) LOOP\n -- The campaign rule applies to a report too: this ENQUEUES, it does not\n -- send. One engine, one queue, one place a delivery can be retried.\n v_res := to_jsonb(public.notifications_enqueue(\n p_tenant_id => s.tenant_id,\n p_template_key => s.template_key,\n p_person_id => nullif(v_recipient ->> 'person_id', '')::uuid,\n p_payload => jsonb_build_object('report_key', s.definition_key, 'format', s.format),\n p_dedupe_key => 'report:' || s.id::text || ':' || to_char(now(), 'YYYY-MM-DD') || ':' || coalesce(v_recipient ->> 'person_id', ''),\n p_unit_id => s.unit_id));\n v_sent := v_sent + 1;\n END LOOP;\n\n UPDATE public.plg_reports_schedules\n SET last_run_at = now(),\n next_run_at = now() + interval '1 day'\n WHERE id = s.id;\n END LOOP;\n\n RETURN jsonb_build_object('schedules', v_runs, 'queued', v_sent);\nEND $$;\n\nCREATE FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text DEFAULT 'email'::text) RETURNS uuid\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $$\nDECLARE v_id uuid;\nBEGIN\n IF to_regclass('public.plg_notifications_templates') IS NULL THEN\n RAISE EXCEPTION 'reports_ensure_delivery_template: plugin-notifications is not installed' USING ERRCODE = '0A000';\n END IF;\n INSERT INTO public.plg_notifications_templates (tenant_id, key, channel, locale, subject, body, is_default, purpose)\n VALUES (p_tenant, 'report.delivered', p_channel, 'pt-BR',\n 'Seu relatório está pronto',\n 'O relatório {{report_key}} foi gerado em {{format}} e está disponível.', true, 'transactional')\n ON CONFLICT (tenant_id, key, channel, locale) DO UPDATE SET is_active = true\n RETURNING id INTO v_id;\n RETURN v_id;\nEND $$;\n\nCREATE FUNCTION public.reports_run(p_key text, p_params jsonb DEFAULT '{}'::jsonb, p_limit integer DEFAULT 1000, p_offset integer DEFAULT 0, p_format text DEFAULT NULL::text) RETURNS jsonb\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $$\nDECLARE\n v_tenant uuid := app.current_tenant_id();\n v_def public.plg_reports_definitions%ROWTYPE;\n v_sql text;\n v_where text := '';\n v_param jsonb;\n v_name text;\n v_value text;\n v_rows jsonb;\n v_count bigint := 0;\n v_start timestamptz := clock_timestamp();\n v_has_unit boolean;\nBEGIN\n IF v_tenant IS NULL THEN\n RAISE EXCEPTION 'reports_run: no active tenant' USING ERRCODE = '42501';\n END IF;\n\n v_def := public.reports_definition(p_key, v_tenant);\n IF v_def.id IS NULL THEN\n RAISE EXCEPTION 'reports_run: no active report called %', p_key USING ERRCODE = 'P0002';\n END IF;\n\n -- ── refuse BEFORE the query, not after the rows ──────────────────────\n --\n -- The refusal is RETURNED rather than raised, and the reason is mechanical:\n -- raising rolls the statement back, taking the run record with it, and a\n -- refusal nobody can see afterwards is the thing this history exists for.\n -- No rows are read either way — which is what \"refuse before the query\" means\n -- — and a caller that ignores \\`status\\` still gets nothing.\n IF NOT (select app.has_permission(v_def.required_permission, NULL)) THEN\n INSERT INTO public.plg_reports_runs (tenant_id, definition_key, definition_version, params, requested_by, status, error)\n VALUES (v_tenant, p_key, v_def.version, coalesce(p_params, '{}'::jsonb), auth.uid(), 'refused',\n format('%s is required', v_def.required_permission));\n RETURN jsonb_build_object(\n 'key', p_key, 'version', v_def.version, 'title', v_def.title,\n 'status', 'refused', 'required_permission', v_def.required_permission,\n 'columns', '[]'::jsonb, 'rows', '[]'::jsonb, 'row_count', 0);\n END IF;\n\n -- ── scope the engine injects, and no definition can switch off ───────\n v_where := format('%I = %L', 'tenant_id', v_tenant);\n\n SELECT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = v_def.source_view AND column_name = 'unit_id')\n INTO v_has_unit;\n IF v_has_unit THEN\n v_where := v_where || ' AND (unit_id IS NULL OR (select app.has_unit(unit_id)))';\n END IF;\n\n -- ── the declared parameters, and only those ──────────────────────────\n FOR v_param IN SELECT * FROM jsonb_array_elements(coalesce(v_def.params, '[]'::jsonb)) LOOP\n v_name := v_param ->> 'name';\n v_value := coalesce(p_params ->> v_name, v_param ->> 'default');\n IF v_value IS NULL THEN\n IF coalesce((v_param ->> 'required')::boolean, false) THEN\n RAISE EXCEPTION 'reports_run: % requires the parameter %', p_key, v_name USING ERRCODE = '22023';\n END IF;\n CONTINUE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = v_def.source_view\n AND column_name = coalesce(v_param ->> 'column', v_name)) THEN\n RAISE EXCEPTION 'reports_run: parameter % has no column on %', v_name, v_def.source_view USING ERRCODE = '42703';\n END IF;\n v_where := v_where || format(' AND %I %s %L',\n coalesce(v_param ->> 'column', v_name),\n CASE v_param ->> 'operator' WHEN '>=' THEN '>=' WHEN '<=' THEN '<=' WHEN '>' THEN '>' WHEN '<' THEN '<' WHEN 'ilike' THEN 'ILIKE' ELSE '=' END,\n v_value);\n END LOOP;\n\n -- A parameter the caller sent that the definition never declared is refused\n -- rather than ignored: silently dropping a filter shows the wrong number.\n IF p_params IS NOT NULL AND jsonb_typeof(p_params) = 'object' THEN\n FOR v_name IN SELECT key FROM jsonb_each_text(p_params) LOOP\n IF NOT EXISTS (SELECT 1 FROM jsonb_array_elements(coalesce(v_def.params, '[]'::jsonb)) d WHERE d ->> 'name' = v_name) THEN\n RAISE EXCEPTION 'reports_run: % does not declare a parameter called %', p_key, v_name USING ERRCODE = '22023';\n END IF;\n END LOOP;\n END IF;\n\n v_sql := format('SELECT coalesce(jsonb_agg(t), ''[]''::jsonb), count(*) FROM (SELECT * FROM public.%I WHERE %s %s LIMIT %s OFFSET %s) t',\n v_def.source_view, v_where,\n CASE WHEN v_def.default_order_by IS NULL THEN '' ELSE 'ORDER BY ' || quote_ident(v_def.default_order_by) END,\n greatest(coalesce(p_limit, 1000), 0), greatest(coalesce(p_offset, 0), 0));\n\n EXECUTE v_sql INTO v_rows, v_count;\n\n INSERT INTO public.plg_reports_runs (tenant_id, definition_key, definition_version, params, requested_by,\n row_count, duration_ms, status, format)\n VALUES (v_tenant, p_key, v_def.version, coalesce(p_params, '{}'::jsonb), auth.uid(),\n v_count, (extract(epoch FROM clock_timestamp() - v_start) * 1000)::integer, 'ok', p_format);\n\n RETURN jsonb_build_object(\n 'key', p_key, 'version', v_def.version, 'title', v_def.title,\n 'status', 'ok', 'columns', v_def.columns, 'rows', v_rows, 'row_count', v_count);\nEND $$;\n\nCREATE FUNCTION public.trg_plg_reports_definitions_source() RETURNS trigger\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $_$\nDECLARE v_kind char;\nBEGIN\n IF NEW.source_view !~ '^[a-z_][a-z0-9_]*$' THEN\n RAISE EXCEPTION 'plg_reports_definitions: source_view % is not a bare relation name in public', NEW.source_view\n USING ERRCODE = '22023';\n END IF;\n\n SELECT c.relkind INTO v_kind\n FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace\n WHERE n.nspname = 'public' AND c.relname = NEW.source_view;\n\n IF v_kind IS NULL THEN\n RAISE EXCEPTION 'plg_reports_definitions: public.% does not exist', NEW.source_view USING ERRCODE = '42P01';\n END IF;\n\n -- A view or a materialized view is a read model by construction. A TABLE is\n -- only allowed when its name says so — that is the \\`plg_<x>_rep_*\\` convention\n -- Phase 1 established, and it is checked rather than trusted.\n IF v_kind NOT IN ('v', 'm') AND NEW.source_view !~ '^plg_[a-z0-9_]+_rep_' THEN\n RAISE EXCEPTION 'plg_reports_definitions: public.% is a business table, not a read model', NEW.source_view\n USING ERRCODE = '23514',\n HINT = 'Point the definition at a view or at a plg_<plugin>_rep_* read model. Reporting off a business table is how a report starts holding a schema still.';\n END IF;\n RETURN NEW;\nEND $_$;\n\n\n-- ── constraint ──────────────────────────────────────────────────────────\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_tenant_id_id_key UNIQUE (tenant_id, id);\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_tenant_id_id_key UNIQUE (tenant_id, id);\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_tenant_id_id_key UNIQUE (tenant_id, id);\n\n\n-- ── index ───────────────────────────────────────────────────────────────\n\nCREATE UNIQUE INDEX plg_reports_definitions_key_uq ON public.plg_reports_definitions USING btree (COALESCE(tenant_id, '00000000-0000-0000-0000-000000000000'::uuid), key, version);\n\nCREATE INDEX plg_reports_definitions_module_idx ON public.plg_reports_definitions USING btree (module) WHERE is_active;\n\nCREATE INDEX plg_reports_definitions_tenant_owner_idx ON public.plg_reports_definitions USING btree (tenant_id, owner_id) WHERE (owner_id IS NOT NULL);\n\nCREATE INDEX plg_reports_definitions_tenant_unit_idx ON public.plg_reports_definitions USING btree (tenant_id, unit_id);\n\nCREATE INDEX plg_reports_runs_key_idx ON public.plg_reports_runs USING btree (tenant_id, definition_key, created_at DESC);\n\nCREATE INDEX plg_reports_runs_tenant_owner_idx ON public.plg_reports_runs USING btree (tenant_id, owner_id) WHERE (owner_id IS NOT NULL);\n\nCREATE INDEX plg_reports_runs_tenant_unit_idx ON public.plg_reports_runs USING btree (tenant_id, unit_id);\n\nCREATE INDEX plg_reports_schedules_due_idx ON public.plg_reports_schedules USING btree (next_run_at) WHERE is_active;\n\nCREATE INDEX plg_reports_schedules_tenant_owner_idx ON public.plg_reports_schedules USING btree (tenant_id, owner_id) WHERE (owner_id IS NOT NULL);\n\nCREATE INDEX plg_reports_schedules_tenant_unit_idx ON public.plg_reports_schedules USING btree (tenant_id, unit_id);\n\n\n-- ── fk constraint ───────────────────────────────────────────────────────\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_owner_fk FOREIGN KEY (tenant_id, owner_id) REFERENCES app.memberships(tenant_id, user_id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_unit_fk FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_owner_fk FOREIGN KEY (tenant_id, owner_id) REFERENCES app.memberships(tenant_id, user_id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_unit_fk FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_owner_fk FOREIGN KEY (tenant_id, owner_id) REFERENCES app.memberships(tenant_id, user_id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_unit_fk FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n\n\n-- ── table data ──────────────────────────────────────────────────────────\n\nCOPY public.plg_reports_definitions (id, tenant_id, unit_id, key, version, title, description, module, source_view, params, columns, default_order_by, required_permission, is_active, metadata, created_by, owner_id, created_at, updated_at) FROM stdin;\nb9bdb96e-2219-4bea-a83d-be54e28c4bda\t\\\\N\t\\\\N\torders.sales\t1\tVendas\tEvery sale, whichever door it came through — the query the order vocabulary made possible.\torders\tv_sales\t[{\"name\": \"channel\", \"column\": \"channel\"}, {\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"from\", \"column\": \"created_at\", \"operator\": \">=\"}, {\"name\": \"to\", \"column\": \"created_at\", \"operator\": \"<=\"}]\t[]\tcreated_at\torders.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n706d0d78-193c-4abe-8828-5e00d719d155\t\\\\N\t\\\\N\torders.fulfillment\t1\tEntregas pendentes\tOrdered against delivered, per line. A positive pending is what a boolean could never describe.\torders\tv_order_fulfillment\t[{\"name\": \"state\", \"column\": \"state\"}]\t[]\t\\\\N\torders.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n6e27d897-55d8-4f39-b963-b5cb3121069d\t\\\\N\t\\\\N\tfinancial.receivables\t1\tContas a receber\tInstalments and what is still owed on them, straight from the allocations.\tfinancial\tv_financial_installment_balances\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"due_from\", \"column\": \"due_date\", \"operator\": \">=\"}, {\"name\": \"due_to\", \"column\": \"due_date\", \"operator\": \"<=\"}]\t[]\tdue_date\tfinancial.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n66d7f336-fff1-40ea-b754-6b158f1b0dea\t\\\\N\t\\\\N\tfinancial.uninvoiced\t1\tVendas sem título\tSales that produced no invoice. Empty is the bar this phase closes on.\tfinancial\tv_orders_sem_invoice\t[{\"name\": \"kind\", \"column\": \"kind\"}]\t[]\tcreated_at\tfinancial.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\na5a3ffab-e6e1-46ad-942f-f36582b4e126\t\\\\N\t\\\\N\tinventory.balances\t1\tSaldo de estoque\tThe balance, from the one ledger that owns it.\tinventory\tv_inventory_balances\t[]\t[]\t\\\\N\tinventory.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\na2d3191e-5a8d-4e03-892f-0c9573675ea5\t\\\\N\t\\\\N\tnotifications.queue\t1\tFila de notificações\tWhat is waiting, what is overdue, what was abandoned and what was refused.\tnotifications\tv_notification_queue\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"channel\", \"column\": \"channel\"}]\t[]\t\\\\N\tnotifications.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\nc616ae83-b861-41fb-959a-bbb85431ed77\t\\\\N\t\\\\N\tagenda.appointments\t1\tAgendamentos\tThe calendar as a table, with the Venda and the payment state each booking carries.\tagenda\tv_appointments\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"from\", \"column\": \"starts_at\", \"operator\": \">=\"}, {\"name\": \"to\", \"column\": \"starts_at\", \"operator\": \"<=\"}]\t[]\tstarts_at\tagenda.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n5af4a8c8-903b-4ea6-8829-98877b017883\t\\\\N\t\\\\N\tcrm.funnel\t1\tFunil\tThe funnel over plg_crm_deals, with won_at and lost_at — which is what makes a cycle length measurable.\tcrm\tv_deals\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"stage\", \"column\": \"stage_name\"}]\t[]\tcreated_at\tcrm.pipeline.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n9143ce67-ecaa-46a3-8028-7c354c34f301\t\\\\N\t\\\\N\tmarketing.campaigns\t1\tCampanhas\tReach, delivery and conversion per campaign — the metric comes from here, never from a counter on the campaign.\tmarketing\tv_marketing_campaign_metrics\t[{\"name\": \"status\", \"column\": \"status\"}]\t[]\t\\\\N\tmarketing.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n\\\\.\n\n\n-- ── trigger ─────────────────────────────────────────────────────────────\n\nCREATE TRIGGER plg_reports_definitions_source BEFORE INSERT OR UPDATE OF source_view ON public.plg_reports_definitions FOR EACH ROW EXECUTE FUNCTION public.trg_plg_reports_definitions_source();\n\nCREATE TRIGGER plg_reports_definitions_updated_at BEFORE UPDATE ON public.plg_reports_definitions FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\n\nCREATE TRIGGER plg_reports_runs_updated_at BEFORE UPDATE ON public.plg_reports_runs FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\n\nCREATE TRIGGER plg_reports_schedules_updated_at BEFORE UPDATE ON public.plg_reports_schedules FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\n\n\n-- ── row security ────────────────────────────────────────────────────────\n\nALTER TABLE public.plg_reports_definitions ENABLE ROW LEVEL SECURITY;\n\nALTER TABLE public.plg_reports_runs ENABLE ROW LEVEL SECURITY;\n\nALTER TABLE public.plg_reports_schedules ENABLE ROW LEVEL SECURITY;\n\n\n-- ── policy ──────────────────────────────────────────────────────────────\n\nCREATE POLICY plg_reports_definitions_authz_delete ON public.plg_reports_definitions FOR DELETE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.definition'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.definition'::text, plg_reports_definitions.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_definitions.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.delete'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_authz_insert ON public.plg_reports_definitions FOR INSERT TO authenticated WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.create'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_authz_select ON public.plg_reports_definitions FOR SELECT TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.definition'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.definition'::text, plg_reports_definitions.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_definitions.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.read'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_authz_update ON public.plg_reports_definitions FOR UPDATE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.definition'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.definition'::text, plg_reports_definitions.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_definitions.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_definitions.unit_id) AS has_permission))) WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_platform_read ON public.plg_reports_definitions FOR SELECT TO authenticated USING (((tenant_id IS NULL) AND is_active));\n\nCREATE POLICY plg_reports_runs_authz_delete ON public.plg_reports_runs FOR DELETE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.run'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.run'::text, plg_reports_runs.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_runs.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.delete'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_runs_authz_insert ON public.plg_reports_runs FOR INSERT TO authenticated WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.create'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_runs_authz_select ON public.plg_reports_runs FOR SELECT TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.run'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.run'::text, plg_reports_runs.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_runs.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.read'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_runs_authz_update ON public.plg_reports_runs FOR UPDATE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.run'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.run'::text, plg_reports_runs.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_runs.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_runs.unit_id) AS has_permission))) WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_delete ON public.plg_reports_schedules FOR DELETE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.schedule'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.schedule'::text, plg_reports_schedules.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_schedules.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.delete'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_insert ON public.plg_reports_schedules FOR INSERT TO authenticated WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.create'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_select ON public.plg_reports_schedules FOR SELECT TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.schedule'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.schedule'::text, plg_reports_schedules.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_schedules.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.read'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_update ON public.plg_reports_schedules FOR UPDATE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.schedule'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.schedule'::text, plg_reports_schedules.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_schedules.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_schedules.unit_id) AS has_permission))) WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\n\n-- ── acl ─────────────────────────────────────────────────────────────────\n\nGRANT MAINTAIN ON TABLE public.plg_reports_definitions TO anon;\nGRANT ALL ON TABLE public.plg_reports_definitions TO authenticated;\nGRANT ALL ON TABLE public.plg_reports_definitions TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_definition(p_key text, p_tenant uuid) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_definition(p_key text, p_tenant uuid) TO authenticated;\nGRANT ALL ON FUNCTION public.reports_definition(p_key text, p_tenant uuid) TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_deliver_due(p_limit integer) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_deliver_due(p_limit integer) TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text) TO authenticated;\nGRANT ALL ON FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text) TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) TO authenticated;\nGRANT ALL ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) TO service_role;\n\nREVOKE ALL ON FUNCTION public.trg_plg_reports_definitions_source() FROM PUBLIC;\nGRANT ALL ON FUNCTION public.trg_plg_reports_definitions_source() TO service_role;\n\nGRANT MAINTAIN ON TABLE public.plg_reports_runs TO anon;\nGRANT ALL ON TABLE public.plg_reports_runs TO authenticated;\nGRANT ALL ON TABLE public.plg_reports_runs TO service_role;\n\nGRANT MAINTAIN ON TABLE public.plg_reports_schedules TO anon;\nGRANT ALL ON TABLE public.plg_reports_schedules TO authenticated;\nGRANT ALL ON TABLE public.plg_reports_schedules TO service_role;\n\n\n-- ── comment ─────────────────────────────────────────────────────────────\n\nCOMMENT ON TABLE public.plg_reports_definitions IS 'The report catalogue (PRD 08). Versioned, so changing a report does not rewrite the history of everyone who ran the previous one; and \\`required_permission\\` is declared HERE rather than on a screen, so the engine can refuse before it queries.';\n\nCOMMENT ON FUNCTION public.reports_deliver_due(p_limit integer) IS 'Queue the scheduled reports that are due (PRD 08). It enqueues through the notification engine rather than sending — the same mechanism as dunning and as a campaign, which is what made building that engine first worth doing.';\n\nCOMMENT ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) IS 'Run a report from the catalogue (PRD 08). The permission is checked BEFORE the query is built — a refusal reads no rows and comes back as status=refused, recorded in plg_reports_runs — the tenant and unit predicates are injected by the engine and cannot be switched off by a definition, and an undeclared parameter is refused rather than ignored.';\n\nCOMMENT ON TABLE public.plg_reports_runs IS 'Who ran what, with which parameters, against which VERSION of the definition (PRD 08). A refusal is recorded too — \"the report is empty\" and \"you were not allowed to see it\" are different answers and the history has to keep them apart.';\n\nCOMMENT ON TABLE public.plg_reports_schedules IS 'A report on a schedule (PRD 08). Delivery is the notification engine''s job (PRD 03) — the same queue, retry and opt-out that carry a receipt carry a report, which is the whole reason that engine was built first.';\n\n\n-- ── default privileges: restore ─────────────────────────────────────────\n-- Put back, so the NEXT thing installed inherits what the chain had.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEND $dp$;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000_baseline\", sql: MIGRATION_000_BASELINE },\n]\n","import type { AnalyticsCardDef, AnalyticsColumnDef, AnalyticsFilterDef } from '@fayz-ai/core'\nimport type { ReportDef } from '../types'\n\n// ---------------------------------------------------------------------------\n// ReportDef → AnalyticsCardDef.\n//\n// Consuming apps declare hundreds of lines of ReportDef today. Rewriting them\n// all in one commit is how a refactor stalls, so the old shape keeps working: a\n// legacy report becomes a card with a table viz and no dashboard placement — it\n// appears in the report list, opens in the viewer, and simply never claims a\n// tile on the overview.\n//\n// Nothing here is lossy. When an app is ready, it upgrades a report in place by\n// adding dimensions/measures and a `dashboard` block, and the same definition\n// starts also being a chart on the overview.\n// ---------------------------------------------------------------------------\n\nexport function reportDefToCard(report: ReportDef, createdBy?: string): AnalyticsCardDef {\n return {\n id: report.id,\n name: report.name,\n description: report.description,\n icon: report.icon,\n category: report.category,\n createdBy,\n available: report.available,\n grain: report.grain,\n canonicalOwner: report.canonicalOwner,\n permission: report.permission,\n query: {\n source: {\n kind: report.dataSource.kind,\n name: report.dataSource.name,\n columnMap: report.dataSource.columnMap,\n },\n dateColumn: report.dataSource.dateColumn,\n defaultSort: report.dataSource.defaultSort,\n defaultSortDir: report.dataSource.defaultSortDir,\n filters: (report.filters ?? []).map((f): AnalyticsFilterDef => ({\n key: f.key,\n label: f.label,\n type: f.type,\n options: f.options,\n defaultValue: f.defaultValue,\n placeholder: f.placeholder,\n // Legacy filters declared no category. Grouping them under the report's\n // own category keeps the picker organised instead of dumping every\n // filter from every report into one flat list.\n group: report.category,\n })),\n },\n // No dimensions/measures: a legacy report is a detail listing, and inventing\n // aggregations for it would change what the numbers mean.\n viz: { type: 'table' },\n columns: report.columns.map((c): AnalyticsColumnDef => ({\n key: c.key,\n label: c.label,\n type: c.type as AnalyticsColumnDef['type'],\n sortable: c.sortable,\n currency: c.currency,\n idKey: c.idKey,\n personKind: c.personKind,\n renderCell: c.renderCell,\n visible: c.visible,\n align: c.align,\n aggregate: c.aggregate,\n })),\n }\n}\n\nexport function reportDefsToCards(reports: ReportDef[], createdBy?: string): AnalyticsCardDef[] {\n return reports.map((r) => reportDefToCard(r, createdBy))\n}\n","import * as React from 'react'\n\n// ---------------------------------------------------------------------------\n// \"Last viewed\" for the report list.\n//\n// A catalogue of eighty reports sorted alphabetically is a filing cabinet; the\n// three a merchant actually opens each Monday are what they came for. This is\n// per-browser rather than per-tenant on purpose — it is a convenience ordering,\n// not a business fact, and it should not cost a write to the database on every\n// report a user glances at.\n// ---------------------------------------------------------------------------\n\nconst KEY = 'fayz.analytics.lastViewed'\n\ntype LastViewedMap = Record<string, string>\n\nfunction read(): LastViewedMap {\n if (typeof window === 'undefined') return {}\n try {\n const raw = window.localStorage.getItem(KEY)\n return raw ? (JSON.parse(raw) as LastViewedMap) : {}\n } catch {\n return {}\n }\n}\n\nfunction write(map: LastViewedMap): void {\n if (typeof window === 'undefined') return\n try {\n window.localStorage.setItem(KEY, JSON.stringify(map))\n } catch {\n /* quota or private mode — losing this costs an ordering, not data */\n }\n}\n\nconst listeners = new Set<(map: LastViewedMap) => void>()\n\nexport function markViewed(cardId: string): void {\n const next = { ...read(), [cardId]: new Date().toISOString() }\n write(next)\n for (const listener of listeners) listener(next)\n}\n\nexport function useLastViewed(): LastViewedMap {\n const [map, setMap] = React.useState<LastViewedMap>(() => read())\n React.useEffect(() => {\n listeners.add(setMap)\n return () => { listeners.delete(setMap) }\n }, [])\n return map\n}\n","import * as React from 'react'\nimport type {\n AnalyticsCardDef, AnalyticsDimension, AnalyticsMeasure, AnalyticsVizType,\n} from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// What the user decided about the report catalogue.\n//\n// The catalogue itself is code: an app declares its cards, a plugin contributes\n// the ones it owns the data for. This file is the LAYER ON TOP — which of them\n// this user wants on the overview, in what order, showing which columns, plus\n// the reports they built themselves. Nothing here edits a shipped definition;\n// it records an override next to it, so an app update still moves the base\n// card and the user's choices survive it.\n//\n// A CUSTOM REPORT IS NOT A FREE-FORM QUERY. It stores a base card id plus the\n// dimensions and measures picked from that source's field palette. That is a\n// deliberate ceiling: a user cannot invent a data source, and a builder that\n// pretends otherwise produces reports that fail at read time. What they CAN do\n// is ask a different question of a source the app already exposes — which is\n// what \"quero esse relatório quebrado por praça\" actually means.\n//\n// Per-browser (localStorage), like `lastViewed`. Moving it to the tenant is a\n// swap of read/write below plus a table; every caller reads through the hook.\n// ---------------------------------------------------------------------------\n\nconst KEY = 'fayz.analytics.prefs'\n\nexport interface AnalyticsCardPref {\n /** Drop from the catalogue entirely — a built-in this tenant does not use. */\n hidden?: boolean\n /** Force onto (true) or off (false) the overview, whatever the card declares. */\n pinned?: boolean\n /** Position on the overview grid. */\n order?: number\n /** Tile width, in grid columns. */\n span?: 1 | 2 | 3 | 4\n /** Rename — the vocabulary of the house beats the vocabulary of the plugin. */\n name?: string\n /** Chart type override. */\n viz?: AnalyticsVizType\n /** Measure keys to keep. Absent = all. Ratio operands are always kept. */\n measures?: string[]\n /** Visible dimension keys to keep. Absent = all. Hidden ones always survive. */\n dimensions?: string[]\n}\n\nexport interface CustomReport {\n id: string\n name: string\n description?: string\n category: string\n icon?: string\n /** Shown in the list's \"Created by\" column — the house, not the product. */\n createdBy?: string\n /** The card whose data source this report reads. */\n baseId: string\n dimensions: string[]\n measures: string[]\n viz: AnalyticsVizType\n createdAt: string\n}\n\nexport interface AnalyticsPrefs {\n version: 1\n cards: Record<string, AnalyticsCardPref>\n custom: CustomReport[]\n}\n\nconst EMPTY: AnalyticsPrefs = { version: 1, cards: {}, custom: [] }\n\nfunction read(): AnalyticsPrefs {\n if (typeof window === 'undefined') return EMPTY\n try {\n const raw = window.localStorage.getItem(KEY)\n if (!raw) return EMPTY\n const parsed = JSON.parse(raw) as Partial<AnalyticsPrefs>\n return {\n version: 1,\n cards: parsed.cards && typeof parsed.cards === 'object' ? parsed.cards : {},\n custom: Array.isArray(parsed.custom) ? parsed.custom : [],\n }\n } catch {\n return EMPTY\n }\n}\n\nfunction write(prefs: AnalyticsPrefs): void {\n if (typeof window === 'undefined') return\n try {\n const empty = Object.keys(prefs.cards).length === 0 && prefs.custom.length === 0\n if (empty) window.localStorage.removeItem(KEY)\n else window.localStorage.setItem(KEY, JSON.stringify(prefs))\n } catch {\n /* quota / private mode */\n }\n}\n\nconst listeners = new Set<(prefs: AnalyticsPrefs) => void>()\n\nfunction publish(next: AnalyticsPrefs): void {\n write(next)\n for (const listener of listeners) listener(next)\n}\n\n/** Read the saved preferences and re-render when any surface changes them. */\nexport function useAnalyticsPrefs(): AnalyticsPrefs {\n const [prefs, setPrefs] = React.useState<AnalyticsPrefs>(() => read())\n React.useEffect(() => {\n listeners.add(setPrefs)\n return () => { listeners.delete(setPrefs) }\n }, [])\n return prefs\n}\n\n// --- mutations -------------------------------------------------------------\n\nexport function setCardPref(cardId: string, patch: AnalyticsCardPref): void {\n const current = read()\n const merged = { ...current.cards[cardId], ...patch }\n // A pref that says nothing is not a pref: drop the entry so a later app\n // update can move the base card freely.\n const meaningful = Object.entries(merged).filter(([, v]) => v !== undefined && v !== null)\n const cards = { ...current.cards }\n if (meaningful.length === 0) delete cards[cardId]\n else cards[cardId] = Object.fromEntries(meaningful) as AnalyticsCardPref\n publish({ ...current, cards })\n}\n\nexport function clearCardPref(cardId: string): void {\n const current = read()\n const cards = { ...current.cards }\n delete cards[cardId]\n publish({ ...current, cards })\n}\n\n/** Persist the overview order for the ids given, in the order given. */\nexport function setOverviewOrder(ids: string[]): void {\n const current = read()\n const cards = { ...current.cards }\n ids.forEach((id, index) => {\n cards[id] = { ...cards[id], order: index, pinned: cards[id]?.pinned ?? true }\n })\n publish({ ...current, cards })\n}\n\nexport function saveCustomReport(report: CustomReport): void {\n const current = read()\n const custom = current.custom.some((r) => r.id === report.id)\n ? current.custom.map((r) => (r.id === report.id ? report : r))\n : [...current.custom, report]\n publish({ ...current, custom })\n}\n\nexport function deleteCustomReport(id: string): void {\n const current = read()\n const cards = { ...current.cards }\n delete cards[id]\n publish({ ...current, cards, custom: current.custom.filter((r) => r.id !== id) })\n}\n\nexport function resetAnalyticsPrefs(): void {\n publish({ ...EMPTY })\n}\n\n// --- resolution ------------------------------------------------------------\n\n/**\n * Which cards read the same rows.\n *\n * A view or an RPC is named, so its name IS the identity. A function source has\n * no name the outside can see, so the card's declared `grain` stands in — two\n * cards at order grain over the same app function answer about the same rows,\n * and that is exactly the set whose fields can be mixed in one report. A card\n * with neither falls back to its own id: alone in its group, which is the safe\n * answer when nothing says otherwise.\n */\nexport function sourceKey(card: AnalyticsCardDef): string {\n const source = card.query.source\n if (source.kind === 'fn') return card.grain ? `fn:${card.grain}` : `fn:${card.id}`\n return `${source.kind}:${source.name ?? card.id}`\n}\n\nexport interface FieldPalette {\n dimensions: AnalyticsDimension[]\n measures: AnalyticsMeasure[]\n}\n\nexport interface AnalyticsSourceGroup extends FieldPalette {\n key: string\n /** A real card over this source — what a new report inherits its query from. */\n base: AnalyticsCardDef\n label: string\n}\n\n/**\n * The distinct data sources behind a catalogue, each with everything askable of\n * it.\n *\n * The builder offers THESE, not the seventeen cards: six of them read the same\n * order rows, and a source picker listing all six asks the user to choose\n * between six spellings of one answer. Sources with nothing to aggregate are\n * left out — a detail listing has no measures, and a report with no measure is\n * a table of raw rows the user already has.\n */\nexport function analyticsSources(pool: AnalyticsCardDef[]): AnalyticsSourceGroup[] {\n const groups = new Map<string, AnalyticsCardDef[]>()\n for (const card of pool) {\n const key = sourceKey(card)\n const list = groups.get(key)\n if (list) list.push(card)\n else groups.set(key, [card])\n }\n const out: AnalyticsSourceGroup[] = []\n for (const [key, cards] of groups) {\n const base = cards.find((c) => (c.query.measures?.length ?? 0) > 0)\n if (!base) continue\n const palette = fieldPalette(pool, base)\n if (palette.measures.length === 0) continue\n out.push({ key, base, label: base.name, ...palette })\n }\n return out\n}\n\n/** Every field any card offers over the same source, de-duplicated by key. */\nexport function fieldPalette(pool: AnalyticsCardDef[], base: AnalyticsCardDef): FieldPalette {\n const key = sourceKey(base)\n const dimensions = new Map<string, AnalyticsDimension>()\n const measures = new Map<string, AnalyticsMeasure>()\n for (const card of pool) {\n if (sourceKey(card) !== key) continue\n for (const d of card.query.dimensions ?? []) {\n if (!d.hidden && !dimensions.has(d.key)) dimensions.set(d.key, d)\n }\n for (const m of card.query.measures ?? []) {\n if (!measures.has(m.key)) measures.set(m.key, m)\n }\n }\n return { dimensions: [...dimensions.values()], measures: [...measures.values()] }\n}\n\n/** Ratio measures are computed from two others; keeping one without its\n * operands leaves the card dividing by a number nobody fetched. */\nfunction withRatioOperands(kept: string[], all: AnalyticsMeasure[]): Set<string> {\n const set = new Set(kept)\n for (const key of kept) {\n const measure = all.find((m) => m.key === key)\n for (const operand of measure?.ratioOf ?? []) set.add(operand)\n }\n return set\n}\n\nfunction applyPref(card: AnalyticsCardDef, pref: AnalyticsCardPref | undefined): AnalyticsCardDef {\n if (!pref) return card\n const next: AnalyticsCardDef = { ...card, query: { ...card.query }, viz: { ...card.viz } }\n\n if (pref.name) next.name = pref.name\n if (pref.viz) next.viz.type = pref.viz\n\n if (pref.measures?.length) {\n const all = card.query.measures ?? []\n const keep = withRatioOperands(pref.measures, all)\n next.query.measures = all.filter((m) => keep.has(m.key))\n // The tile's own measure pick has to stay inside what the query still\n // fetches, or a KPI ends up pointing at a column that no longer exists.\n if (card.viz.measures?.length) {\n next.viz.measures = card.viz.measures.filter((k) => keep.has(k))\n }\n }\n\n if (pref.dimensions?.length) {\n const keep = new Set(pref.dimensions)\n // Hidden dimensions survive on purpose: they carry ids and sort keys, and\n // dropping one turns a chronological axis into an alphabetical one.\n next.query.dimensions = (card.query.dimensions ?? []).filter((d) => d.hidden || keep.has(d.key))\n }\n\n const placed = pref.pinned ?? Boolean(card.dashboard && card.dashboard.defaultVisible !== false)\n if (!placed) {\n next.dashboard = undefined\n } else {\n next.dashboard = {\n ...card.dashboard,\n defaultVisible: true,\n order: pref.order ?? card.dashboard?.order ?? 999,\n span: pref.span ?? card.dashboard?.span,\n }\n }\n\n return next\n}\n\n/** A stored custom report, rebuilt against the catalogue it derives from. */\nexport function resolveCustomReport(\n report: CustomReport,\n pool: AnalyticsCardDef[],\n): AnalyticsCardDef | null {\n const base = pool.find((c) => c.id === report.baseId)\n if (!base) return null\n\n const palette = fieldPalette(pool, base)\n const dimensions = report.dimensions\n .map((key) => palette.dimensions.find((d) => d.key === key))\n .filter((d): d is AnalyticsDimension => Boolean(d))\n const keep = withRatioOperands(report.measures, palette.measures)\n const measures = palette.measures.filter((m) => keep.has(m.key))\n\n return {\n id: report.id,\n name: report.name,\n description: report.description,\n icon: report.icon ?? 'FileText',\n category: report.category,\n createdBy: report.createdBy,\n grain: base.grain,\n available: base.available,\n compare: base.compare,\n permission: base.permission,\n query: {\n source: base.query.source,\n dateColumn: base.query.dateColumn,\n dimensions,\n measures,\n filters: base.query.filters,\n defaultSort: report.measures[0] ?? dimensions[0]?.key,\n defaultSortDir: 'desc',\n },\n viz: { type: report.viz },\n }\n}\n\n/**\n * The catalogue as this user sees it: overrides applied, their own reports\n * appended, the ones they removed gone.\n */\nexport function resolveCards(catalogue: AnalyticsCardDef[], prefs: AnalyticsPrefs): AnalyticsCardDef[] {\n const custom = prefs.custom\n .map((report) => resolveCustomReport(report, catalogue))\n .filter((c): c is AnalyticsCardDef => Boolean(c))\n return [...catalogue, ...custom]\n .filter((card) => !prefs.cards[card.id]?.hidden)\n .map((card) => applyPref(card, prefs.cards[card.id]))\n}\n","import React from 'react'\nimport {\n usePluginRuntime, getAnalyticsCards, hashRouterAdapter,\n type AnalyticsCardDef, type AnalyticsProvider as AnalyticsProviderType, type AnalyticsColumnDef,\n type AnalyticsCompare, type AgentRole,\n} from '@fayz-ai/core'\nimport { AnalyticsContextProvider, type AnalyticsRangePreset } from '@fayz-ai/ui'\nimport { markViewed } from '../lib/lastViewed'\nimport { resolveCards, useAnalyticsPrefs } from '../lib/preferences'\n\n// ---------------------------------------------------------------------------\n// The surface every analytics page mounts inside.\n//\n// Cards arrive from two places and are merged here: the plugins that own the\n// data contribute them through the runtime registry (`analyticsCards` on the\n// manifest), and the host app adds or overrides via options. Registry first,\n// app last — an app curating its own pack must be able to win.\n// ---------------------------------------------------------------------------\n\nexport const ANALYTICS_BASE = '/analytics'\nexport const REPORTS_BASE = `${ANALYTICS_BASE}/reports`\nexport const SETTINGS_ROUTE = `${ANALYTICS_BASE}/settings`\n\nexport interface AnalyticsLabels {\n analytics: string\n reports: string\n liveView: string\n /** Rail entry for the card grid. Falls back to the `reports.overview` key. */\n overview?: string\n /** Rail entry for the customisation screen. Falls back to the locale key. */\n settings?: string\n overviewSubtitle: string\n reportsSubtitle: string\n searchReports: string\n category: string\n createdBy: string\n /** Cleared state of each facet chip: \"All categories\" / \"All authors\". */\n allCategories: string\n allCreatedBy: string\n lastViewed: string\n name: string\n noResults: string\n never: string\n back: string\n export: string\n print: string\n unavailableTitle: string\n unavailableDescription: string\n emptyOverviewTitle: string\n emptyOverviewDescription: string\n liveViewSoon: string\n results: string\n}\n\n/** How the assistant introduces itself on the analytics screens. Every field is\n * optional: what is not set falls back to the plugin's own locale strings. */\nexport interface AnalyticsAssistantConfig {\n /** Which colleague reads the numbers here. Defaults to the plugin's own\n * (`growth`) — an app whose analytics are a finance conversation says so. */\n role?: AgentRole\n /** Names the task here — \"Growth Analyst\". */\n persona?: string\n /** Hero headline. `{{name}}` resolves to the signed-in user's first name. */\n headline?: string\n pitch?: string\n description?: string\n placeholder?: string\n suggestions?: { label: string; prompt?: string }[]\n /** `true` opens on the hero takeover. Default FALSE here, unlike the shell's:\n * the analytics home is a page of numbers, and a full-column invitation over\n * them hides the very thing the user navigated to. The composer docks at the\n * bottom instead — the assistant is offered, the metrics stay readable. */\n auto?: boolean\n}\n\nexport interface ResolvedAnalyticsConfig {\n /** Cards declared by the host app (merged with the plugin registry at render). */\n cards: AnalyticsCardDef[]\n labels: AnalyticsLabels\n currency: { code: string; locale: string; symbol: string }\n /** Attribution for pre-built cards — the product name, e.g. \"FayzShop\". */\n createdBy: string\n defaultPageSize: number\n showHeader: boolean\n /** Range the surface opens on. A salon reads 30 days; a school reads a term. */\n defaultRange: AnalyticsRangePreset\n defaultCompare: AnalyticsCompare\n /** Whether the Live View entry appears in the module rail. */\n showLiveView: boolean\n /** `null` mounts no invite — the screen opens on its numbers, not on a\n * conversation. Otherwise: the overrides, over the locale defaults. */\n assistant: AnalyticsAssistantConfig | null\n}\n\nconst ConfigContext = React.createContext<ResolvedAnalyticsConfig | null>(null)\n\nexport function useAnalyticsConfig(): ResolvedAnalyticsConfig {\n const ctx = React.useContext(ConfigContext)\n if (!ctx) throw new Error('useAnalyticsConfig must be used inside <AnalyticsSurface>')\n return ctx\n}\n\n/**\n * The catalogue AS SHIPPED — registry + app, de-duplicated by id, with no user\n * overrides applied.\n *\n * The app's own definition wins a collision so a host can retune a card the\n * plugin shipped (relabel it, move it off the overview) without forking the\n * plugin — the alternative is apps carrying patched copies of plugin cards.\n *\n * Only the settings screen wants this: it has to show what the defaults ARE in\n * order to offer a way back to them. Everything else reads `useAnalyticsCards`.\n */\nexport function useAnalyticsCatalogue(): AnalyticsCardDef[] {\n const runtime = usePluginRuntime()\n const { cards, createdBy } = useAnalyticsConfig()\n return React.useMemo(() => {\n const byId = new Map<string, AnalyticsCardDef>()\n for (const card of getAnalyticsCards(runtime)) byId.set(card.id, card)\n for (const card of cards) byId.set(card.id, card)\n return [...byId.values()].map((c) => (c.createdBy ? c : { ...c, createdBy }))\n }, [runtime, cards, createdBy])\n}\n\n/**\n * Every card visible on this surface, with the user's own layer applied:\n * their order, their columns, their reports, minus what they removed.\n *\n * The overview, the rail, the list and the viewer all read THIS — a preference\n * that only the grid honoured would rename a card in one place and not the\n * other, which is how a \"customisable\" screen becomes two screens.\n */\nexport function useAnalyticsCards(): AnalyticsCardDef[] {\n const catalogue = useAnalyticsCatalogue()\n const prefs = useAnalyticsPrefs()\n return React.useMemo(() => resolveCards(catalogue, prefs), [catalogue, prefs])\n}\n\n/** Cards a pack placed on the overview grid, in their declared order. */\nexport function useOverviewCards(): AnalyticsCardDef[] {\n const all = useAnalyticsCards()\n return React.useMemo(\n () => all\n .filter((c) => c.dashboard && c.dashboard.defaultVisible !== false)\n .sort((a, b) => (a.dashboard?.order ?? 0) - (b.dashboard?.order ?? 0)),\n [all],\n )\n}\n\n/**\n * Columns for a card's tabular view.\n *\n * An aggregate card has no `columns` of its own — its table IS its dimensions\n * and measures, so deriving them keeps one definition instead of asking every\n * card author to restate the same fields twice and let the two drift.\n */\nexport function cardColumns(card: AnalyticsCardDef): AnalyticsColumnDef[] {\n if (card.columns?.length) return card.columns\n return [\n // A hidden dimension is group-by only — the id a person column reads from,\n // never a column of UUIDs next to the name it belongs to.\n ...(card.query.dimensions ?? []).filter((d) => !d.hidden).map((d): AnalyticsColumnDef => ({\n key: d.key,\n label: d.label,\n type: d.person ? 'person' : (d.format ?? (d.grain ? 'date' : 'text')),\n idKey: d.person?.idKey,\n personKind: d.person?.kind,\n align: 'left',\n })),\n ...(card.query.measures ?? []).map((m): AnalyticsColumnDef => ({\n key: m.key,\n label: m.label,\n type: m.format ?? 'number',\n align: 'right',\n sortable: true,\n })),\n ]\n}\n\nexport function navigateAnalytics(path: string): void {\n hashRouterAdapter().navigate(path)\n}\n\nexport interface AnalyticsSurfaceProps {\n config: ResolvedAnalyticsConfig\n provider: AnalyticsProviderType\n children?: React.ReactNode\n}\n\nexport function AnalyticsSurface({ config, provider, children }: AnalyticsSurfaceProps) {\n const openCard = React.useCallback((card: AnalyticsCardDef) => {\n markViewed(card.id)\n navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(card.id)}`)\n }, [])\n\n return (\n <ConfigContext.Provider value={config}>\n <AnalyticsContextProvider\n provider={provider}\n currency={config.currency}\n defaultPreset={config.defaultRange}\n defaultCompare={config.defaultCompare}\n defaultPageSize={config.defaultPageSize}\n onOpenCard={openCard}\n createdBy={config.createdBy}\n >\n {children}\n </AnalyticsContextProvider>\n </ConfigContext.Provider>\n )\n}\n","import React from 'react'\nimport { useTranslation } from '@fayz-ai/core'\nimport { AssistantInvite } from '@fayz-ai/admin'\nimport { useAnalyticsConfig } from './AnalyticsSurface'\n\n// ---------------------------------------------------------------------------\n// The assistant's offer on Analytics.\n//\n// It belongs to the MODULE, not to the overview: a question about a report is\n// asked while reading that report, and a composer that only exists on the home\n// screen makes the user navigate away from the number to ask about it.\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsAssistant() {\n const { assistant } = useAnalyticsConfig()\n const t = useTranslation()\n\n // Prompts the screen offers. App overrides win whole; otherwise the plugin's\n // own three, which are business questions and not report names on purpose.\n const suggestions = React.useMemo(\n () => assistant?.suggestions ?? [0, 1, 2].map((i) => ({ label: t(`reports.assistant.suggestion.${i}`) })),\n [assistant?.suggestions, t],\n )\n\n if (!assistant) return null\n\n return (\n <AssistantInvite\n // One id across the module: the same invitation followed from the grid to\n // a report, which is what lets the bar stay put instead of folding back\n // into the FAB and unrolling again on every internal navigation.\n id=\"analytics\"\n auto={assistant.auto ?? false}\n role={assistant.role ?? 'growth'}\n persona={assistant.persona ?? t('reports.assistant.persona')}\n headline={assistant.headline ?? t('reports.assistant.headline')}\n pitch={assistant.pitch ?? t('reports.assistant.pitch')}\n description={assistant.description ?? t('reports.assistant.description')}\n placeholder={assistant.placeholder ?? t('reports.assistant.placeholder')}\n suggestions={suggestions}\n />\n )\n}\n","import React from 'react'\nimport { ModulePage, useModuleLayout, type ModuleNavItem, type NavigationItem } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { AnalyticsCardDef } from '@fayz-ai/core'\nimport { useContextualNav, useShellRailAvailable } from '@fayz-ai/admin'\nimport {\n useAnalyticsConfig, useAnalyticsCards, navigateAnalytics,\n ANALYTICS_BASE, REPORTS_BASE, SETTINGS_ROUTE,\n} from './AnalyticsSurface'\nimport { AnalyticsAssistant } from './AnalyticsAssistant'\n\n// ---------------------------------------------------------------------------\n// Analytics is ONE entry in the app nav, not two.\n//\n// \"Analytics\" and \"Reports\" were two top-level links to the same engine, which\n// made the user pick a door before knowing what was behind it. There is one\n// door now; inside it, the report groups (a card's `category`) and the reports\n// themselves ARE the navigation.\n//\n// Where that navigation is drawn depends on the product's shell, and the module\n// declares the tree once either way:\n//\n// sidebar layout — it takes over the app rail, exactly as /settings does\n// (useContextualNav). A second left column beside the app\n// rail is a menu inside a menu.\n// topbar layout — there is no rail to take over, so ModulePage draws its own\n// in-page one, like every other module.\n//\n// Charts are not re-implemented here: AnalyticsCard renders through the same\n// ChartWidget the dashboard uses.\n// ---------------------------------------------------------------------------\n\nexport type AnalyticsView = 'overview' | 'reports' | 'report' | 'live' | 'settings'\n\nexport interface AnalyticsModuleProps {\n view: AnalyticsView\n /** Route param when `view === 'report'` — marks the active entry. */\n cardId?: string\n children?: React.ReactNode\n}\n\nconst reportRoute = (cardId: string) => `${REPORTS_BASE}/${encodeURIComponent(cardId)}`\n\n/** Cards by category, categories A→Z, reports A→Z inside each. */\nfunction groupCards(cards: AnalyticsCardDef[]): [string, AnalyticsCardDef[]][] {\n const groups = new Map<string, AnalyticsCardDef[]>()\n for (const card of cards) {\n const list = groups.get(card.category)\n if (list) list.push(card)\n else groups.set(card.category, [card])\n }\n return [...groups.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([category, list]) => [category, [...list].sort((a, b) => a.name.localeCompare(b.name))])\n}\n\n/** The module's whole tree, in the order both renderers walk it. */\nfunction useAnalyticsTree() {\n const t = useTranslation()\n const { labels, showLiveView } = useAnalyticsConfig()\n const cards = useAnalyticsCards()\n\n return React.useMemo(() => ({\n title: labels.analytics,\n // Only the overview. The searchable catalogue (/analytics/reports) is still\n // routed — bookmarks and the legacy /reports link resolve — but it is not\n // listed: the tree below already IS the catalogue, and a link named \"all\n // reports\" sitting above the reports reads as a different, fuller list.\n fixed: [\n { id: 'overview', label: labels.overview ?? t('reports.overview'), icon: 'BarChart3', route: ANALYTICS_BASE, view: 'overview' as const },\n ],\n groups: groupCards(cards),\n live: showLiveView\n ? { id: 'live', label: labels.liveView, icon: 'Radio', route: `${ANALYTICS_BASE}/live`, view: 'live' as const }\n : null,\n // Depois dos relatórios, não antes: é a tela que fala SOBRE a lista, e uma\n // engrenagem no topo empurra para baixo o que a pessoa veio ver.\n settings: {\n id: 'settings',\n label: labels.settings ?? t('reports.settings.nav'),\n icon: 'SlidersHorizontal',\n route: SETTINGS_ROUTE,\n view: 'settings' as const,\n },\n }), [labels, showLiveView, cards, t])\n}\n\nexport function AnalyticsModule({ view, cardId, children }: AnalyticsModuleProps) {\n const t = useTranslation()\n const { labels } = useAnalyticsConfig()\n const variant = useModuleLayout()\n const tree = useAnalyticsTree()\n const activeId = cardId ? decodeURIComponent(cardId) : undefined\n // Does a shell rail exist to take over? The SHELL answers — it is the only\n // thing that knows. Asking the module-nav context instead meant reading its\n // default ('rail' = \"draw your own\") whenever the provider was out of the\n // tree, and the app rail plus this module's own column made exactly the two\n // menus the takeover exists to remove. The context is the fallback, for a\n // module mounted outside an AdminShell at all.\n const shellRail = useShellRailAvailable()\n const claimsRail = shellRail ?? (variant !== 'rail')\n\n // --- the shell rail (sidebar layout) -------------------------------------\n const entries = React.useMemo<NavigationItem[]>(() => [\n ...tree.fixed.map((f) => ({\n id: `analytics:${f.id}`, label: f.label, icon: f.icon, route: f.route, section: 'main' as const,\n })),\n ...tree.groups.flatMap(([category, list]) => list.map((card) => ({\n id: `analytics:${card.id}`,\n label: card.name,\n icon: card.icon ?? 'FileText',\n route: reportRoute(card.id),\n section: 'main' as const,\n // Consecutive items sharing a group render under one heading — the same\n // mechanism that heads the settings rail's plugin runs.\n group: category,\n }))),\n ...(tree.live ? [{\n id: 'analytics:live', label: tree.live.label, icon: tree.live.icon, route: tree.live.route, section: 'main' as const,\n }] : []),\n {\n id: 'analytics:settings',\n label: tree.settings.label,\n icon: tree.settings.icon,\n route: tree.settings.route,\n section: 'main' as const,\n },\n ], [tree])\n\n // A busca na rail não é conforto: o catálogo do ChefControl já passa de trinta\n // relatórios em quatro grupos, e uma rail desse tamanho deixa de ser navegação\n // e vira rolagem. Quem sabe o nome do que quer não deveria caçá-lo por grupo.\n useContextualNav(claimsRail\n ? {\n base: ANALYTICS_BASE,\n entries,\n label: tree.title,\n searchPlaceholder: labels.searchReports ?? t('reports.search'),\n }\n : null)\n\n // --- the in-page rail (topbar layout) ------------------------------------\n const nav = React.useMemo<ModuleNavItem[]>(() => {\n if (claimsRail) return []\n return [\n ...tree.fixed.map((f) => ({\n id: f.id, label: f.label, icon: f.icon, active: view === f.view, onClick: () => navigateAnalytics(f.route),\n })),\n ...tree.groups.map(([category, list]): ModuleNavItem => ({\n id: `group:${category}`,\n label: category,\n children: list.map((card) => ({\n id: card.id,\n label: card.name,\n active: view === 'report' && card.id === activeId,\n onClick: () => navigateAnalytics(reportRoute(card.id)),\n })),\n })),\n ...(tree.live ? [{\n id: tree.live.id, label: tree.live.label, icon: tree.live.icon,\n active: view === 'live', onClick: () => navigateAnalytics(tree.live!.route),\n }] : []),\n {\n id: tree.settings.id, label: tree.settings.label, icon: tree.settings.icon,\n active: view === 'settings', onClick: () => navigateAnalytics(tree.settings.route),\n },\n ]\n }, [tree, view, activeId, claimsRail])\n\n return (\n <ModulePage\n title={tree.title}\n nav={nav}\n // 'sidebar' renders no sub-nav in the page: the shell rail is carrying it.\n navVariant={claimsRail ? 'sidebar' : 'rail'}\n showHeader={false}\n viewKey={view === 'report' ? `report:${activeId}` : view}\n >\n {/* Above the page body and outside its flow: the invite occupies no\n layout, it only measures where the content column is. */}\n <AnalyticsAssistant />\n {/* Tail room for the docked composer, which floats over the column —\n without it the last row of every analytics page ends underneath it. */}\n <div className=\"md:pb-16\">{children}</div>\n </ModulePage>\n )\n}\n","import React from 'react'\nimport { BarChart3 } from 'lucide-react'\nimport { AnalyticsControls, AnalyticsGrid, collectFilters } from '@fayz-ai/ui'\nimport { useAnalyticsConfig, useOverviewCards } from './AnalyticsSurface'\n\n// ---------------------------------------------------------------------------\n// The one general dashboard.\n//\n// It is not a separate feature from the report list — it is the subset of cards\n// a pack chose to place, rendered at tile size. Every tile's ↗ opens the very\n// same definition as a full report, which is why there is no \"dashboard metric\"\n// that has no report behind it.\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsOverview() {\n const { labels } = useAnalyticsConfig()\n const cards = useOverviewCards()\n const filters = React.useMemo(() => collectFilters(cards), [cards])\n\n // The assistant's invite is mounted by the module, not here: it follows the\n // user from this grid into a report instead of belonging to one screen.\n return (\n <>\n <div className=\"space-y-4\">\n {/* Sem título nem descrição: a barra da shell já escreve \"Análises\", e a\n frase abaixo custava uma linha antes do primeiro número. */}\n {/* A superfície, o encosto à direita e o grudar no topo são de\n PageToolbar agora — a mesma barra que o dashboard usa. */}\n <AnalyticsControls filters={filters} />\n\n {cards.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <BarChart3 className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"font-medium\">{labels.emptyOverviewTitle}</p>\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{labels.emptyOverviewDescription}</p>\n </div>\n ) : (\n <AnalyticsGrid cards={cards} />\n )}\n </div>\n </>\n )\n}\n","import React from 'react'\nimport { Search, User } from 'lucide-react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport {\n Card, DataTable, FilterChip, type FilterChipOption,\n} from '@fayz-ai/ui'\nimport type { AnalyticsCardDef } from '@fayz-ai/core'\nimport { useAnalyticsConfig, useAnalyticsCards, navigateAnalytics, REPORTS_BASE } from './AnalyticsSurface'\nimport { useLastViewed, markViewed } from '../lib/lastViewed'\n\n// ---------------------------------------------------------------------------\n// The one list where a user finds what they want.\n//\n// This replaces the old category-card hub. Cards-in-a-grid look richer but stop\n// working past about twenty reports: you cannot sort them, cannot see when you\n// last opened one, and finding \"sales by vendor\" means reading every tile. A\n// table sorts, scans and filters — which is what a catalogue is for.\n//\n// It renders through the shared DataTable rather than a hand-rolled <table>.\n// The first version copied DataTable's classes by hand and drifted from it\n// immediately — wrong header tint, wrong corner radius — because a copy has to\n// be re-copied every time the original moves. `variant=\"bare\"` exists for this\n// exact shape: a table under a search toolbar, inside a card that already owns\n// the border and radius.\n// ---------------------------------------------------------------------------\n\nfunction formatViewed(iso: string | undefined, locale: string, never: string): string {\n if (!iso) return never\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return never\n return d.toLocaleDateString(locale, { day: 'numeric', month: 'short', year: 'numeric' })\n}\n\nexport function ReportsListPage() {\n const { labels, currency, showHeader } = useAnalyticsConfig()\n const cards = useAnalyticsCards()\n const lastViewed = useLastViewed()\n\n const [search, setSearch] = React.useState('')\n // Single-select, like every other facet in the product (see FilterChip):\n // the chip states what is filtering right now, and picking \"all\" clears it.\n const [category, setCategory] = React.useState<string | undefined>()\n const [author, setAuthor] = React.useState<string | undefined>()\n\n const categoryOptions = React.useMemo<FilterChipOption[]>(\n () => [...new Set(cards.map((c) => c.category))]\n .sort((a, b) => a.localeCompare(b))\n .map((c) => ({ value: c, label: c })),\n [cards],\n )\n const authorOptions = React.useMemo<FilterChipOption[]>(\n () => [...new Set(cards.map((c) => c.createdBy ?? '—'))]\n .sort((a, b) => a.localeCompare(b))\n .map((a) => ({ value: a, label: a })),\n [cards],\n )\n\n const rows = React.useMemo(() => {\n const q = search.trim().toLowerCase()\n return cards.filter((card) => {\n if (category && card.category !== category) return false\n if (author && (card.createdBy ?? '—') !== author) return false\n if (!q) return true\n // Description is searched too: users look for \"no-show\" long before they\n // remember a report is filed under \"Cancellations\".\n return card.name.toLowerCase().includes(q)\n || card.description?.toLowerCase().includes(q)\n || card.category.toLowerCase().includes(q)\n })\n }, [cards, search, category, author])\n\n const columns = React.useMemo<ColumnDef<AnalyticsCardDef, unknown>[]>(() => [\n {\n id: 'name',\n accessorFn: (card) => card.name,\n header: labels.name,\n cell: ({ row }) => (\n <div className=\"min-w-0\">\n <span className=\"font-medium\">{row.original.name}</span>\n {row.original.available === false ? (\n <span className=\"ml-2 rounded-full border px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n {labels.unavailableTitle}\n </span>\n ) : null}\n {row.original.description ? (\n <p className=\"mt-0.5 line-clamp-1 text-muted-foreground sm:hidden\">{row.original.description}</p>\n ) : null}\n </div>\n ),\n },\n {\n id: 'category',\n accessorFn: (card) => card.category,\n header: labels.category,\n cell: ({ getValue }) => (\n <span className=\"rounded-md bg-muted px-2 py-0.5\">{String(getValue() ?? '')}</span>\n ),\n },\n {\n id: 'lastViewed',\n // Sorts on the timestamp, renders the date. Never-opened reports carry\n // undefined so they sink to the bottom in BOTH directions rather than\n // topping \"most recent\" as an epoch-zero date.\n accessorFn: (card) => {\n const iso = lastViewed[card.id]\n return iso ? new Date(iso).getTime() : undefined\n },\n sortUndefined: 1,\n header: labels.lastViewed,\n cell: ({ row }) => (\n <span className=\"text-muted-foreground\">\n {formatViewed(lastViewed[row.original.id], currency.locale, labels.never)}\n </span>\n ),\n },\n {\n id: 'createdBy',\n accessorFn: (card) => card.createdBy ?? '—',\n header: labels.createdBy,\n cell: ({ getValue }) => (\n <span className=\"inline-flex items-center gap-1.5 text-muted-foreground\">\n <User className=\"h-3 w-3\" />\n {String(getValue() ?? '—')}\n </span>\n ),\n },\n ], [labels, currency.locale, lastViewed])\n\n const open = (card: AnalyticsCardDef) => {\n markViewed(card.id)\n navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(card.id)}`)\n }\n\n return (\n <div className=\"space-y-4\">\n {showHeader ? (\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">{labels.reports}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{labels.reportsSubtitle}</p>\n </div>\n ) : null}\n\n {/* Same composition as CrudListView: search, tools and the table are ONE\n surface, because they act on the same rows. The Card owns the border\n and radius, so the table inside goes `bare`. */}\n <Card className=\"overflow-hidden\">\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2\">\n <div className=\"min-w-[10rem] flex-1\">\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground\" />\n {/* Borderless, exactly as CrudListView's search box: the card\n already draws the boundary, and a second box inside it would\n be a frame inside a frame. */}\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={labels.searchReports}\n className=\"w-full bg-transparent py-1.5 pl-8 pr-3 text-sm placeholder:text-muted-foreground focus:outline-none\"\n />\n </div>\n </div>\n\n <div className=\"flex shrink-0 flex-wrap items-center gap-1.5\">\n <FilterChip\n label={labels.category}\n allLabel={labels.allCategories}\n options={categoryOptions}\n value={category}\n onChange={setCategory}\n />\n <FilterChip\n label={labels.createdBy}\n allLabel={labels.allCreatedBy}\n options={authorOptions}\n value={author}\n onChange={setAuthor}\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n data={rows}\n variant=\"bare\"\n compact\n onRowClick={open}\n emptyMessage={labels.noResults}\n />\n\n <div className=\"border-t border-border px-3 py-2 text-xs text-muted-foreground\">\n {rows.length} {labels.results}\n </div>\n </Card>\n </div>\n )\n}\n","import { exportCSV } from '@fayz-ai/core'\nimport type { CSVColumn } from '@fayz-ai/core'\nimport type { ReportColumnDef } from '../types'\nimport { expandBagColumns, formatValuePlain } from '../lib/columns'\n\nexport function exportToCsv(\n columns: ReportColumnDef[],\n data: Record<string, any>[],\n filename: string,\n currency?: string,\n): void {\n // Uma coluna por resposta de formulário, não um JSON dentro da célula: é o\n // que deixa a planilha ordenável e filtrável por \"Estilo\".\n const { columns: cols, rows } = expandBagColumns(columns, data)\n const visibleCols = cols.filter((c) => c.visible !== false)\n\n const csvColumns: CSVColumn[] = visibleCols.map((col) => ({\n key: col.key,\n label: col.label,\n format: (value: any) => formatValuePlain(value, col, currency),\n }))\n\n exportCSV(csvColumns, rows, filename)\n}\n","import React, { useEffect, useState } from 'react'\nimport { Download } from 'lucide-react'\nimport {\n Dropdown,\n DropdownTrigger,\n DropdownContent,\n DropdownItem,\n ToolbarAction,\n} from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { ReportColumnDef } from '../types'\nimport { exportToCsv } from '../export/csv'\n\ninterface ExportDropdownProps {\n columns: ReportColumnDef[]\n data: Record<string, any>[]\n filename: string\n currency?: string\n title?: string\n /**\n * Fetch the WHOLE result set. The table on screen is one page of 50, and a\n * file holding 50 of 4,000 rows says nothing about being a fragment — so the\n * export asks for everything before it writes. Absent ⇒ the page is exported.\n */\n fetchAll?: () => Promise<Record<string, any>[]>\n}\n\nexport function ExportDropdown({ columns, data, filename, currency, title, fetchAll }: ExportDropdownProps) {\n const t = useTranslation()\n const [excelAvailable, setExcelAvailable] = useState(false)\n const [pdfAvailable, setPdfAvailable] = useState(false)\n const [busy, setBusy] = useState(false)\n\n useEffect(() => {\n import('../export/excel').then((m) => m.isExcelAvailable()).then(setExcelAvailable).catch(() => {})\n import('../export/pdf').then((m) => m.isPdfAvailable()).then(setPdfAvailable).catch(() => {})\n }, [])\n\n // One writer for the three formats: whichever one is picked, the rows come\n // from the same fetch, so a CSV and a PDF of the same report cannot hold\n // different numbers of lines. A failed fetch falls back to the page on\n // screen — a partial file beats a button that does nothing.\n const withRows = async (write: (rows: Record<string, any>[]) => void | Promise<void>) => {\n if (busy) return\n setBusy(true)\n try {\n const rows = fetchAll ? await fetchAll().catch(() => data) : data\n await write(rows.length ? rows : data)\n } finally {\n setBusy(false)\n }\n }\n\n const handleCsv = () => withRows((rows) => exportToCsv(columns, rows, filename, currency))\n\n const handleExcel = () => withRows(async (rows) => {\n const { exportToExcel } = await import('../export/excel')\n await exportToExcel(columns, rows, filename, currency)\n })\n\n const handlePdf = () => withRows(async (rows) => {\n const { exportToPdf } = await import('../export/pdf')\n await exportToPdf(columns, rows, filename, { title, currency })\n })\n\n return (\n <Dropdown>\n <DropdownTrigger asChild>\n {/* Sem contorno, como o resto da barra — ver ToolbarAction. */}\n <ToolbarAction icon={Download} caret disabled={busy}>{t('reports.export')}</ToolbarAction>\n </DropdownTrigger>\n <DropdownContent align=\"end\">\n <DropdownItem onClick={handleCsv}>{t('reports.exportCsv')}</DropdownItem>\n {excelAvailable && (\n <DropdownItem onClick={handleExcel}>{t('reports.exportExcel')}</DropdownItem>\n )}\n {pdfAvailable && (\n <DropdownItem onClick={handlePdf}>{t('reports.exportPdf')}</DropdownItem>\n )}\n </DropdownContent>\n </Dropdown>\n )\n}\n","import React from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { useTranslation } from '@fayz-ai/core'\nimport { Button } from '@fayz-ai/ui'\n\ninterface ReportPaginationProps {\n page: number\n pageSize: number\n total: number\n onPageChange: (page: number) => void\n onPageSizeChange: (size: number) => void\n}\n\nexport function ReportPagination({ page, pageSize, total, onPageChange, onPageSizeChange }: ReportPaginationProps) {\n // Translated, not literal: this row printed \"1–12 of 12\" and \"50 / page\"\n // under a pt-BR shell, which is the one place a user counts on the app\n // knowing what language it speaks.\n const t = useTranslation()\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n const from = (page - 1) * pageSize + 1\n const to = Math.min(page * pageSize, total)\n\n return (\n <div className=\"flex items-center justify-between border-t px-4 py-3\">\n <div className=\"text-sm text-muted-foreground\">\n {total > 0 ? t('reports.pagination.range', { from, to, total }) : t('reports.pagination.empty')}\n </div>\n\n <div className=\"flex items-center gap-3\">\n <select\n value={pageSize}\n onChange={(e) => onPageSizeChange(Number(e.target.value))}\n className=\"h-8 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 text-sm\"\n >\n {[25, 50, 100].map((size) => (\n <option key={size} value={size}>{t('reports.pagination.perPage', { size })}</option>\n ))}\n </select>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={page <= 1}\n onClick={() => onPageChange(page - 1)}\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <span className=\"text-sm px-2\">\n {page} / {totalPages}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={page >= totalPages}\n onClick={() => onPageChange(page + 1)}\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport { ArrowLeft, Construction, Printer } from 'lucide-react'\nimport {\n Button, SubpageHeader, ToolbarAction, AnalyticsCard, AnalyticsControls,\n useAnalyticsContext, useAnalyticsCard, useAnalyticsCardRows, useAnalyticsAllRows,\n useToolbarPanelClose,\n} from '@fayz-ai/ui'\nimport type { AnalyticsCardDef, AnalyticsRow } from '@fayz-ai/core'\nimport { DataTable, StatementTable, formatBucket } from '@fayz-ai/ui'\nimport { expandBagColumns, reportColumnsToTanstack } from '../lib/columns'\nimport { ExportDropdown } from '../components/ExportDropdown'\nimport { ReportPagination } from '../components/ReportPagination'\nimport type { ReportColumnDef } from '../types'\nimport {\n useAnalyticsConfig, useAnalyticsCards, cardColumns, navigateAnalytics,\n ANALYTICS_BASE, REPORTS_BASE,\n} from './AnalyticsSurface'\nimport { markViewed } from '../lib/lastViewed'\n\n// ---------------------------------------------------------------------------\n// A report, full size.\n//\n// The chart is not decoration bolted onto a table: it is the SAME card that\n// renders as a tile on the overview, given the whole width. Underneath sits the\n// data it was computed from — so \"show me the number\" and \"show me the rows\n// behind the number\" stop being two different features in two different places.\n// ---------------------------------------------------------------------------\n\nfunction ViewerBody({ card }: { card: AnalyticsCardDef }) {\n const { labels, currency, defaultRange } = useAnalyticsConfig()\n const { state, setPage, setPageSize, setPreset } = useAnalyticsContext()\n const cardDefaultRange = (card as AnalyticsCardDef & { defaultRange?: typeof defaultRange }).defaultRange\n React.useEffect(() => {\n if (!cardDefaultRange) return\n setPreset(cardDefaultRange)\n return () => setPreset(defaultRange)\n }, [card.id, cardDefaultRange, defaultRange, setPreset])\n const isStatement = card.viz.type === 'statement' && !!card.viz.statement\n // Same query as the chart above and the export below — the provider\n // de-duplicates them into one round trip.\n // A statement reads the whole set below. Running the paged card query too\n // executed the same heavy DRE twice and made both requests hit the timeout.\n const { result, loading, error, engineMissing } = useAnalyticsCard(card, { enabled: !isStatement })\n // Um demonstrativo lê o CONJUNTO, nunca a página — ver `useAnalyticsAllRows`.\n const all = useAnalyticsAllRows(card, isStatement && card.available !== false)\n\n const columns = React.useMemo(() => cardColumns(card), [card])\n // As respostas do formulário viram COLUNAS de verdade — \"Estilo\", \"Perfil\" —\n // descobertas nas linhas desta página, porque cada campanha pergunta outra\n // coisa e declarar as colunas no card tornaria o próximo formulário\n // invisível. Mesma expansão que a planilha usa, então tela e arquivo mostram\n // as mesmas colunas.\n const expanded = React.useMemo(\n () => expandBagColumns(columns as unknown as ReportColumnDef[], (result?.rows ?? []) as Record<string, any>[]),\n [columns, result?.rows],\n )\n const tanstackColumns = React.useMemo(\n () => reportColumnsToTanstack(expanded.columns, currency.code),\n [expanded.columns, currency.code],\n )\n const rows = expanded.rows\n\n if (card.available === false) {\n return (\n <div className=\"flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Construction className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"font-medium\">{labels.unavailableTitle}</p>\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{labels.unavailableDescription}</p>\n </div>\n )\n }\n\n // A pure detail listing has nothing to chart — rendering an empty card frame\n // above the table would be chrome pretending to be information.\n const hasViz = card.viz.type !== 'table' || (card.query.measures?.length ?? 0) > 0\n\n // Um demonstrativo JÁ É a tela inteira. Repetir as mesmas linhas embaixo como\n // grade plana daria duas respostas para a mesma pergunta — e a de baixo, sem\n // hierarquia nem totalizadores, é a pior das duas.\n if (isStatement && card.viz.statement) {\n return (\n <>\n {engineMissing ? (\n <div className=\"rounded-lg border bg-muted/40 p-3 text-sm\">\n <p className=\"font-medium\">Analytics engine not installed</p>\n <p className=\"mt-0.5 text-muted-foreground\">\n This report aggregates server-side and needs migration 0039\n (<code className=\"text-xs\">analytics_run</code> + the read models) applied to this project.\n </p>\n </div>\n ) : (error ?? all.error) ? (\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive\">\n {error ?? all.error}\n </div>\n ) : null}\n <StatementTable\n rows={all.rows}\n def={card.viz.statement}\n currency={currency}\n formatPeriod={(p) => formatBucket(p, 'month')}\n emptyMessage={labels.noResults}\n loading={all.loading}\n />\n </>\n )\n }\n\n return (\n <>\n {hasViz ? (\n <AnalyticsCard\n card={{ ...card, viz: { ...card.viz, height: card.viz.height ?? 280, limit: undefined } }}\n hideOpen\n />\n ) : null}\n\n {engineMissing ? (\n <div className=\"rounded-lg border bg-muted/40 p-3 text-sm\">\n <p className=\"font-medium\">Analytics engine not installed</p>\n <p className=\"mt-0.5 text-muted-foreground\">\n This report aggregates server-side and needs migration 0039\n (<code className=\"text-xs\">analytics_run</code> + the read models) applied to this project.\n </p>\n </div>\n ) : error ? (\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive\">\n {error}\n </div>\n ) : null}\n\n {/* `print-flow`: sem ele a regra de cartão (`break-inside: avoid`) prende a\n tabela inteira numa página e o resto do relatório não sai no papel. */}\n <div className=\"print-flow\">\n <DataTable\n columns={tanstackColumns}\n data={rows}\n loading={loading}\n skeletonRows={5}\n emptyMessage={labels.noResults}\n variant=\"card\"\n compact\n />\n </div>\n\n {!loading ? (\n <div className=\"no-print\">\n <ReportPagination\n page={state.page}\n pageSize={state.pageSize}\n total={result?.total ?? 0}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n </div>\n ) : null}\n </>\n )\n}\n\nexport function AnalyticsReportViewer({ cardId }: { cardId?: string }) {\n const { labels } = useAnalyticsConfig()\n const cards = useAnalyticsCards()\n const card = cards.find((c) => c.id === decodeURIComponent(cardId ?? ''))\n\n React.useEffect(() => { if (card) markViewed(card.id) }, [card?.id])\n\n if (!card) {\n return (\n <div className=\"space-y-4\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateAnalytics(REPORTS_BASE)}>\n <ArrowLeft className=\"mr-1.5 h-3.5 w-3.5\" />\n {labels.reports}\n </Button>\n <p className=\"py-12 text-center text-sm text-muted-foreground\">{labels.noResults}</p>\n </div>\n )\n }\n\n return (\n <div className=\"space-y-4\">\n {/* O título vive na barra da shell, não no corpo. Escrever \"← Relatórios /\n Nome\" aqui E deixar a rota declarar `parentRoute` produzia três\n cabeçalhos empilhados dizendo a mesma coisa. SubpageHeader reivindica a\n barra com o nome do card — que depende de dado e por isso não cabe em\n `route.title`. */}\n {/* A descrição vai para o (i) do breadcrumb, não para um parágrafo aqui.\n Era uma linha inteira entre o nome do relatório e o número que a\n pessoa abriu a tela para ver — lida uma vez, ruído em todas as\n visitas seguintes. No ícone ela continua a um gesto de distância. */}\n <SubpageHeader\n title={card.name}\n description={card.description}\n parentLabel={labels.analytics}\n onBack={() => navigateAnalytics(ANALYTICS_BASE)}\n />\n\n <AnalyticsControls\n filters={card.query.filters ?? []}\n showCompare={card.compare !== false}\n className=\"no-print\"\n actions={<ViewerActions card={card} />}\n />\n\n <ViewerBody card={card} />\n </div>\n )\n}\n\nfunction ViewerActions({ card }: { card: AnalyticsCardDef }) {\n const { currency, labels } = useAnalyticsConfig()\n const closePanel = useToolbarPanelClose()\n // Imprimir a partir de dentro do painel imprimia o PAINEL: `window.print()`\n // congela o documento como ele está, e como está inclui o popover aberto por\n // cima do relatório. Fecha primeiro, deixa o navegador pintar o quadro sem\n // ele, e só então manda imprimir.\n const print = React.useCallback(() => {\n closePanel()\n requestAnimationFrame(() => {\n requestAnimationFrame(() => window.setTimeout(() => window.print(), 120))\n })\n }, [closePanel])\n const { result } = useAnalyticsCard(card)\n const columns = React.useMemo(() => cardColumns(card), [card])\n // O arquivo leva o relatório INTEIRO, não a página de 50 que está na tela:\n // uma planilha com 50 de 4.000 leads não avisa em lugar nenhum que é um\n // pedaço, e é ela que sai por e-mail como se fosse o mês fechado.\n const fetchAll = useAnalyticsCardRows(card)\n if (!result?.rows?.length) return null\n return (\n <>\n <ExportDropdown\n columns={columns as unknown as ReportColumnDef[]}\n data={result.rows as Record<string, unknown>[]}\n fetchAll={fetchAll as () => Promise<Record<string, any>[]>}\n filename={card.id}\n currency={currency.code}\n title={card.name}\n />\n <ToolbarAction icon={Printer} onClick={print}>{labels.print}</ToolbarAction>\n </>\n )\n}\n","import React from 'react'\nimport { Radio } from 'lucide-react'\nimport { useAnalyticsConfig } from './AnalyticsSurface'\n\n// ---------------------------------------------------------------------------\n// Live View — the real-time surface.\n//\n// A deliberate stub. It needs a storefront event stream (sessions, carts,\n// checkouts) that does not exist yet, and the honest thing on a page with no\n// data source is to say so rather than render zeroes that look like a quiet\n// afternoon. It holds its nav slot so the shape of the section is visible.\n// ---------------------------------------------------------------------------\n\nexport function LiveViewPage() {\n const { labels } = useAnalyticsConfig()\n return (\n <div className=\"flex flex-col items-center justify-center rounded-xl border border-dashed py-20 text-center\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Radio className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"font-medium\">{labels.liveView}</p>\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{labels.liveViewSoon}</p>\n </div>\n )\n}\n","import React from 'react'\nimport {\n Eye, EyeOff, GripVertical, RotateCcw, SlidersHorizontal, Trash2,\n ChevronUp, ChevronDown,\n} from 'lucide-react'\nimport type {\n AnalyticsCardDef, AnalyticsVizType, PluginAITool, PluginQuickAction,\n} from '@fayz-ai/core'\nimport { useTranslation } from '@fayz-ai/core'\nimport {\n Badge, Button, Card, Checkbox, Input, PageHeaderActions, SubpageHeader, getLucideIcon,\n Select, SelectTrigger, SelectValue, SelectContent, SelectItem,\n} from '@fayz-ai/ui'\nimport {\n QuickActionsButton, RightRailPage, askAI, useAgentSurface,\n type AgentSurfaceContribution, type AskAIIntro,\n} from '@fayz-ai/admin'\nimport {\n useAnalyticsConfig, useAnalyticsCatalogue, useAnalyticsCards, navigateAnalytics,\n ANALYTICS_BASE, REPORTS_BASE,\n} from './AnalyticsSurface'\nimport {\n analyticsSources, clearCardPref, deleteCustomReport, resetAnalyticsPrefs, saveCustomReport,\n setCardPref, setOverviewOrder, useAnalyticsPrefs,\n type AnalyticsSourceGroup, type CustomReport,\n} from '../lib/preferences'\n\n// ---------------------------------------------------------------------------\n// Configurar relatórios.\n//\n// One screen for the four things a user asks of a report catalogue: which ones\n// I see, in what order, what each one shows, and one of my own.\n//\n// It edits the PREFERENCE LAYER (lib/preferences), never the shipped card. Two\n// consequences worth stating: an app update still moves the base definition\n// under a user's choices instead of being overwritten by them, and \"restaurar\n// padrões\" is a delete, not a re-import — there is always a way back.\n//\n// Reordering is native drag-and-drop plus up/down buttons. Both, not either:\n// the drag is what a mouse expects and the buttons are what a keyboard, a\n// screen reader and a touch screen can actually use.\n// ---------------------------------------------------------------------------\n\nconst VIZ_TYPES: AnalyticsVizType[] = ['kpi', 'line', 'bar', 'area', 'donut', 'breakdown', 'table']\n\n/** A card with nothing to group by has no category axis — only a headline\n * number or a row listing can honestly render it. */\nfunction vizOptionsFor(card: AnalyticsCardDef): AnalyticsVizType[] {\n const hasDimension = (card.query.dimensions ?? []).some((d) => !d.hidden)\n return hasDimension ? VIZ_TYPES : ['kpi', 'table']\n}\n\nfunction CardIcon({ name, className }: { name?: string; className?: string }) {\n const Icon = getLucideIcon(name ?? 'FileText') ?? getLucideIcon('FileText')\n return Icon ? <Icon className={className} /> : null\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\ninterface RowProps {\n card: AnalyticsCardDef\n custom: boolean\n onEdit: () => void\n children?: React.ReactNode\n drag?: {\n onDragStart: () => void\n onDragOver: (event: React.DragEvent) => void\n onDragEnd: () => void\n dragging: boolean\n }\n}\n\nfunction ReportRow({ card, custom, onEdit, children, drag }: RowProps) {\n const t = useTranslation()\n return (\n <li\n draggable={Boolean(drag)}\n onDragStart={drag?.onDragStart}\n onDragOver={drag?.onDragOver}\n onDragEnd={drag?.onDragEnd}\n className={[\n 'flex items-center gap-2 border-b border-border/60 px-3 py-2 last:border-0',\n drag ? 'cursor-grab active:cursor-grabbing' : '',\n drag?.dragging ? 'opacity-40' : '',\n ].join(' ')}\n >\n {drag ? (\n <GripVertical className=\"h-4 w-4 shrink-0 text-muted-foreground/50\" aria-hidden />\n ) : (\n <span className=\"w-4 shrink-0\" aria-hidden />\n )}\n <CardIcon name={card.icon} className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium\">{card.name}</span>\n {custom ? <Badge variant=\"secondary\">{t('reports.settings.custom')}</Badge> : null}\n </div>\n <p className=\"truncate text-xs text-muted-foreground\">{card.category}</p>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {children}\n <Button variant=\"ghost\" size=\"sm\" onClick={onEdit} aria-label={t('reports.settings.edit')} title={t('reports.settings.edit')}>\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n </li>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Editor — one card's name, chart and columns\n// ---------------------------------------------------------------------------\n\nfunction CardEditor({ card, onClose }: { card: AnalyticsCardDef; onClose: () => void }) {\n const t = useTranslation()\n const prefs = useAnalyticsPrefs()\n const pref = prefs.cards[card.id] ?? {}\n const isCustom = prefs.custom.some((r) => r.id === card.id)\n\n const [name, setName] = React.useState(card.name)\n const measures = card.query.measures ?? []\n const dimensions = (card.query.dimensions ?? []).filter((d) => !d.hidden)\n\n const keptMeasures = new Set(pref.measures ?? measures.map((m) => m.key))\n const keptDimensions = new Set(pref.dimensions ?? dimensions.map((d) => d.key))\n\n const toggle = (set: Set<string>, key: string, field: 'measures' | 'dimensions', all: string[]) => {\n const next = new Set(set)\n if (next.has(key)) next.delete(key)\n else next.add(key)\n // Everything selected is the same as no preference — record it as one and\n // the card stops tracking a list it would have to keep in sync forever.\n setCardPref(card.id, { [field]: next.size === all.length ? undefined : [...next] })\n }\n\n return (\n // A coluna da direita, não uma gaveta só desta tela: ajustar um relatório é\n // olhar a lista enquanto se mexe nele, e uma gaveta cobre exatamente a\n // lista. É a mesma coluna do assistente — RightRailPage cai numa Sheet\n // sozinha quando a shell não tem coluna nenhuma.\n <RightRailPage title={card.name} open onClose={onClose} width=\"max-w-md\">\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">\n <div className=\"space-y-5\">\n {card.description ? (\n <p className=\"text-sm text-muted-foreground\">{card.description}</p>\n ) : null}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.name')}</label>\n <Input\n value={name}\n onChange={(e) => setName(e.target.value)}\n onBlur={() => setCardPref(card.id, { name: name.trim() && name !== card.name ? name.trim() : undefined })}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.viz')}</label>\n <Select\n value={card.viz.type}\n onValueChange={(value) => setCardPref(card.id, { viz: value as AnalyticsVizType })}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {vizOptionsFor(card).map((viz) => (\n <SelectItem key={viz} value={viz}>{t(`reports.viz.${viz}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {dimensions.length > 0 ? (\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.dimensions')}</p>\n {dimensions.map((d) => (\n <label key={d.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n checked={keptDimensions.has(d.key)}\n onChange={() => toggle(keptDimensions, d.key, 'dimensions', dimensions.map((x) => x.key))}\n />\n {d.label}\n </label>\n ))}\n </div>\n ) : null}\n\n {measures.length > 0 ? (\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.measures')}</p>\n {measures.map((m) => (\n <label key={m.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n checked={keptMeasures.has(m.key)}\n onChange={() => toggle(keptMeasures, m.key, 'measures', measures.map((x) => x.key))}\n />\n {m.label}\n </label>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n\n {/* Sem \"Salvar\": cada controle grava ao mudar, e a coluna reflete o\n resultado atrás dela. O rodapé guarda só a saída — o desfazer. */}\n <div className=\"flex items-center justify-between border-t border-border p-3\">\n {isCustom ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { deleteCustomReport(card.id); onClose() }}>\n <Trash2 className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.delete')}\n </Button>\n ) : (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { clearCardPref(card.id); onClose() }}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.resetCard')}\n </Button>\n )}\n <Button size=\"sm\" onClick={onClose}>{t('reports.settings.done')}</Button>\n </div>\n </RightRailPage>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Builder — a new report over a source the app already exposes\n// ---------------------------------------------------------------------------\n\nfunction slugify(value: string): string {\n return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'report'\n}\n\n/** Build a stored report from validated pieces. Shared by the form and by the\n * assistant's tool, so both produce the same object. */\nexport function buildCustomReport(input: {\n name: string\n category: string\n createdBy?: string\n source: AnalyticsSourceGroup\n dimensions: string[]\n measures: string[]\n viz: AnalyticsVizType\n}): CustomReport {\n const dimensionKeys = new Set(input.source.dimensions.map((d) => d.key))\n const measureKeys = new Set(input.source.measures.map((m) => m.key))\n return {\n id: `custom.${slugify(input.name)}-${Date.now().toString(36)}`,\n name: input.name.trim(),\n category: input.category.trim() || 'Geral',\n icon: 'FileText',\n createdBy: input.createdBy,\n baseId: input.source.base.id,\n // Filtered, not trusted: a field the source does not have would resolve to\n // nothing and the report would open empty with no explanation.\n dimensions: input.dimensions.filter((k) => dimensionKeys.has(k)),\n measures: input.measures.filter((k) => measureKeys.has(k)),\n viz: input.viz,\n createdAt: new Date().toISOString(),\n }\n}\n\nfunction NewReportPanel({\n sources, categories, onClose,\n}: { sources: AnalyticsSourceGroup[]; categories: string[]; onClose: () => void }) {\n const t = useTranslation()\n const { createdBy } = useAnalyticsConfig()\n\n const [name, setName] = React.useState('')\n const [category, setCategory] = React.useState(categories[0] ?? 'Geral')\n const [sourceKeyState, setSourceKey] = React.useState(sources[0]?.key ?? '')\n const [dimensions, setDimensions] = React.useState<string[]>([])\n const [measures, setMeasures] = React.useState<string[]>([])\n const [viz, setViz] = React.useState<AnalyticsVizType>('table')\n\n const source = sources.find((s) => s.key === sourceKeyState)\n\n // Switching source invalidates every field picked from the old one.\n React.useEffect(() => { setDimensions([]); setMeasures([]) }, [sourceKeyState])\n\n const toggle = (list: string[], set: (next: string[]) => void, key: string) => {\n set(list.includes(key) ? list.filter((k) => k !== key) : [...list, key])\n }\n\n const error = !name.trim()\n ? t('reports.settings.needName')\n : measures.length === 0\n ? t('reports.settings.needMeasure')\n : null\n\n const submit = () => {\n if (error || !source) return\n saveCustomReport(buildCustomReport({\n name, category, createdBy, source, dimensions, measures, viz,\n }))\n onClose()\n }\n\n return (\n <RightRailPage title={t('reports.settings.new')} open onClose={onClose} width=\"max-w-md\">\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">\n <div className=\"space-y-5\">\n {/* Só o caminho manual. \"Criar com IA\" mora na barra do cabeçalho, ao\n lado do botão que abre este painel — duas portas para a mesma sala,\n uma dentro da outra, é o desenho que faz a de fora parecer inútil. */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.name')}</label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.category')}</label>\n <Input value={category} onChange={(e) => setCategory(e.target.value)} list=\"fayz-analytics-categories\" />\n <datalist id=\"fayz-analytics-categories\">\n {categories.map((c) => <option key={c} value={c} />)}\n </datalist>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.source')}</label>\n <Select value={sourceKeyState} onValueChange={setSourceKey}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {sources.map((s) => (\n <SelectItem key={s.key} value={s.key}>{s.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-xs text-muted-foreground\">{t('reports.settings.sourceHint')}</p>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.dimensions')}</p>\n {(source?.dimensions ?? []).length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">—</p>\n ) : source!.dimensions.map((d) => (\n <label key={d.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox checked={dimensions.includes(d.key)} onChange={() => toggle(dimensions, setDimensions, d.key)} />\n {d.label}\n </label>\n ))}\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.measures')}</p>\n {(source?.measures ?? []).map((m) => (\n <label key={m.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox checked={measures.includes(m.key)} onChange={() => toggle(measures, setMeasures, m.key)} />\n {m.label}\n </label>\n ))}\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.viz')}</label>\n <Select value={viz} onValueChange={(value) => setViz(value as AnalyticsVizType)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {(dimensions.length > 0 ? VIZ_TYPES : (['kpi', 'table'] as AnalyticsVizType[])).map((v) => (\n <SelectItem key={v} value={v}>{t(`reports.viz.${v}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-2 border-t border-border p-3\">\n <span className=\"truncate text-xs text-destructive\">{error}</span>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose}>{t('reports.settings.cancel')}</Button>\n <Button size=\"sm\" onClick={submit} disabled={Boolean(error)}>{t('reports.settings.save')}</Button>\n </div>\n </div>\n </RightRailPage>\n )\n}\n\n// ---------------------------------------------------------------------------\n// The assistant's way in\n//\n// Choosing a source, then dimensions, then measures is exactly the work someone\n// who already knows what they want should not have to do — and it is the work a\n// model does well GIVEN THE FIELD TABLE, which is why `describe()` below ships\n// every source with its askable fields rather than a prose summary.\n//\n// Client-plane on purpose: a custom report is a per-browser preference, not a\n// row in the tenant. The executor is the same `buildCustomReport` the form\n// calls, so a report built by conversation and one built by clicking are the\n// same object with the same guarantees.\n// ---------------------------------------------------------------------------\n\nconst CREATE_REPORT_TOOL: PluginAITool = {\n id: 'reports.createAnalyticsReport',\n name: 'createAnalyticsReport',\n description:\n 'Creates a custom analytics report for this user. Pick ONE source from the `sources` list in the surface state, then group_by and measures USING ONLY that source\\'s field keys — a key from another source resolves to nothing and the report opens empty. '\n + 'Understand the intent and propose the whole report in one call instead of asking field by field. '\n + 'Rules of thumb: one time dimension + one measure reads best as a line; a category dimension with one measure as bar or breakdown; three or more measures as a table; no dimension at all as a kpi.',\n icon: 'FileText',\n mode: 'persist',\n execution: { plane: 'client' },\n category: 'Analytics',\n suggestions: [\n { label: 'Um relatório de receita por mesa' },\n { label: 'Quanto cada praça produz por turno' },\n ],\n parameters: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Report name, in the user\\'s language.' },\n source: { type: 'string', description: 'A `key` from the surface state\\'s `sources`.' },\n group_by: {\n type: 'array',\n description: 'Dimension keys from that source. Empty means a single headline number.',\n items: { type: 'string' },\n },\n measures: {\n type: 'array',\n description: 'Measure keys from that source. At least one.',\n items: { type: 'string' },\n },\n viz: {\n type: 'string',\n enum: ['kpi', 'line', 'bar', 'area', 'donut', 'breakdown', 'table'],\n description: 'How to draw it. Defaults to table.',\n },\n category: { type: 'string', description: 'Group it sits under in the rail. Reuse an existing one when it fits.' },\n pin: { type: 'boolean', description: 'Also place it on the overview grid.' },\n },\n required: ['name', 'source', 'measures'],\n },\n}\n\nconst AGENT_INSTRUCTIONS =\n 'The user is on the report configuration screen. `sources` in the surface state lists every data source with the exact dimension and measure keys askable of it — use those keys verbatim. '\n + 'When they describe a report, call createAnalyticsReport once with the full shape; do not interview them field by field. '\n + 'Name the report the way they said it. After creating, say in one line what it groups by and what it measures.'\n\n// ---------------------------------------------------------------------------\n// Page\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsSettingsPage() {\n const t = useTranslation()\n const { labels } = useAnalyticsConfig()\n const catalogue = useAnalyticsCatalogue()\n const cards = useAnalyticsCards()\n const prefs = useAnalyticsPrefs()\n\n const { createdBy } = useAnalyticsConfig()\n const [editing, setEditing] = React.useState<string | null>(null)\n const [creating, setCreating] = React.useState(false)\n const [dragId, setDragId] = React.useState<string | null>(null)\n\n // A copy com que o assistente abre quando o handoff parte DESTA tela. Sem\n // ela o painel abre falando do que a tela oferecia antes (\"pergunte sobre\n // produção, cardápio e movimento\"), que é verdade e não é o assunto.\n const askIntro = React.useMemo<AskAIIntro>(() => ({\n role: 'setup',\n persona: t('reports.settings.askPersona'),\n pitch: t('reports.settings.askPitch'),\n description: t('reports.settings.askDescription'),\n suggestions: [0, 1, 2].map((i) => ({ label: t(`reports.settings.askSuggestion.${i}`) })),\n }), [t])\n\n const createActions = React.useMemo<PluginQuickAction[]>(() => [\n {\n id: 'with-ai',\n label: t('assistant.askAI'),\n description: t('reports.settings.newWithAIHint'),\n icon: 'WandSparkles',\n highlight: true,\n action: () => askAI({ hint: t('reports.settings.askPlaceholder'), intro: askIntro }),\n },\n {\n id: 'by-hand',\n label: t('reports.settings.newByHand'),\n description: t('reports.settings.newByHandHint'),\n icon: 'SlidersHorizontal',\n action: () => setCreating(true),\n },\n ], [t, askIntro])\n\n const sources = React.useMemo(() => analyticsSources(cards), [cards])\n const categories = React.useMemo(\n () => [...new Set(cards.map((c) => c.category))].sort((a, b) => a.localeCompare(b)),\n [cards],\n )\n\n const pinned = React.useMemo(\n () => cards.filter((c) => c.dashboard).sort((a, b) => (a.dashboard?.order ?? 0) - (b.dashboard?.order ?? 0)),\n [cards],\n )\n const unpinned = React.useMemo(\n () => cards.filter((c) => !c.dashboard).sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name)),\n [cards],\n )\n // Removed built-ins live nowhere else — without this section a card taken out\n // of the catalogue can never be found again.\n const removed = React.useMemo(\n () => catalogue.filter((c) => prefs.cards[c.id]?.hidden),\n [catalogue, prefs],\n )\n\n // Live order during a drag: the committed order only moves on drop, so the\n // list under the cursor is state, not props.\n const [order, setOrder] = React.useState<string[] | null>(null)\n const pinnedIds = order ?? pinned.map((c) => c.id)\n const pinnedInOrder = pinnedIds\n .map((id) => pinned.find((c) => c.id === id))\n .filter((c): c is AnalyticsCardDef => Boolean(c))\n\n const move = (id: string, delta: number) => {\n const ids = pinned.map((c) => c.id)\n const from = ids.indexOf(id)\n const to = from + delta\n if (from < 0 || to < 0 || to >= ids.length) return\n ids.splice(to, 0, ids.splice(from, 1)[0]!)\n setOverviewOrder(ids)\n }\n\n const onDragOver = (targetId: string) => (event: React.DragEvent) => {\n event.preventDefault()\n if (!dragId || dragId === targetId) return\n const ids = [...pinnedIds]\n const from = ids.indexOf(dragId)\n const to = ids.indexOf(targetId)\n if (from < 0 || to < 0) return\n ids.splice(to, 0, ids.splice(from, 1)[0]!)\n setOrder(ids)\n }\n\n const commitDrag = () => {\n if (order) setOverviewOrder(order)\n setOrder(null)\n setDragId(null)\n }\n\n const editingCard = cards.find((c) => c.id === editing)\n const isCustom = (id: string) => prefs.custom.some((r) => r.id === id)\n\n // --- assistant surface ---------------------------------------------------\n // Read through a ref: `useAgentSurface` registers once and calls back later,\n // so a captured `sources` would go stale the moment a report is added.\n const surfaceRef = React.useRef({ sources, categories, cards, prefs, createdBy })\n surfaceRef.current = { sources, categories, cards, prefs, createdBy }\n\n const agentSurface = React.useMemo<AgentSurfaceContribution>(() => ({\n id: 'analytics.reports',\n pluginId: 'reports',\n instructions: AGENT_INSTRUCTIONS,\n describe: () => {\n const o = surfaceRef.current\n return {\n title: 'Configuração de relatórios',\n state: {\n sources: o.sources.map((source) => ({\n key: source.key,\n label: source.label,\n grain: source.base.grain ?? null,\n group_by: source.dimensions.map((d) => ({ key: d.key, label: d.label })),\n measures: source.measures.map((m) => ({ key: m.key, label: m.label, format: m.format ?? 'number' })),\n })),\n categories: o.categories,\n onOverview: o.cards.filter((c) => c.dashboard).map((c) => c.name),\n yourReports: o.prefs.custom.map((r) => r.name),\n },\n }\n },\n tools: [{\n tool: CREATE_REPORT_TOOL,\n execute: (args) => {\n const o = surfaceRef.current\n const source = o.sources.find((s) => s.key === args.source)\n ?? o.sources.find((s) => s.label === args.source)\n if (!source) {\n return { ok: false, error: 'unknown_source', sources: o.sources.map((s) => s.key) }\n }\n const report = buildCustomReport({\n name: String(args.name ?? '').trim() || 'Relatório',\n category: String(args.category ?? o.categories[0] ?? 'Geral'),\n createdBy: o.createdBy,\n source,\n dimensions: Array.isArray(args.group_by) ? (args.group_by as string[]) : [],\n measures: Array.isArray(args.measures) ? (args.measures as string[]) : [],\n viz: (args.viz as AnalyticsVizType) ?? 'table',\n })\n if (report.measures.length === 0) {\n return {\n ok: false,\n error: 'no_valid_measure',\n available: source.measures.map((m) => m.key),\n }\n }\n saveCustomReport(report)\n if (args.pin) setCardPref(report.id, { pinned: true, order: 999 })\n // Land on the thing that was just built: a report created and left\n // unopened is a claim the user has to go verify.\n navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(report.id)}`)\n return {\n ok: true,\n id: report.id,\n name: report.name,\n group_by: report.dimensions,\n measures: report.measures,\n viz: report.viz,\n }\n },\n }],\n }), [])\n useAgentSurface(agentSurface)\n\n return (\n <div className=\"space-y-4\">\n <SubpageHeader\n title={t('reports.settings.title')}\n parentLabel={labels.analytics}\n onBack={() => navigateAnalytics(ANALYTICS_BASE)}\n />\n\n {/* Na barra da shell, junto do título — é onde toda tela do produto põe\n a sua ação principal. Numa faixa própria logo abaixo, elas abriam uma\n segunda barra de cabeçalho dizendo respeito à mesma página.\n \"Criar com IA\" é a PRIMÁRIA e o formulário fica em `outline`: descrever\n o relatório é o caminho curto, e enterrá-lo dentro do painel do\n caminho longo é escondê-lo atrás do que ele existe para evitar. */}\n <PageHeaderActions>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => resetAnalyticsPrefs()}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.reset')}\n </Button>\n {/* O mesmo menu de \"novo\" que o resto do produto usa (QuickActionsButton):\n ícone em ladrilho, rótulo e uma linha do que aquilo faz. A entrada de\n IA vai `highlight` — ver PluginQuickAction. */}\n <QuickActionsButton label={t('reports.settings.new')} variant=\"default\" actions={createActions} />\n </PageHeaderActions>\n\n <p className=\"max-w-2xl text-sm text-muted-foreground\">{t('reports.settings.subtitle')}</p>\n\n <Card className=\"overflow-hidden\">\n <div className=\"border-b border-border px-3 py-2\">\n <p className=\"text-sm font-medium\">{t('reports.settings.onOverview')}</p>\n <p className=\"text-xs text-muted-foreground\">{t('reports.settings.onOverviewHint')}</p>\n </div>\n {pinnedInOrder.length === 0 ? (\n <p className=\"px-3 py-6 text-center text-sm text-muted-foreground\">{t('reports.settings.empty')}</p>\n ) : (\n <ul>\n {pinnedInOrder.map((card, index) => (\n <ReportRow\n key={card.id}\n card={card}\n custom={isCustom(card.id)}\n onEdit={() => setEditing(card.id)}\n drag={{\n dragging: dragId === card.id,\n onDragStart: () => setDragId(card.id),\n onDragOver: onDragOver(card.id),\n onDragEnd: commitDrag,\n }}\n >\n <Select\n value={String(card.dashboard?.span ?? '')}\n onValueChange={(value) => setCardPref(card.id, { span: Number(value) as 1 | 2 | 3 | 4 })}\n >\n <SelectTrigger className=\"h-8 w-[150px]\">\n <SelectValue placeholder={t('reports.settings.width')} />\n </SelectTrigger>\n <SelectContent>\n {[1, 2, 3, 4].map((span) => (\n <SelectItem key={span} value={String(span)}>{t(`reports.settings.width.${span}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Button\n variant=\"ghost\" size=\"sm\" disabled={index === 0}\n onClick={() => move(card.id, -1)} aria-label={t('reports.settings.up')} title={t('reports.settings.up')}\n >\n <ChevronUp className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\" disabled={index === pinnedInOrder.length - 1}\n onClick={() => move(card.id, 1)} aria-label={t('reports.settings.down')} title={t('reports.settings.down')}\n >\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => setCardPref(card.id, { pinned: false })}\n aria-label={t('reports.settings.unpin')} title={t('reports.settings.unpin')}\n >\n <EyeOff className=\"h-3.5 w-3.5\" />\n </Button>\n </ReportRow>\n ))}\n </ul>\n )}\n </Card>\n\n <Card className=\"overflow-hidden\">\n <div className=\"border-b border-border px-3 py-2\">\n <p className=\"text-sm font-medium\">{t('reports.settings.offOverview')}</p>\n <p className=\"text-xs text-muted-foreground\">{t('reports.settings.offOverviewHint')}</p>\n </div>\n <ul>\n {unpinned.map((card) => (\n <ReportRow key={card.id} card={card} custom={isCustom(card.id)} onEdit={() => setEditing(card.id)}>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => setCardPref(card.id, { pinned: true, order: pinned.length })}\n aria-label={t('reports.settings.pin')} title={t('reports.settings.pin')}\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </Button>\n {isCustom(card.id) ? (\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => deleteCustomReport(card.id)}\n aria-label={t('reports.settings.delete')} title={t('reports.settings.delete')}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n ) : (\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => setCardPref(card.id, { hidden: true })}\n aria-label={t('reports.settings.remove')} title={t('reports.settings.remove')}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </ReportRow>\n ))}\n </ul>\n </Card>\n\n {removed.length > 0 ? (\n <Card className=\"overflow-hidden\">\n <div className=\"border-b border-border px-3 py-2\">\n <p className=\"text-sm font-medium\">{t('reports.settings.hidden')}</p>\n </div>\n <ul>\n {removed.map((card) => (\n <li key={card.id} className=\"flex items-center gap-2 border-b border-border/60 px-3 py-2 last:border-0\">\n <span className=\"w-4 shrink-0\" aria-hidden />\n <CardIcon name={card.icon} className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <span className=\"truncate text-sm text-muted-foreground\">{card.name}</span>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setCardPref(card.id, { hidden: undefined })}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.restore')}\n </Button>\n </li>\n ))}\n </ul>\n </Card>\n ) : null}\n\n {editingCard ? <CardEditor card={editingCard} onClose={() => setEditing(null)} /> : null}\n {creating ? <NewReportPanel sources={sources} categories={categories} onClose={() => setCreating(false)} /> : null}\n </div>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { ReportColumnDef } from '../types'\nimport { exportToCsv } from '../export/csv'\nimport { exportToExcel } from '../export/excel'\nimport { exportToPdf } from '../export/pdf'\n\n// ---------------------------------------------------------------------------\n// The client half of the report engine (PRD 08).\n//\n// The catalogue, the permission and the query live in the database — the engine\n// refuses BEFORE it reads a row, and it records the refusal, because \"empty\" and\n// \"you were not allowed to see it\" are different answers. This module is what\n// carries that answer to a screen and, when asked, into a file.\n//\n// The three exporters already existed and had nothing to export from: they took\n// columns and rows from whatever a screen happened to hold. Now they take what\n// the engine actually returned, with the definition's own column list.\n// ---------------------------------------------------------------------------\n\nexport type ReportFormat = 'csv' | 'xlsx' | 'pdf'\n\nexport interface ReportRunResult {\n key: string\n version: number\n title: string\n /** 'ok' or 'refused' — a refusal reads no rows and is recorded server-side. */\n status: 'ok' | 'refused'\n requiredPermission?: string\n columns: ReportColumnDef[]\n rows: Record<string, any>[]\n rowCount: number\n}\n\nfunction db() {\n const client = getSupabaseClientOptional() as any\n if (!client) throw new Error('Supabase client is not configured')\n return client\n}\n\n/** Run a report from the catalogue. Throws only on a real error — a refusal comes back as data. */\nexport async function runReport(\n key: string,\n params: Record<string, unknown> = {},\n options?: { limit?: number; offset?: number; format?: ReportFormat },\n): Promise<ReportRunResult> {\n const { data, error } = await db().rpc('reports_run', {\n p_key: key,\n p_params: params,\n p_limit: options?.limit ?? 1000,\n p_offset: options?.offset ?? 0,\n p_format: options?.format ?? null,\n })\n if (error) throw new Error(error.message)\n\n const r = (data ?? {}) as Record<string, any>\n return {\n key: r.key ?? key,\n version: Number(r.version) || 1,\n title: r.title ?? key,\n status: r.status === 'refused' ? 'refused' : 'ok',\n requiredPermission: r.required_permission ?? undefined,\n columns: (r.columns ?? []) as ReportColumnDef[],\n rows: (r.rows ?? []) as Record<string, any>[],\n rowCount: Number(r.row_count) || 0,\n }\n}\n\n/**\n * Run it and hand the result to the exporter for the format.\n *\n * A refusal exports NOTHING and says so. Writing an empty spreadsheet for\n * someone who was not allowed to see the data is the version of this that looks\n * like a bug in the report.\n */\nexport async function runAndExportReport(\n key: string,\n format: ReportFormat,\n params: Record<string, unknown> = {},\n options?: { limit?: number; filename?: string; currency?: string },\n): Promise<ReportRunResult> {\n const result = await runReport(key, params, { limit: options?.limit ?? 5000, format })\n if (result.status === 'refused') return result\n\n const filename = options?.filename ?? `${result.key}-${new Date().toISOString().slice(0, 10)}`\n const columns = result.columns.length > 0\n ? result.columns\n // A definition that declared no columns still exports: the keys of the\n // first row are a worse header than a curated list, and a better one than\n // nothing.\n : Object.keys(result.rows[0] ?? {}).map((key) => ({ key, label: key } as ReportColumnDef))\n\n if (format === 'csv') exportToCsv(columns, result.rows, filename, options?.currency)\n else if (format === 'xlsx') await exportToExcel(columns, result.rows, filename, options?.currency)\n else await exportToPdf(columns, result.rows, filename, { title: result.title, currency: options?.currency })\n\n return result\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { ReportDef, ReportQueryState } from '../types'\nimport type { ReportDataProvider, ReportResult } from './types'\n\n// ---------------------------------------------------------------------------\n// Case conversion\n// ---------------------------------------------------------------------------\n\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (c) => '_' + c.toLowerCase())\n}\n\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase())\n}\n\nfunction mapRow(row: Record<string, unknown>, columnMap?: Record<string, string>): Record<string, any> {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n const camelKey = columnMap?.[key] ?? snakeToCamel(key)\n result[camelKey] = value\n }\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Provider factory\n// ---------------------------------------------------------------------------\n\nexport interface SupabaseReportProviderConfig {\n tenantId: string | (() => string | undefined)\n tenantIdColumn?: string\n schema?: string\n}\n\nexport function createSupabaseReportProvider(config: SupabaseReportProviderConfig): ReportDataProvider {\n const schema = config.schema ?? 'public'\n const tenantIdCol = config.tenantIdColumn ?? 'tenant_id'\n\n function resolveTenantId(): string | undefined {\n return typeof config.tenantId === 'function' ? config.tenantId() : config.tenantId\n }\n\n function getClient() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase client not available')\n return schema === 'public' ? supabase : supabase.schema(schema)\n }\n\n return {\n async fetch(reportDef: ReportDef, query: ReportQueryState): Promise<ReportResult> {\n const { dataSource } = reportDef\n const columnMap = dataSource.columnMap\n\n if (dataSource.kind === 'rpc') {\n return fetchViaRpc(reportDef, query, getClient, resolveTenantId, columnMap)\n }\n\n return fetchViaView(reportDef, query, getClient, resolveTenantId, tenantIdCol, columnMap)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// View-based fetch\n// ---------------------------------------------------------------------------\n\nasync function fetchViaView(\n reportDef: ReportDef,\n query: ReportQueryState,\n getClient: () => any,\n resolveTenantId: () => string | undefined,\n tenantIdCol: string,\n columnMap?: Record<string, string>,\n): Promise<ReportResult> {\n const { dataSource } = reportDef\n let q = getClient().from(dataSource.name).select('*', { count: 'exact' })\n\n // Tenant scoping\n const tenantId = resolveTenantId()\n if (tenantId) {\n q = q.eq(tenantIdCol, tenantId)\n }\n\n // Date range\n const dateCol = dataSource.dateColumn ?? 'created_at'\n if (query.dateRange.from) {\n q = q.gte(dateCol, query.dateRange.from)\n }\n if (query.dateRange.to) {\n // For date-type columns, plain date string is sufficient.\n // For timestamptz columns, extend to end of day.\n const toValue = dateCol === 'created_at' || dateCol.endsWith('_at')\n ? query.dateRange.to + 'T23:59:59'\n : query.dateRange.to\n q = q.lte(dateCol, toValue)\n }\n\n // Custom filters\n for (const [key, value] of Object.entries(query.filters)) {\n if (value == null || value === '') continue\n const col = camelToSnake(key)\n if (Array.isArray(value)) {\n q = q.in(col, value)\n } else {\n q = q.eq(col, value)\n }\n }\n\n // Search\n if (query.search) {\n const searchableCols = reportDef.columns\n .filter((c) => c.type === 'text' || c.type === 'email' || c.type === 'person')\n .map((c: any) => camelToSnake(c.key))\n if (searchableCols.length > 0) {\n const term = `%${query.search}%`\n const orClause = searchableCols.map((col) => `${col}.ilike.${term}`).join(',')\n q = q.or(orClause)\n }\n }\n\n // Sort\n const sortCol = query.sortBy\n ? camelToSnake(query.sortBy)\n : dataSource.defaultSort\n ? camelToSnake(dataSource.defaultSort)\n : dateCol\n const ascending = query.sortDir\n ? query.sortDir === 'asc'\n : dataSource.defaultSortDir\n ? dataSource.defaultSortDir === 'asc'\n : false\n q = q.order(sortCol, { ascending })\n\n // Pagination\n const from = (query.page - 1) * query.pageSize\n const to = from + query.pageSize - 1\n q = q.range(from, to)\n\n const { data, error, count } = await q\n\n if (error) throw error\n\n return {\n data: (data ?? []).map((row: any) => mapRow(row, columnMap)),\n total: count ?? 0,\n }\n}\n\n// ---------------------------------------------------------------------------\n// RPC-based fetch\n// ---------------------------------------------------------------------------\n\nasync function fetchViaRpc(\n reportDef: ReportDef,\n query: ReportQueryState,\n getClient: () => any,\n resolveTenantId: () => string | undefined,\n columnMap?: Record<string, string>,\n): Promise<ReportResult> {\n const { dataSource } = reportDef\n const tenantId = resolveTenantId()\n\n const params: Record<string, any> = {\n p_tenant_id: tenantId,\n p_from: query.dateRange.from,\n p_to: query.dateRange.to,\n p_page: query.page,\n p_page_size: query.pageSize,\n }\n\n // Custom filters\n for (const [key, value] of Object.entries(query.filters)) {\n if (value == null || value === '') continue\n params[`p_${camelToSnake(key)}`] = value\n }\n\n if (query.sortBy) {\n params.p_sort_by = camelToSnake(query.sortBy)\n params.p_sort_dir = query.sortDir ?? 'desc'\n }\n\n const { data, error } = await getClient().rpc(dataSource.name, params)\n if (error) throw error\n\n // RPC expected to return { data: [...], total: number }\n if (data && typeof data === 'object' && 'data' in data) {\n return {\n data: (data.data ?? []).map((row: any) => mapRow(row, columnMap)),\n total: data.total ?? 0,\n }\n }\n\n // Fallback: RPC returns a plain array\n const rows = Array.isArray(data) ? data : []\n return {\n data: rows.map((row: any) => mapRow(row, columnMap)),\n total: rows.length,\n }\n}\n","import type { ReportDataProvider } from './types'\n\nexport function createMockReportProvider(): ReportDataProvider {\n return {\n async fetch() {\n return { data: [], total: 0 }\n },\n }\n}\n","import React from 'react'\nimport type {\n PluginManifest, PluginScope, VerticalId, AnalyticsCardDef, AnalyticsProvider, AnalyticsCompare,\n} from '@fayz-ai/core'\nimport type { AnalyticsRangePreset } from '@fayz-ai/ui'\nimport { createSafeDataProvider, registerTranslations } from '@fayz-ai/core'\nimport { createSupabaseAnalyticsProvider } from './data/analytics-supabase'\nimport { createMockAnalyticsProvider } from './data/analytics-mock'\nimport { getReportsTenantId } from './lib/tenant'\nimport { reportsLocales } from './locales'\nimport { MIGRATIONS } from './migrations'\nimport { reportDefsToCards } from './lib/legacy'\nimport {\n AnalyticsSurface, ANALYTICS_BASE, REPORTS_BASE, SETTINGS_ROUTE,\n type AnalyticsLabels, type ResolvedAnalyticsConfig, type AnalyticsAssistantConfig,\n} from './views/AnalyticsSurface'\nimport { AnalyticsModule, type AnalyticsView } from './views/AnalyticsModule'\nimport { AnalyticsOverview } from './views/AnalyticsOverview'\nimport { ReportsListPage } from './views/ReportsListPage'\nimport { AnalyticsReportViewer } from './views/AnalyticsReportViewer'\nimport { LiveViewPage } from './views/LiveViewPage'\nimport { AnalyticsSettingsPage } from './views/AnalyticsSettingsPage'\nimport type { ReportsPluginOptions } from './types'\n\n// ---------------------------------------------------------------------------\n// Analytics — one engine, one door, several rooms.\n//\n// /analytics the general dashboard: the cards a pack placed\n// /analytics/reports the one list where a user finds what they want\n// /analytics/reports/:id a report, full size (chart AND rows)\n// /analytics/live real-time (stub, awaiting a storefront event stream)\n// /analytics/settings which reports, in what order, showing what\n//\n// ONE nav entry. Analytics and Reports used to be two top-level links to the\n// same engine — the app menu asked the user to choose a door before showing\n// what was behind either. Everything below /analytics now hangs off the module\n// rail (AnalyticsModule), where the report groups and the reports themselves\n// are the navigation.\n//\n// The package is still called plugin-reports so the six consuming apps keep\n// their imports; the CONCEPT it exposes is Analytics, with Reports as the\n// catalogue inside it.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_LABELS: AnalyticsLabels = {\n analytics: 'Analytics',\n reports: 'Reports',\n liveView: 'Live View',\n overviewSubtitle: 'Key metrics for your business',\n reportsSubtitle: 'Every report available to you',\n searchReports: 'Search reports',\n category: 'Category',\n createdBy: 'Created by',\n allCategories: 'All categories',\n allCreatedBy: 'All authors',\n lastViewed: 'Last viewed',\n name: 'Name',\n noResults: 'No results found.',\n never: '—',\n back: 'Back',\n export: 'Export',\n print: 'Print',\n unavailableTitle: 'Coming soon',\n unavailableDescription: 'This report is not connected to data yet. It will be enabled in a future update.',\n emptyOverviewTitle: 'No metrics yet',\n emptyOverviewDescription: 'Enable a plugin that contributes analytics cards, or add them to this app’s pack.',\n liveViewSoon: 'Real-time visitor and checkout activity will appear here once storefront events are being collected.',\n results: 'reports',\n}\n\nconst DEFAULT_CURRENCY = { code: 'BRL', locale: 'pt-BR', symbol: 'R$' }\n\nexport interface AnalyticsPluginOptions {\n /**\n * Cards the host app contributes or overrides. Cards owned by a plugin come\n * through the runtime registry automatically — this is for app-specific ones\n * and for retuning a plugin card by re-declaring its id.\n */\n cards?: AnalyticsCardDef[]\n /**\n * Legacy ReportDef catalogue. Still fully supported: each becomes a table\n * card in the report list. See lib/legacy.ts.\n */\n reports?: import('./types').ReportDef[]\n /** Attribution for pre-built cards — the product name, e.g. 'FayzShop'. */\n createdBy?: string\n labels?: Partial<AnalyticsLabels>\n currency?: { code?: string; locale?: string; symbol?: string }\n dataProvider?: AnalyticsProvider\n navPosition?: number\n navSection?: 'main' | 'secondary'\n scope?: PluginScope\n verticalId?: VerticalId\n defaultPageSize?: number\n /**\n * Render an in-content title above the page. Default: FALSE, matching\n * DashboardCanvas — the admin shell's top bar already names the page from the\n * active nav entry, so a title here prints the same word twice. Pass true\n * only where the surface is embedded with no chrome of its own.\n */\n showHeader?: boolean\n /** Register the Live View nav entry. Default: false while it is a stub. */\n showLiveView?: boolean\n /**\n * Range the surface opens on. Default 'last_30_days' — the common business\n * month. Set it where the domain's natural period differs (a school term, a\n * quarter), not to compensate for how much data a demo tenant happens to have.\n */\n defaultRange?: AnalyticsRangePreset\n defaultCompare?: AnalyticsCompare\n /**\n * The assistant's invitation on /analytics: a persona, a headline and the\n * questions worth asking here. Defaults come from the plugin's locales — pass\n * an object to retune the voice for a vertical, or `false` for an app whose\n * analytics screen should open on the numbers alone.\n */\n assistant?: false | AnalyticsAssistantConfig\n}\n\nfunction resolveConfig(options: AnalyticsPluginOptions): ResolvedAnalyticsConfig {\n const labels = { ...DEFAULT_LABELS, ...options.labels }\n const createdBy = options.createdBy ?? 'Fayz'\n return {\n labels,\n currency: { ...DEFAULT_CURRENCY, ...options.currency },\n createdBy,\n cards: [\n ...(options.cards ?? []),\n ...reportDefsToCards(options.reports ?? [], createdBy),\n ],\n defaultPageSize: options.defaultPageSize ?? 50,\n showHeader: options.showHeader === true,\n defaultRange: options.defaultRange ?? 'last_30_days',\n defaultCompare: options.defaultCompare ?? 'previous_period',\n showLiveView: options.showLiveView === true,\n assistant: options.assistant === false ? null : (options.assistant ?? {}),\n }\n}\n\nexport function createAnalyticsPlugin(options: AnalyticsPluginOptions = {}): PluginManifest {\n const config = resolveConfig(options)\n registerTranslations(reportsLocales)\n\n const provider: AnalyticsProvider = options.dataProvider ?? createSafeDataProvider(\n () => createSupabaseAnalyticsProvider({ tenantId: () => getReportsTenantId() }),\n () => createMockAnalyticsProvider(),\n )\n\n /**\n * Every page mounts inside the same surface AND the same module rail, so the\n * report tree is on screen wherever you are inside Analytics — and the app\n * nav never has to list a second Analytics entry to get you there.\n */\n const page = (Body: React.ComponentType<any>, view: AnalyticsView): React.FC<any> =>\n (props) => React.createElement(\n AnalyticsSurface,\n { config, provider },\n React.createElement(\n AnalyticsModule,\n { view, cardId: props?.cardId },\n React.createElement(Body, props),\n ),\n )\n\n const READ = { feature: 'reports', action: 'read' as const }\n const position = options.navPosition ?? 9\n const section = options.navSection ?? 'main'\n\n // One entry. Sub-paths of /analytics would be nested as children by the shell\n // (findModuleParent) and drawn as a dropdown — which is the split this module\n // exists to remove.\n const nav = [\n {\n section, position,\n label: config.labels.analytics,\n route: ANALYTICS_BASE,\n icon: 'BarChart3',\n permission: READ,\n },\n ]\n\n return {\n id: 'reports',\n defaultAgentRole: 'growth',\n name: config.labels.analytics,\n icon: 'BarChart3',\n version: '2.0.0',\n scope: options.scope ?? 'universal',\n verticalId: options.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [\n { id: 'reports', label: config.labels.analytics, group: config.labels.analytics },\n ],\n navigation: nav,\n routes: [\n { path: ANALYTICS_BASE, component: page(AnalyticsOverview, 'overview'), permission: READ },\n { path: REPORTS_BASE, component: page(ReportsListPage, 'reports'), permission: READ },\n // Registered before the list would ever shadow it: matchRoute scores\n // static segments above params, so /analytics/reports still wins its own\n // exact path and only /analytics/reports/<id> lands here.\n // No `parentRoute` here on purpose: the viewer's title depends on DATA\n // (the card's name), so it claims the shell bar itself via PageHeader.\n // Declaring both gave the page two stacked back-crumbs saying the same\n // thing, one of them generic.\n { path: `${REPORTS_BASE}/:cardId`, component: page(AnalyticsReportViewer, 'report'), permission: READ },\n { path: `${ANALYTICS_BASE}/live`, component: page(LiveViewPage, 'live'), permission: READ },\n // Read permission on purpose: the screen writes a per-user preference,\n // not tenant data — gating it behind a write scope would mean a viewer\n // cannot choose which of the reports they can see are on their overview.\n { path: SETTINGS_ROUTE, component: page(AnalyticsSettingsPage, 'settings'), permission: READ },\n // The old top-level route kept as a redirect target: bookmarks, saved\n // links and the five apps still pointing at /reports must not 404.\n { path: '/reports', component: page(ReportsListPage, 'reports'), permission: READ },\n ],\n widgets: [],\n registries: [],\n // Measurement, not acquisition — what the Fayz plugin page lists for\n // Analytics.\n integrations: ['google-analytics', 'hotjar'],\n // The engine, at last (Phase 2, PRD 08). This package shipped ZERO\n // migrations until now: a package and a screen, never a catalogue of\n // versioned definitions with a declared permission, a run history and an\n // export. Without them \"report\" meant \"a query somebody wrote into a\n // screen\", which is how a report ships with no authorization rule by simple\n // forgetfulness.\n migrations: MIGRATIONS.map((m) => ({\n id: `reports-${m.id}`,\n version: '1.0.0',\n sql: m.sql,\n description: m.id,\n })),\n locales: reportsLocales,\n }\n}\n\n/**\n * @deprecated Prefer `createAnalyticsPlugin`. Kept so the apps that call\n * `createReportsPlugin({ reports: [...] })` keep working unchanged — the legacy\n * `reports` option is still first-class and their catalogues need no rewrite.\n */\nexport function createReportsPlugin(options: ReportsPluginOptions): PluginManifest {\n return createAnalyticsPlugin({\n reports: options.reports,\n labels: {\n ...(options.labels?.pageTitle ? { analytics: options.labels.pageTitle } : {}),\n ...(options.labels?.pageSubtitle ? { overviewSubtitle: options.labels.pageSubtitle } : {}),\n },\n currency: options.currency,\n navPosition: options.navPosition,\n navSection: options.navSection,\n scope: options.scope,\n verticalId: options.verticalId,\n defaultPageSize: options.defaultPageSize,\n showHeader: options.showHeader,\n })\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport {\n AnalyticsSurface, ANALYTICS_BASE, REPORTS_BASE, SETTINGS_ROUTE, cardColumns,\n useAnalyticsConfig, useAnalyticsCards, useAnalyticsCatalogue, useOverviewCards,\n} from './views/AnalyticsSurface'\nexport type {\n AnalyticsLabels, ResolvedAnalyticsConfig, AnalyticsAssistantConfig,\n} from './views/AnalyticsSurface'\nexport { AnalyticsModule } from './views/AnalyticsModule'\nexport type { AnalyticsView, AnalyticsModuleProps } from './views/AnalyticsModule'\nexport { AnalyticsOverview } from './views/AnalyticsOverview'\nexport { AnalyticsSettingsPage } from './views/AnalyticsSettingsPage'\nexport { ReportsListPage } from './views/ReportsListPage'\nexport { AnalyticsReportViewer } from './views/AnalyticsReportViewer'\nexport { reportDefToCard, reportDefsToCards } from './lib/legacy'\nexport { aggregateRows } from './data/aggregate'\nexport { createSupabaseAnalyticsProvider } from './data/analytics-supabase'\nexport type { SupabaseAnalyticsProviderConfig } from './data/analytics-supabase'\nexport { createMockAnalyticsProvider } from './data/analytics-mock'\nexport { markViewed, useLastViewed } from './lib/lastViewed'\nexport {\n useAnalyticsPrefs, resolveCards, resolveCustomReport, fieldPalette, sourceKey,\n setCardPref, clearCardPref, setOverviewOrder, saveCustomReport, deleteCustomReport,\n resetAnalyticsPrefs,\n} from './lib/preferences'\nexport type { AnalyticsPrefs, AnalyticsCardPref, CustomReport, FieldPalette } from './lib/preferences'\nexport { setReportsTenantId, getReportsTenantId } from './lib/tenant'\n\n// The report ENGINE (PRD 08): the catalogue, the permission and the query live\n// in the database; these carry the answer to a screen and into a file.\nexport { runReport, runAndExportReport } from './lib/engine'\nexport type { ReportFormat, ReportRunResult } from './lib/engine'\nexport { exportToCsv } from './export/csv'\nexport { exportToExcel } from './export/excel'\nexport { exportToPdf } from './export/pdf'\n\nexport type {\n ReportDef,\n ReportColumnDef,\n ReportFilterDef,\n ReportDateRange,\n ReportQueryState,\n ReportBadge,\n ReportDataSource,\n ReportGrain,\n ReportAllowedAction,\n ReportFilterOption,\n ReportsPluginOptions,\n ReportsPluginLabels,\n ResolvedReportsConfig,\n} from './types'\n\nexport type { ReportDataProvider, ReportResult } from './data/types'\nexport { createSupabaseReportProvider } from './data/supabase'\nexport type { SupabaseReportProviderConfig } from './data/supabase'\nexport { createMockReportProvider } from './data/mock'\n"]}
1
+ {"version":3,"sources":["../src/data/aggregate.ts","../src/data/analytics-supabase.ts","../src/data/analytics-mock.ts","../src/lib/tenant.ts","../src/locales/en.ts","../src/locales/pt-BR.ts","../src/locales/index.ts","../src/migrations/index.ts","../src/lib/legacy.ts","../src/lib/lastViewed.ts","../src/lib/preferences.ts","../src/views/AnalyticsSurface.tsx","../src/views/AnalyticsAssistant.tsx","../src/views/AnalyticsModule.tsx","../src/views/AnalyticsOverview.tsx","../src/views/ReportsListPage.tsx","../src/export/csv.ts","../src/components/ExportDropdown.tsx","../src/components/ReportPagination.tsx","../src/views/AnalyticsReportViewer.tsx","../src/views/LiveViewPage.tsx","../src/views/AnalyticsSettingsPage.tsx","../src/lib/engine.ts","../src/data/supabase.ts","../src/data/mock.ts","../src/index.ts"],"names":["db","data","error","React","KEY","read","write","listeners","React2","jsx","useTranslation","jsxs","useState","useEffect","exportToExcel","exportToPdf","page","Fragment","DataTable","Button","AnalyticsControls","ToolbarAction","SubpageHeader","Card","getSupabaseClientOptional","key","camelToSnake","snakeToCamel","mapRow"],"mappings":"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A;AAAA;AAAA;AAAA;;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA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","file":"index.js","sourcesContent":["import type {\n AnalyticsCardDef, AnalyticsGrain, AnalyticsQueryState, AnalyticsResult, AnalyticsRow,\n} from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Client-side aggregation.\n//\n// The SQL engine (analytics_run) is the real one; this exists for the two cases\n// that cannot reach it — the mock provider, and cards whose source is an app\n// function rather than a read model. It deliberately mirrors the SQL semantics\n// step for step, because a card must not change meaning depending on which\n// provider answered it.\n// ---------------------------------------------------------------------------\n\nfunction num(value: unknown): number {\n if (value == null) return 0\n const n = typeof value === 'number' ? value : Number(value)\n return Number.isFinite(n) ? n : 0\n}\n\n/** Truncate a timestamp to the start of its bucket — the JS date_trunc. */\nexport function truncate(value: unknown, grain: AnalyticsGrain): string | null {\n const d = new Date(String(value))\n if (Number.isNaN(d.getTime())) return null\n const out = new Date(d)\n switch (grain) {\n case 'hour': out.setMinutes(0, 0, 0); break\n case 'week': {\n // ISO weeks start Monday; getDay() calls Sunday 0, hence the shift.\n const day = (out.getDay() + 6) % 7\n out.setDate(out.getDate() - day)\n out.setHours(0, 0, 0, 0)\n break\n }\n case 'month': out.setDate(1); out.setHours(0, 0, 0, 0); break\n case 'quarter': out.setMonth(Math.floor(out.getMonth() / 3) * 3, 1); out.setHours(0, 0, 0, 0); break\n case 'year': out.setMonth(0, 1); out.setHours(0, 0, 0, 0); break\n default: out.setHours(0, 0, 0, 0); break\n }\n return out.toISOString()\n}\n\nfunction matchesFilters(row: AnalyticsRow, filters: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(filters)) {\n if (value == null || value === '') continue\n const actual = row[key]\n if (Array.isArray(value)) {\n if (value.length > 0 && !value.map(String).includes(String(actual))) return false\n } else if (String(actual) !== String(value)) {\n return false\n }\n }\n return true\n}\n\nfunction inRange(row: AnalyticsRow, dateColumn: string, from?: string, to?: string): boolean {\n const raw = row[dateColumn]\n if (raw == null) return true\n const t = new Date(String(raw)).getTime()\n if (Number.isNaN(t)) return true\n // `to` is an inclusive DAY, so the window closes at its final millisecond —\n // comparing against midnight would silently drop everything ordered that day.\n if (from && t < new Date(`${from}T00:00:00`).getTime()) return false\n if (to && t > new Date(`${to}T23:59:59.999`).getTime()) return false\n return true\n}\n\n/** Apply one measure over a bucket of rows. 'ratio' is resolved by the UI layer. */\nfunction applyMeasure(rows: AnalyticsRow[], agg: string, column: string): number | null {\n if (agg === 'count') return rows.length\n const values = rows.map((r) => r[column]).filter((v) => v != null)\n if (agg === 'count_distinct') return new Set(values.map(String)).size\n const numbers = values.map(num)\n if (numbers.length === 0) return agg === 'sum' ? 0 : null\n switch (agg) {\n case 'sum': return numbers.reduce((a, b) => a + b, 0)\n case 'avg': return numbers.reduce((a, b) => a + b, 0) / numbers.length\n case 'min': return Math.min(...numbers)\n case 'max': return Math.max(...numbers)\n default: return null\n }\n}\n\nexport interface AggregateOptions {\n /** Skip pagination and return every group (the export path). */\n all?: boolean\n}\n\n/**\n * Group, aggregate, sort and page a row set exactly as analytics_run does.\n * Returns the same {rows, total, summary} envelope so callers cannot tell which\n * engine answered.\n */\nexport function aggregateRows(\n source: AnalyticsRow[],\n card: AnalyticsCardDef,\n state: AnalyticsQueryState,\n options?: AggregateOptions,\n): AnalyticsResult {\n // dateColumn null ⇒ a snapshot: the range must not apply (see AnalyticsQuery).\n const snapshot = card.query.dateColumn === null\n const dateColumn = card.query.dateColumn ?? 'created_at'\n const dimensions = card.query.dimensions ?? []\n const measures = (card.query.measures ?? []).filter((m) => m.agg !== 'ratio')\n\n const filtered = source\n .filter((row) => snapshot || inRange(row, dateColumn, state.dateRange?.from, state.dateRange?.to))\n .filter((row) => matchesFilters(row, state.filters ?? {}))\n\n // The rollup: same rows, same filters, no grouping. Identical to SQL 8.11.\n const summary: Record<string, number> = {}\n for (const m of measures) {\n const value = applyMeasure(filtered, m.agg, m.column ?? m.key)\n summary[m.key] = value ?? 0\n }\n\n // No measures ⇒ a detail listing; the rows pass through untouched.\n if (measures.length === 0 && dimensions.length === 0) {\n const sorted = sortRows(filtered, state.sortBy ?? card.query.defaultSort, state.sortDir ?? card.query.defaultSortDir)\n return { rows: page(sorted, state, options), total: sorted.length, summary }\n }\n\n const buckets = new Map<string, { key: AnalyticsRow; rows: AnalyticsRow[] }>()\n for (const row of filtered) {\n const keyParts: AnalyticsRow = {}\n for (const d of dimensions) {\n const raw = row[d.key]\n keyParts[d.key] = d.grain && d.grain !== 'auto' ? truncate(raw, d.grain) : (raw ?? null)\n }\n const id = JSON.stringify(dimensions.map((d) => keyParts[d.key]))\n const existing = buckets.get(id)\n if (existing) existing.rows.push(row)\n else buckets.set(id, { key: keyParts, rows: [row] })\n }\n\n let grouped: AnalyticsRow[] = [...buckets.values()].map(({ key, rows }) => {\n const out: AnalyticsRow = { ...key }\n for (const m of measures) out[m.key] = applyMeasure(rows, m.agg, m.column ?? m.key)\n return out\n })\n\n grouped = sortRows(grouped, state.sortBy ?? card.query.defaultSort, state.sortDir ?? card.query.defaultSortDir)\n if (card.query.limit) grouped = grouped.slice(0, card.query.limit)\n\n return { rows: page(grouped, state, options), total: grouped.length, summary }\n}\n\nfunction sortRows(rows: AnalyticsRow[], sortBy?: string, dir?: 'asc' | 'desc'): AnalyticsRow[] {\n if (!sortBy) return rows\n const sign = dir === 'asc' ? 1 : -1\n return [...rows].sort((a, b) => {\n const av = a[sortBy]\n const bv = b[sortBy]\n // Nulls sort last in both directions — matching SQL's NULLS LAST, so a\n // never-shipped order does not top a \"fastest fulfillment\" report.\n if (av == null && bv == null) return 0\n if (av == null) return 1\n if (bv == null) return -1\n if (typeof av === 'number' || typeof bv === 'number') return (num(av) - num(bv)) * sign\n return String(av).localeCompare(String(bv)) * sign\n })\n}\n\nfunction page(rows: AnalyticsRow[], state: AnalyticsQueryState, options?: AggregateOptions): AnalyticsRow[] {\n if (options?.all) return rows\n const size = state.pageSize || 50\n const start = ((state.page || 1) - 1) * size\n return rows.slice(start, start + size)\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type {\n AnalyticsBatchRequest, AnalyticsCardDef, AnalyticsProvider, AnalyticsQueryState,\n AnalyticsResult, AnalyticsRow,\n} from '@fayz-ai/core'\nimport { aggregateRows } from './aggregate'\n\n// ---------------------------------------------------------------------------\n// The Supabase analytics provider.\n//\n// Everything a card asks for goes through ONE server function, analytics_run:\n// \"orders over time\" and \"sales by product\" are the same call with different\n// dimensions. That is what removes the per-report SQL that made adding a report\n// a database migration.\n//\n// kind 'view' → analytics_run over a registered read model (the normal path)\n// kind 'rpc' → a bespoke function, for the rare card the generic engine\n// cannot express (escape hatch, not the default)\n// kind 'fn' → an app-supplied async function, aggregated client-side\n// ---------------------------------------------------------------------------\n\nfunction snakeToCamel(s: string): string {\n return s.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())\n}\n\n/**\n * Map DB keys to JS keys. Measure and dimension keys are passed through\n * UNTOUCHED — the card named them, the SQL aliased them to exactly that, and\n * silently camelCasing `net_sales` into `netSales` would make every card whose\n * viz references `net_sales` render blank.\n */\nfunction mapRow(row: AnalyticsRow, reserved: Set<string>, columnMap?: Record<string, string>): AnalyticsRow {\n const out: AnalyticsRow = {}\n for (const [key, value] of Object.entries(row)) {\n if (reserved.has(key)) { out[key] = value; continue }\n out[columnMap?.[key] ?? snakeToCamel(key)] = value\n // Keep the raw key too: column definitions written against the read model's\n // snake_case still resolve, so adopting a card needs no rename pass.\n if (!(key in out)) out[key] = value\n }\n return out\n}\n\nfunction reservedKeys(card: AnalyticsCardDef): Set<string> {\n return new Set([\n ...(card.query.dimensions ?? []).map((d) => d.key),\n ...(card.query.measures ?? []).map((m) => m.key),\n ])\n}\n\n/** Text columns free-text search scans, taken from the card's own columns. */\nfunction searchColumns(card: AnalyticsCardDef): string[] | undefined {\n const cols = (card.columns ?? [])\n // 'person' is a text column with a richer cell — searching a customer list\n // by name has to keep working after the name became a link.\n .filter((c) => c.type === 'text' || c.type === 'email' || c.type === 'person')\n .map((c) => c.key)\n return cols.length ? cols : undefined\n}\n\nfunction camelToSnake(s: string): string {\n return s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`)\n}\n\n/**\n * Direct read of a view — the path every pre-existing ReportDef takes.\n *\n * Ports the semantics of the original report provider verbatim (tenant scope,\n * inclusive date window, equality/IN filters, ILIKE search over text columns,\n * sort, page) so adopting the analytics engine changed no existing report's\n * answer.\n */\nasync function selectFromView(\n card: AnalyticsCardDef,\n state: AnalyticsQueryState,\n db: any,\n tenantId: string | undefined,\n reserved: Set<string>,\n): Promise<AnalyticsResult> {\n const { source } = card.query\n const size = state.pageSize || 50\n let q = db.from(source.name!).select('*', { count: 'exact' })\n\n if (tenantId) q = q.eq(source.tenantColumn ?? 'tenant_id', tenantId)\n\n const snapshot = card.query.dateColumn === null\n const dateCol = card.query.dateColumn ?? 'created_at'\n if (!snapshot && state.dateRange?.from) q = q.gte(dateCol, state.dateRange.from)\n if (!snapshot && state.dateRange?.to) {\n // A timestamp column needs the whole final day; a plain date column does\n // not — appending a time to a `date` would compare against a cast and drop\n // the last day of every range.\n q = q.lte(dateCol, dateCol.endsWith('_at') ? `${state.dateRange.to}T23:59:59.999` : state.dateRange.to)\n }\n\n for (const [key, value] of Object.entries(state.filters ?? {})) {\n if (value == null || value === '') continue\n const col = camelToSnake(key)\n q = Array.isArray(value) ? q.in(col, value) : q.eq(col, value)\n }\n\n const searchable = searchColumns(card)\n if (state.search?.trim() && searchable?.length) {\n const term = `%${state.search.trim()}%`\n q = q.or(searchable.map((c) => `${camelToSnake(c)}.ilike.${term}`).join(','))\n }\n\n const sortBy = state.sortBy ?? card.query.defaultSort\n if (sortBy) {\n q = q.order(camelToSnake(sortBy), {\n ascending: (state.sortDir ?? card.query.defaultSortDir ?? 'desc') === 'asc',\n })\n }\n\n const from = ((state.page || 1) - 1) * size\n const { data, error, count } = await q.range(from, from + size - 1)\n if (error) throw error\n\n return {\n rows: (data ?? []).map((r: AnalyticsRow) => mapRow(r, reserved, source.columnMap)),\n total: count ?? 0,\n }\n}\n\n/**\n * A rejection the card can actually print.\n *\n * PostgREST rejects with a PLAIN OBJECT ({ message, details, hint, code }), not\n * an Error — so `new Error(String(err))` turned every failed card into the words\n * \"[object Object]\" and threw away the one sentence that says what broke.\n */\nfunction toError(err: unknown): Error {\n if (err instanceof Error) return err\n if (err && typeof err === 'object') {\n const e = err as Record<string, unknown>\n const message = [...new Set(\n [e.message, e.details, e.hint].filter(\n (part): part is string => typeof part === 'string' && part.trim().length > 0,\n ),\n )].join(' — ')\n if (message) return Object.assign(new Error(message), e.code ? { code: e.code } : {})\n }\n return new Error(String(err))\n}\n\n/**\n * True when the card is answered by the generic aggregate engine — the only\n * shape that can travel in a batch, because the batch function IS analytics_run\n * called in a loop. A detail listing is a plain PostgREST select and an 'fn'\n * card never touches the database at all.\n */\nfunction isAggregateCard(card: AnalyticsCardDef): boolean {\n const { source } = card.query\n if (source.kind !== 'view' || !source.name) return false\n return (card.query.dimensions?.length ?? 0) > 0 || (card.query.measures?.length ?? 0) > 0\n}\n\n/**\n * The arguments analytics_run wants, as a plain object. Named once so a single\n * call and a batched element cannot drift into asking different questions —\n * the bug that would show up as a KPI disagreeing with itself depending on how\n * many other cards happened to be on screen.\n */\nfunction runArgs(card: AnalyticsCardDef, state: AnalyticsQueryState, tenantId: string | undefined) {\n const size = state.pageSize || 50\n // A snapshot card (dateColumn: null) sends no window at all, so \"stock on\n // hand\" stays stock on hand no matter what the range picker says.\n const snapshot = card.query.dateColumn === null\n return {\n source: card.query.source.name!,\n tenant_id: tenantId ?? null,\n from: !snapshot && state.dateRange.from ? `${state.dateRange.from}T00:00:00` : null,\n // Inclusive end-of-day: the range picker speaks in days, the column is a\n // timestamp, and closing at midnight loses everything sold that day.\n to: !snapshot && state.dateRange.to ? `${state.dateRange.to}T23:59:59.999` : null,\n dimensions: (card.query.dimensions ?? []).map((d) => ({\n key: d.key,\n ...(d.grain && d.grain !== 'auto' ? { grain: d.grain } : {}),\n })),\n measures: (card.query.measures ?? [])\n .filter((m) => m.agg !== 'ratio')\n .map((m) => ({ key: m.key, agg: m.agg, ...(m.column ? { column: m.column } : {}) })),\n filters: state.filters ?? {},\n search: state.search ?? null,\n search_columns: searchColumns(card) ?? null,\n sort: state.sortBy ?? card.query.defaultSort ?? null,\n dir: state.sortDir ?? card.query.defaultSortDir ?? 'desc',\n limit: card.query.limit ?? size,\n offset: card.query.limit ? 0 : ((state.page || 1) - 1) * size,\n }\n}\n\n/** Shape analytics_run's envelope into a result, mapping row keys. */\nfunction toResult(data: any, card: AnalyticsCardDef, reserved: Set<string>): AnalyticsResult {\n const rows: AnalyticsRow[] = data?.rows ?? []\n return {\n rows: rows.map((r) => mapRow(r, reserved, card.query.source.columnMap)),\n total: data?.total ?? rows.length,\n summary: data?.summary ?? undefined,\n }\n}\n\n/** The batch function is missing on this project — 025 was never applied. */\nfunction batchUnavailable(err: any): boolean {\n const code = typeof err?.code === 'string' ? err.code : ''\n if (['42883', 'PGRST202'].includes(code)) return true\n return typeof err?.message === 'string' && err.message.includes('analytics_run_batch')\n}\n\nexport interface SupabaseAnalyticsProviderConfig {\n tenantId: string | (() => string | undefined)\n schema?: string\n}\n\nexport function createSupabaseAnalyticsProvider(config: SupabaseAnalyticsProviderConfig): AnalyticsProvider {\n const resolveTenantId = () =>\n (typeof config.tenantId === 'function' ? config.tenantId() : config.tenantId) || undefined\n\n function client() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase client not available')\n return config.schema && config.schema !== 'public' ? supabase.schema(config.schema) : supabase\n }\n\n // Flipped off for good on the first \"function does not exist\", so an older\n // pool degrades to one-request-per-card instead of failing every card.\n let batchSupported = true\n\n return {\n async run(card: AnalyticsCardDef, state: AnalyticsQueryState): Promise<AnalyticsResult> {\n const { source } = card.query\n const reserved = reservedKeys(card)\n\n if (source.kind === 'fn') {\n if (!source.run) throw new Error(`analytics: card ${card.id} declares kind 'fn' with no run()`)\n const rows = await source.run({\n tenantId: resolveTenantId(),\n dateRange: state.dateRange,\n filters: state.filters,\n })\n return aggregateRows(rows, card, state)\n }\n\n if (!source.name) throw new Error(`analytics: card ${card.id} has no source name`)\n\n // A card with neither dimensions nor measures is a flat listing, and a\n // flat listing has nothing to aggregate. It reads the view DIRECTLY.\n //\n // This is not an optimisation — it is what keeps the five apps that\n // already ship ReportDef catalogues working. Their views (rep_appointments\n // _by_period, plg_courses_rep_revenue, …) predate analytics_run and are\n // not in its allowlist, so sending a plain SELECT through the aggregate\n // engine turned every existing report into PGRST202. Registration is the\n // price of GROUP BY, not the price of reading rows.\n const isDetail = (card.query.dimensions?.length ?? 0) === 0\n && (card.query.measures?.length ?? 0) === 0\n if (source.kind === 'view' && isDetail) {\n return selectFromView(card, state, client(), resolveTenantId(), reserved)\n }\n\n if (source.kind === 'rpc') {\n const { data, error } = await client().rpc(source.name, {\n p_tenant_id: resolveTenantId(),\n p_from: state.dateRange.from,\n p_to: state.dateRange.to,\n ...Object.fromEntries(Object.entries(state.filters ?? {}).map(([k, v]) => [`p_${k}`, v])),\n })\n if (error) throw error\n const rows: AnalyticsRow[] = Array.isArray(data) ? data : (data?.rows ?? [])\n return {\n rows: rows.map((r) => mapRow(r, reserved, source.columnMap)),\n total: Array.isArray(data) ? rows.length : (data?.total ?? rows.length),\n summary: Array.isArray(data) ? undefined : data?.summary,\n }\n }\n\n // The standard path: the generic aggregate engine.\n const args = runArgs(card, state, resolveTenantId())\n const { data, error } = await client().rpc('analytics_run', {\n p_source: args.source,\n p_tenant_id: args.tenant_id,\n p_from: args.from,\n p_to: args.to,\n p_dimensions: args.dimensions,\n p_measures: args.measures,\n p_filters: args.filters,\n p_search: args.search,\n p_search_columns: args.search_columns,\n p_sort: args.sort,\n p_dir: args.dir,\n p_limit: args.limit,\n p_offset: args.offset,\n })\n if (error) throw error\n return toResult(data, card, reserved)\n },\n\n // -----------------------------------------------------------------------\n // The batched path.\n //\n // Every aggregate card in the batch becomes ONE analytics_run_batch call;\n // detail listings and 'fn' cards, which the batch function cannot express,\n // still go one by one — but a dashboard is all aggregates, so opening\n // /analytics went from forty-one requests to one.\n //\n // Results keep their INDEX. The caller matched a promise to a position, and\n // returning a compacted array would silently hand card 7 card 9's numbers.\n // -----------------------------------------------------------------------\n async runMany(requests: AnalyticsBatchRequest[]): Promise<Array<AnalyticsResult | Error>> {\n const out: Array<AnalyticsResult | Error> = new Array(requests.length)\n const batchable: number[] = []\n\n for (let i = 0; i < requests.length; i++) {\n if (batchSupported && isAggregateCard(requests[i]!.card)) batchable.push(i)\n }\n\n // Anything the batch cannot carry runs on its own, concurrently.\n const singles = requests\n .map((req, i) => ({ req, i }))\n .filter(({ i }) => !batchable.includes(i))\n .map(({ req, i }) =>\n this.run(req.card, req.state)\n .then((r) => { out[i] = r })\n .catch((e: unknown) => { out[i] = toError(e) }))\n\n if (batchable.length > 0) {\n const tenantId = resolveTenantId()\n const payload = batchable.map((i) => runArgs(requests[i]!.card, requests[i]!.state, tenantId))\n const { data, error } = await client().rpc('analytics_run_batch', { p_requests: payload })\n\n if (error && batchUnavailable(error)) {\n // A pool that has analytics_run but not 034 must keep working rather\n // than reporting \"engine not installed\" on every card. Latched, so\n // the fallback costs one failed call per session, not per fetch.\n batchSupported = false\n await Promise.all([\n ...singles,\n ...batchable.map((i) =>\n this.run(requests[i]!.card, requests[i]!.state)\n .then((r) => { out[i] = r })\n .catch((e: unknown) => { out[i] = toError(e) })),\n ])\n return out\n }\n if (error) throw error\n\n const results: any[] = Array.isArray(data) ? data : []\n batchable.forEach((cardIndex, slot) => {\n const entry = results[slot]\n const { card } = requests[cardIndex]!\n out[cardIndex] = entry?.error\n ? Object.assign(toError(entry.error), { code: entry.code })\n : toResult(entry, card, reservedKeys(card))\n })\n }\n\n await Promise.all(singles)\n return out\n },\n }\n}\n","import type {\n AnalyticsCardDef, AnalyticsProvider, AnalyticsQueryState, AnalyticsRow,\n} from '@fayz-ai/core'\nimport { aggregateRows } from './aggregate'\n\n// ---------------------------------------------------------------------------\n// Mock analytics provider — synthesises rows shaped by whatever the card asks\n// for, then runs them through the SAME aggregator the 'fn' source uses. The\n// numbers are invented; the grouping, bucketing and rollup behaviour is real,\n// so a card that looks right against the mock is not lying about its shape.\n//\n// Deterministic on purpose: a seeded generator means the dev dashboard does not\n// reshuffle on every keystroke, and a screenshot stays reproducible.\n// ---------------------------------------------------------------------------\n\nfunction seeded(seed: string): () => number {\n let h = 2166136261\n for (let i = 0; i < seed.length; i++) {\n h ^= seed.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n return () => {\n h += 0x6d2b79f5\n let t = h\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\nconst SAMPLE_LABELS: Record<string, string[]> = {\n product_name: ['Camiseta Preta', 'Caneca Fayz', 'Moletom', 'Boné', 'Adesivos'],\n category_name: ['Vestuário', 'Acessórios', 'Casa'],\n customer_name: ['Ana Souza', 'Bruno Lima', 'Carla Dias', 'Diego Alves'],\n status: ['open', 'archived', 'cancelled'],\n financial_status: ['paid', 'pending', 'refunded'],\n fulfillment_status: ['fulfilled', 'unfulfilled', 'partially_fulfilled'],\n}\n\nfunction labelsFor(key: string, rand: () => number): string[] {\n const known = SAMPLE_LABELS[key]\n if (known) return known\n const n = 3 + Math.floor(rand() * 3)\n return Array.from({ length: n }, (_, i) => `${key.replace(/_/g, ' ')} ${i + 1}`)\n}\n\nexport function createMockAnalyticsProvider(): AnalyticsProvider {\n return {\n async run(card: AnalyticsCardDef, state: AnalyticsQueryState) {\n const rand = seeded(card.id)\n const dateColumn = card.query.dateColumn ?? 'created_at'\n const dimensions = card.query.dimensions ?? []\n const measures = card.query.measures ?? []\n\n const from = new Date(`${state.dateRange.from}T12:00:00`).getTime()\n const to = new Date(`${state.dateRange.to}T12:00:00`).getTime()\n const span = Math.max(to - from, 86_400_000)\n\n // Enough rows that every bucket and every category is represented, capped\n // so a 90-day range does not synthesise thousands of throwaway objects.\n const rowCount = Math.min(400, Math.max(60, Math.round(span / 86_400_000) * 4))\n const categoricalDims = dimensions.filter((d) => !d.grain && d.key !== dateColumn)\n const labelPools = new Map(categoricalDims.map((d) => [d.key, labelsFor(d.key, rand)]))\n\n const rows: AnalyticsRow[] = Array.from({ length: rowCount }, () => {\n const row: AnalyticsRow = {\n [dateColumn]: new Date(from + rand() * span).toISOString(),\n }\n for (const [key, pool] of labelPools) {\n row[key] = pool[Math.floor(rand() * pool.length)]\n }\n for (const m of measures) {\n if (m.agg === 'count' || m.agg === 'ratio') continue\n const column = m.column ?? m.key\n row[column] = m.format === 'currency'\n ? Math.round(rand() * 40000) / 100\n : m.format === 'percent'\n ? Math.round(rand() * 10000) / 100\n : Math.round(rand() * 50)\n }\n for (const c of card.columns ?? []) {\n if (c.key in row) continue\n row[c.key] = c.type === 'currency' || c.type === 'number'\n ? Math.round(rand() * 10000) / 100\n : c.type === 'date'\n ? new Date(from + rand() * span).toISOString()\n : `${c.label} ${Math.ceil(rand() * 20)}`\n }\n return row\n })\n\n return aggregateRows(rows, card, state)\n },\n\n // There is no transport to save a round trip on, so this is just the loop.\n // It exists because the mock is reached through createSafeDataProvider,\n // whose Proxy answers EVERY property with a function — `provider.runMany`\n // is truthy even for a provider that never declared it, and the caller's\n // feature check therefore cannot detect its absence. Implementing it is how\n // the mock stops being a landmine behind that Proxy.\n async runMany(requests) {\n return Promise.all(requests.map((r) =>\n this.run(r.card, r.state).catch((e: unknown) => (e instanceof Error ? e : new Error(String(e))))))\n },\n }\n}\n","import { useOrganizationStore } from '@fayz-ai/admin'\n\n// ---------------------------------------------------------------------------\n// Which tenant the analytics surface is reporting on.\n//\n// Defaults to the organization the shell is currently switched to. Leaving it\n// undefined is NOT equivalent: with no tenant the engine sends no predicate and\n// falls back to RLS alone, and RLS on the shop tables admits every tenant the\n// user is a member of (`tenant_id IN user_tenant_ids()`). In a multi-org app\n// that is one page reporting the sum of every store the operator can see, while\n// every other screen beside it shows only the active one.\n// ---------------------------------------------------------------------------\n\nlet override: string | undefined\n\n/** Pin the surface to a tenant, overriding the active organization. */\nexport function setReportsTenantId(id: string | undefined): void {\n override = id\n}\n\nexport function getReportsTenantId(): string | undefined {\n if (override) return override\n try {\n return useOrganizationStore.getState().currentOrg?.id\n } catch {\n // No org store mounted (a bespoke host, a test): fall back to RLS rather\n // than throwing inside a data provider.\n return undefined\n }\n}\n","export const en: Record<string, string> = {\n 'reports.pageTitle': 'Reports',\n 'reports.pageSubtitle': 'Access complete reports for analysis and decision making',\n 'reports.overview': 'Overview',\n 'reports.allReports': 'All reports',\n 'reports.dateRange': 'Date Range',\n 'reports.from': 'From',\n 'reports.to': 'To',\n 'reports.export': 'Export',\n 'reports.exportCsv': 'Export CSV',\n 'reports.exportExcel': 'Export Excel',\n 'reports.exportPdf': 'Export PDF',\n 'reports.noResults': 'No results found.',\n 'reports.backToReports': 'Back',\n 'reports.reports': 'reports',\n 'reports.search': 'Search reports...',\n 'reports.today': 'Today',\n 'reports.yesterday': 'Yesterday',\n 'reports.last7Days': 'Last 7 days',\n 'reports.thisMonth': 'This month',\n 'reports.lastMonth': 'Last month',\n 'reports.thisQuarter': 'This quarter',\n 'reports.custom': 'Custom',\n 'reports.generate': 'Generate',\n 'reports.emptyStateTitle': 'Ready to generate',\n 'reports.emptyStateDescription': 'Select a date range and filters, then click Generate to view the report.',\n // The assistant's invitation on /analytics. It opens on a question, not on a\n // grid: the numbers are already downstairs, and what the owner actually wants\n // is to know what they mean.\n 'reports.assistant.persona': 'Growth Analyst',\n 'reports.assistant.headline': 'Hi {{name}}, what would you like to learn today?',\n 'reports.assistant.pitch': \"Let's find the opportunities hiding in your business\",\n 'reports.assistant.description':\n \"Tell me your goals and I'll help build a plan to hit them. I read the same data these reports do, and I'll point at what changed and what to do about it.\",\n 'reports.assistant.placeholder': 'Build a custom report...',\n 'reports.assistant.suggestion.0': 'How is my business doing this month?',\n 'reports.assistant.suggestion.1': \"What's growing and what's falling?\",\n 'reports.assistant.suggestion.2': 'Where am I losing money?',\n 'reports.print': 'Print',\n 'reports.pagination.range': '{{from}}–{{to}} of {{total}}',\n 'reports.pagination.empty': 'No results',\n 'reports.pagination.perPage': '{{size}} / page',\n 'reports.settings.nav': 'Configure reports',\n 'reports.settings.title': 'Configure reports',\n 'reports.settings.subtitle': 'Choose what appears on the overview, in what order, and what each report shows. Saved in this browser.',\n 'reports.settings.new': 'New report',\n 'reports.settings.newHint': 'A new report asks a different question of a source the app already exposes.',\n 'reports.settings.newWithAIHint': 'Describe what you want to see and I build it.',\n 'reports.settings.newByHand': 'Create by hand',\n 'reports.settings.newByHandHint': 'Pick the source, the grouping and the measures.',\n 'reports.settings.askPersona': 'Report analyst',\n 'reports.settings.askPitch': 'Tell me the report you want.',\n 'reports.settings.askDescription': 'I know this app\\'s data sources and the fields on each. Describe what you want to see — I pick the grouping, the measures and the format, build it and open it for you to check.',\n 'reports.settings.askSuggestion.0': 'Revenue by table, highest first',\n 'reports.settings.askSuggestion.1': 'How much each station produces per service',\n 'reports.settings.askSuggestion.2': 'Average ticket by channel, month by month',\n 'reports.settings.askPlaceholder': 'Describe the report…',\n 'reports.settings.orByHand': 'or build it by hand',\n 'reports.settings.reset': 'Reset to defaults',\n 'reports.settings.onOverview': 'On the overview',\n 'reports.settings.onOverviewHint': 'Drag to reorder. Width is in grid columns.',\n 'reports.settings.offOverview': 'Off the overview',\n 'reports.settings.offOverviewHint': 'Still in the list and still open full size — they just do not claim a tile.',\n 'reports.settings.hidden': 'Removed from the catalogue',\n 'reports.settings.empty': 'No reports on the overview.',\n 'reports.settings.custom': 'Yours',\n 'reports.settings.pin': 'Add to the overview',\n 'reports.settings.unpin': 'Remove from the overview',\n 'reports.settings.up': 'Move up',\n 'reports.settings.down': 'Move down',\n 'reports.settings.edit': 'Adjust',\n 'reports.settings.remove': 'Remove from the catalogue',\n 'reports.settings.restore': 'Restore',\n 'reports.settings.delete': 'Delete',\n 'reports.settings.width': 'Width',\n 'reports.settings.width.1': 'Quarter',\n 'reports.settings.width.2': 'Half',\n 'reports.settings.width.3': 'Three quarters',\n 'reports.settings.width.4': 'Full',\n 'reports.settings.name': 'Name',\n 'reports.settings.category': 'Category',\n 'reports.settings.source': 'Data source',\n 'reports.settings.sourceHint': 'Where the rows come from — it decides which fields you can use.',\n 'reports.settings.viz': 'Visualization',\n 'reports.settings.dimensions': 'Group by',\n 'reports.settings.measures': 'Measures',\n 'reports.settings.resetCard': 'Reset this report',\n 'reports.settings.needName': 'Give the report a name.',\n 'reports.settings.needMeasure': 'Pick at least one measure.',\n 'reports.settings.save': 'Create',\n 'reports.settings.cancel': 'Cancel',\n 'reports.settings.done': 'Done',\n 'reports.viz.kpi': 'Number',\n 'reports.viz.line': 'Line',\n 'reports.viz.bar': 'Bars',\n 'reports.viz.area': 'Area',\n 'reports.viz.donut': 'Donut',\n 'reports.viz.breakdown': 'Ranking',\n 'reports.viz.table': 'Table',\n 'reports.viz.funnel': 'Funnel',\n 'reports.unavailableTitle': 'Coming soon',\n 'reports.unavailableDescription': 'This report is not available yet. It will be enabled in a future update.',\n}\n","export const ptBR: Record<string, string> = {\n 'reports.pageTitle': 'Relatórios',\n 'reports.pageSubtitle': 'Acesse relatórios completos para análise e tomada de decisão',\n 'reports.overview': 'Visão geral',\n 'reports.allReports': 'Todos os relatórios',\n 'reports.dateRange': 'Período',\n 'reports.from': 'De',\n 'reports.to': 'Até',\n 'reports.export': 'Exportar',\n 'reports.exportCsv': 'Exportar CSV',\n 'reports.exportExcel': 'Exportar Excel',\n 'reports.exportPdf': 'Exportar PDF',\n 'reports.noResults': 'Nenhum resultado encontrado.',\n 'reports.backToReports': 'Voltar',\n 'reports.reports': 'relatórios',\n 'reports.search': 'Buscar relatórios...',\n 'reports.today': 'Hoje',\n 'reports.yesterday': 'Ontem',\n 'reports.last7Days': 'Últimos 7 dias',\n 'reports.thisMonth': 'Este mês',\n 'reports.lastMonth': 'Mês passado',\n 'reports.thisQuarter': 'Este trimestre',\n 'reports.custom': 'Personalizado',\n 'reports.generate': 'Gerar',\n 'reports.emptyStateTitle': 'Pronto para gerar',\n 'reports.emptyStateDescription': 'Selecione o período e os filtros desejados, depois clique em Gerar para visualizar o relatório.',\n 'reports.assistant.persona': 'Analista de Crescimento',\n 'reports.assistant.headline': 'Oi {{name}}, o que você quer entender hoje?',\n 'reports.assistant.pitch': 'Vamos achar as oportunidades escondidas no seu negócio',\n 'reports.assistant.description':\n 'Me conte sua meta e eu ajudo a montar o plano para bater. Leio os mesmos dados destes relatórios e aponto o que mudou e o que fazer a respeito.',\n 'reports.assistant.placeholder': 'Peça um relatório do seu jeito...',\n 'reports.assistant.suggestion.0': 'Como está meu negócio neste mês?',\n 'reports.assistant.suggestion.1': 'O que está crescendo e o que está caindo?',\n 'reports.assistant.suggestion.2': 'Onde estou perdendo dinheiro?',\n 'reports.print': 'Imprimir',\n 'reports.pagination.range': '{{from}}–{{to}} de {{total}}',\n 'reports.pagination.empty': 'Nenhum resultado',\n 'reports.pagination.perPage': '{{size}} / página',\n 'reports.settings.nav': 'Configurar relatórios',\n 'reports.settings.title': 'Configurar relatórios',\n 'reports.settings.subtitle': 'Escolha o que aparece no painel, em que ordem e o que cada relatório mostra. As escolhas ficam neste navegador.',\n 'reports.settings.new': 'Novo relatório',\n 'reports.settings.newHint': 'Um relatório novo pergunta outra coisa a uma fonte que o app já expõe.',\n 'reports.settings.newWithAIHint': 'Descreva o que quer ver e eu monto.',\n 'reports.settings.newByHand': 'Criar manualmente',\n 'reports.settings.newByHandHint': 'Escolher fonte, agrupamento e medidas.',\n 'reports.settings.askPersona': 'Analista de relatórios',\n 'reports.settings.askPitch': 'Diga o relatório que você quer.',\n 'reports.settings.askDescription': 'Conheço as fontes deste app e os campos de cada uma. Descreva o que quer ver — eu escolho o agrupamento, as medidas e o formato, monto e abro para você conferir.',\n 'reports.settings.askSuggestion.0': 'Receita por mesa, do maior para o menor',\n 'reports.settings.askSuggestion.1': 'Quanto cada praça produz por turno',\n 'reports.settings.askSuggestion.2': 'Ticket médio por canal, mês a mês',\n 'reports.settings.askPlaceholder': 'Descreva o relatório…',\n 'reports.settings.orByHand': 'ou monte à mão',\n 'reports.settings.reset': 'Restaurar padrões',\n 'reports.settings.onOverview': 'No painel',\n 'reports.settings.onOverviewHint': 'Arraste para reordenar. A largura é em colunas da grade.',\n 'reports.settings.offOverview': 'Fora do painel',\n 'reports.settings.offOverviewHint': 'Continuam na lista e abrem inteiros; só não ocupam um bloco do painel.',\n 'reports.settings.hidden': 'Removidos do catálogo',\n 'reports.settings.empty': 'Nenhum relatório no painel.',\n 'reports.settings.custom': 'Seu',\n 'reports.settings.pin': 'Pôr no painel',\n 'reports.settings.unpin': 'Tirar do painel',\n 'reports.settings.up': 'Subir',\n 'reports.settings.down': 'Descer',\n 'reports.settings.edit': 'Ajustar',\n 'reports.settings.remove': 'Remover do catálogo',\n 'reports.settings.restore': 'Devolver',\n 'reports.settings.delete': 'Excluir',\n 'reports.settings.width': 'Largura',\n 'reports.settings.width.1': 'Um quarto',\n 'reports.settings.width.2': 'Metade',\n 'reports.settings.width.3': 'Três quartos',\n 'reports.settings.width.4': 'Inteiro',\n 'reports.settings.name': 'Nome',\n 'reports.settings.category': 'Categoria',\n 'reports.settings.source': 'Fonte de dados',\n 'reports.settings.sourceHint': 'De onde vêm as linhas — é ela que decide quais campos você pode usar.',\n 'reports.settings.viz': 'Visualização',\n 'reports.settings.dimensions': 'Agrupar por',\n 'reports.settings.measures': 'Medidas',\n 'reports.settings.resetCard': 'Restaurar este relatório',\n 'reports.settings.needName': 'Dê um nome ao relatório.',\n 'reports.settings.needMeasure': 'Escolha ao menos uma medida.',\n 'reports.settings.save': 'Criar',\n 'reports.settings.cancel': 'Cancelar',\n 'reports.settings.done': 'Pronto',\n 'reports.viz.kpi': 'Número',\n 'reports.viz.line': 'Linha',\n 'reports.viz.bar': 'Barras',\n 'reports.viz.area': 'Área',\n 'reports.viz.donut': 'Rosca',\n 'reports.viz.breakdown': 'Ranking',\n 'reports.viz.table': 'Tabela',\n 'reports.viz.funnel': 'Funil',\n 'reports.unavailableTitle': 'Em breve',\n 'reports.unavailableDescription': 'Este relatório ainda não está disponível. Será habilitado em uma atualização futura.',\n}\n","import { en } from './en'\nimport { ptBR } from './pt-BR'\n\nexport const reportsLocales: Record<string, Record<string, string>> = {\n en,\n 'pt-BR': ptBR,\n}\n","// AUTO-GENERATED from 000_baseline.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000_BASELINE = `-- ============================================================================\n-- plugins/plugin-reports/src/migrations/000_baseline.sql — what installing this provisions, as one file.\n--\n-- GENERATED by scripts/emit-unit-baselines.mjs (#338). Do not edit by hand:\n-- change the schema, regenerate, and let scripts/check-chain-equivalence.mjs\n-- prove the result still matches.\n--\n-- This replaced 3 migration files. They are kept, unapplied, in\n-- migrations.archive/ — a year of decisions is worth reading even when it is no\n-- longer worth replaying.\n--\n-- Object order is fixed rather than dependency-sorted: schemas, types,\n-- sequences, tables, defaults, functions, constraints, views, indexes, foreign\n-- keys, triggers, row security, policies, grants. Dependencies BETWEEN units\n-- are carried by the order packages/db/chain.json declares.\n-- ============================================================================\n\n-- A LANGUAGE sql function binds its body at CREATE time, and 570 functions\n-- sorted by name are not sorted by who calls whom. This is what lets them load\n-- in any order; every body is still compiled on first call, so a genuinely\n-- broken reference surfaces then rather than never. Session-scoped.\nSET check_function_bodies = false;\n\n\n\n-- ── default privileges: reset ───────────────────────────────────────────\n-- Cleared BEFORE anything is created, so every object below gets the ACL the\n-- dump describes rather than the image's defaults on top of it. Restored at\n-- the end of this file.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\n\n-- ── table ───────────────────────────────────────────────────────────────\n\nCREATE TABLE public.plg_reports_definitions (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid,\n unit_id uuid,\n key text NOT NULL,\n version integer DEFAULT 1 NOT NULL,\n title text NOT NULL,\n description text,\n module text NOT NULL,\n source_view text NOT NULL,\n params jsonb DEFAULT '[]'::jsonb NOT NULL,\n columns jsonb DEFAULT '[]'::jsonb NOT NULL,\n default_order_by text,\n required_permission text NOT NULL,\n is_active boolean DEFAULT true NOT NULL,\n metadata jsonb DEFAULT '{}'::jsonb NOT NULL,\n created_by uuid,\n owner_id uuid,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reports_definitions_required_permission_check CHECK ((btrim(required_permission) <> ''::text)),\n CONSTRAINT plg_reports_definitions_version_check CHECK ((version >= 1))\n);\n\nALTER TABLE ONLY public.plg_reports_definitions FORCE ROW LEVEL SECURITY;\n\nCREATE TABLE public.plg_reports_runs (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n unit_id uuid,\n definition_key text NOT NULL,\n definition_version integer DEFAULT 1 NOT NULL,\n params jsonb DEFAULT '{}'::jsonb NOT NULL,\n requested_by uuid,\n row_count bigint,\n duration_ms integer,\n status text DEFAULT 'ok'::text NOT NULL,\n error text,\n format text,\n owner_id uuid,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reports_runs_status_check CHECK ((status = ANY (ARRAY['ok'::text, 'refused'::text, 'error'::text])))\n);\n\nALTER TABLE ONLY public.plg_reports_runs FORCE ROW LEVEL SECURITY;\n\nCREATE TABLE public.plg_reports_schedules (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n unit_id uuid,\n definition_key text NOT NULL,\n cron text NOT NULL,\n params jsonb DEFAULT '{}'::jsonb NOT NULL,\n recipients jsonb DEFAULT '[]'::jsonb NOT NULL,\n format text DEFAULT 'csv'::text NOT NULL,\n template_key text DEFAULT 'report.delivered'::text NOT NULL,\n is_active boolean DEFAULT true NOT NULL,\n last_run_at timestamp with time zone,\n next_run_at timestamp with time zone,\n owner_id uuid,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reports_schedules_format_check CHECK ((format = ANY (ARRAY['csv'::text, 'xlsx'::text, 'pdf'::text])))\n);\n\nALTER TABLE ONLY public.plg_reports_schedules FORCE ROW LEVEL SECURITY;\n\n\n-- ── function ────────────────────────────────────────────────────────────\n\nCREATE FUNCTION public.reports_definition(p_key text, p_tenant uuid DEFAULT NULL::uuid) RETURNS public.plg_reports_definitions\n LANGUAGE sql STABLE SECURITY DEFINER\n SET search_path TO ''\n AS $$\n SELECT d.* FROM public.plg_reports_definitions d\n WHERE d.key = p_key AND d.is_active\n AND (d.tenant_id = coalesce(p_tenant, app.current_tenant_id()) OR d.tenant_id IS NULL)\n -- A tenant's own definition beats the platform one, and the newest version\n -- beats an older one.\n ORDER BY (d.tenant_id IS NOT NULL) DESC, d.version DESC\n LIMIT 1\n$$;\n\nCREATE FUNCTION public.reports_deliver_due(p_limit integer DEFAULT 50) RETURNS jsonb\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $$\nDECLARE\n s public.plg_reports_schedules%ROWTYPE;\n v_recipient jsonb;\n v_res jsonb;\n v_sent integer := 0;\n v_runs integer := 0;\nBEGIN\n IF to_regprocedure('public.notifications_enqueue(uuid, text, uuid, jsonb, text, timestamptz, text, text, uuid, uuid)') IS NULL THEN\n RETURN jsonb_build_object('skipped', 'plugin-notifications is not installed');\n END IF;\n\n FOR s IN\n SELECT * FROM public.plg_reports_schedules\n WHERE is_active AND (next_run_at IS NULL OR next_run_at <= now())\n ORDER BY next_run_at NULLS FIRST\n LIMIT greatest(p_limit, 0)\n FOR UPDATE SKIP LOCKED\n LOOP\n v_runs := v_runs + 1;\n FOR v_recipient IN SELECT * FROM jsonb_array_elements(coalesce(s.recipients, '[]'::jsonb)) LOOP\n -- The campaign rule applies to a report too: this ENQUEUES, it does not\n -- send. One engine, one queue, one place a delivery can be retried.\n v_res := to_jsonb(public.notifications_enqueue(\n p_tenant_id => s.tenant_id,\n p_template_key => s.template_key,\n p_person_id => nullif(v_recipient ->> 'person_id', '')::uuid,\n p_payload => jsonb_build_object('report_key', s.definition_key, 'format', s.format),\n p_dedupe_key => 'report:' || s.id::text || ':' || to_char(now(), 'YYYY-MM-DD') || ':' || coalesce(v_recipient ->> 'person_id', ''),\n p_unit_id => s.unit_id));\n v_sent := v_sent + 1;\n END LOOP;\n\n UPDATE public.plg_reports_schedules\n SET last_run_at = now(),\n next_run_at = now() + interval '1 day'\n WHERE id = s.id;\n END LOOP;\n\n RETURN jsonb_build_object('schedules', v_runs, 'queued', v_sent);\nEND $$;\n\nCREATE FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text DEFAULT 'email'::text) RETURNS uuid\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $$\nDECLARE v_id uuid;\nBEGIN\n IF to_regclass('public.plg_notifications_templates') IS NULL THEN\n RAISE EXCEPTION 'reports_ensure_delivery_template: plugin-notifications is not installed' USING ERRCODE = '0A000';\n END IF;\n INSERT INTO public.plg_notifications_templates (tenant_id, key, channel, locale, subject, body, is_default, purpose)\n VALUES (p_tenant, 'report.delivered', p_channel, 'pt-BR',\n 'Seu relatório está pronto',\n 'O relatório {{report_key}} foi gerado em {{format}} e está disponível.', true, 'transactional')\n ON CONFLICT (tenant_id, key, channel, locale) DO UPDATE SET is_active = true\n RETURNING id INTO v_id;\n RETURN v_id;\nEND $$;\n\nCREATE FUNCTION public.reports_run(p_key text, p_params jsonb DEFAULT '{}'::jsonb, p_limit integer DEFAULT 1000, p_offset integer DEFAULT 0, p_format text DEFAULT NULL::text) RETURNS jsonb\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $$\nDECLARE\n v_tenant uuid := app.current_tenant_id();\n v_def public.plg_reports_definitions%ROWTYPE;\n v_sql text;\n v_where text := '';\n v_param jsonb;\n v_name text;\n v_value text;\n v_rows jsonb;\n v_count bigint := 0;\n v_start timestamptz := clock_timestamp();\n v_has_unit boolean;\nBEGIN\n IF v_tenant IS NULL THEN\n RAISE EXCEPTION 'reports_run: no active tenant' USING ERRCODE = '42501';\n END IF;\n\n v_def := public.reports_definition(p_key, v_tenant);\n IF v_def.id IS NULL THEN\n RAISE EXCEPTION 'reports_run: no active report called %', p_key USING ERRCODE = 'P0002';\n END IF;\n\n -- ── refuse BEFORE the query, not after the rows ──────────────────────\n --\n -- The refusal is RETURNED rather than raised, and the reason is mechanical:\n -- raising rolls the statement back, taking the run record with it, and a\n -- refusal nobody can see afterwards is the thing this history exists for.\n -- No rows are read either way — which is what \"refuse before the query\" means\n -- — and a caller that ignores \\`status\\` still gets nothing.\n IF NOT (select app.has_permission(v_def.required_permission, NULL)) THEN\n INSERT INTO public.plg_reports_runs (tenant_id, definition_key, definition_version, params, requested_by, status, error)\n VALUES (v_tenant, p_key, v_def.version, coalesce(p_params, '{}'::jsonb), auth.uid(), 'refused',\n format('%s is required', v_def.required_permission));\n RETURN jsonb_build_object(\n 'key', p_key, 'version', v_def.version, 'title', v_def.title,\n 'status', 'refused', 'required_permission', v_def.required_permission,\n 'columns', '[]'::jsonb, 'rows', '[]'::jsonb, 'row_count', 0);\n END IF;\n\n -- ── scope the engine injects, and no definition can switch off ───────\n v_where := format('%I = %L', 'tenant_id', v_tenant);\n\n SELECT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = v_def.source_view AND column_name = 'unit_id')\n INTO v_has_unit;\n IF v_has_unit THEN\n v_where := v_where || ' AND (unit_id IS NULL OR (select app.has_unit(unit_id)))';\n END IF;\n\n -- ── the declared parameters, and only those ──────────────────────────\n FOR v_param IN SELECT * FROM jsonb_array_elements(coalesce(v_def.params, '[]'::jsonb)) LOOP\n v_name := v_param ->> 'name';\n v_value := coalesce(p_params ->> v_name, v_param ->> 'default');\n IF v_value IS NULL THEN\n IF coalesce((v_param ->> 'required')::boolean, false) THEN\n RAISE EXCEPTION 'reports_run: % requires the parameter %', p_key, v_name USING ERRCODE = '22023';\n END IF;\n CONTINUE;\n END IF;\n IF NOT EXISTS (SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = v_def.source_view\n AND column_name = coalesce(v_param ->> 'column', v_name)) THEN\n RAISE EXCEPTION 'reports_run: parameter % has no column on %', v_name, v_def.source_view USING ERRCODE = '42703';\n END IF;\n v_where := v_where || format(' AND %I %s %L',\n coalesce(v_param ->> 'column', v_name),\n CASE v_param ->> 'operator' WHEN '>=' THEN '>=' WHEN '<=' THEN '<=' WHEN '>' THEN '>' WHEN '<' THEN '<' WHEN 'ilike' THEN 'ILIKE' ELSE '=' END,\n v_value);\n END LOOP;\n\n -- A parameter the caller sent that the definition never declared is refused\n -- rather than ignored: silently dropping a filter shows the wrong number.\n IF p_params IS NOT NULL AND jsonb_typeof(p_params) = 'object' THEN\n FOR v_name IN SELECT key FROM jsonb_each_text(p_params) LOOP\n IF NOT EXISTS (SELECT 1 FROM jsonb_array_elements(coalesce(v_def.params, '[]'::jsonb)) d WHERE d ->> 'name' = v_name) THEN\n RAISE EXCEPTION 'reports_run: % does not declare a parameter called %', p_key, v_name USING ERRCODE = '22023';\n END IF;\n END LOOP;\n END IF;\n\n v_sql := format('SELECT coalesce(jsonb_agg(t), ''[]''::jsonb), count(*) FROM (SELECT * FROM public.%I WHERE %s %s LIMIT %s OFFSET %s) t',\n v_def.source_view, v_where,\n CASE WHEN v_def.default_order_by IS NULL THEN '' ELSE 'ORDER BY ' || quote_ident(v_def.default_order_by) END,\n greatest(coalesce(p_limit, 1000), 0), greatest(coalesce(p_offset, 0), 0));\n\n EXECUTE v_sql INTO v_rows, v_count;\n\n INSERT INTO public.plg_reports_runs (tenant_id, definition_key, definition_version, params, requested_by,\n row_count, duration_ms, status, format)\n VALUES (v_tenant, p_key, v_def.version, coalesce(p_params, '{}'::jsonb), auth.uid(),\n v_count, (extract(epoch FROM clock_timestamp() - v_start) * 1000)::integer, 'ok', p_format);\n\n RETURN jsonb_build_object(\n 'key', p_key, 'version', v_def.version, 'title', v_def.title,\n 'status', 'ok', 'columns', v_def.columns, 'rows', v_rows, 'row_count', v_count);\nEND $$;\n\nCREATE FUNCTION public.trg_plg_reports_definitions_source() RETURNS trigger\n LANGUAGE plpgsql SECURITY DEFINER\n SET search_path TO ''\n AS $_$\nDECLARE v_kind char;\nBEGIN\n IF NEW.source_view !~ '^[a-z_][a-z0-9_]*$' THEN\n RAISE EXCEPTION 'plg_reports_definitions: source_view % is not a bare relation name in public', NEW.source_view\n USING ERRCODE = '22023';\n END IF;\n\n SELECT c.relkind INTO v_kind\n FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace\n WHERE n.nspname = 'public' AND c.relname = NEW.source_view;\n\n IF v_kind IS NULL THEN\n RAISE EXCEPTION 'plg_reports_definitions: public.% does not exist', NEW.source_view USING ERRCODE = '42P01';\n END IF;\n\n -- A view or a materialized view is a read model by construction. A TABLE is\n -- only allowed when its name says so — that is the \\`plg_<x>_rep_*\\` convention\n -- Phase 1 established, and it is checked rather than trusted.\n IF v_kind NOT IN ('v', 'm') AND NEW.source_view !~ '^plg_[a-z0-9_]+_rep_' THEN\n RAISE EXCEPTION 'plg_reports_definitions: public.% is a business table, not a read model', NEW.source_view\n USING ERRCODE = '23514',\n HINT = 'Point the definition at a view or at a plg_<plugin>_rep_* read model. Reporting off a business table is how a report starts holding a schema still.';\n END IF;\n RETURN NEW;\nEND $_$;\n\n\n-- ── constraint ──────────────────────────────────────────────────────────\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_tenant_id_id_key UNIQUE (tenant_id, id);\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_tenant_id_id_key UNIQUE (tenant_id, id);\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_pkey PRIMARY KEY (id);\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_tenant_id_id_key UNIQUE (tenant_id, id);\n\n\n-- ── index ───────────────────────────────────────────────────────────────\n\nCREATE UNIQUE INDEX plg_reports_definitions_key_uq ON public.plg_reports_definitions USING btree (COALESCE(tenant_id, '00000000-0000-0000-0000-000000000000'::uuid), key, version);\n\nCREATE INDEX plg_reports_definitions_module_idx ON public.plg_reports_definitions USING btree (module) WHERE is_active;\n\nCREATE INDEX plg_reports_definitions_tenant_owner_idx ON public.plg_reports_definitions USING btree (tenant_id, owner_id) WHERE (owner_id IS NOT NULL);\n\nCREATE INDEX plg_reports_definitions_tenant_unit_idx ON public.plg_reports_definitions USING btree (tenant_id, unit_id);\n\nCREATE INDEX plg_reports_runs_key_idx ON public.plg_reports_runs USING btree (tenant_id, definition_key, created_at DESC);\n\nCREATE INDEX plg_reports_runs_tenant_owner_idx ON public.plg_reports_runs USING btree (tenant_id, owner_id) WHERE (owner_id IS NOT NULL);\n\nCREATE INDEX plg_reports_runs_tenant_unit_idx ON public.plg_reports_runs USING btree (tenant_id, unit_id);\n\nCREATE INDEX plg_reports_schedules_due_idx ON public.plg_reports_schedules USING btree (next_run_at) WHERE is_active;\n\nCREATE INDEX plg_reports_schedules_tenant_owner_idx ON public.plg_reports_schedules USING btree (tenant_id, owner_id) WHERE (owner_id IS NOT NULL);\n\nCREATE INDEX plg_reports_schedules_tenant_unit_idx ON public.plg_reports_schedules USING btree (tenant_id, unit_id);\n\n\n-- ── fk constraint ───────────────────────────────────────────────────────\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_owner_fk FOREIGN KEY (tenant_id, owner_id) REFERENCES app.memberships(tenant_id, user_id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY public.plg_reports_definitions\n ADD CONSTRAINT plg_reports_definitions_unit_fk FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_owner_fk FOREIGN KEY (tenant_id, owner_id) REFERENCES app.memberships(tenant_id, user_id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY public.plg_reports_runs\n ADD CONSTRAINT plg_reports_runs_unit_fk FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_owner_fk FOREIGN KEY (tenant_id, owner_id) REFERENCES app.memberships(tenant_id, user_id) ON DELETE SET NULL;\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\nALTER TABLE ONLY public.plg_reports_schedules\n ADD CONSTRAINT plg_reports_schedules_unit_fk FOREIGN KEY (tenant_id, unit_id) REFERENCES app.units(tenant_id, id) ON DELETE SET NULL;\n\n\n-- ── table data ──────────────────────────────────────────────────────────\n\nCOPY public.plg_reports_definitions (id, tenant_id, unit_id, key, version, title, description, module, source_view, params, columns, default_order_by, required_permission, is_active, metadata, created_by, owner_id, created_at, updated_at) FROM stdin;\nb9bdb96e-2219-4bea-a83d-be54e28c4bda\t\\\\N\t\\\\N\torders.sales\t1\tVendas\tEvery sale, whichever door it came through — the query the order vocabulary made possible.\torders\tv_sales\t[{\"name\": \"channel\", \"column\": \"channel\"}, {\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"from\", \"column\": \"created_at\", \"operator\": \">=\"}, {\"name\": \"to\", \"column\": \"created_at\", \"operator\": \"<=\"}]\t[]\tcreated_at\torders.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n706d0d78-193c-4abe-8828-5e00d719d155\t\\\\N\t\\\\N\torders.fulfillment\t1\tEntregas pendentes\tOrdered against delivered, per line. A positive pending is what a boolean could never describe.\torders\tv_order_fulfillment\t[{\"name\": \"state\", \"column\": \"state\"}]\t[]\t\\\\N\torders.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n6e27d897-55d8-4f39-b963-b5cb3121069d\t\\\\N\t\\\\N\tfinancial.receivables\t1\tContas a receber\tInstalments and what is still owed on them, straight from the allocations.\tfinancial\tv_financial_installment_balances\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"due_from\", \"column\": \"due_date\", \"operator\": \">=\"}, {\"name\": \"due_to\", \"column\": \"due_date\", \"operator\": \"<=\"}]\t[]\tdue_date\tfinancial.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n66d7f336-fff1-40ea-b754-6b158f1b0dea\t\\\\N\t\\\\N\tfinancial.uninvoiced\t1\tVendas sem título\tSales that produced no invoice. Empty is the bar this phase closes on.\tfinancial\tv_orders_sem_invoice\t[{\"name\": \"kind\", \"column\": \"kind\"}]\t[]\tcreated_at\tfinancial.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\na5a3ffab-e6e1-46ad-942f-f36582b4e126\t\\\\N\t\\\\N\tinventory.balances\t1\tSaldo de estoque\tThe balance, from the one ledger that owns it.\tinventory\tv_inventory_balances\t[]\t[]\t\\\\N\tinventory.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\na2d3191e-5a8d-4e03-892f-0c9573675ea5\t\\\\N\t\\\\N\tnotifications.queue\t1\tFila de notificações\tWhat is waiting, what is overdue, what was abandoned and what was refused.\tnotifications\tv_notification_queue\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"channel\", \"column\": \"channel\"}]\t[]\t\\\\N\tnotifications.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\nc616ae83-b861-41fb-959a-bbb85431ed77\t\\\\N\t\\\\N\tagenda.appointments\t1\tAgendamentos\tThe calendar as a table, with the Venda and the payment state each booking carries.\tagenda\tv_appointments\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"from\", \"column\": \"starts_at\", \"operator\": \">=\"}, {\"name\": \"to\", \"column\": \"starts_at\", \"operator\": \"<=\"}]\t[]\tstarts_at\tagenda.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n5af4a8c8-903b-4ea6-8829-98877b017883\t\\\\N\t\\\\N\tcrm.funnel\t1\tFunil\tThe funnel over plg_crm_deals, with won_at and lost_at — which is what makes a cycle length measurable.\tcrm\tv_deals\t[{\"name\": \"status\", \"column\": \"status\"}, {\"name\": \"stage\", \"column\": \"stage_name\"}]\t[]\tcreated_at\tcrm.pipeline.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n9143ce67-ecaa-46a3-8028-7c354c34f301\t\\\\N\t\\\\N\tmarketing.campaigns\t1\tCampanhas\tReach, delivery and conversion per campaign — the metric comes from here, never from a counter on the campaign.\tmarketing\tv_marketing_campaign_metrics\t[{\"name\": \"status\", \"column\": \"status\"}]\t[]\t\\\\N\tmarketing.read\tt\t{}\t\\\\N\t\\\\N\t2026-09-04 15:03:27.267053+00\t2026-09-04 15:03:27.267053+00\n\\\\.\n\n\n-- ── trigger ─────────────────────────────────────────────────────────────\n\nCREATE TRIGGER plg_reports_definitions_source BEFORE INSERT OR UPDATE OF source_view ON public.plg_reports_definitions FOR EACH ROW EXECUTE FUNCTION public.trg_plg_reports_definitions_source();\n\nCREATE TRIGGER plg_reports_definitions_updated_at BEFORE UPDATE ON public.plg_reports_definitions FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\n\nCREATE TRIGGER plg_reports_runs_updated_at BEFORE UPDATE ON public.plg_reports_runs FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\n\nCREATE TRIGGER plg_reports_schedules_updated_at BEFORE UPDATE ON public.plg_reports_schedules FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at();\n\n\n-- ── row security ────────────────────────────────────────────────────────\n\nALTER TABLE public.plg_reports_definitions ENABLE ROW LEVEL SECURITY;\n\nALTER TABLE public.plg_reports_runs ENABLE ROW LEVEL SECURITY;\n\nALTER TABLE public.plg_reports_schedules ENABLE ROW LEVEL SECURITY;\n\n\n-- ── policy ──────────────────────────────────────────────────────────────\n\nCREATE POLICY plg_reports_definitions_authz_delete ON public.plg_reports_definitions FOR DELETE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.definition'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.definition'::text, plg_reports_definitions.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_definitions.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.delete'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_authz_insert ON public.plg_reports_definitions FOR INSERT TO authenticated WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.create'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_authz_select ON public.plg_reports_definitions FOR SELECT TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.definition'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.definition'::text, plg_reports_definitions.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_definitions.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.read'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_authz_update ON public.plg_reports_definitions FOR UPDATE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.definition'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.definition'::text, plg_reports_definitions.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_definitions.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_definitions.unit_id) AS has_permission))) WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_definitions.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_definitions.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_definitions_platform_read ON public.plg_reports_definitions FOR SELECT TO authenticated USING (((tenant_id IS NULL) AND is_active));\n\nCREATE POLICY plg_reports_runs_authz_delete ON public.plg_reports_runs FOR DELETE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.run'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.run'::text, plg_reports_runs.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_runs.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.delete'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_runs_authz_insert ON public.plg_reports_runs FOR INSERT TO authenticated WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.create'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_runs_authz_select ON public.plg_reports_runs FOR SELECT TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.run'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.run'::text, plg_reports_runs.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_runs.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.read'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_runs_authz_update ON public.plg_reports_runs FOR UPDATE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.run'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.run'::text, plg_reports_runs.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_runs.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_runs.unit_id) AS has_permission))) WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_runs.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_runs.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_delete ON public.plg_reports_schedules FOR DELETE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.schedule'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.schedule'::text, plg_reports_schedules.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_schedules.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.delete'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_insert ON public.plg_reports_schedules FOR INSERT TO authenticated WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.create'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_select ON public.plg_reports_schedules FOR SELECT TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.schedule'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.schedule'::text, plg_reports_schedules.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_schedules.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.read'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\nCREATE POLICY plg_reports_schedules_authz_update ON public.plg_reports_schedules FOR UPDATE TO authenticated USING (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ((NOT ( SELECT app.owner_scoped('reports.schedule'::text) AS owner_scoped)) OR (owner_id IS NULL) OR (owner_id = ( SELECT auth.uid() AS uid)) OR ( SELECT app.has_grant('reports.schedule'::text, plg_reports_schedules.id, ARRAY['shared_with'::text]) AS has_grant) OR ( SELECT app.has_permission('reports.read_all'::text, plg_reports_schedules.unit_id) AS has_permission)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_schedules.unit_id) AS has_permission))) WITH CHECK (((tenant_id = ( SELECT app.current_tenant_id() AS current_tenant_id)) AND ((unit_id IS NULL) OR ( SELECT app.has_unit(plg_reports_schedules.unit_id) AS has_unit)) AND ( SELECT app.has_permission('reports.edit'::text, plg_reports_schedules.unit_id) AS has_permission)));\n\n\n-- ── acl ─────────────────────────────────────────────────────────────────\n\nGRANT MAINTAIN ON TABLE public.plg_reports_definitions TO anon;\nGRANT ALL ON TABLE public.plg_reports_definitions TO authenticated;\nGRANT ALL ON TABLE public.plg_reports_definitions TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_definition(p_key text, p_tenant uuid) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_definition(p_key text, p_tenant uuid) TO authenticated;\nGRANT ALL ON FUNCTION public.reports_definition(p_key text, p_tenant uuid) TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_deliver_due(p_limit integer) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_deliver_due(p_limit integer) TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text) TO authenticated;\nGRANT ALL ON FUNCTION public.reports_ensure_delivery_template(p_tenant uuid, p_channel text) TO service_role;\n\nREVOKE ALL ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) FROM PUBLIC;\nGRANT ALL ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) TO authenticated;\nGRANT ALL ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) TO service_role;\n\nREVOKE ALL ON FUNCTION public.trg_plg_reports_definitions_source() FROM PUBLIC;\nGRANT ALL ON FUNCTION public.trg_plg_reports_definitions_source() TO service_role;\n\nGRANT MAINTAIN ON TABLE public.plg_reports_runs TO anon;\nGRANT ALL ON TABLE public.plg_reports_runs TO authenticated;\nGRANT ALL ON TABLE public.plg_reports_runs TO service_role;\n\nGRANT MAINTAIN ON TABLE public.plg_reports_schedules TO anon;\nGRANT ALL ON TABLE public.plg_reports_schedules TO authenticated;\nGRANT ALL ON TABLE public.plg_reports_schedules TO service_role;\n\n\n-- ── comment ─────────────────────────────────────────────────────────────\n\nCOMMENT ON TABLE public.plg_reports_definitions IS 'The report catalogue (PRD 08). Versioned, so changing a report does not rewrite the history of everyone who ran the previous one; and \\`required_permission\\` is declared HERE rather than on a screen, so the engine can refuse before it queries.';\n\nCOMMENT ON FUNCTION public.reports_deliver_due(p_limit integer) IS 'Queue the scheduled reports that are due (PRD 08). It enqueues through the notification engine rather than sending — the same mechanism as dunning and as a campaign, which is what made building that engine first worth doing.';\n\nCOMMENT ON FUNCTION public.reports_run(p_key text, p_params jsonb, p_limit integer, p_offset integer, p_format text) IS 'Run a report from the catalogue (PRD 08). The permission is checked BEFORE the query is built — a refusal reads no rows and comes back as status=refused, recorded in plg_reports_runs — the tenant and unit predicates are injected by the engine and cannot be switched off by a definition, and an undeclared parameter is refused rather than ignored.';\n\nCOMMENT ON TABLE public.plg_reports_runs IS 'Who ran what, with which parameters, against which VERSION of the definition (PRD 08). A refusal is recorded too — \"the report is empty\" and \"you were not allowed to see it\" are different answers and the history has to keep them apart.';\n\nCOMMENT ON TABLE public.plg_reports_schedules IS 'A report on a schedule (PRD 08). Delivery is the notification engine''s job (PRD 03) — the same queue, retry and opt-out that carry a receipt carry a report, which is the whole reason that engine was built first.';\n\n\n-- ── default privileges: restore ─────────────────────────────────────────\n-- Put back, so the NEXT thing installed inherits what the chain had.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEND $dp$;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000_baseline\", sql: MIGRATION_000_BASELINE },\n]\n","import type { AnalyticsCardDef, AnalyticsColumnDef, AnalyticsFilterDef } from '@fayz-ai/core'\nimport type { ReportDef } from '../types'\n\n// ---------------------------------------------------------------------------\n// ReportDef → AnalyticsCardDef.\n//\n// Consuming apps declare hundreds of lines of ReportDef today. Rewriting them\n// all in one commit is how a refactor stalls, so the old shape keeps working: a\n// legacy report becomes a card with a table viz and no dashboard placement — it\n// appears in the report list, opens in the viewer, and simply never claims a\n// tile on the overview.\n//\n// Nothing here is lossy. When an app is ready, it upgrades a report in place by\n// adding dimensions/measures and a `dashboard` block, and the same definition\n// starts also being a chart on the overview.\n// ---------------------------------------------------------------------------\n\nexport function reportDefToCard(report: ReportDef, createdBy?: string): AnalyticsCardDef {\n return {\n id: report.id,\n name: report.name,\n description: report.description,\n icon: report.icon,\n category: report.category,\n createdBy,\n available: report.available,\n grain: report.grain,\n canonicalOwner: report.canonicalOwner,\n permission: report.permission,\n query: {\n source: {\n kind: report.dataSource.kind,\n name: report.dataSource.name,\n columnMap: report.dataSource.columnMap,\n },\n dateColumn: report.dataSource.dateColumn,\n defaultSort: report.dataSource.defaultSort,\n defaultSortDir: report.dataSource.defaultSortDir,\n filters: (report.filters ?? []).map((f): AnalyticsFilterDef => ({\n key: f.key,\n label: f.label,\n type: f.type,\n options: f.options,\n defaultValue: f.defaultValue,\n placeholder: f.placeholder,\n // Legacy filters declared no category. Grouping them under the report's\n // own category keeps the picker organised instead of dumping every\n // filter from every report into one flat list.\n group: report.category,\n })),\n },\n // No dimensions/measures: a legacy report is a detail listing, and inventing\n // aggregations for it would change what the numbers mean.\n viz: { type: 'table' },\n columns: report.columns.map((c): AnalyticsColumnDef => ({\n key: c.key,\n label: c.label,\n type: c.type as AnalyticsColumnDef['type'],\n sortable: c.sortable,\n currency: c.currency,\n idKey: c.idKey,\n personKind: c.personKind,\n renderCell: c.renderCell,\n visible: c.visible,\n align: c.align,\n aggregate: c.aggregate,\n })),\n }\n}\n\nexport function reportDefsToCards(reports: ReportDef[], createdBy?: string): AnalyticsCardDef[] {\n return reports.map((r) => reportDefToCard(r, createdBy))\n}\n","import * as React from 'react'\n\n// ---------------------------------------------------------------------------\n// \"Last viewed\" for the report list.\n//\n// A catalogue of eighty reports sorted alphabetically is a filing cabinet; the\n// three a merchant actually opens each Monday are what they came for. This is\n// per-browser rather than per-tenant on purpose — it is a convenience ordering,\n// not a business fact, and it should not cost a write to the database on every\n// report a user glances at.\n// ---------------------------------------------------------------------------\n\nconst KEY = 'fayz.analytics.lastViewed'\n\ntype LastViewedMap = Record<string, string>\n\nfunction read(): LastViewedMap {\n if (typeof window === 'undefined') return {}\n try {\n const raw = window.localStorage.getItem(KEY)\n return raw ? (JSON.parse(raw) as LastViewedMap) : {}\n } catch {\n return {}\n }\n}\n\nfunction write(map: LastViewedMap): void {\n if (typeof window === 'undefined') return\n try {\n window.localStorage.setItem(KEY, JSON.stringify(map))\n } catch {\n /* quota or private mode — losing this costs an ordering, not data */\n }\n}\n\nconst listeners = new Set<(map: LastViewedMap) => void>()\n\nexport function markViewed(cardId: string): void {\n const next = { ...read(), [cardId]: new Date().toISOString() }\n write(next)\n for (const listener of listeners) listener(next)\n}\n\nexport function useLastViewed(): LastViewedMap {\n const [map, setMap] = React.useState<LastViewedMap>(() => read())\n React.useEffect(() => {\n listeners.add(setMap)\n return () => { listeners.delete(setMap) }\n }, [])\n return map\n}\n","import * as React from 'react'\nimport type {\n AnalyticsCardDef, AnalyticsDimension, AnalyticsMeasure, AnalyticsVizType,\n} from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// What the user decided about the report catalogue.\n//\n// The catalogue itself is code: an app declares its cards, a plugin contributes\n// the ones it owns the data for. This file is the LAYER ON TOP — which of them\n// this user wants on the overview, in what order, showing which columns, plus\n// the reports they built themselves. Nothing here edits a shipped definition;\n// it records an override next to it, so an app update still moves the base\n// card and the user's choices survive it.\n//\n// A CUSTOM REPORT IS NOT A FREE-FORM QUERY. It stores a base card id plus the\n// dimensions and measures picked from that source's field palette. That is a\n// deliberate ceiling: a user cannot invent a data source, and a builder that\n// pretends otherwise produces reports that fail at read time. What they CAN do\n// is ask a different question of a source the app already exposes — which is\n// what \"quero esse relatório quebrado por praça\" actually means.\n//\n// Per-browser (localStorage), like `lastViewed`. Moving it to the tenant is a\n// swap of read/write below plus a table; every caller reads through the hook.\n// ---------------------------------------------------------------------------\n\nconst KEY = 'fayz.analytics.prefs'\n\nexport interface AnalyticsCardPref {\n /** Drop from the catalogue entirely — a built-in this tenant does not use. */\n hidden?: boolean\n /** Force onto (true) or off (false) the overview, whatever the card declares. */\n pinned?: boolean\n /** Position on the overview grid. */\n order?: number\n /** Tile width, in grid columns. */\n span?: 1 | 2 | 3 | 4\n /** Rename — the vocabulary of the house beats the vocabulary of the plugin. */\n name?: string\n /** Chart type override. */\n viz?: AnalyticsVizType\n /** Measure keys to keep. Absent = all. Ratio operands are always kept. */\n measures?: string[]\n /** Visible dimension keys to keep. Absent = all. Hidden ones always survive. */\n dimensions?: string[]\n}\n\nexport interface CustomReport {\n id: string\n name: string\n description?: string\n category: string\n icon?: string\n /** Shown in the list's \"Created by\" column — the house, not the product. */\n createdBy?: string\n /** The card whose data source this report reads. */\n baseId: string\n dimensions: string[]\n measures: string[]\n viz: AnalyticsVizType\n createdAt: string\n}\n\nexport interface AnalyticsPrefs {\n version: 1\n cards: Record<string, AnalyticsCardPref>\n custom: CustomReport[]\n}\n\nconst EMPTY: AnalyticsPrefs = { version: 1, cards: {}, custom: [] }\n\nfunction read(): AnalyticsPrefs {\n if (typeof window === 'undefined') return EMPTY\n try {\n const raw = window.localStorage.getItem(KEY)\n if (!raw) return EMPTY\n const parsed = JSON.parse(raw) as Partial<AnalyticsPrefs>\n return {\n version: 1,\n cards: parsed.cards && typeof parsed.cards === 'object' ? parsed.cards : {},\n custom: Array.isArray(parsed.custom) ? parsed.custom : [],\n }\n } catch {\n return EMPTY\n }\n}\n\nfunction write(prefs: AnalyticsPrefs): void {\n if (typeof window === 'undefined') return\n try {\n const empty = Object.keys(prefs.cards).length === 0 && prefs.custom.length === 0\n if (empty) window.localStorage.removeItem(KEY)\n else window.localStorage.setItem(KEY, JSON.stringify(prefs))\n } catch {\n /* quota / private mode */\n }\n}\n\nconst listeners = new Set<(prefs: AnalyticsPrefs) => void>()\n\nfunction publish(next: AnalyticsPrefs): void {\n write(next)\n for (const listener of listeners) listener(next)\n}\n\n/** Read the saved preferences and re-render when any surface changes them. */\nexport function useAnalyticsPrefs(): AnalyticsPrefs {\n const [prefs, setPrefs] = React.useState<AnalyticsPrefs>(() => read())\n React.useEffect(() => {\n listeners.add(setPrefs)\n return () => { listeners.delete(setPrefs) }\n }, [])\n return prefs\n}\n\n// --- mutations -------------------------------------------------------------\n\nexport function setCardPref(cardId: string, patch: AnalyticsCardPref): void {\n const current = read()\n const merged = { ...current.cards[cardId], ...patch }\n // A pref that says nothing is not a pref: drop the entry so a later app\n // update can move the base card freely.\n const meaningful = Object.entries(merged).filter(([, v]) => v !== undefined && v !== null)\n const cards = { ...current.cards }\n if (meaningful.length === 0) delete cards[cardId]\n else cards[cardId] = Object.fromEntries(meaningful) as AnalyticsCardPref\n publish({ ...current, cards })\n}\n\nexport function clearCardPref(cardId: string): void {\n const current = read()\n const cards = { ...current.cards }\n delete cards[cardId]\n publish({ ...current, cards })\n}\n\n/** Persist the overview order for the ids given, in the order given. */\nexport function setOverviewOrder(ids: string[]): void {\n const current = read()\n const cards = { ...current.cards }\n ids.forEach((id, index) => {\n cards[id] = { ...cards[id], order: index, pinned: cards[id]?.pinned ?? true }\n })\n publish({ ...current, cards })\n}\n\nexport function saveCustomReport(report: CustomReport): void {\n const current = read()\n const custom = current.custom.some((r) => r.id === report.id)\n ? current.custom.map((r) => (r.id === report.id ? report : r))\n : [...current.custom, report]\n publish({ ...current, custom })\n}\n\nexport function deleteCustomReport(id: string): void {\n const current = read()\n const cards = { ...current.cards }\n delete cards[id]\n publish({ ...current, cards, custom: current.custom.filter((r) => r.id !== id) })\n}\n\nexport function resetAnalyticsPrefs(): void {\n publish({ ...EMPTY })\n}\n\n// --- resolution ------------------------------------------------------------\n\n/**\n * Which cards read the same rows.\n *\n * A view or an RPC is named, so its name IS the identity. A function source has\n * no name the outside can see, so the card's declared `grain` stands in — two\n * cards at order grain over the same app function answer about the same rows,\n * and that is exactly the set whose fields can be mixed in one report. A card\n * with neither falls back to its own id: alone in its group, which is the safe\n * answer when nothing says otherwise.\n */\nexport function sourceKey(card: AnalyticsCardDef): string {\n const source = card.query.source\n if (source.kind === 'fn') return card.grain ? `fn:${card.grain}` : `fn:${card.id}`\n return `${source.kind}:${source.name ?? card.id}`\n}\n\nexport interface FieldPalette {\n dimensions: AnalyticsDimension[]\n measures: AnalyticsMeasure[]\n}\n\nexport interface AnalyticsSourceGroup extends FieldPalette {\n key: string\n /** A real card over this source — what a new report inherits its query from. */\n base: AnalyticsCardDef\n label: string\n}\n\n/**\n * The distinct data sources behind a catalogue, each with everything askable of\n * it.\n *\n * The builder offers THESE, not the seventeen cards: six of them read the same\n * order rows, and a source picker listing all six asks the user to choose\n * between six spellings of one answer. Sources with nothing to aggregate are\n * left out — a detail listing has no measures, and a report with no measure is\n * a table of raw rows the user already has.\n */\nexport function analyticsSources(pool: AnalyticsCardDef[]): AnalyticsSourceGroup[] {\n const groups = new Map<string, AnalyticsCardDef[]>()\n for (const card of pool) {\n const key = sourceKey(card)\n const list = groups.get(key)\n if (list) list.push(card)\n else groups.set(key, [card])\n }\n const out: AnalyticsSourceGroup[] = []\n for (const [key, cards] of groups) {\n const base = cards.find((c) => (c.query.measures?.length ?? 0) > 0)\n if (!base) continue\n const palette = fieldPalette(pool, base)\n if (palette.measures.length === 0) continue\n out.push({ key, base, label: base.name, ...palette })\n }\n return out\n}\n\n/** Every field any card offers over the same source, de-duplicated by key. */\nexport function fieldPalette(pool: AnalyticsCardDef[], base: AnalyticsCardDef): FieldPalette {\n const key = sourceKey(base)\n const dimensions = new Map<string, AnalyticsDimension>()\n const measures = new Map<string, AnalyticsMeasure>()\n for (const card of pool) {\n if (sourceKey(card) !== key) continue\n for (const d of card.query.dimensions ?? []) {\n if (!d.hidden && !dimensions.has(d.key)) dimensions.set(d.key, d)\n }\n for (const m of card.query.measures ?? []) {\n if (!measures.has(m.key)) measures.set(m.key, m)\n }\n }\n return { dimensions: [...dimensions.values()], measures: [...measures.values()] }\n}\n\n/** Ratio measures are computed from two others; keeping one without its\n * operands leaves the card dividing by a number nobody fetched. */\nfunction withRatioOperands(kept: string[], all: AnalyticsMeasure[]): Set<string> {\n const set = new Set(kept)\n for (const key of kept) {\n const measure = all.find((m) => m.key === key)\n for (const operand of measure?.ratioOf ?? []) set.add(operand)\n }\n return set\n}\n\nfunction applyPref(card: AnalyticsCardDef, pref: AnalyticsCardPref | undefined): AnalyticsCardDef {\n if (!pref) return card\n const next: AnalyticsCardDef = { ...card, query: { ...card.query }, viz: { ...card.viz } }\n\n if (pref.name) next.name = pref.name\n if (pref.viz) next.viz.type = pref.viz\n\n if (pref.measures?.length) {\n const all = card.query.measures ?? []\n const keep = withRatioOperands(pref.measures, all)\n next.query.measures = all.filter((m) => keep.has(m.key))\n // The tile's own measure pick has to stay inside what the query still\n // fetches, or a KPI ends up pointing at a column that no longer exists.\n if (card.viz.measures?.length) {\n next.viz.measures = card.viz.measures.filter((k) => keep.has(k))\n }\n }\n\n if (pref.dimensions?.length) {\n const keep = new Set(pref.dimensions)\n // Hidden dimensions survive on purpose: they carry ids and sort keys, and\n // dropping one turns a chronological axis into an alphabetical one.\n next.query.dimensions = (card.query.dimensions ?? []).filter((d) => d.hidden || keep.has(d.key))\n }\n\n const placed = pref.pinned ?? Boolean(card.dashboard && card.dashboard.defaultVisible !== false)\n if (!placed) {\n next.dashboard = undefined\n } else {\n next.dashboard = {\n ...card.dashboard,\n defaultVisible: true,\n order: pref.order ?? card.dashboard?.order ?? 999,\n span: pref.span ?? card.dashboard?.span,\n }\n }\n\n return next\n}\n\n/** A stored custom report, rebuilt against the catalogue it derives from. */\nexport function resolveCustomReport(\n report: CustomReport,\n pool: AnalyticsCardDef[],\n): AnalyticsCardDef | null {\n const base = pool.find((c) => c.id === report.baseId)\n if (!base) return null\n\n const palette = fieldPalette(pool, base)\n const dimensions = report.dimensions\n .map((key) => palette.dimensions.find((d) => d.key === key))\n .filter((d): d is AnalyticsDimension => Boolean(d))\n const keep = withRatioOperands(report.measures, palette.measures)\n const measures = palette.measures.filter((m) => keep.has(m.key))\n\n return {\n id: report.id,\n name: report.name,\n description: report.description,\n icon: report.icon ?? 'FileText',\n category: report.category,\n createdBy: report.createdBy,\n grain: base.grain,\n available: base.available,\n compare: base.compare,\n permission: base.permission,\n query: {\n source: base.query.source,\n dateColumn: base.query.dateColumn,\n dimensions,\n measures,\n filters: base.query.filters,\n defaultSort: report.measures[0] ?? dimensions[0]?.key,\n defaultSortDir: 'desc',\n },\n viz: { type: report.viz },\n }\n}\n\n/**\n * The catalogue as this user sees it: overrides applied, their own reports\n * appended, the ones they removed gone.\n */\nexport function resolveCards(catalogue: AnalyticsCardDef[], prefs: AnalyticsPrefs): AnalyticsCardDef[] {\n const custom = prefs.custom\n .map((report) => resolveCustomReport(report, catalogue))\n .filter((c): c is AnalyticsCardDef => Boolean(c))\n return [...catalogue, ...custom]\n .filter((card) => !prefs.cards[card.id]?.hidden)\n .map((card) => applyPref(card, prefs.cards[card.id]))\n}\n","import React from 'react'\nimport {\n usePluginRuntime, getAnalyticsCards, hashRouterAdapter,\n type AnalyticsCardDef, type AnalyticsProvider as AnalyticsProviderType, type AnalyticsColumnDef,\n type AnalyticsCompare, type AgentRole,\n} from '@fayz-ai/core'\nimport { AnalyticsContextProvider, type AnalyticsRangePreset } from '@fayz-ai/ui'\nimport { markViewed } from '../lib/lastViewed'\nimport { resolveCards, useAnalyticsPrefs } from '../lib/preferences'\n\n// ---------------------------------------------------------------------------\n// The surface every analytics page mounts inside.\n//\n// Cards arrive from two places and are merged here: the plugins that own the\n// data contribute them through the runtime registry (`analyticsCards` on the\n// manifest), and the host app adds or overrides via options. Registry first,\n// app last — an app curating its own pack must be able to win.\n// ---------------------------------------------------------------------------\n\nexport const ANALYTICS_BASE = '/analytics'\nexport const REPORTS_BASE = `${ANALYTICS_BASE}/reports`\nexport const SETTINGS_ROUTE = `${ANALYTICS_BASE}/settings`\n\nexport interface AnalyticsLabels {\n analytics: string\n reports: string\n liveView: string\n /** Rail entry for the card grid. Falls back to the `reports.overview` key. */\n overview?: string\n /** Rail entry for the customisation screen. Falls back to the locale key. */\n settings?: string\n overviewSubtitle: string\n reportsSubtitle: string\n searchReports: string\n category: string\n createdBy: string\n /** Cleared state of each facet chip: \"All categories\" / \"All authors\". */\n allCategories: string\n allCreatedBy: string\n lastViewed: string\n name: string\n noResults: string\n never: string\n back: string\n export: string\n print: string\n unavailableTitle: string\n unavailableDescription: string\n emptyOverviewTitle: string\n emptyOverviewDescription: string\n liveViewSoon: string\n results: string\n}\n\n/** How the assistant introduces itself on the analytics screens. Every field is\n * optional: what is not set falls back to the plugin's own locale strings. */\nexport interface AnalyticsAssistantConfig {\n /** Which colleague reads the numbers here. Defaults to the plugin's own\n * (`growth`) — an app whose analytics are a finance conversation says so. */\n role?: AgentRole\n /** Names the task here — \"Growth Analyst\". */\n persona?: string\n /** Hero headline. `{{name}}` resolves to the signed-in user's first name. */\n headline?: string\n pitch?: string\n description?: string\n placeholder?: string\n suggestions?: { label: string; prompt?: string }[]\n /** `true` opens on the hero takeover. Default FALSE here, unlike the shell's:\n * the analytics home is a page of numbers, and a full-column invitation over\n * them hides the very thing the user navigated to. The composer docks at the\n * bottom instead — the assistant is offered, the metrics stay readable. */\n auto?: boolean\n}\n\nexport interface ResolvedAnalyticsConfig {\n /** Cards declared by the host app (merged with the plugin registry at render). */\n cards: AnalyticsCardDef[]\n labels: AnalyticsLabels\n currency: { code: string; locale: string; symbol: string }\n /** Attribution for pre-built cards — the product name, e.g. \"FayzShop\". */\n createdBy: string\n defaultPageSize: number\n showHeader: boolean\n /** Range the surface opens on. A salon reads 30 days; a school reads a term. */\n defaultRange: AnalyticsRangePreset\n defaultCompare: AnalyticsCompare\n /** Whether the Live View entry appears in the module rail. */\n showLiveView: boolean\n /** `null` mounts no invite — the screen opens on its numbers, not on a\n * conversation. Otherwise: the overrides, over the locale defaults. */\n assistant: AnalyticsAssistantConfig | null\n}\n\nconst ConfigContext = React.createContext<ResolvedAnalyticsConfig | null>(null)\n\nexport function useAnalyticsConfig(): ResolvedAnalyticsConfig {\n const ctx = React.useContext(ConfigContext)\n if (!ctx) throw new Error('useAnalyticsConfig must be used inside <AnalyticsSurface>')\n return ctx\n}\n\n/**\n * The catalogue AS SHIPPED — registry + app, de-duplicated by id, with no user\n * overrides applied.\n *\n * The app's own definition wins a collision so a host can retune a card the\n * plugin shipped (relabel it, move it off the overview) without forking the\n * plugin — the alternative is apps carrying patched copies of plugin cards.\n *\n * Only the settings screen wants this: it has to show what the defaults ARE in\n * order to offer a way back to them. Everything else reads `useAnalyticsCards`.\n */\nexport function useAnalyticsCatalogue(): AnalyticsCardDef[] {\n const runtime = usePluginRuntime()\n const { cards, createdBy } = useAnalyticsConfig()\n return React.useMemo(() => {\n const byId = new Map<string, AnalyticsCardDef>()\n for (const card of getAnalyticsCards(runtime)) byId.set(card.id, card)\n for (const card of cards) byId.set(card.id, card)\n return [...byId.values()].map((c) => (c.createdBy ? c : { ...c, createdBy }))\n }, [runtime, cards, createdBy])\n}\n\n/**\n * Every card visible on this surface, with the user's own layer applied:\n * their order, their columns, their reports, minus what they removed.\n *\n * The overview, the rail, the list and the viewer all read THIS — a preference\n * that only the grid honoured would rename a card in one place and not the\n * other, which is how a \"customisable\" screen becomes two screens.\n */\nexport function useAnalyticsCards(): AnalyticsCardDef[] {\n const catalogue = useAnalyticsCatalogue()\n const prefs = useAnalyticsPrefs()\n return React.useMemo(() => resolveCards(catalogue, prefs), [catalogue, prefs])\n}\n\n/** Cards a pack placed on the overview grid, in their declared order. */\nexport function useOverviewCards(): AnalyticsCardDef[] {\n const all = useAnalyticsCards()\n return React.useMemo(\n () => all\n .filter((c) => c.dashboard && c.dashboard.defaultVisible !== false)\n .sort((a, b) => (a.dashboard?.order ?? 0) - (b.dashboard?.order ?? 0)),\n [all],\n )\n}\n\n/**\n * Columns for a card's tabular view.\n *\n * An aggregate card has no `columns` of its own — its table IS its dimensions\n * and measures, so deriving them keeps one definition instead of asking every\n * card author to restate the same fields twice and let the two drift.\n */\nexport function cardColumns(card: AnalyticsCardDef): AnalyticsColumnDef[] {\n if (card.columns?.length) return card.columns\n return [\n // A hidden dimension is group-by only — the id a person column reads from,\n // never a column of UUIDs next to the name it belongs to.\n ...(card.query.dimensions ?? []).filter((d) => !d.hidden).map((d): AnalyticsColumnDef => ({\n key: d.key,\n label: d.label,\n type: d.person ? 'person' : (d.format ?? (d.grain ? 'date' : 'text')),\n idKey: d.person?.idKey,\n personKind: d.person?.kind,\n align: 'left',\n })),\n ...(card.query.measures ?? []).map((m): AnalyticsColumnDef => ({\n key: m.key,\n label: m.label,\n type: m.format ?? 'number',\n align: 'right',\n sortable: true,\n })),\n ]\n}\n\nexport function navigateAnalytics(path: string): void {\n hashRouterAdapter().navigate(path)\n}\n\nexport interface AnalyticsSurfaceProps {\n config: ResolvedAnalyticsConfig\n provider: AnalyticsProviderType\n children?: React.ReactNode\n}\n\nexport function AnalyticsSurface({ config, provider, children }: AnalyticsSurfaceProps) {\n const openCard = React.useCallback((card: AnalyticsCardDef) => {\n markViewed(card.id)\n navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(card.id)}`)\n }, [])\n\n return (\n <ConfigContext.Provider value={config}>\n <AnalyticsContextProvider\n provider={provider}\n currency={config.currency}\n defaultPreset={config.defaultRange}\n defaultCompare={config.defaultCompare}\n defaultPageSize={config.defaultPageSize}\n onOpenCard={openCard}\n createdBy={config.createdBy}\n >\n {children}\n </AnalyticsContextProvider>\n </ConfigContext.Provider>\n )\n}\n","import React from 'react'\nimport { useTranslation } from '@fayz-ai/core'\nimport { AssistantInvite } from '@fayz-ai/admin'\nimport { useAnalyticsConfig } from './AnalyticsSurface'\n\n// ---------------------------------------------------------------------------\n// The assistant's offer on Analytics.\n//\n// It belongs to the MODULE, not to the overview: a question about a report is\n// asked while reading that report, and a composer that only exists on the home\n// screen makes the user navigate away from the number to ask about it.\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsAssistant() {\n const { assistant } = useAnalyticsConfig()\n const t = useTranslation()\n\n // Prompts the screen offers. App overrides win whole; otherwise the plugin's\n // own three, which are business questions and not report names on purpose.\n const suggestions = React.useMemo(\n () => assistant?.suggestions ?? [0, 1, 2].map((i) => ({ label: t(`reports.assistant.suggestion.${i}`) })),\n [assistant?.suggestions, t],\n )\n\n if (!assistant) return null\n\n return (\n <AssistantInvite\n // One id across the module: the same invitation followed from the grid to\n // a report, which is what lets the bar stay put instead of folding back\n // into the FAB and unrolling again on every internal navigation.\n id=\"analytics\"\n auto={assistant.auto ?? false}\n role={assistant.role ?? 'growth'}\n persona={assistant.persona ?? t('reports.assistant.persona')}\n headline={assistant.headline ?? t('reports.assistant.headline')}\n pitch={assistant.pitch ?? t('reports.assistant.pitch')}\n description={assistant.description ?? t('reports.assistant.description')}\n placeholder={assistant.placeholder ?? t('reports.assistant.placeholder')}\n suggestions={suggestions}\n />\n )\n}\n","import React from 'react'\nimport { ModulePage, useModuleLayout, type ModuleNavItem, type NavigationItem } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { AnalyticsCardDef } from '@fayz-ai/core'\nimport {\n useAnalyticsConfig, useAnalyticsCards, navigateAnalytics,\n ANALYTICS_BASE, REPORTS_BASE, SETTINGS_ROUTE,\n} from './AnalyticsSurface'\nimport { AnalyticsAssistant } from './AnalyticsAssistant'\n\n// ---------------------------------------------------------------------------\n// Analytics is ONE entry in the app nav, not two.\n//\n// \"Analytics\" and \"Reports\" were two top-level links to the same engine, which\n// made the user pick a door before knowing what was behind it. There is one\n// door now; inside it, the report groups (a card's `category`) and the reports\n// themselves ARE the navigation.\n//\n// Essa navegação mora DENTRO DA PÁGINA, em todo layout: a coluna própria do\n// ModulePage, abaixo da faixa que atravessa o cartão.\n//\n// Ela tomava o rail do aplicativo quando havia um (o mesmo que /settings fazia).\n// Abrir Relatórios apagava o menu do produto e punha trinta relatórios no lugar:\n// quem entrou para ver o ticket médio perdia de vista o Financeiro, a Agenda e\n// tudo o mais, e sair de lá era um \"← Voltar\". Olhar um relatório não é sair do\n// aplicativo. O rail fica; a coluna da direita é que muda.\n//\n// Charts are not re-implemented here: AnalyticsCard renders through the same\n// ChartWidget the dashboard uses.\n// ---------------------------------------------------------------------------\n\nexport type AnalyticsView = 'overview' | 'reports' | 'report' | 'live' | 'settings'\n\nexport interface AnalyticsModuleProps {\n view: AnalyticsView\n /** Route param when `view === 'report'` — marks the active entry. */\n cardId?: string\n children?: React.ReactNode\n}\n\nconst reportRoute = (cardId: string) => `${REPORTS_BASE}/${encodeURIComponent(cardId)}`\n\n/** Cards by category, categories A→Z, reports A→Z inside each. */\nfunction groupCards(cards: AnalyticsCardDef[]): [string, AnalyticsCardDef[]][] {\n const groups = new Map<string, AnalyticsCardDef[]>()\n for (const card of cards) {\n const list = groups.get(card.category)\n if (list) list.push(card)\n else groups.set(card.category, [card])\n }\n return [...groups.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([category, list]) => [category, [...list].sort((a, b) => a.name.localeCompare(b.name))])\n}\n\n/** The module's whole tree, in the order both renderers walk it. */\nfunction useAnalyticsTree() {\n const t = useTranslation()\n const { labels, showLiveView } = useAnalyticsConfig()\n const cards = useAnalyticsCards()\n\n return React.useMemo(() => ({\n title: labels.analytics,\n // Only the overview. The searchable catalogue (/analytics/reports) is still\n // routed — bookmarks and the legacy /reports link resolve — but it is not\n // listed: the tree below already IS the catalogue, and a link named \"all\n // reports\" sitting above the reports reads as a different, fuller list.\n fixed: [\n { id: 'overview', label: labels.overview ?? t('reports.overview'), icon: 'BarChart3', route: ANALYTICS_BASE, view: 'overview' as const },\n ],\n groups: groupCards(cards),\n live: showLiveView\n ? { id: 'live', label: labels.liveView, icon: 'Radio', route: `${ANALYTICS_BASE}/live`, view: 'live' as const }\n : null,\n // Depois dos relatórios, não antes: é a tela que fala SOBRE a lista, e uma\n // engrenagem no topo empurra para baixo o que a pessoa veio ver.\n settings: {\n id: 'settings',\n label: labels.settings ?? t('reports.settings.nav'),\n icon: 'SlidersHorizontal',\n route: SETTINGS_ROUTE,\n view: 'settings' as const,\n },\n }), [labels, showLiveView, cards, t])\n}\n\nexport function AnalyticsModule({ view, cardId, children }: AnalyticsModuleProps) {\n const t = useTranslation()\n const { labels } = useAnalyticsConfig()\n const variant = useModuleLayout()\n const tree = useAnalyticsTree()\n const activeId = cardId ? decodeURIComponent(cardId) : undefined\n // Does a shell rail exist to take over? The SHELL answers — it is the only\n // thing that knows. Asking the module-nav context instead meant reading its\n // default ('rail' = \"draw your own\") whenever the provider was out of the\n // tree, and the app rail plus this module's own column made exactly the two\n // menus the takeover exists to remove. The context is the fallback, for a\n // module mounted outside an AdminShell at all.\n // --- the in-page rail, in every layout ----------------------------------\n const nav = React.useMemo<ModuleNavItem[]>(() => {\n return [\n ...tree.fixed.map((f) => ({\n id: f.id, label: f.label, icon: f.icon, active: view === f.view, onClick: () => navigateAnalytics(f.route),\n })),\n ...tree.groups.map(([category, list]): ModuleNavItem => ({\n id: `group:${category}`,\n label: category,\n children: list.map((card) => ({\n id: card.id,\n label: card.name,\n active: view === 'report' && card.id === activeId,\n onClick: () => navigateAnalytics(reportRoute(card.id)),\n })),\n })),\n ...(tree.live ? [{\n id: tree.live.id, label: tree.live.label, icon: tree.live.icon,\n active: view === 'live', onClick: () => navigateAnalytics(tree.live!.route),\n }] : []),\n {\n id: tree.settings.id, label: tree.settings.label, icon: tree.settings.icon,\n active: view === 'settings', onClick: () => navigateAnalytics(tree.settings.route),\n },\n ]\n }, [tree, view, activeId])\n\n return (\n <ModulePage\n title={tree.title}\n nav={nav}\n // `rail` em todo layout: a coluna é desta página, não do aplicativo.\n navVariant=\"rail\"\n // A busca que a rail do aplicativo carregava vem junto — sem ela, trinta\n // relatórios em quatro grupos são rolagem, não navegação.\n navFilterPlaceholder={labels.searchReports ?? t('reports.search')}\n showHeader={false}\n viewKey={view === 'report' ? `report:${activeId}` : view}\n >\n {/* Above the page body and outside its flow: the invite occupies no\n layout, it only measures where the content column is. */}\n <AnalyticsAssistant />\n {/* Tail room for the docked composer, which floats over the column —\n without it the last row of every analytics page ends underneath it. */}\n <div className=\"md:pb-16\">{children}</div>\n </ModulePage>\n )\n}\n","import React from 'react'\nimport { BarChart3 } from 'lucide-react'\nimport { AnalyticsControls, AnalyticsGrid, collectFilters } from '@fayz-ai/ui'\nimport { useAnalyticsConfig, useOverviewCards } from './AnalyticsSurface'\n\n// ---------------------------------------------------------------------------\n// The one general dashboard.\n//\n// It is not a separate feature from the report list — it is the subset of cards\n// a pack chose to place, rendered at tile size. Every tile's ↗ opens the very\n// same definition as a full report, which is why there is no \"dashboard metric\"\n// that has no report behind it.\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsOverview() {\n const { labels } = useAnalyticsConfig()\n const cards = useOverviewCards()\n const filters = React.useMemo(() => collectFilters(cards), [cards])\n\n // The assistant's invite is mounted by the module, not here: it follows the\n // user from this grid into a report instead of belonging to one screen.\n return (\n <>\n <div className=\"space-y-4\">\n {/* Sem título nem descrição: a barra da shell já escreve \"Análises\", e a\n frase abaixo custava uma linha antes do primeiro número. */}\n {/* A superfície, o encosto à direita e o grudar no topo são de\n PageToolbar agora — a mesma barra que o dashboard usa. */}\n <AnalyticsControls filters={filters} />\n\n {cards.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <BarChart3 className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"font-medium\">{labels.emptyOverviewTitle}</p>\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{labels.emptyOverviewDescription}</p>\n </div>\n ) : (\n <AnalyticsGrid cards={cards} />\n )}\n </div>\n </>\n )\n}\n","import React from 'react'\nimport { Search, User } from 'lucide-react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport {\n Card, DataTable, FilterChip, type FilterChipOption,\n} from '@fayz-ai/ui'\nimport type { AnalyticsCardDef } from '@fayz-ai/core'\nimport { useAnalyticsConfig, useAnalyticsCards, navigateAnalytics, REPORTS_BASE } from './AnalyticsSurface'\nimport { useLastViewed, markViewed } from '../lib/lastViewed'\n\n// ---------------------------------------------------------------------------\n// The one list where a user finds what they want.\n//\n// This replaces the old category-card hub. Cards-in-a-grid look richer but stop\n// working past about twenty reports: you cannot sort them, cannot see when you\n// last opened one, and finding \"sales by vendor\" means reading every tile. A\n// table sorts, scans and filters — which is what a catalogue is for.\n//\n// It renders through the shared DataTable rather than a hand-rolled <table>.\n// The first version copied DataTable's classes by hand and drifted from it\n// immediately — wrong header tint, wrong corner radius — because a copy has to\n// be re-copied every time the original moves. `variant=\"bare\"` exists for this\n// exact shape: a table under a search toolbar, inside a card that already owns\n// the border and radius.\n// ---------------------------------------------------------------------------\n\nfunction formatViewed(iso: string | undefined, locale: string, never: string): string {\n if (!iso) return never\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return never\n return d.toLocaleDateString(locale, { day: 'numeric', month: 'short', year: 'numeric' })\n}\n\nexport function ReportsListPage() {\n const { labels, currency, showHeader } = useAnalyticsConfig()\n const cards = useAnalyticsCards()\n const lastViewed = useLastViewed()\n\n const [search, setSearch] = React.useState('')\n // Single-select, like every other facet in the product (see FilterChip):\n // the chip states what is filtering right now, and picking \"all\" clears it.\n const [category, setCategory] = React.useState<string | undefined>()\n const [author, setAuthor] = React.useState<string | undefined>()\n\n const categoryOptions = React.useMemo<FilterChipOption[]>(\n () => [...new Set(cards.map((c) => c.category))]\n .sort((a, b) => a.localeCompare(b))\n .map((c) => ({ value: c, label: c })),\n [cards],\n )\n const authorOptions = React.useMemo<FilterChipOption[]>(\n () => [...new Set(cards.map((c) => c.createdBy ?? '—'))]\n .sort((a, b) => a.localeCompare(b))\n .map((a) => ({ value: a, label: a })),\n [cards],\n )\n\n const rows = React.useMemo(() => {\n const q = search.trim().toLowerCase()\n return cards.filter((card) => {\n if (category && card.category !== category) return false\n if (author && (card.createdBy ?? '—') !== author) return false\n if (!q) return true\n // Description is searched too: users look for \"no-show\" long before they\n // remember a report is filed under \"Cancellations\".\n return card.name.toLowerCase().includes(q)\n || card.description?.toLowerCase().includes(q)\n || card.category.toLowerCase().includes(q)\n })\n }, [cards, search, category, author])\n\n const columns = React.useMemo<ColumnDef<AnalyticsCardDef, unknown>[]>(() => [\n {\n id: 'name',\n accessorFn: (card) => card.name,\n header: labels.name,\n cell: ({ row }) => (\n <div className=\"min-w-0\">\n <span className=\"font-medium\">{row.original.name}</span>\n {row.original.available === false ? (\n <span className=\"ml-2 rounded-full border px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n {labels.unavailableTitle}\n </span>\n ) : null}\n {row.original.description ? (\n <p className=\"mt-0.5 line-clamp-1 text-muted-foreground sm:hidden\">{row.original.description}</p>\n ) : null}\n </div>\n ),\n },\n {\n id: 'category',\n accessorFn: (card) => card.category,\n header: labels.category,\n cell: ({ getValue }) => (\n <span className=\"rounded-md bg-muted px-2 py-0.5\">{String(getValue() ?? '')}</span>\n ),\n },\n {\n id: 'lastViewed',\n // Sorts on the timestamp, renders the date. Never-opened reports carry\n // undefined so they sink to the bottom in BOTH directions rather than\n // topping \"most recent\" as an epoch-zero date.\n accessorFn: (card) => {\n const iso = lastViewed[card.id]\n return iso ? new Date(iso).getTime() : undefined\n },\n sortUndefined: 1,\n header: labels.lastViewed,\n cell: ({ row }) => (\n <span className=\"text-muted-foreground\">\n {formatViewed(lastViewed[row.original.id], currency.locale, labels.never)}\n </span>\n ),\n },\n {\n id: 'createdBy',\n accessorFn: (card) => card.createdBy ?? '—',\n header: labels.createdBy,\n cell: ({ getValue }) => (\n <span className=\"inline-flex items-center gap-1.5 text-muted-foreground\">\n <User className=\"h-3 w-3\" />\n {String(getValue() ?? '—')}\n </span>\n ),\n },\n ], [labels, currency.locale, lastViewed])\n\n const open = (card: AnalyticsCardDef) => {\n markViewed(card.id)\n navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(card.id)}`)\n }\n\n return (\n <div className=\"space-y-4\">\n {showHeader ? (\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">{labels.reports}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{labels.reportsSubtitle}</p>\n </div>\n ) : null}\n\n {/* Same composition as CrudListView: search, tools and the table are ONE\n surface, because they act on the same rows. The Card owns the border\n and radius, so the table inside goes `bare`. */}\n <Card className=\"overflow-hidden\">\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2\">\n <div className=\"min-w-[10rem] flex-1\">\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground\" />\n {/* Borderless, exactly as CrudListView's search box: the card\n already draws the boundary, and a second box inside it would\n be a frame inside a frame. */}\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={labels.searchReports}\n className=\"w-full bg-transparent py-1.5 pl-8 pr-3 text-sm placeholder:text-muted-foreground focus:outline-none\"\n />\n </div>\n </div>\n\n <div className=\"flex shrink-0 flex-wrap items-center gap-1.5\">\n <FilterChip\n label={labels.category}\n allLabel={labels.allCategories}\n options={categoryOptions}\n value={category}\n onChange={setCategory}\n />\n <FilterChip\n label={labels.createdBy}\n allLabel={labels.allCreatedBy}\n options={authorOptions}\n value={author}\n onChange={setAuthor}\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n data={rows}\n variant=\"bare\"\n compact\n onRowClick={open}\n emptyMessage={labels.noResults}\n />\n\n <div className=\"border-t border-border px-3 py-2 text-xs text-muted-foreground\">\n {rows.length} {labels.results}\n </div>\n </Card>\n </div>\n )\n}\n","import { exportCSV } from '@fayz-ai/core'\nimport type { CSVColumn } from '@fayz-ai/core'\nimport type { ReportColumnDef } from '../types'\nimport { expandBagColumns, formatValuePlain } from '../lib/columns'\n\nexport function exportToCsv(\n columns: ReportColumnDef[],\n data: Record<string, any>[],\n filename: string,\n currency?: string,\n): void {\n // Uma coluna por resposta de formulário, não um JSON dentro da célula: é o\n // que deixa a planilha ordenável e filtrável por \"Estilo\".\n const { columns: cols, rows } = expandBagColumns(columns, data)\n const visibleCols = cols.filter((c) => c.visible !== false)\n\n const csvColumns: CSVColumn[] = visibleCols.map((col) => ({\n key: col.key,\n label: col.label,\n format: (value: any) => formatValuePlain(value, col, currency),\n }))\n\n exportCSV(csvColumns, rows, filename)\n}\n","import React, { useEffect, useState } from 'react'\nimport { Download } from 'lucide-react'\nimport {\n Dropdown,\n DropdownTrigger,\n DropdownContent,\n DropdownItem,\n ToolbarAction,\n} from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { ReportColumnDef } from '../types'\nimport { exportToCsv } from '../export/csv'\n\ninterface ExportDropdownProps {\n columns: ReportColumnDef[]\n data: Record<string, any>[]\n filename: string\n currency?: string\n title?: string\n /**\n * Fetch the WHOLE result set. The table on screen is one page of 50, and a\n * file holding 50 of 4,000 rows says nothing about being a fragment — so the\n * export asks for everything before it writes. Absent ⇒ the page is exported.\n */\n fetchAll?: () => Promise<Record<string, any>[]>\n}\n\nexport function ExportDropdown({ columns, data, filename, currency, title, fetchAll }: ExportDropdownProps) {\n const t = useTranslation()\n const [excelAvailable, setExcelAvailable] = useState(false)\n const [pdfAvailable, setPdfAvailable] = useState(false)\n const [busy, setBusy] = useState(false)\n\n useEffect(() => {\n import('../export/excel').then((m) => m.isExcelAvailable()).then(setExcelAvailable).catch(() => {})\n import('../export/pdf').then((m) => m.isPdfAvailable()).then(setPdfAvailable).catch(() => {})\n }, [])\n\n // One writer for the three formats: whichever one is picked, the rows come\n // from the same fetch, so a CSV and a PDF of the same report cannot hold\n // different numbers of lines. A failed fetch falls back to the page on\n // screen — a partial file beats a button that does nothing.\n const withRows = async (write: (rows: Record<string, any>[]) => void | Promise<void>) => {\n if (busy) return\n setBusy(true)\n try {\n const rows = fetchAll ? await fetchAll().catch(() => data) : data\n await write(rows.length ? rows : data)\n } finally {\n setBusy(false)\n }\n }\n\n const handleCsv = () => withRows((rows) => exportToCsv(columns, rows, filename, currency))\n\n const handleExcel = () => withRows(async (rows) => {\n const { exportToExcel } = await import('../export/excel')\n await exportToExcel(columns, rows, filename, currency)\n })\n\n const handlePdf = () => withRows(async (rows) => {\n const { exportToPdf } = await import('../export/pdf')\n await exportToPdf(columns, rows, filename, { title, currency })\n })\n\n return (\n <Dropdown>\n <DropdownTrigger asChild>\n {/* Sem contorno, como o resto da barra — ver ToolbarAction. */}\n <ToolbarAction icon={Download} caret disabled={busy}>{t('reports.export')}</ToolbarAction>\n </DropdownTrigger>\n <DropdownContent align=\"end\">\n <DropdownItem onClick={handleCsv}>{t('reports.exportCsv')}</DropdownItem>\n {excelAvailable && (\n <DropdownItem onClick={handleExcel}>{t('reports.exportExcel')}</DropdownItem>\n )}\n {pdfAvailable && (\n <DropdownItem onClick={handlePdf}>{t('reports.exportPdf')}</DropdownItem>\n )}\n </DropdownContent>\n </Dropdown>\n )\n}\n","import React from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { useTranslation } from '@fayz-ai/core'\nimport { Button } from '@fayz-ai/ui'\n\ninterface ReportPaginationProps {\n page: number\n pageSize: number\n total: number\n onPageChange: (page: number) => void\n onPageSizeChange: (size: number) => void\n}\n\nexport function ReportPagination({ page, pageSize, total, onPageChange, onPageSizeChange }: ReportPaginationProps) {\n // Translated, not literal: this row printed \"1–12 of 12\" and \"50 / page\"\n // under a pt-BR shell, which is the one place a user counts on the app\n // knowing what language it speaks.\n const t = useTranslation()\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n const from = (page - 1) * pageSize + 1\n const to = Math.min(page * pageSize, total)\n\n return (\n <div className=\"flex items-center justify-between border-t px-4 py-3\">\n <div className=\"text-sm text-muted-foreground\">\n {total > 0 ? t('reports.pagination.range', { from, to, total }) : t('reports.pagination.empty')}\n </div>\n\n <div className=\"flex items-center gap-3\">\n <select\n value={pageSize}\n onChange={(e) => onPageSizeChange(Number(e.target.value))}\n className=\"h-8 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 text-sm\"\n >\n {[25, 50, 100].map((size) => (\n <option key={size} value={size}>{t('reports.pagination.perPage', { size })}</option>\n ))}\n </select>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={page <= 1}\n onClick={() => onPageChange(page - 1)}\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <span className=\"text-sm px-2\">\n {page} / {totalPages}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={page >= totalPages}\n onClick={() => onPageChange(page + 1)}\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport { ArrowLeft, Construction, Printer } from 'lucide-react'\nimport {\n Button, SubpageHeader, ToolbarAction, AnalyticsCard, AnalyticsControls,\n useAnalyticsContext, useAnalyticsCard, useAnalyticsCardRows, useAnalyticsAllRows,\n useToolbarPanelClose,\n} from '@fayz-ai/ui'\nimport type { AnalyticsCardDef, AnalyticsRow } from '@fayz-ai/core'\nimport { DataTable, StatementTable, formatBucket } from '@fayz-ai/ui'\nimport { expandBagColumns, reportColumnsToTanstack } from '../lib/columns'\nimport { ExportDropdown } from '../components/ExportDropdown'\nimport { ReportPagination } from '../components/ReportPagination'\nimport type { ReportColumnDef } from '../types'\nimport {\n useAnalyticsConfig, useAnalyticsCards, cardColumns, navigateAnalytics,\n ANALYTICS_BASE, REPORTS_BASE,\n} from './AnalyticsSurface'\nimport { markViewed } from '../lib/lastViewed'\n\n// ---------------------------------------------------------------------------\n// A report, full size.\n//\n// The chart is not decoration bolted onto a table: it is the SAME card that\n// renders as a tile on the overview, given the whole width. Underneath sits the\n// data it was computed from — so \"show me the number\" and \"show me the rows\n// behind the number\" stop being two different features in two different places.\n// ---------------------------------------------------------------------------\n\nfunction ViewerBody({ card }: { card: AnalyticsCardDef }) {\n const { labels, currency, defaultRange } = useAnalyticsConfig()\n const { state, setPage, setPageSize, setPreset } = useAnalyticsContext()\n const cardDefaultRange = (card as AnalyticsCardDef & { defaultRange?: typeof defaultRange }).defaultRange\n React.useEffect(() => {\n if (!cardDefaultRange) return\n setPreset(cardDefaultRange)\n return () => setPreset(defaultRange)\n }, [card.id, cardDefaultRange, defaultRange, setPreset])\n const isStatement = card.viz.type === 'statement' && !!card.viz.statement\n // Same query as the chart above and the export below — the provider\n // de-duplicates them into one round trip.\n // A statement reads the whole set below. Running the paged card query too\n // executed the same heavy DRE twice and made both requests hit the timeout.\n const { result, loading, error, engineMissing } = useAnalyticsCard(card, { enabled: !isStatement })\n // Um demonstrativo lê o CONJUNTO, nunca a página — ver `useAnalyticsAllRows`.\n const all = useAnalyticsAllRows(card, isStatement && card.available !== false)\n\n const columns = React.useMemo(() => cardColumns(card), [card])\n // As respostas do formulário viram COLUNAS de verdade — \"Estilo\", \"Perfil\" —\n // descobertas nas linhas desta página, porque cada campanha pergunta outra\n // coisa e declarar as colunas no card tornaria o próximo formulário\n // invisível. Mesma expansão que a planilha usa, então tela e arquivo mostram\n // as mesmas colunas.\n const expanded = React.useMemo(\n () => expandBagColumns(columns as unknown as ReportColumnDef[], (result?.rows ?? []) as Record<string, any>[]),\n [columns, result?.rows],\n )\n const tanstackColumns = React.useMemo(\n () => reportColumnsToTanstack(expanded.columns, currency.code),\n [expanded.columns, currency.code],\n )\n const rows = expanded.rows\n\n if (card.available === false) {\n return (\n <div className=\"flex flex-col items-center justify-center rounded-xl border border-dashed py-16 text-center\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Construction className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"font-medium\">{labels.unavailableTitle}</p>\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{labels.unavailableDescription}</p>\n </div>\n )\n }\n\n // A pure detail listing has nothing to chart — rendering an empty card frame\n // above the table would be chrome pretending to be information.\n const hasViz = card.viz.type !== 'table' || (card.query.measures?.length ?? 0) > 0\n\n // Um demonstrativo JÁ É a tela inteira. Repetir as mesmas linhas embaixo como\n // grade plana daria duas respostas para a mesma pergunta — e a de baixo, sem\n // hierarquia nem totalizadores, é a pior das duas.\n if (isStatement && card.viz.statement) {\n return (\n <>\n {engineMissing ? (\n <div className=\"rounded-lg border bg-muted/40 p-3 text-sm\">\n <p className=\"font-medium\">Analytics engine not installed</p>\n <p className=\"mt-0.5 text-muted-foreground\">\n This report aggregates server-side and needs migration 0039\n (<code className=\"text-xs\">analytics_run</code> + the read models) applied to this project.\n </p>\n </div>\n ) : (error ?? all.error) ? (\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive\">\n {error ?? all.error}\n </div>\n ) : null}\n <StatementTable\n rows={all.rows}\n def={card.viz.statement}\n currency={currency}\n formatPeriod={(p) => formatBucket(p, 'month')}\n emptyMessage={labels.noResults}\n loading={all.loading}\n />\n </>\n )\n }\n\n return (\n <>\n {hasViz ? (\n <AnalyticsCard\n card={{ ...card, viz: { ...card.viz, height: card.viz.height ?? 280, limit: undefined } }}\n hideOpen\n />\n ) : null}\n\n {engineMissing ? (\n <div className=\"rounded-lg border bg-muted/40 p-3 text-sm\">\n <p className=\"font-medium\">Analytics engine not installed</p>\n <p className=\"mt-0.5 text-muted-foreground\">\n This report aggregates server-side and needs migration 0039\n (<code className=\"text-xs\">analytics_run</code> + the read models) applied to this project.\n </p>\n </div>\n ) : error ? (\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive\">\n {error}\n </div>\n ) : null}\n\n {/* `print-flow`: sem ele a regra de cartão (`break-inside: avoid`) prende a\n tabela inteira numa página e o resto do relatório não sai no papel. */}\n <div className=\"print-flow\">\n <DataTable\n columns={tanstackColumns}\n data={rows}\n loading={loading}\n skeletonRows={5}\n emptyMessage={labels.noResults}\n variant=\"card\"\n compact\n />\n </div>\n\n {!loading ? (\n <div className=\"no-print\">\n <ReportPagination\n page={state.page}\n pageSize={state.pageSize}\n total={result?.total ?? 0}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n </div>\n ) : null}\n </>\n )\n}\n\nexport function AnalyticsReportViewer({ cardId }: { cardId?: string }) {\n const { labels } = useAnalyticsConfig()\n const cards = useAnalyticsCards()\n const card = cards.find((c) => c.id === decodeURIComponent(cardId ?? ''))\n\n React.useEffect(() => { if (card) markViewed(card.id) }, [card?.id])\n\n if (!card) {\n return (\n <div className=\"space-y-4\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateAnalytics(REPORTS_BASE)}>\n <ArrowLeft className=\"mr-1.5 h-3.5 w-3.5\" />\n {labels.reports}\n </Button>\n <p className=\"py-12 text-center text-sm text-muted-foreground\">{labels.noResults}</p>\n </div>\n )\n }\n\n return (\n <div className=\"space-y-4\">\n {/* O título vive na barra da shell, não no corpo. Escrever \"← Relatórios /\n Nome\" aqui E deixar a rota declarar `parentRoute` produzia três\n cabeçalhos empilhados dizendo a mesma coisa. SubpageHeader reivindica a\n barra com o nome do card — que depende de dado e por isso não cabe em\n `route.title`. */}\n {/* A descrição vai para o (i) do breadcrumb, não para um parágrafo aqui.\n Era uma linha inteira entre o nome do relatório e o número que a\n pessoa abriu a tela para ver — lida uma vez, ruído em todas as\n visitas seguintes. No ícone ela continua a um gesto de distância. */}\n <SubpageHeader\n title={card.name}\n description={card.description}\n parentLabel={labels.analytics}\n onBack={() => navigateAnalytics(ANALYTICS_BASE)}\n />\n\n <AnalyticsControls\n filters={card.query.filters ?? []}\n showCompare={card.compare !== false}\n className=\"no-print\"\n actions={<ViewerActions card={card} />}\n />\n\n <ViewerBody card={card} />\n </div>\n )\n}\n\nfunction ViewerActions({ card }: { card: AnalyticsCardDef }) {\n const { currency, labels } = useAnalyticsConfig()\n const closePanel = useToolbarPanelClose()\n // Imprimir a partir de dentro do painel imprimia o PAINEL: `window.print()`\n // congela o documento como ele está, e como está inclui o popover aberto por\n // cima do relatório. Fecha primeiro, deixa o navegador pintar o quadro sem\n // ele, e só então manda imprimir.\n const print = React.useCallback(() => {\n closePanel()\n requestAnimationFrame(() => {\n requestAnimationFrame(() => window.setTimeout(() => window.print(), 120))\n })\n }, [closePanel])\n const { result } = useAnalyticsCard(card)\n const columns = React.useMemo(() => cardColumns(card), [card])\n // O arquivo leva o relatório INTEIRO, não a página de 50 que está na tela:\n // uma planilha com 50 de 4.000 leads não avisa em lugar nenhum que é um\n // pedaço, e é ela que sai por e-mail como se fosse o mês fechado.\n const fetchAll = useAnalyticsCardRows(card)\n if (!result?.rows?.length) return null\n return (\n <>\n <ExportDropdown\n columns={columns as unknown as ReportColumnDef[]}\n data={result.rows as Record<string, unknown>[]}\n fetchAll={fetchAll as () => Promise<Record<string, any>[]>}\n filename={card.id}\n currency={currency.code}\n title={card.name}\n />\n <ToolbarAction icon={Printer} onClick={print}>{labels.print}</ToolbarAction>\n </>\n )\n}\n","import React from 'react'\nimport { Radio } from 'lucide-react'\nimport { useAnalyticsConfig } from './AnalyticsSurface'\n\n// ---------------------------------------------------------------------------\n// Live View — the real-time surface.\n//\n// A deliberate stub. It needs a storefront event stream (sessions, carts,\n// checkouts) that does not exist yet, and the honest thing on a page with no\n// data source is to say so rather than render zeroes that look like a quiet\n// afternoon. It holds its nav slot so the shape of the section is visible.\n// ---------------------------------------------------------------------------\n\nexport function LiveViewPage() {\n const { labels } = useAnalyticsConfig()\n return (\n <div className=\"flex flex-col items-center justify-center rounded-xl border border-dashed py-20 text-center\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Radio className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"font-medium\">{labels.liveView}</p>\n <p className=\"mt-1 max-w-sm text-sm text-muted-foreground\">{labels.liveViewSoon}</p>\n </div>\n )\n}\n","import React from 'react'\nimport {\n Eye, EyeOff, GripVertical, RotateCcw, SlidersHorizontal, Trash2,\n ChevronUp, ChevronDown,\n} from 'lucide-react'\nimport type {\n AnalyticsCardDef, AnalyticsVizType, PluginAITool, PluginQuickAction,\n} from '@fayz-ai/core'\nimport { useTranslation } from '@fayz-ai/core'\nimport {\n Badge, Button, Card, Checkbox, Input, PageHeaderActions, SubpageHeader, getLucideIcon,\n Select, SelectTrigger, SelectValue, SelectContent, SelectItem,\n} from '@fayz-ai/ui'\nimport {\n QuickActionsButton, RightRailPage, askAI, useAgentSurface,\n type AgentSurfaceContribution, type AskAIIntro,\n} from '@fayz-ai/admin'\nimport {\n useAnalyticsConfig, useAnalyticsCatalogue, useAnalyticsCards, navigateAnalytics,\n ANALYTICS_BASE, REPORTS_BASE,\n} from './AnalyticsSurface'\nimport {\n analyticsSources, clearCardPref, deleteCustomReport, resetAnalyticsPrefs, saveCustomReport,\n setCardPref, setOverviewOrder, useAnalyticsPrefs,\n type AnalyticsSourceGroup, type CustomReport,\n} from '../lib/preferences'\n\n// ---------------------------------------------------------------------------\n// Configurar relatórios.\n//\n// One screen for the four things a user asks of a report catalogue: which ones\n// I see, in what order, what each one shows, and one of my own.\n//\n// It edits the PREFERENCE LAYER (lib/preferences), never the shipped card. Two\n// consequences worth stating: an app update still moves the base definition\n// under a user's choices instead of being overwritten by them, and \"restaurar\n// padrões\" is a delete, not a re-import — there is always a way back.\n//\n// Reordering is native drag-and-drop plus up/down buttons. Both, not either:\n// the drag is what a mouse expects and the buttons are what a keyboard, a\n// screen reader and a touch screen can actually use.\n// ---------------------------------------------------------------------------\n\nconst VIZ_TYPES: AnalyticsVizType[] = ['kpi', 'line', 'bar', 'area', 'donut', 'breakdown', 'table']\n\n/** A card with nothing to group by has no category axis — only a headline\n * number or a row listing can honestly render it. */\nfunction vizOptionsFor(card: AnalyticsCardDef): AnalyticsVizType[] {\n const hasDimension = (card.query.dimensions ?? []).some((d) => !d.hidden)\n return hasDimension ? VIZ_TYPES : ['kpi', 'table']\n}\n\nfunction CardIcon({ name, className }: { name?: string; className?: string }) {\n const Icon = getLucideIcon(name ?? 'FileText') ?? getLucideIcon('FileText')\n return Icon ? <Icon className={className} /> : null\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\ninterface RowProps {\n card: AnalyticsCardDef\n custom: boolean\n onEdit: () => void\n children?: React.ReactNode\n drag?: {\n onDragStart: () => void\n onDragOver: (event: React.DragEvent) => void\n onDragEnd: () => void\n dragging: boolean\n }\n}\n\nfunction ReportRow({ card, custom, onEdit, children, drag }: RowProps) {\n const t = useTranslation()\n return (\n <li\n draggable={Boolean(drag)}\n onDragStart={drag?.onDragStart}\n onDragOver={drag?.onDragOver}\n onDragEnd={drag?.onDragEnd}\n className={[\n 'flex items-center gap-2 border-b border-border/60 px-3 py-2 last:border-0',\n drag ? 'cursor-grab active:cursor-grabbing' : '',\n drag?.dragging ? 'opacity-40' : '',\n ].join(' ')}\n >\n {drag ? (\n <GripVertical className=\"h-4 w-4 shrink-0 text-muted-foreground/50\" aria-hidden />\n ) : (\n <span className=\"w-4 shrink-0\" aria-hidden />\n )}\n <CardIcon name={card.icon} className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium\">{card.name}</span>\n {custom ? <Badge variant=\"secondary\">{t('reports.settings.custom')}</Badge> : null}\n </div>\n <p className=\"truncate text-xs text-muted-foreground\">{card.category}</p>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {children}\n <Button variant=\"ghost\" size=\"sm\" onClick={onEdit} aria-label={t('reports.settings.edit')} title={t('reports.settings.edit')}>\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n </li>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Editor — one card's name, chart and columns\n// ---------------------------------------------------------------------------\n\nfunction CardEditor({ card, onClose }: { card: AnalyticsCardDef; onClose: () => void }) {\n const t = useTranslation()\n const prefs = useAnalyticsPrefs()\n const pref = prefs.cards[card.id] ?? {}\n const isCustom = prefs.custom.some((r) => r.id === card.id)\n\n const [name, setName] = React.useState(card.name)\n const measures = card.query.measures ?? []\n const dimensions = (card.query.dimensions ?? []).filter((d) => !d.hidden)\n\n const keptMeasures = new Set(pref.measures ?? measures.map((m) => m.key))\n const keptDimensions = new Set(pref.dimensions ?? dimensions.map((d) => d.key))\n\n const toggle = (set: Set<string>, key: string, field: 'measures' | 'dimensions', all: string[]) => {\n const next = new Set(set)\n if (next.has(key)) next.delete(key)\n else next.add(key)\n // Everything selected is the same as no preference — record it as one and\n // the card stops tracking a list it would have to keep in sync forever.\n setCardPref(card.id, { [field]: next.size === all.length ? undefined : [...next] })\n }\n\n return (\n // A coluna da direita, não uma gaveta só desta tela: ajustar um relatório é\n // olhar a lista enquanto se mexe nele, e uma gaveta cobre exatamente a\n // lista. É a mesma coluna do assistente — RightRailPage cai numa Sheet\n // sozinha quando a shell não tem coluna nenhuma.\n <RightRailPage title={card.name} open onClose={onClose} width=\"max-w-md\">\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">\n <div className=\"space-y-5\">\n {card.description ? (\n <p className=\"text-sm text-muted-foreground\">{card.description}</p>\n ) : null}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.name')}</label>\n <Input\n value={name}\n onChange={(e) => setName(e.target.value)}\n onBlur={() => setCardPref(card.id, { name: name.trim() && name !== card.name ? name.trim() : undefined })}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.viz')}</label>\n <Select\n value={card.viz.type}\n onValueChange={(value) => setCardPref(card.id, { viz: value as AnalyticsVizType })}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {vizOptionsFor(card).map((viz) => (\n <SelectItem key={viz} value={viz}>{t(`reports.viz.${viz}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {dimensions.length > 0 ? (\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.dimensions')}</p>\n {dimensions.map((d) => (\n <label key={d.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n checked={keptDimensions.has(d.key)}\n onChange={() => toggle(keptDimensions, d.key, 'dimensions', dimensions.map((x) => x.key))}\n />\n {d.label}\n </label>\n ))}\n </div>\n ) : null}\n\n {measures.length > 0 ? (\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.measures')}</p>\n {measures.map((m) => (\n <label key={m.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n checked={keptMeasures.has(m.key)}\n onChange={() => toggle(keptMeasures, m.key, 'measures', measures.map((x) => x.key))}\n />\n {m.label}\n </label>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n\n {/* Sem \"Salvar\": cada controle grava ao mudar, e a coluna reflete o\n resultado atrás dela. O rodapé guarda só a saída — o desfazer. */}\n <div className=\"flex items-center justify-between border-t border-border p-3\">\n {isCustom ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { deleteCustomReport(card.id); onClose() }}>\n <Trash2 className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.delete')}\n </Button>\n ) : (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { clearCardPref(card.id); onClose() }}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.resetCard')}\n </Button>\n )}\n <Button size=\"sm\" onClick={onClose}>{t('reports.settings.done')}</Button>\n </div>\n </RightRailPage>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Builder — a new report over a source the app already exposes\n// ---------------------------------------------------------------------------\n\nfunction slugify(value: string): string {\n return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'report'\n}\n\n/** Build a stored report from validated pieces. Shared by the form and by the\n * assistant's tool, so both produce the same object. */\nexport function buildCustomReport(input: {\n name: string\n category: string\n createdBy?: string\n source: AnalyticsSourceGroup\n dimensions: string[]\n measures: string[]\n viz: AnalyticsVizType\n}): CustomReport {\n const dimensionKeys = new Set(input.source.dimensions.map((d) => d.key))\n const measureKeys = new Set(input.source.measures.map((m) => m.key))\n return {\n id: `custom.${slugify(input.name)}-${Date.now().toString(36)}`,\n name: input.name.trim(),\n category: input.category.trim() || 'Geral',\n icon: 'FileText',\n createdBy: input.createdBy,\n baseId: input.source.base.id,\n // Filtered, not trusted: a field the source does not have would resolve to\n // nothing and the report would open empty with no explanation.\n dimensions: input.dimensions.filter((k) => dimensionKeys.has(k)),\n measures: input.measures.filter((k) => measureKeys.has(k)),\n viz: input.viz,\n createdAt: new Date().toISOString(),\n }\n}\n\nfunction NewReportPanel({\n sources, categories, onClose,\n}: { sources: AnalyticsSourceGroup[]; categories: string[]; onClose: () => void }) {\n const t = useTranslation()\n const { createdBy } = useAnalyticsConfig()\n\n const [name, setName] = React.useState('')\n const [category, setCategory] = React.useState(categories[0] ?? 'Geral')\n const [sourceKeyState, setSourceKey] = React.useState(sources[0]?.key ?? '')\n const [dimensions, setDimensions] = React.useState<string[]>([])\n const [measures, setMeasures] = React.useState<string[]>([])\n const [viz, setViz] = React.useState<AnalyticsVizType>('table')\n\n const source = sources.find((s) => s.key === sourceKeyState)\n\n // Switching source invalidates every field picked from the old one.\n React.useEffect(() => { setDimensions([]); setMeasures([]) }, [sourceKeyState])\n\n const toggle = (list: string[], set: (next: string[]) => void, key: string) => {\n set(list.includes(key) ? list.filter((k) => k !== key) : [...list, key])\n }\n\n const error = !name.trim()\n ? t('reports.settings.needName')\n : measures.length === 0\n ? t('reports.settings.needMeasure')\n : null\n\n const submit = () => {\n if (error || !source) return\n saveCustomReport(buildCustomReport({\n name, category, createdBy, source, dimensions, measures, viz,\n }))\n onClose()\n }\n\n return (\n <RightRailPage title={t('reports.settings.new')} open onClose={onClose} width=\"max-w-md\">\n <div className=\"min-h-0 flex-1 overflow-y-auto p-4\">\n <div className=\"space-y-5\">\n {/* Só o caminho manual. \"Criar com IA\" mora na barra do cabeçalho, ao\n lado do botão que abre este painel — duas portas para a mesma sala,\n uma dentro da outra, é o desenho que faz a de fora parecer inútil. */}\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.name')}</label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.category')}</label>\n <Input value={category} onChange={(e) => setCategory(e.target.value)} list=\"fayz-analytics-categories\" />\n <datalist id=\"fayz-analytics-categories\">\n {categories.map((c) => <option key={c} value={c} />)}\n </datalist>\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.source')}</label>\n <Select value={sourceKeyState} onValueChange={setSourceKey}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {sources.map((s) => (\n <SelectItem key={s.key} value={s.key}>{s.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-xs text-muted-foreground\">{t('reports.settings.sourceHint')}</p>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.dimensions')}</p>\n {(source?.dimensions ?? []).length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">—</p>\n ) : source!.dimensions.map((d) => (\n <label key={d.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox checked={dimensions.includes(d.key)} onChange={() => toggle(dimensions, setDimensions, d.key)} />\n {d.label}\n </label>\n ))}\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.measures')}</p>\n {(source?.measures ?? []).map((m) => (\n <label key={m.key} className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <Checkbox checked={measures.includes(m.key)} onChange={() => toggle(measures, setMeasures, m.key)} />\n {m.label}\n </label>\n ))}\n </div>\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('reports.settings.viz')}</label>\n <Select value={viz} onValueChange={(value) => setViz(value as AnalyticsVizType)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {(dimensions.length > 0 ? VIZ_TYPES : (['kpi', 'table'] as AnalyticsVizType[])).map((v) => (\n <SelectItem key={v} value={v}>{t(`reports.viz.${v}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-2 border-t border-border p-3\">\n <span className=\"truncate text-xs text-destructive\">{error}</span>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose}>{t('reports.settings.cancel')}</Button>\n <Button size=\"sm\" onClick={submit} disabled={Boolean(error)}>{t('reports.settings.save')}</Button>\n </div>\n </div>\n </RightRailPage>\n )\n}\n\n// ---------------------------------------------------------------------------\n// The assistant's way in\n//\n// Choosing a source, then dimensions, then measures is exactly the work someone\n// who already knows what they want should not have to do — and it is the work a\n// model does well GIVEN THE FIELD TABLE, which is why `describe()` below ships\n// every source with its askable fields rather than a prose summary.\n//\n// Client-plane on purpose: a custom report is a per-browser preference, not a\n// row in the tenant. The executor is the same `buildCustomReport` the form\n// calls, so a report built by conversation and one built by clicking are the\n// same object with the same guarantees.\n// ---------------------------------------------------------------------------\n\nconst CREATE_REPORT_TOOL: PluginAITool = {\n id: 'reports.createAnalyticsReport',\n name: 'createAnalyticsReport',\n description:\n 'Creates a custom analytics report for this user. Pick ONE source from the `sources` list in the surface state, then group_by and measures USING ONLY that source\\'s field keys — a key from another source resolves to nothing and the report opens empty. '\n + 'Understand the intent and propose the whole report in one call instead of asking field by field. '\n + 'Rules of thumb: one time dimension + one measure reads best as a line; a category dimension with one measure as bar or breakdown; three or more measures as a table; no dimension at all as a kpi.',\n icon: 'FileText',\n mode: 'persist',\n execution: { plane: 'client' },\n category: 'Analytics',\n suggestions: [\n { label: 'Um relatório de receita por mesa' },\n { label: 'Quanto cada praça produz por turno' },\n ],\n parameters: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Report name, in the user\\'s language.' },\n source: { type: 'string', description: 'A `key` from the surface state\\'s `sources`.' },\n group_by: {\n type: 'array',\n description: 'Dimension keys from that source. Empty means a single headline number.',\n items: { type: 'string' },\n },\n measures: {\n type: 'array',\n description: 'Measure keys from that source. At least one.',\n items: { type: 'string' },\n },\n viz: {\n type: 'string',\n enum: ['kpi', 'line', 'bar', 'area', 'donut', 'breakdown', 'table'],\n description: 'How to draw it. Defaults to table.',\n },\n category: { type: 'string', description: 'Group it sits under in the rail. Reuse an existing one when it fits.' },\n pin: { type: 'boolean', description: 'Also place it on the overview grid.' },\n },\n required: ['name', 'source', 'measures'],\n },\n}\n\nconst AGENT_INSTRUCTIONS =\n 'The user is on the report configuration screen. `sources` in the surface state lists every data source with the exact dimension and measure keys askable of it — use those keys verbatim. '\n + 'When they describe a report, call createAnalyticsReport once with the full shape; do not interview them field by field. '\n + 'Name the report the way they said it. After creating, say in one line what it groups by and what it measures.'\n\n// ---------------------------------------------------------------------------\n// Page\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsSettingsPage() {\n const t = useTranslation()\n const { labels } = useAnalyticsConfig()\n const catalogue = useAnalyticsCatalogue()\n const cards = useAnalyticsCards()\n const prefs = useAnalyticsPrefs()\n\n const { createdBy } = useAnalyticsConfig()\n const [editing, setEditing] = React.useState<string | null>(null)\n const [creating, setCreating] = React.useState(false)\n const [dragId, setDragId] = React.useState<string | null>(null)\n\n // A copy com que o assistente abre quando o handoff parte DESTA tela. Sem\n // ela o painel abre falando do que a tela oferecia antes (\"pergunte sobre\n // produção, cardápio e movimento\"), que é verdade e não é o assunto.\n const askIntro = React.useMemo<AskAIIntro>(() => ({\n role: 'setup',\n persona: t('reports.settings.askPersona'),\n pitch: t('reports.settings.askPitch'),\n description: t('reports.settings.askDescription'),\n suggestions: [0, 1, 2].map((i) => ({ label: t(`reports.settings.askSuggestion.${i}`) })),\n }), [t])\n\n const createActions = React.useMemo<PluginQuickAction[]>(() => [\n {\n id: 'with-ai',\n label: t('assistant.askAI'),\n description: t('reports.settings.newWithAIHint'),\n icon: 'WandSparkles',\n highlight: true,\n action: () => askAI({ hint: t('reports.settings.askPlaceholder'), intro: askIntro }),\n },\n {\n id: 'by-hand',\n label: t('reports.settings.newByHand'),\n description: t('reports.settings.newByHandHint'),\n icon: 'SlidersHorizontal',\n action: () => setCreating(true),\n },\n ], [t, askIntro])\n\n const sources = React.useMemo(() => analyticsSources(cards), [cards])\n const categories = React.useMemo(\n () => [...new Set(cards.map((c) => c.category))].sort((a, b) => a.localeCompare(b)),\n [cards],\n )\n\n const pinned = React.useMemo(\n () => cards.filter((c) => c.dashboard).sort((a, b) => (a.dashboard?.order ?? 0) - (b.dashboard?.order ?? 0)),\n [cards],\n )\n const unpinned = React.useMemo(\n () => cards.filter((c) => !c.dashboard).sort((a, b) => a.category.localeCompare(b.category) || a.name.localeCompare(b.name)),\n [cards],\n )\n // Removed built-ins live nowhere else — without this section a card taken out\n // of the catalogue can never be found again.\n const removed = React.useMemo(\n () => catalogue.filter((c) => prefs.cards[c.id]?.hidden),\n [catalogue, prefs],\n )\n\n // Live order during a drag: the committed order only moves on drop, so the\n // list under the cursor is state, not props.\n const [order, setOrder] = React.useState<string[] | null>(null)\n const pinnedIds = order ?? pinned.map((c) => c.id)\n const pinnedInOrder = pinnedIds\n .map((id) => pinned.find((c) => c.id === id))\n .filter((c): c is AnalyticsCardDef => Boolean(c))\n\n const move = (id: string, delta: number) => {\n const ids = pinned.map((c) => c.id)\n const from = ids.indexOf(id)\n const to = from + delta\n if (from < 0 || to < 0 || to >= ids.length) return\n ids.splice(to, 0, ids.splice(from, 1)[0]!)\n setOverviewOrder(ids)\n }\n\n const onDragOver = (targetId: string) => (event: React.DragEvent) => {\n event.preventDefault()\n if (!dragId || dragId === targetId) return\n const ids = [...pinnedIds]\n const from = ids.indexOf(dragId)\n const to = ids.indexOf(targetId)\n if (from < 0 || to < 0) return\n ids.splice(to, 0, ids.splice(from, 1)[0]!)\n setOrder(ids)\n }\n\n const commitDrag = () => {\n if (order) setOverviewOrder(order)\n setOrder(null)\n setDragId(null)\n }\n\n const editingCard = cards.find((c) => c.id === editing)\n const isCustom = (id: string) => prefs.custom.some((r) => r.id === id)\n\n // --- assistant surface ---------------------------------------------------\n // Read through a ref: `useAgentSurface` registers once and calls back later,\n // so a captured `sources` would go stale the moment a report is added.\n const surfaceRef = React.useRef({ sources, categories, cards, prefs, createdBy })\n surfaceRef.current = { sources, categories, cards, prefs, createdBy }\n\n const agentSurface = React.useMemo<AgentSurfaceContribution>(() => ({\n id: 'analytics.reports',\n pluginId: 'reports',\n instructions: AGENT_INSTRUCTIONS,\n describe: () => {\n const o = surfaceRef.current\n return {\n title: 'Configuração de relatórios',\n state: {\n sources: o.sources.map((source) => ({\n key: source.key,\n label: source.label,\n grain: source.base.grain ?? null,\n group_by: source.dimensions.map((d) => ({ key: d.key, label: d.label })),\n measures: source.measures.map((m) => ({ key: m.key, label: m.label, format: m.format ?? 'number' })),\n })),\n categories: o.categories,\n onOverview: o.cards.filter((c) => c.dashboard).map((c) => c.name),\n yourReports: o.prefs.custom.map((r) => r.name),\n },\n }\n },\n tools: [{\n tool: CREATE_REPORT_TOOL,\n execute: (args) => {\n const o = surfaceRef.current\n const source = o.sources.find((s) => s.key === args.source)\n ?? o.sources.find((s) => s.label === args.source)\n if (!source) {\n return { ok: false, error: 'unknown_source', sources: o.sources.map((s) => s.key) }\n }\n const report = buildCustomReport({\n name: String(args.name ?? '').trim() || 'Relatório',\n category: String(args.category ?? o.categories[0] ?? 'Geral'),\n createdBy: o.createdBy,\n source,\n dimensions: Array.isArray(args.group_by) ? (args.group_by as string[]) : [],\n measures: Array.isArray(args.measures) ? (args.measures as string[]) : [],\n viz: (args.viz as AnalyticsVizType) ?? 'table',\n })\n if (report.measures.length === 0) {\n return {\n ok: false,\n error: 'no_valid_measure',\n available: source.measures.map((m) => m.key),\n }\n }\n saveCustomReport(report)\n if (args.pin) setCardPref(report.id, { pinned: true, order: 999 })\n // Land on the thing that was just built: a report created and left\n // unopened is a claim the user has to go verify.\n navigateAnalytics(`${REPORTS_BASE}/${encodeURIComponent(report.id)}`)\n return {\n ok: true,\n id: report.id,\n name: report.name,\n group_by: report.dimensions,\n measures: report.measures,\n viz: report.viz,\n }\n },\n }],\n }), [])\n useAgentSurface(agentSurface)\n\n return (\n <div className=\"space-y-4\">\n <SubpageHeader\n title={t('reports.settings.title')}\n parentLabel={labels.analytics}\n onBack={() => navigateAnalytics(ANALYTICS_BASE)}\n />\n\n {/* Na barra da shell, junto do título — é onde toda tela do produto põe\n a sua ação principal. Numa faixa própria logo abaixo, elas abriam uma\n segunda barra de cabeçalho dizendo respeito à mesma página.\n \"Criar com IA\" é a PRIMÁRIA e o formulário fica em `outline`: descrever\n o relatório é o caminho curto, e enterrá-lo dentro do painel do\n caminho longo é escondê-lo atrás do que ele existe para evitar. */}\n <PageHeaderActions>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => resetAnalyticsPrefs()}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.reset')}\n </Button>\n {/* O mesmo menu de \"novo\" que o resto do produto usa (QuickActionsButton):\n ícone em ladrilho, rótulo e uma linha do que aquilo faz. A entrada de\n IA vai `highlight` — ver PluginQuickAction. */}\n <QuickActionsButton label={t('reports.settings.new')} variant=\"default\" actions={createActions} />\n </PageHeaderActions>\n\n <p className=\"max-w-2xl text-sm text-muted-foreground\">{t('reports.settings.subtitle')}</p>\n\n <Card className=\"overflow-hidden\">\n <div className=\"border-b border-border px-3 py-2\">\n <p className=\"text-sm font-medium\">{t('reports.settings.onOverview')}</p>\n <p className=\"text-xs text-muted-foreground\">{t('reports.settings.onOverviewHint')}</p>\n </div>\n {pinnedInOrder.length === 0 ? (\n <p className=\"px-3 py-6 text-center text-sm text-muted-foreground\">{t('reports.settings.empty')}</p>\n ) : (\n <ul>\n {pinnedInOrder.map((card, index) => (\n <ReportRow\n key={card.id}\n card={card}\n custom={isCustom(card.id)}\n onEdit={() => setEditing(card.id)}\n drag={{\n dragging: dragId === card.id,\n onDragStart: () => setDragId(card.id),\n onDragOver: onDragOver(card.id),\n onDragEnd: commitDrag,\n }}\n >\n <Select\n value={String(card.dashboard?.span ?? '')}\n onValueChange={(value) => setCardPref(card.id, { span: Number(value) as 1 | 2 | 3 | 4 })}\n >\n <SelectTrigger className=\"h-8 w-[150px]\">\n <SelectValue placeholder={t('reports.settings.width')} />\n </SelectTrigger>\n <SelectContent>\n {[1, 2, 3, 4].map((span) => (\n <SelectItem key={span} value={String(span)}>{t(`reports.settings.width.${span}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Button\n variant=\"ghost\" size=\"sm\" disabled={index === 0}\n onClick={() => move(card.id, -1)} aria-label={t('reports.settings.up')} title={t('reports.settings.up')}\n >\n <ChevronUp className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\" disabled={index === pinnedInOrder.length - 1}\n onClick={() => move(card.id, 1)} aria-label={t('reports.settings.down')} title={t('reports.settings.down')}\n >\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => setCardPref(card.id, { pinned: false })}\n aria-label={t('reports.settings.unpin')} title={t('reports.settings.unpin')}\n >\n <EyeOff className=\"h-3.5 w-3.5\" />\n </Button>\n </ReportRow>\n ))}\n </ul>\n )}\n </Card>\n\n <Card className=\"overflow-hidden\">\n <div className=\"border-b border-border px-3 py-2\">\n <p className=\"text-sm font-medium\">{t('reports.settings.offOverview')}</p>\n <p className=\"text-xs text-muted-foreground\">{t('reports.settings.offOverviewHint')}</p>\n </div>\n <ul>\n {unpinned.map((card) => (\n <ReportRow key={card.id} card={card} custom={isCustom(card.id)} onEdit={() => setEditing(card.id)}>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => setCardPref(card.id, { pinned: true, order: pinned.length })}\n aria-label={t('reports.settings.pin')} title={t('reports.settings.pin')}\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </Button>\n {isCustom(card.id) ? (\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => deleteCustomReport(card.id)}\n aria-label={t('reports.settings.delete')} title={t('reports.settings.delete')}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n ) : (\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => setCardPref(card.id, { hidden: true })}\n aria-label={t('reports.settings.remove')} title={t('reports.settings.remove')}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </ReportRow>\n ))}\n </ul>\n </Card>\n\n {removed.length > 0 ? (\n <Card className=\"overflow-hidden\">\n <div className=\"border-b border-border px-3 py-2\">\n <p className=\"text-sm font-medium\">{t('reports.settings.hidden')}</p>\n </div>\n <ul>\n {removed.map((card) => (\n <li key={card.id} className=\"flex items-center gap-2 border-b border-border/60 px-3 py-2 last:border-0\">\n <span className=\"w-4 shrink-0\" aria-hidden />\n <CardIcon name={card.icon} className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <span className=\"truncate text-sm text-muted-foreground\">{card.name}</span>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setCardPref(card.id, { hidden: undefined })}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n {t('reports.settings.restore')}\n </Button>\n </li>\n ))}\n </ul>\n </Card>\n ) : null}\n\n {editingCard ? <CardEditor card={editingCard} onClose={() => setEditing(null)} /> : null}\n {creating ? <NewReportPanel sources={sources} categories={categories} onClose={() => setCreating(false)} /> : null}\n </div>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { ReportColumnDef } from '../types'\nimport { exportToCsv } from '../export/csv'\nimport { exportToExcel } from '../export/excel'\nimport { exportToPdf } from '../export/pdf'\n\n// ---------------------------------------------------------------------------\n// The client half of the report engine (PRD 08).\n//\n// The catalogue, the permission and the query live in the database — the engine\n// refuses BEFORE it reads a row, and it records the refusal, because \"empty\" and\n// \"you were not allowed to see it\" are different answers. This module is what\n// carries that answer to a screen and, when asked, into a file.\n//\n// The three exporters already existed and had nothing to export from: they took\n// columns and rows from whatever a screen happened to hold. Now they take what\n// the engine actually returned, with the definition's own column list.\n// ---------------------------------------------------------------------------\n\nexport type ReportFormat = 'csv' | 'xlsx' | 'pdf'\n\nexport interface ReportRunResult {\n key: string\n version: number\n title: string\n /** 'ok' or 'refused' — a refusal reads no rows and is recorded server-side. */\n status: 'ok' | 'refused'\n requiredPermission?: string\n columns: ReportColumnDef[]\n rows: Record<string, any>[]\n rowCount: number\n}\n\nfunction db() {\n const client = getSupabaseClientOptional() as any\n if (!client) throw new Error('Supabase client is not configured')\n return client\n}\n\n/** Run a report from the catalogue. Throws only on a real error — a refusal comes back as data. */\nexport async function runReport(\n key: string,\n params: Record<string, unknown> = {},\n options?: { limit?: number; offset?: number; format?: ReportFormat },\n): Promise<ReportRunResult> {\n const { data, error } = await db().rpc('reports_run', {\n p_key: key,\n p_params: params,\n p_limit: options?.limit ?? 1000,\n p_offset: options?.offset ?? 0,\n p_format: options?.format ?? null,\n })\n if (error) throw new Error(error.message)\n\n const r = (data ?? {}) as Record<string, any>\n return {\n key: r.key ?? key,\n version: Number(r.version) || 1,\n title: r.title ?? key,\n status: r.status === 'refused' ? 'refused' : 'ok',\n requiredPermission: r.required_permission ?? undefined,\n columns: (r.columns ?? []) as ReportColumnDef[],\n rows: (r.rows ?? []) as Record<string, any>[],\n rowCount: Number(r.row_count) || 0,\n }\n}\n\n/**\n * Run it and hand the result to the exporter for the format.\n *\n * A refusal exports NOTHING and says so. Writing an empty spreadsheet for\n * someone who was not allowed to see the data is the version of this that looks\n * like a bug in the report.\n */\nexport async function runAndExportReport(\n key: string,\n format: ReportFormat,\n params: Record<string, unknown> = {},\n options?: { limit?: number; filename?: string; currency?: string },\n): Promise<ReportRunResult> {\n const result = await runReport(key, params, { limit: options?.limit ?? 5000, format })\n if (result.status === 'refused') return result\n\n const filename = options?.filename ?? `${result.key}-${new Date().toISOString().slice(0, 10)}`\n const columns = result.columns.length > 0\n ? result.columns\n // A definition that declared no columns still exports: the keys of the\n // first row are a worse header than a curated list, and a better one than\n // nothing.\n : Object.keys(result.rows[0] ?? {}).map((key) => ({ key, label: key } as ReportColumnDef))\n\n if (format === 'csv') exportToCsv(columns, result.rows, filename, options?.currency)\n else if (format === 'xlsx') await exportToExcel(columns, result.rows, filename, options?.currency)\n else await exportToPdf(columns, result.rows, filename, { title: result.title, currency: options?.currency })\n\n return result\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { ReportDef, ReportQueryState } from '../types'\nimport type { ReportDataProvider, ReportResult } from './types'\n\n// ---------------------------------------------------------------------------\n// Case conversion\n// ---------------------------------------------------------------------------\n\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (c) => '_' + c.toLowerCase())\n}\n\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase())\n}\n\nfunction mapRow(row: Record<string, unknown>, columnMap?: Record<string, string>): Record<string, any> {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n const camelKey = columnMap?.[key] ?? snakeToCamel(key)\n result[camelKey] = value\n }\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Provider factory\n// ---------------------------------------------------------------------------\n\nexport interface SupabaseReportProviderConfig {\n tenantId: string | (() => string | undefined)\n tenantIdColumn?: string\n schema?: string\n}\n\nexport function createSupabaseReportProvider(config: SupabaseReportProviderConfig): ReportDataProvider {\n const schema = config.schema ?? 'public'\n const tenantIdCol = config.tenantIdColumn ?? 'tenant_id'\n\n function resolveTenantId(): string | undefined {\n return typeof config.tenantId === 'function' ? config.tenantId() : config.tenantId\n }\n\n function getClient() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase client not available')\n return schema === 'public' ? supabase : supabase.schema(schema)\n }\n\n return {\n async fetch(reportDef: ReportDef, query: ReportQueryState): Promise<ReportResult> {\n const { dataSource } = reportDef\n const columnMap = dataSource.columnMap\n\n if (dataSource.kind === 'rpc') {\n return fetchViaRpc(reportDef, query, getClient, resolveTenantId, columnMap)\n }\n\n return fetchViaView(reportDef, query, getClient, resolveTenantId, tenantIdCol, columnMap)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// View-based fetch\n// ---------------------------------------------------------------------------\n\nasync function fetchViaView(\n reportDef: ReportDef,\n query: ReportQueryState,\n getClient: () => any,\n resolveTenantId: () => string | undefined,\n tenantIdCol: string,\n columnMap?: Record<string, string>,\n): Promise<ReportResult> {\n const { dataSource } = reportDef\n let q = getClient().from(dataSource.name).select('*', { count: 'exact' })\n\n // Tenant scoping\n const tenantId = resolveTenantId()\n if (tenantId) {\n q = q.eq(tenantIdCol, tenantId)\n }\n\n // Date range\n const dateCol = dataSource.dateColumn ?? 'created_at'\n if (query.dateRange.from) {\n q = q.gte(dateCol, query.dateRange.from)\n }\n if (query.dateRange.to) {\n // For date-type columns, plain date string is sufficient.\n // For timestamptz columns, extend to end of day.\n const toValue = dateCol === 'created_at' || dateCol.endsWith('_at')\n ? query.dateRange.to + 'T23:59:59'\n : query.dateRange.to\n q = q.lte(dateCol, toValue)\n }\n\n // Custom filters\n for (const [key, value] of Object.entries(query.filters)) {\n if (value == null || value === '') continue\n const col = camelToSnake(key)\n if (Array.isArray(value)) {\n q = q.in(col, value)\n } else {\n q = q.eq(col, value)\n }\n }\n\n // Search\n if (query.search) {\n const searchableCols = reportDef.columns\n .filter((c) => c.type === 'text' || c.type === 'email' || c.type === 'person')\n .map((c: any) => camelToSnake(c.key))\n if (searchableCols.length > 0) {\n const term = `%${query.search}%`\n const orClause = searchableCols.map((col) => `${col}.ilike.${term}`).join(',')\n q = q.or(orClause)\n }\n }\n\n // Sort\n const sortCol = query.sortBy\n ? camelToSnake(query.sortBy)\n : dataSource.defaultSort\n ? camelToSnake(dataSource.defaultSort)\n : dateCol\n const ascending = query.sortDir\n ? query.sortDir === 'asc'\n : dataSource.defaultSortDir\n ? dataSource.defaultSortDir === 'asc'\n : false\n q = q.order(sortCol, { ascending })\n\n // Pagination\n const from = (query.page - 1) * query.pageSize\n const to = from + query.pageSize - 1\n q = q.range(from, to)\n\n const { data, error, count } = await q\n\n if (error) throw error\n\n return {\n data: (data ?? []).map((row: any) => mapRow(row, columnMap)),\n total: count ?? 0,\n }\n}\n\n// ---------------------------------------------------------------------------\n// RPC-based fetch\n// ---------------------------------------------------------------------------\n\nasync function fetchViaRpc(\n reportDef: ReportDef,\n query: ReportQueryState,\n getClient: () => any,\n resolveTenantId: () => string | undefined,\n columnMap?: Record<string, string>,\n): Promise<ReportResult> {\n const { dataSource } = reportDef\n const tenantId = resolveTenantId()\n\n const params: Record<string, any> = {\n p_tenant_id: tenantId,\n p_from: query.dateRange.from,\n p_to: query.dateRange.to,\n p_page: query.page,\n p_page_size: query.pageSize,\n }\n\n // Custom filters\n for (const [key, value] of Object.entries(query.filters)) {\n if (value == null || value === '') continue\n params[`p_${camelToSnake(key)}`] = value\n }\n\n if (query.sortBy) {\n params.p_sort_by = camelToSnake(query.sortBy)\n params.p_sort_dir = query.sortDir ?? 'desc'\n }\n\n const { data, error } = await getClient().rpc(dataSource.name, params)\n if (error) throw error\n\n // RPC expected to return { data: [...], total: number }\n if (data && typeof data === 'object' && 'data' in data) {\n return {\n data: (data.data ?? []).map((row: any) => mapRow(row, columnMap)),\n total: data.total ?? 0,\n }\n }\n\n // Fallback: RPC returns a plain array\n const rows = Array.isArray(data) ? data : []\n return {\n data: rows.map((row: any) => mapRow(row, columnMap)),\n total: rows.length,\n }\n}\n","import type { ReportDataProvider } from './types'\n\nexport function createMockReportProvider(): ReportDataProvider {\n return {\n async fetch() {\n return { data: [], total: 0 }\n },\n }\n}\n","import React from 'react'\nimport type {\n PluginManifest, PluginScope, VerticalId, AnalyticsCardDef, AnalyticsProvider, AnalyticsCompare,\n} from '@fayz-ai/core'\nimport type { AnalyticsRangePreset } from '@fayz-ai/ui'\nimport { createSafeDataProvider, registerTranslations } from '@fayz-ai/core'\nimport { createSupabaseAnalyticsProvider } from './data/analytics-supabase'\nimport { createMockAnalyticsProvider } from './data/analytics-mock'\nimport { getReportsTenantId } from './lib/tenant'\nimport { reportsLocales } from './locales'\nimport { MIGRATIONS } from './migrations'\nimport { reportDefsToCards } from './lib/legacy'\nimport {\n AnalyticsSurface, ANALYTICS_BASE, REPORTS_BASE, SETTINGS_ROUTE,\n type AnalyticsLabels, type ResolvedAnalyticsConfig, type AnalyticsAssistantConfig,\n} from './views/AnalyticsSurface'\nimport { AnalyticsModule, type AnalyticsView } from './views/AnalyticsModule'\nimport { AnalyticsOverview } from './views/AnalyticsOverview'\nimport { ReportsListPage } from './views/ReportsListPage'\nimport { AnalyticsReportViewer } from './views/AnalyticsReportViewer'\nimport { LiveViewPage } from './views/LiveViewPage'\nimport { AnalyticsSettingsPage } from './views/AnalyticsSettingsPage'\nimport type { ReportsPluginOptions } from './types'\n\n// ---------------------------------------------------------------------------\n// Analytics — one engine, one door, several rooms.\n//\n// /analytics the general dashboard: the cards a pack placed\n// /analytics/reports the one list where a user finds what they want\n// /analytics/reports/:id a report, full size (chart AND rows)\n// /analytics/live real-time (stub, awaiting a storefront event stream)\n// /analytics/settings which reports, in what order, showing what\n//\n// ONE nav entry. Analytics and Reports used to be two top-level links to the\n// same engine — the app menu asked the user to choose a door before showing\n// what was behind either. Everything below /analytics now hangs off the module\n// rail (AnalyticsModule), where the report groups and the reports themselves\n// are the navigation.\n//\n// The package is still called plugin-reports so the six consuming apps keep\n// their imports; the CONCEPT it exposes is Analytics, with Reports as the\n// catalogue inside it.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_LABELS: AnalyticsLabels = {\n analytics: 'Analytics',\n reports: 'Reports',\n liveView: 'Live View',\n overviewSubtitle: 'Key metrics for your business',\n reportsSubtitle: 'Every report available to you',\n searchReports: 'Search reports',\n category: 'Category',\n createdBy: 'Created by',\n allCategories: 'All categories',\n allCreatedBy: 'All authors',\n lastViewed: 'Last viewed',\n name: 'Name',\n noResults: 'No results found.',\n never: '—',\n back: 'Back',\n export: 'Export',\n print: 'Print',\n unavailableTitle: 'Coming soon',\n unavailableDescription: 'This report is not connected to data yet. It will be enabled in a future update.',\n emptyOverviewTitle: 'No metrics yet',\n emptyOverviewDescription: 'Enable a plugin that contributes analytics cards, or add them to this app’s pack.',\n liveViewSoon: 'Real-time visitor and checkout activity will appear here once storefront events are being collected.',\n results: 'reports',\n}\n\nconst DEFAULT_CURRENCY = { code: 'BRL', locale: 'pt-BR', symbol: 'R$' }\n\nexport interface AnalyticsPluginOptions {\n /**\n * Cards the host app contributes or overrides. Cards owned by a plugin come\n * through the runtime registry automatically — this is for app-specific ones\n * and for retuning a plugin card by re-declaring its id.\n */\n cards?: AnalyticsCardDef[]\n /**\n * Legacy ReportDef catalogue. Still fully supported: each becomes a table\n * card in the report list. See lib/legacy.ts.\n */\n reports?: import('./types').ReportDef[]\n /** Attribution for pre-built cards — the product name, e.g. 'FayzShop'. */\n createdBy?: string\n labels?: Partial<AnalyticsLabels>\n currency?: { code?: string; locale?: string; symbol?: string }\n dataProvider?: AnalyticsProvider\n navPosition?: number\n navSection?: 'main' | 'secondary'\n scope?: PluginScope\n verticalId?: VerticalId\n defaultPageSize?: number\n /**\n * Render an in-content title above the page. Default: FALSE, matching\n * DashboardCanvas — the admin shell's top bar already names the page from the\n * active nav entry, so a title here prints the same word twice. Pass true\n * only where the surface is embedded with no chrome of its own.\n */\n showHeader?: boolean\n /** Register the Live View nav entry. Default: false while it is a stub. */\n showLiveView?: boolean\n /**\n * Range the surface opens on. Default 'last_30_days' — the common business\n * month. Set it where the domain's natural period differs (a school term, a\n * quarter), not to compensate for how much data a demo tenant happens to have.\n */\n defaultRange?: AnalyticsRangePreset\n defaultCompare?: AnalyticsCompare\n /**\n * The assistant's invitation on /analytics: a persona, a headline and the\n * questions worth asking here. Defaults come from the plugin's locales — pass\n * an object to retune the voice for a vertical, or `false` for an app whose\n * analytics screen should open on the numbers alone.\n */\n assistant?: false | AnalyticsAssistantConfig\n}\n\nfunction resolveConfig(options: AnalyticsPluginOptions): ResolvedAnalyticsConfig {\n const labels = { ...DEFAULT_LABELS, ...options.labels }\n const createdBy = options.createdBy ?? 'Fayz'\n return {\n labels,\n currency: { ...DEFAULT_CURRENCY, ...options.currency },\n createdBy,\n cards: [\n ...(options.cards ?? []),\n ...reportDefsToCards(options.reports ?? [], createdBy),\n ],\n defaultPageSize: options.defaultPageSize ?? 50,\n showHeader: options.showHeader === true,\n defaultRange: options.defaultRange ?? 'last_30_days',\n defaultCompare: options.defaultCompare ?? 'previous_period',\n showLiveView: options.showLiveView === true,\n assistant: options.assistant === false ? null : (options.assistant ?? {}),\n }\n}\n\nexport function createAnalyticsPlugin(options: AnalyticsPluginOptions = {}): PluginManifest {\n const config = resolveConfig(options)\n registerTranslations(reportsLocales)\n\n const provider: AnalyticsProvider = options.dataProvider ?? createSafeDataProvider(\n () => createSupabaseAnalyticsProvider({ tenantId: () => getReportsTenantId() }),\n () => createMockAnalyticsProvider(),\n )\n\n /**\n * Every page mounts inside the same surface AND the same module rail, so the\n * report tree is on screen wherever you are inside Analytics — and the app\n * nav never has to list a second Analytics entry to get you there.\n */\n const page = (Body: React.ComponentType<any>, view: AnalyticsView): React.FC<any> =>\n (props) => React.createElement(\n AnalyticsSurface,\n { config, provider },\n React.createElement(\n AnalyticsModule,\n { view, cardId: props?.cardId },\n React.createElement(Body, props),\n ),\n )\n\n const READ = { feature: 'reports', action: 'read' as const }\n const position = options.navPosition ?? 9\n const section = options.navSection ?? 'main'\n\n // One entry. Sub-paths of /analytics would be nested as children by the shell\n // (findModuleParent) and drawn as a dropdown — which is the split this module\n // exists to remove.\n const nav = [\n {\n section, position,\n label: config.labels.analytics,\n route: ANALYTICS_BASE,\n icon: 'BarChart3',\n permission: READ,\n },\n ]\n\n return {\n id: 'reports',\n defaultAgentRole: 'growth',\n name: config.labels.analytics,\n icon: 'BarChart3',\n version: '2.0.0',\n scope: options.scope ?? 'universal',\n verticalId: options.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [\n { id: 'reports', label: config.labels.analytics, group: config.labels.analytics },\n ],\n navigation: nav,\n routes: [\n { path: ANALYTICS_BASE, component: page(AnalyticsOverview, 'overview'), permission: READ },\n { path: REPORTS_BASE, component: page(ReportsListPage, 'reports'), permission: READ },\n // Registered before the list would ever shadow it: matchRoute scores\n // static segments above params, so /analytics/reports still wins its own\n // exact path and only /analytics/reports/<id> lands here.\n // No `parentRoute` here on purpose: the viewer's title depends on DATA\n // (the card's name), so it claims the shell bar itself via PageHeader.\n // Declaring both gave the page two stacked back-crumbs saying the same\n // thing, one of them generic.\n { path: `${REPORTS_BASE}/:cardId`, component: page(AnalyticsReportViewer, 'report'), permission: READ },\n { path: `${ANALYTICS_BASE}/live`, component: page(LiveViewPage, 'live'), permission: READ },\n // Read permission on purpose: the screen writes a per-user preference,\n // not tenant data — gating it behind a write scope would mean a viewer\n // cannot choose which of the reports they can see are on their overview.\n { path: SETTINGS_ROUTE, component: page(AnalyticsSettingsPage, 'settings'), permission: READ },\n // The old top-level route kept as a redirect target: bookmarks, saved\n // links and the five apps still pointing at /reports must not 404.\n { path: '/reports', component: page(ReportsListPage, 'reports'), permission: READ },\n ],\n widgets: [],\n registries: [],\n // Measurement, not acquisition — what the Fayz plugin page lists for\n // Analytics.\n integrations: ['google-analytics', 'hotjar'],\n // The engine, at last (Phase 2, PRD 08). This package shipped ZERO\n // migrations until now: a package and a screen, never a catalogue of\n // versioned definitions with a declared permission, a run history and an\n // export. Without them \"report\" meant \"a query somebody wrote into a\n // screen\", which is how a report ships with no authorization rule by simple\n // forgetfulness.\n migrations: MIGRATIONS.map((m) => ({\n id: `reports-${m.id}`,\n version: '1.0.0',\n sql: m.sql,\n description: m.id,\n })),\n locales: reportsLocales,\n }\n}\n\n/**\n * @deprecated Prefer `createAnalyticsPlugin`. Kept so the apps that call\n * `createReportsPlugin({ reports: [...] })` keep working unchanged — the legacy\n * `reports` option is still first-class and their catalogues need no rewrite.\n */\nexport function createReportsPlugin(options: ReportsPluginOptions): PluginManifest {\n return createAnalyticsPlugin({\n reports: options.reports,\n labels: {\n ...(options.labels?.pageTitle ? { analytics: options.labels.pageTitle } : {}),\n ...(options.labels?.pageSubtitle ? { overviewSubtitle: options.labels.pageSubtitle } : {}),\n },\n currency: options.currency,\n navPosition: options.navPosition,\n navSection: options.navSection,\n scope: options.scope,\n verticalId: options.verticalId,\n defaultPageSize: options.defaultPageSize,\n showHeader: options.showHeader,\n })\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports\n// ---------------------------------------------------------------------------\n\nexport {\n AnalyticsSurface, ANALYTICS_BASE, REPORTS_BASE, SETTINGS_ROUTE, cardColumns,\n useAnalyticsConfig, useAnalyticsCards, useAnalyticsCatalogue, useOverviewCards,\n} from './views/AnalyticsSurface'\nexport type {\n AnalyticsLabels, ResolvedAnalyticsConfig, AnalyticsAssistantConfig,\n} from './views/AnalyticsSurface'\nexport { AnalyticsModule } from './views/AnalyticsModule'\nexport type { AnalyticsView, AnalyticsModuleProps } from './views/AnalyticsModule'\nexport { AnalyticsOverview } from './views/AnalyticsOverview'\nexport { AnalyticsSettingsPage } from './views/AnalyticsSettingsPage'\nexport { ReportsListPage } from './views/ReportsListPage'\nexport { AnalyticsReportViewer } from './views/AnalyticsReportViewer'\nexport { reportDefToCard, reportDefsToCards } from './lib/legacy'\nexport { aggregateRows } from './data/aggregate'\nexport { createSupabaseAnalyticsProvider } from './data/analytics-supabase'\nexport type { SupabaseAnalyticsProviderConfig } from './data/analytics-supabase'\nexport { createMockAnalyticsProvider } from './data/analytics-mock'\nexport { markViewed, useLastViewed } from './lib/lastViewed'\nexport {\n useAnalyticsPrefs, resolveCards, resolveCustomReport, fieldPalette, sourceKey,\n setCardPref, clearCardPref, setOverviewOrder, saveCustomReport, deleteCustomReport,\n resetAnalyticsPrefs,\n} from './lib/preferences'\nexport type { AnalyticsPrefs, AnalyticsCardPref, CustomReport, FieldPalette } from './lib/preferences'\nexport { setReportsTenantId, getReportsTenantId } from './lib/tenant'\n\n// The report ENGINE (PRD 08): the catalogue, the permission and the query live\n// in the database; these carry the answer to a screen and into a file.\nexport { runReport, runAndExportReport } from './lib/engine'\nexport type { ReportFormat, ReportRunResult } from './lib/engine'\nexport { exportToCsv } from './export/csv'\nexport { exportToExcel } from './export/excel'\nexport { exportToPdf } from './export/pdf'\n\nexport type {\n ReportDef,\n ReportColumnDef,\n ReportFilterDef,\n ReportDateRange,\n ReportQueryState,\n ReportBadge,\n ReportDataSource,\n ReportGrain,\n ReportAllowedAction,\n ReportFilterOption,\n ReportsPluginOptions,\n ReportsPluginLabels,\n ResolvedReportsConfig,\n} from './types'\n\nexport type { ReportDataProvider, ReportResult } from './data/types'\nexport { createSupabaseReportProvider } from './data/supabase'\nexport type { SupabaseReportProviderConfig } from './data/supabase'\nexport { createMockReportProvider } from './data/mock'\n"]}