@burdenoff/microfe-assethandler 2026.826.13 → 2026.826.14

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.
@@ -1 +1 @@
1
- {"version":3,"file":"SamLicensesPage.js","names":[],"sources":["../../../src/assethandler/pages/SamLicensesPage.tsx"],"sourcesContent":["import {\n KeyRound,\n Plus,\n Search,\n Pencil,\n Layers,\n UserCheck,\n UserPlus,\n ShieldCheck,\n} from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport {\n Button,\n GradientText,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Pagination,\n usePagination,\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n ProgressMeter,\n} from '../components';\nimport { notify } from '../utils/toast';\nimport { cn } from '../utils/cn';\n\nconst SOFTWARE_ASSETS_QUERY = gql`\n query AssetHandlerSoftwareAssets {\n softwareAssets {\n id\n name\n vendor\n version\n licenseType\n seatsPurchased\n seatsUsed\n compliancePercent\n }\n }\n`;\n\nconst UPSERT_SOFTWARE_ASSET_MUTATION = gql`\n mutation AssetHandlerUpsertSoftwareAsset($input: UpsertSoftwareAssetInput!) {\n upsertSoftwareAsset(input: $input) {\n id\n name\n }\n }\n`;\n\ninterface SoftwareAsset {\n id: string;\n name: string;\n vendor: string;\n version: string;\n licenseType: string;\n seatsPurchased: number | null;\n seatsUsed: number | null;\n compliancePercent: number;\n}\n\ninterface UpsertSoftwareAssetResult {\n upsertSoftwareAsset: { id: string; name: string };\n}\n\nconst LICENSE_TYPES = [\n 'PERPETUAL',\n 'SUBSCRIPTION',\n 'CONCURRENT',\n 'NAMED_USER',\n 'OPEN_SOURCE',\n] as const;\n\nconst humanizeLicense = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nfunction NewSoftwareAssetDialog({\n open,\n onOpenChange,\n onSaved,\n editing,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSaved: () => void;\n editing: SoftwareAsset | null;\n}) {\n const [name, setName] = useState('');\n const [vendor, setVendor] = useState('');\n const [version, setVersion] = useState('');\n const [licenseType, setLicenseType] = useState<(typeof LICENSE_TYPES)[number]>('SUBSCRIPTION');\n const [seatsPurchased, setSeatsPurchased] = useState('');\n const [seatsUsed, setSeatsUsed] = useState('');\n\n // Prime the form when opening in edit mode.\n const [primedId, setPrimedId] = useState<string | null>(null);\n if (open && editing && primedId !== editing.id) {\n setPrimedId(editing.id);\n setName(editing.name);\n setVendor(editing.vendor);\n setVersion(editing.version);\n setLicenseType(\n (LICENSE_TYPES as readonly string[]).includes(editing.licenseType)\n ? (editing.licenseType as (typeof LICENSE_TYPES)[number])\n : 'SUBSCRIPTION'\n );\n setSeatsPurchased(editing.seatsPurchased != null ? String(editing.seatsPurchased) : '');\n setSeatsUsed(editing.seatsUsed != null ? String(editing.seatsUsed) : '');\n }\n if (open && !editing && primedId !== null) {\n setPrimedId(null);\n }\n\n const reset = () => {\n setName('');\n setVendor('');\n setVersion('');\n setLicenseType('SUBSCRIPTION');\n setSeatsPurchased('');\n setSeatsUsed('');\n setPrimedId(null);\n };\n\n const [upsertAsset, { loading }] = useMutation<UpsertSoftwareAssetResult>(\n UPSERT_SOFTWARE_ASSET_MUTATION,\n {\n onCompleted: (data) => {\n notify.success('Software asset saved', `${data.upsertSoftwareAsset.name} is now tracked.`);\n reset();\n onOpenChange(false);\n onSaved();\n },\n onError: (error) => notify.error('Could not save software asset', error.message),\n }\n );\n\n const handleSubmit = () => {\n if (!name.trim() || !vendor.trim() || !version.trim()) {\n notify.warning('Missing details', 'Name, vendor and version are required.');\n return;\n }\n const optionalInt = (value: string): number | null => {\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const parsed = Number(trimmed);\n return Number.isInteger(parsed) ? parsed : null;\n };\n void upsertAsset({\n variables: {\n input: {\n ...(editing ? { id: editing.id } : {}),\n name: name.trim(),\n vendor: vendor.trim(),\n version: version.trim(),\n licenseType,\n seatsPurchased: optionalInt(seatsPurchased),\n seatsUsed: optionalInt(seatsUsed),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {editing ? 'Edit Software Asset' : 'New Software Asset'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {editing\n ? 'Update this software entitlement and its seat allocation.'\n : 'Register a software entitlement to track license compliance.'}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Vendor *</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Version *</Label>\n <Input\n placeholder=\"e.g., 2026.1\"\n value={version}\n onChange={(e) => setVersion(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>License Type</Label>\n <Select\n value={licenseType}\n onValueChange={(v) => setLicenseType(v as typeof licenseType)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Seats Purchased</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsPurchased}\n onChange={(e) => setSeatsPurchased(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Seats Used</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsUsed}\n onChange={(e) => setSeatsUsed(e.target.value)}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? 'Saving…' : editing ? 'Save changes' : 'Save asset'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// Compliance bar cell — green when within entitlement, red when over-used.\nfunction ComplianceCell({ asset }: { asset: SoftwareAsset }) {\n const purchased = asset.seatsPurchased ?? 0;\n const used = asset.seatsUsed ?? 0;\n const overUsed = purchased > 0 && used > purchased;\n return (\n <div className=\"min-w-[140px]\">\n <ProgressMeter\n value={Math.min(100, Math.max(0, asset.compliancePercent))}\n max={100}\n higherIsWorse={false}\n size=\"sm\"\n showValue={false}\n />\n <p\n className={cn(\n 'mt-1 text-xs font-medium tabular-nums',\n overUsed ? 'text-status-error-text' : 'text-text-secondary'\n )}\n >\n {asset.compliancePercent.toFixed(1)}%{overUsed ? ' · over-used' : ''}\n </p>\n </div>\n );\n}\n\nexport function SamLicensesPage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [editing, setEditing] = useState<SoftwareAsset | null>(null);\n const [search, setSearch] = useState('');\n const [licenseFilter, setLicenseFilter] = useState<string>('all');\n const [sort, setSort] = useState<string>('compliance-asc');\n\n const { data, loading, refetch } = useQuery<{ softwareAssets: SoftwareAsset[] }>(\n SOFTWARE_ASSETS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n\n const softwareAssets = useMemo(() => data?.softwareAssets ?? [], [data]);\n\n // ─── KPI rollups (all real, derived from the fetched list) ───\n const kpis = useMemo(() => {\n let purchased = 0;\n let used = 0;\n for (const a of softwareAssets) {\n purchased += a.seatsPurchased ?? 0;\n used += a.seatsUsed ?? 0;\n }\n const available = Math.max(0, purchased - used);\n // Seats-weighted compliance (fallback to simple average).\n const totalWeight = softwareAssets.reduce((s, a) => s + (a.seatsPurchased ?? 0), 0);\n const compliance =\n totalWeight > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent * (a.seatsPurchased ?? 0), 0) /\n totalWeight\n : softwareAssets.length > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent, 0) / softwareAssets.length\n : 0;\n return { purchased, used, available, compliance };\n }, [softwareAssets]);\n\n const licenseTypeDonut = useMemo(() => {\n const counts = new Map<string, number>();\n for (const a of softwareAssets) counts.set(a.licenseType, (counts.get(a.licenseType) ?? 0) + 1);\n return [...counts.entries()].map(([type, value]) => ({\n name: humanizeLicense(type),\n value,\n }));\n }, [softwareAssets]);\n\n const seatsBars = useMemo(\n () =>\n [...softwareAssets]\n .sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0))\n .slice(0, 6)\n .map((a) => ({\n name: a.name.length > 18 ? a.name.slice(0, 17) + '…' : a.name,\n purchased: a.seatsPurchased ?? 0,\n used: a.seatsUsed ?? 0,\n })),\n [softwareAssets]\n );\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n const rows = softwareAssets.filter((a) => {\n if (licenseFilter !== 'all' && a.licenseType !== licenseFilter) return false;\n if (!q) return true;\n return a.name.toLowerCase().includes(q) || a.vendor.toLowerCase().includes(q);\n });\n const sorted = [...rows];\n switch (sort) {\n case 'compliance-asc':\n sorted.sort((a, b) => a.compliancePercent - b.compliancePercent);\n break;\n case 'compliance-desc':\n sorted.sort((a, b) => b.compliancePercent - a.compliancePercent);\n break;\n case 'seats-desc':\n sorted.sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0));\n break;\n case 'name-asc':\n sorted.sort((a, b) => a.name.localeCompare(b.name));\n break;\n default:\n break;\n }\n return sorted;\n }, [softwareAssets, search, licenseFilter, sort]);\n\n const pagination = usePagination(filtered, {\n pageSize: 12,\n resetKey: `${search}|${licenseFilter}|${sort}`,\n });\n\n const openCreate = () => {\n setEditing(null);\n setDialogOpen(true);\n };\n const openEdit = (asset: SoftwareAsset) => {\n setEditing(asset);\n setDialogOpen(true);\n };\n\n const hasCharts = softwareAssets.length > 0;\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-muted\">\n Software Asset Management (SAM / licenses)\n </p>\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <KeyRound className=\"h-6 w-6\" /> <GradientText>Software Asset Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Track entitlements against real usage and stay license-compliant.\n </p>\n </div>\n <Button className=\"w-full sm:w-auto\" onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n </div>\n <PagePurpose>\n Software Asset Management (SAM): track every software entitlement against actual usage so\n you stay license-compliant and stop paying for seats nobody uses. Spot over- and\n under-licensing here to avoid audit penalties and reclaim wasted spend.\n </PagePurpose>\n\n <NewSoftwareAssetDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSaved={() => void refetch()}\n editing={editing}\n />\n\n {/* ─── KPI rollups ─── */}\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <StatTile label=\"Total Licenses\" value={kpis.purchased} icon={Layers} hero />\n <StatTile label=\"Seats Used\" value={kpis.used} icon={UserCheck} />\n <StatTile label=\"Seats Available\" value={kpis.available} icon={UserPlus} />\n <StatTile\n label=\"Compliance\"\n value={kpis.compliance}\n format={(v) => `${v.toFixed(1)}%`}\n icon={ShieldCheck}\n deltaTone={kpis.compliance >= 90 ? 'positive' : 'negative'}\n />\n </div>\n\n {/* ─── Charts ─── */}\n {hasCharts ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Licenses by type\" subtitle=\"Entitlement mix\" icon={KeyRound}>\n <DonutChart\n data={licenseTypeDonut}\n height={240}\n centerLabel=\"products\"\n centerValue={softwareAssets.length}\n ariaLabel=\"Software assets by license type\"\n />\n </ChartCard>\n <ChartCard title=\"Seats: purchased vs used\" subtitle=\"Top products by entitlement\">\n <BarsChart\n data={seatsBars}\n xKey=\"name\"\n orientation=\"horizontal\"\n categoryWidth={120}\n height={240}\n series={[\n { key: 'purchased', label: 'Purchased' },\n { key: 'used', label: 'Used' },\n ]}\n ariaLabel=\"Seats purchased versus used per software product\"\n />\n </ChartCard>\n </div>\n ) : null}\n\n {/* ─── Filters ─── */}\n {softwareAssets.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n className=\"pl-9\"\n placeholder=\"Search software or vendor…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <Select value={licenseFilter} onValueChange={setLicenseFilter}>\n <SelectTrigger className=\"w-full sm:w-[170px]\">\n <SelectValue placeholder=\"License type\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All license types</SelectItem>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={sort} onValueChange={setSort}>\n <SelectTrigger className=\"w-full sm:w-[190px]\">\n <SelectValue placeholder=\"Sort\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compliance-asc\">Compliance: low → high</SelectItem>\n <SelectItem value=\"compliance-desc\">Compliance: high → low</SelectItem>\n <SelectItem value=\"seats-desc\">Most seats</SelectItem>\n <SelectItem value=\"name-asc\">Name A–Z</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </GlassCard>\n ) : null}\n\n {/* ─── Loading / Empty ─── */}\n {loading && softwareAssets.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-2 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {!loading && softwareAssets.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No software assets found\"\n description=\"Register a software asset to start tracking license compliance.\"\n action={\n <Button onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n }\n />\n ) : null}\n\n {softwareAssets.length > 0 && filtered.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching software\"\n description=\"Adjust your search or filters to see software assets.\"\n />\n ) : null}\n\n {/* ─── Table (desktop) + card list (mobile) ─── */}\n {filtered.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-xs uppercase tracking-wide text-text-secondary\">\n <th className=\"p-3 text-left font-semibold\">Software</th>\n <th className=\"p-3 text-left font-semibold\">Vendor</th>\n <th className=\"p-3 text-left font-semibold\">Version</th>\n <th className=\"p-3 text-left font-semibold\">License Type</th>\n <th className=\"p-3 text-right font-semibold\">Seats Purchased</th>\n <th className=\"p-3 text-right font-semibold\">Seats Used</th>\n <th className=\"p-3 text-left font-semibold\">Compliance</th>\n <th className=\"p-3 text-right font-semibold\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {pagination.pageItems.map((asset) => (\n <tr\n key={asset.id}\n className=\"cursor-pointer border-b border-border-seam hover:bg-bg-sunken/50\"\n onClick={() => openEdit(asset)}\n >\n <td className=\"max-w-[220px] truncate p-3 font-medium\" title={asset.name}>\n {asset.name}\n </td>\n <td className=\"p-3 text-text-secondary\">{asset.vendor}</td>\n <td className=\"p-3 text-text-secondary\">{asset.version}</td>\n <td className=\"p-3\">\n <span className=\"inline-flex items-center rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsPurchased ?? '—'}</td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsUsed ?? '—'}</td>\n <td className=\"p-3\">\n <ComplianceCell asset={asset} />\n </td>\n <td className=\"p-3 text-right\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n openEdit(asset);\n }}\n >\n <Pencil className=\"mr-1 h-3.5 w-3.5\" />\n Edit\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile card list */}\n <div className=\"divide-y divide-border-seam md:hidden\">\n {pagination.pageItems.map((asset) => (\n <div\n key={asset.id}\n className=\"cursor-pointer space-y-2 p-4\"\n onClick={() => openEdit(asset)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\" title={asset.name}>\n {asset.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {asset.vendor} · v{asset.version}\n </p>\n </div>\n <span className=\"shrink-0 rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-3 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">\n {asset.seatsUsed ?? 0} / {asset.seatsPurchased ?? '—'} seats\n </span>\n </div>\n <ComplianceCell asset={asset} />\n </div>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"software assets\"\n />\n </div>\n </GlassCard>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SamLicensesPage.js","names":[],"sources":["../../../src/assethandler/pages/SamLicensesPage.tsx"],"sourcesContent":["import {\n KeyRound,\n Plus,\n Search,\n Pencil,\n Layers,\n UserCheck,\n UserPlus,\n ShieldCheck,\n Trash2,\n} from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport {\n Button,\n GradientText,\n IllustratedEmptyState,\n GlassCard,\n PagePurpose,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport {\n Pagination,\n usePagination,\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n ProgressMeter,\n} from '../components';\nimport { notify } from '../utils/toast';\nimport { cn } from '../utils/cn';\n\nconst SOFTWARE_ASSETS_QUERY = gql`\n query AssetHandlerSoftwareAssets {\n softwareAssets {\n id\n name\n vendor\n version\n licenseType\n seatsPurchased\n seatsUsed\n compliancePercent\n }\n }\n`;\n\nconst UPSERT_SOFTWARE_ASSET_MUTATION = gql`\n mutation AssetHandlerUpsertSoftwareAsset($input: UpsertSoftwareAssetInput!) {\n upsertSoftwareAsset(input: $input) {\n id\n name\n }\n }\n`;\n\nconst DELETE_SOFTWARE_ASSET_MUTATION = gql`\n mutation AssetHandlerDeleteSoftwareAsset($id: ID!) {\n deleteSoftwareAsset(id: $id)\n }\n`;\n\ninterface SoftwareAsset {\n id: string;\n name: string;\n vendor: string;\n version: string;\n licenseType: string;\n seatsPurchased: number | null;\n seatsUsed: number | null;\n compliancePercent: number;\n}\n\ninterface UpsertSoftwareAssetResult {\n upsertSoftwareAsset: { id: string; name: string };\n}\n\nconst LICENSE_TYPES = [\n 'PERPETUAL',\n 'SUBSCRIPTION',\n 'CONCURRENT',\n 'NAMED_USER',\n 'OPEN_SOURCE',\n] as const;\n\nconst humanizeLicense = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nfunction NewSoftwareAssetDialog({\n open,\n onOpenChange,\n onSaved,\n editing,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSaved: () => void;\n editing: SoftwareAsset | null;\n}) {\n const [name, setName] = useState('');\n const [vendor, setVendor] = useState('');\n const [version, setVersion] = useState('');\n const [licenseType, setLicenseType] = useState<(typeof LICENSE_TYPES)[number]>('SUBSCRIPTION');\n const [seatsPurchased, setSeatsPurchased] = useState('');\n const [seatsUsed, setSeatsUsed] = useState('');\n\n // Prime the form when opening in edit mode.\n const [primedId, setPrimedId] = useState<string | null>(null);\n if (open && editing && primedId !== editing.id) {\n setPrimedId(editing.id);\n setName(editing.name);\n setVendor(editing.vendor);\n setVersion(editing.version);\n setLicenseType(\n (LICENSE_TYPES as readonly string[]).includes(editing.licenseType)\n ? (editing.licenseType as (typeof LICENSE_TYPES)[number])\n : 'SUBSCRIPTION'\n );\n setSeatsPurchased(editing.seatsPurchased != null ? String(editing.seatsPurchased) : '');\n setSeatsUsed(editing.seatsUsed != null ? String(editing.seatsUsed) : '');\n }\n if (open && !editing && primedId !== null) {\n setPrimedId(null);\n }\n\n const reset = () => {\n setName('');\n setVendor('');\n setVersion('');\n setLicenseType('SUBSCRIPTION');\n setSeatsPurchased('');\n setSeatsUsed('');\n setPrimedId(null);\n };\n\n const [upsertAsset, { loading }] = useMutation<UpsertSoftwareAssetResult>(\n UPSERT_SOFTWARE_ASSET_MUTATION,\n {\n onCompleted: (data) => {\n notify.success('Software asset saved', `${data.upsertSoftwareAsset.name} is now tracked.`);\n reset();\n onOpenChange(false);\n onSaved();\n },\n onError: (error) => notify.error('Could not save software asset', error.message),\n }\n );\n\n const handleSubmit = () => {\n if (!name.trim() || !vendor.trim() || !version.trim()) {\n notify.warning('Missing details', 'Name, vendor and version are required.');\n return;\n }\n const optionalInt = (value: string): number | null => {\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const parsed = Number(trimmed);\n return Number.isInteger(parsed) ? parsed : null;\n };\n void upsertAsset({\n variables: {\n input: {\n ...(editing ? { id: editing.id } : {}),\n name: name.trim(),\n vendor: vendor.trim(),\n version: version.trim(),\n licenseType,\n seatsPurchased: optionalInt(seatsPurchased),\n seatsUsed: optionalInt(seatsUsed),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {editing ? 'Edit Software Asset' : 'New Software Asset'}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {editing\n ? 'Update this software entitlement and its seat allocation.'\n : 'Register a software entitlement to track license compliance.'}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Vendor *</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Version *</Label>\n <Input\n placeholder=\"e.g., 2026.1\"\n value={version}\n onChange={(e) => setVersion(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>License Type</Label>\n <Select\n value={licenseType}\n onValueChange={(v) => setLicenseType(v as typeof licenseType)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Seats Purchased</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsPurchased}\n onChange={(e) => setSeatsPurchased(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Seats Used</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={seatsUsed}\n onChange={(e) => setSeatsUsed(e.target.value)}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? 'Saving…' : editing ? 'Save changes' : 'Save asset'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// Compliance bar cell — green when within entitlement, red when over-used.\nfunction ComplianceCell({ asset }: { asset: SoftwareAsset }) {\n const purchased = asset.seatsPurchased ?? 0;\n const used = asset.seatsUsed ?? 0;\n const overUsed = purchased > 0 && used > purchased;\n return (\n <div className=\"min-w-[140px]\">\n <ProgressMeter\n value={Math.min(100, Math.max(0, asset.compliancePercent))}\n max={100}\n higherIsWorse={false}\n size=\"sm\"\n showValue={false}\n />\n <p\n className={cn(\n 'mt-1 text-xs font-medium tabular-nums',\n overUsed ? 'text-status-error-text' : 'text-text-secondary'\n )}\n >\n {asset.compliancePercent.toFixed(1)}%{overUsed ? ' · over-used' : ''}\n </p>\n </div>\n );\n}\n\nexport function SamLicensesPage() {\n const [dialogOpen, setDialogOpen] = useState(false);\n const [editing, setEditing] = useState<SoftwareAsset | null>(null);\n const [search, setSearch] = useState('');\n const [licenseFilter, setLicenseFilter] = useState<string>('all');\n const [sort, setSort] = useState<string>('compliance-asc');\n\n const { data, loading, refetch } = useQuery<{ softwareAssets: SoftwareAsset[] }>(\n SOFTWARE_ASSETS_QUERY,\n { fetchPolicy: 'cache-and-network' }\n );\n const [deleteAsset, { loading: deleting }] = useMutation(DELETE_SOFTWARE_ASSET_MUTATION, {\n onCompleted: () => {\n notify.success('Software asset deleted');\n void refetch();\n },\n onError: (error) => notify.error('Could not delete software asset', error.message),\n });\n\n const softwareAssets = useMemo(() => data?.softwareAssets ?? [], [data]);\n\n // ─── KPI rollups (all real, derived from the fetched list) ───\n const kpis = useMemo(() => {\n let purchased = 0;\n let used = 0;\n for (const a of softwareAssets) {\n purchased += a.seatsPurchased ?? 0;\n used += a.seatsUsed ?? 0;\n }\n const available = Math.max(0, purchased - used);\n // Seats-weighted compliance (fallback to simple average).\n const totalWeight = softwareAssets.reduce((s, a) => s + (a.seatsPurchased ?? 0), 0);\n const compliance =\n totalWeight > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent * (a.seatsPurchased ?? 0), 0) /\n totalWeight\n : softwareAssets.length > 0\n ? softwareAssets.reduce((s, a) => s + a.compliancePercent, 0) / softwareAssets.length\n : 0;\n return { purchased, used, available, compliance };\n }, [softwareAssets]);\n\n const licenseTypeDonut = useMemo(() => {\n const counts = new Map<string, number>();\n for (const a of softwareAssets) counts.set(a.licenseType, (counts.get(a.licenseType) ?? 0) + 1);\n return [...counts.entries()].map(([type, value]) => ({\n name: humanizeLicense(type),\n value,\n }));\n }, [softwareAssets]);\n\n const seatsBars = useMemo(\n () =>\n [...softwareAssets]\n .sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0))\n .slice(0, 6)\n .map((a) => ({\n name: a.name.length > 18 ? a.name.slice(0, 17) + '…' : a.name,\n purchased: a.seatsPurchased ?? 0,\n used: a.seatsUsed ?? 0,\n })),\n [softwareAssets]\n );\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n const rows = softwareAssets.filter((a) => {\n if (licenseFilter !== 'all' && a.licenseType !== licenseFilter) return false;\n if (!q) return true;\n return a.name.toLowerCase().includes(q) || a.vendor.toLowerCase().includes(q);\n });\n const sorted = [...rows];\n switch (sort) {\n case 'compliance-asc':\n sorted.sort((a, b) => a.compliancePercent - b.compliancePercent);\n break;\n case 'compliance-desc':\n sorted.sort((a, b) => b.compliancePercent - a.compliancePercent);\n break;\n case 'seats-desc':\n sorted.sort((a, b) => (b.seatsPurchased ?? 0) - (a.seatsPurchased ?? 0));\n break;\n case 'name-asc':\n sorted.sort((a, b) => a.name.localeCompare(b.name));\n break;\n default:\n break;\n }\n return sorted;\n }, [softwareAssets, search, licenseFilter, sort]);\n\n const pagination = usePagination(filtered, {\n pageSize: 12,\n resetKey: `${search}|${licenseFilter}|${sort}`,\n });\n\n const openCreate = () => {\n setEditing(null);\n setDialogOpen(true);\n };\n const openEdit = (asset: SoftwareAsset) => {\n setEditing(asset);\n setDialogOpen(true);\n };\n const handleDelete = (asset: SoftwareAsset) => {\n if (!window.confirm(`Delete ${asset.name}?`)) return;\n void deleteAsset({ variables: { id: asset.id } });\n };\n\n const hasCharts = softwareAssets.length > 0;\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-muted\">\n Software Asset Management (SAM / licenses)\n </p>\n <h1 className=\"flex items-center gap-2 text-2xl font-semibold\">\n <KeyRound className=\"h-6 w-6\" /> <GradientText>Software Asset Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Track purchased seats against self-reported usage.\n </p>\n </div>\n <Button className=\"w-full sm:w-auto\" onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n </div>\n <PagePurpose>\n Track purchased seats against the usage your team enters and review the resulting compliance\n percentage. Usage is self-reported; it is not installation- or discovery-verified yet.\n </PagePurpose>\n\n <NewSoftwareAssetDialog\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSaved={() => void refetch()}\n editing={editing}\n />\n\n {/* ─── KPI rollups ─── */}\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <StatTile label=\"Total Licenses\" value={kpis.purchased} icon={Layers} hero />\n <StatTile label=\"Seats Used\" value={kpis.used} icon={UserCheck} />\n <StatTile label=\"Seats Available\" value={kpis.available} icon={UserPlus} />\n <StatTile\n label=\"Compliance\"\n value={kpis.compliance}\n format={(v) => `${v.toFixed(1)}%`}\n icon={ShieldCheck}\n deltaTone={kpis.compliance >= 90 ? 'positive' : 'negative'}\n />\n </div>\n\n {/* ─── Charts ─── */}\n {hasCharts ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard title=\"Licenses by type\" subtitle=\"Entitlement mix\" icon={KeyRound}>\n <DonutChart\n data={licenseTypeDonut}\n height={240}\n centerLabel=\"products\"\n centerValue={softwareAssets.length}\n ariaLabel=\"Software assets by license type\"\n />\n </ChartCard>\n <ChartCard title=\"Seats: purchased vs used\" subtitle=\"Top products by entitlement\">\n <BarsChart\n data={seatsBars}\n xKey=\"name\"\n orientation=\"horizontal\"\n categoryWidth={120}\n height={240}\n series={[\n { key: 'purchased', label: 'Purchased' },\n { key: 'used', label: 'Used' },\n ]}\n ariaLabel=\"Seats purchased versus used per software product\"\n />\n </ChartCard>\n </div>\n ) : null}\n\n {/* ─── Filters ─── */}\n {softwareAssets.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n className=\"pl-9\"\n placeholder=\"Search software or vendor…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <Select value={licenseFilter} onValueChange={setLicenseFilter}>\n <SelectTrigger className=\"w-full sm:w-[170px]\">\n <SelectValue placeholder=\"License type\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All license types</SelectItem>\n {LICENSE_TYPES.map((l) => (\n <SelectItem key={l} value={l}>\n {humanizeLicense(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={sort} onValueChange={setSort}>\n <SelectTrigger className=\"w-full sm:w-[190px]\">\n <SelectValue placeholder=\"Sort\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compliance-asc\">Compliance: low → high</SelectItem>\n <SelectItem value=\"compliance-desc\">Compliance: high → low</SelectItem>\n <SelectItem value=\"seats-desc\">Most seats</SelectItem>\n <SelectItem value=\"name-asc\">Name A–Z</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </GlassCard>\n ) : null}\n\n {/* ─── Loading / Empty ─── */}\n {loading && softwareAssets.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-2 p-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-8 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n </GlassCard>\n ) : null}\n\n {!loading && softwareAssets.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No software assets found\"\n description=\"Register a software asset to start tracking license compliance.\"\n action={\n <Button onClick={openCreate}>\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Software\n </Button>\n }\n />\n ) : null}\n\n {softwareAssets.length > 0 && filtered.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching software\"\n description=\"Adjust your search or filters to see software assets.\"\n />\n ) : null}\n\n {/* ─── Table (desktop) + card list (mobile) ─── */}\n {filtered.length > 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/50 text-xs uppercase tracking-wide text-text-secondary\">\n <th className=\"p-3 text-left font-semibold\">Software</th>\n <th className=\"p-3 text-left font-semibold\">Vendor</th>\n <th className=\"p-3 text-left font-semibold\">Version</th>\n <th className=\"p-3 text-left font-semibold\">License Type</th>\n <th className=\"p-3 text-right font-semibold\">Seats Purchased</th>\n <th className=\"p-3 text-right font-semibold\">Seats Used</th>\n <th className=\"p-3 text-left font-semibold\">Compliance</th>\n <th className=\"p-3 text-right font-semibold\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {pagination.pageItems.map((asset) => (\n <tr\n key={asset.id}\n className=\"cursor-pointer border-b border-border-seam hover:bg-bg-sunken/50\"\n onClick={() => openEdit(asset)}\n >\n <td className=\"max-w-[220px] truncate p-3 font-medium\" title={asset.name}>\n {asset.name}\n </td>\n <td className=\"p-3 text-text-secondary\">{asset.vendor}</td>\n <td className=\"p-3 text-text-secondary\">{asset.version}</td>\n <td className=\"p-3\">\n <span className=\"inline-flex items-center rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsPurchased ?? '—'}</td>\n <td className=\"p-3 text-right tabular-nums\">{asset.seatsUsed ?? '—'}</td>\n <td className=\"p-3\">\n <ComplianceCell asset={asset} />\n </td>\n <td className=\"p-3 text-right\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={(e) => {\n e.stopPropagation();\n openEdit(asset);\n }}\n >\n <Pencil className=\"mr-1 h-3.5 w-3.5\" />\n Edit\n </Button>\n <Button\n className=\"ml-2\"\n size=\"sm\"\n variant=\"outline\"\n disabled={deleting}\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(asset);\n }}\n aria-label={`Delete ${asset.name}`}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile card list */}\n <div className=\"divide-y divide-border-seam md:hidden\">\n {pagination.pageItems.map((asset) => (\n <div\n key={asset.id}\n className=\"cursor-pointer space-y-2 p-4\"\n onClick={() => openEdit(asset)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium\" title={asset.name}>\n {asset.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {asset.vendor} · v{asset.version}\n </p>\n </div>\n <span className=\"shrink-0 rounded-full bg-status-neutral-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-neutral-text\">\n {humanizeLicense(asset.licenseType)}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-3 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">\n {asset.seatsUsed ?? 0} / {asset.seatsPurchased ?? '—'} seats\n </span>\n </div>\n <ComplianceCell asset={asset} />\n </div>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={pagination.page}\n pageCount={pagination.pageCount}\n rangeStart={pagination.rangeStart}\n rangeEnd={pagination.rangeEnd}\n totalItems={pagination.totalItems}\n canPrev={pagination.canPrev}\n canNext={pagination.canNext}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"software assets\"\n />\n </div>\n </GlassCard>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-assethandler",
3
- "version": "2026.826.13",
3
+ "version": "2026.826.14",
4
4
  "description": "Burdenoff AssetHandler Microfrontend",
5
5
  "type": "module",
6
6
  "files": [