feat(ui) : clickable entity links, site→machines links, DataTable fixedLayout
- Add NuxtLink on component/piece/product names in machine hierarchy
(using composantId, pieceId, product.id)
- Make site machine count badges clickable → /machines?sites={id}
- Add opt-in fixedLayout prop and minWidth to DataTable columns
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,15 @@
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 flex-wrap">
|
||||
<h3 class="text-sm font-semibold truncate" :class="component.pendingEntity ? 'text-error' : 'text-base-content'">
|
||||
{{ component.name }}
|
||||
<NuxtLink
|
||||
v-if="!isEditMode && !component.pendingEntity && component.composantId"
|
||||
:to="`/component/${component.composantId}`"
|
||||
class="hover:underline hover:text-primary transition-colors"
|
||||
@click.stop
|
||||
>
|
||||
{{ component.name }}
|
||||
</NuxtLink>
|
||||
<span v-else>{{ component.name }}</span>
|
||||
</h3>
|
||||
<button
|
||||
v-if="component.pendingEntity"
|
||||
|
||||
@@ -29,7 +29,15 @@
|
||||
</button>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="text-lg font-semibold" :class="{ 'text-error': piece._emptySlot || piece.pendingEntity }">
|
||||
{{ pieceData.name }}
|
||||
<NuxtLink
|
||||
v-if="!isEditMode && !piece.pendingEntity && !piece._emptySlot && piece.pieceId"
|
||||
:to="`/piece/${piece.pieceId}`"
|
||||
class="hover:underline hover:text-primary transition-colors"
|
||||
@click.stop
|
||||
>
|
||||
{{ pieceData.name }}
|
||||
</NuxtLink>
|
||||
<template v-else>{{ pieceData.name }}</template>
|
||||
<span v-if="piece._emptySlot" class="text-sm font-semibold text-error ml-1">— manquant</span>
|
||||
<button
|
||||
v-if="piece.pendingEntity"
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
>
|
||||
<span class="loading loading-spinner text-primary" aria-hidden="true" />
|
||||
</div>
|
||||
<table :class="['table table-sm md:table-md', tableClass]">
|
||||
<table :class="['table table-sm md:table-md', tableClass, { 'table-fixed': fixedLayout }]">
|
||||
<thead>
|
||||
<!-- Header labels + sort -->
|
||||
<tr>
|
||||
@@ -85,6 +85,7 @@
|
||||
alignClass(col),
|
||||
{ 'hidden sm:table-cell': col.hiddenMobile },
|
||||
]"
|
||||
:style="col.minWidth ? { minWidth: col.minWidth } : undefined"
|
||||
>
|
||||
<slot :name="`header-${col.key}`" :column="col">
|
||||
<span
|
||||
@@ -221,6 +222,8 @@ const props = withDefaults(defineProps<{
|
||||
tableClass?: string
|
||||
showCounter?: boolean
|
||||
showPerPage?: boolean
|
||||
/** Use table-layout: fixed for stable column widths. Only enable on tables where columns define width/minWidth. */
|
||||
fixedLayout?: boolean
|
||||
}>(), {
|
||||
rowKey: 'id',
|
||||
loading: false,
|
||||
|
||||
@@ -29,7 +29,14 @@
|
||||
>
|
||||
<div class="flex items-center justify-between flex-wrap gap-2">
|
||||
<p class="font-semibold" :class="product.pendingEntity ? 'text-error' : 'text-base-content'">
|
||||
{{ product.name }}
|
||||
<NuxtLink
|
||||
v-if="!product.pendingEntity && product.id"
|
||||
:to="`/product/${product.id}`"
|
||||
class="hover:underline hover:text-primary transition-colors"
|
||||
>
|
||||
{{ product.name }}
|
||||
</NuxtLink>
|
||||
<span v-else>{{ product.name }}</span>
|
||||
</p>
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
<h3 class="card-title text-lg text-base-content">
|
||||
{{ site.name }}
|
||||
</h3>
|
||||
<div
|
||||
class="badge font-bold"
|
||||
<NuxtLink
|
||||
:to="`/machines?sites=${site.id}`"
|
||||
class="badge font-bold hover:opacity-80 transition-opacity"
|
||||
:style="site.color ? { backgroundColor: site.color + '30', color: site.color, borderColor: site.color + '50' } : {}"
|
||||
:class="!site.color ? 'badge-primary' : ''"
|
||||
>
|
||||
{{ machineCount }} machines
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3 text-sm">
|
||||
@@ -39,10 +40,10 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 text-base-content/60">
|
||||
<NuxtLink :to="`/machines?sites=${site.id}`" class="flex items-center gap-2 text-base-content/60 hover:text-primary transition-colors">
|
||||
<IconLucideFactory class="w-4 h-4 text-blue-500" aria-hidden="true" />
|
||||
<span>{{ machineCount }} machine(s)</span>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="card-actions justify-end mt-4">
|
||||
|
||||
@@ -141,13 +141,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<span
|
||||
class="badge font-bold"
|
||||
<NuxtLink
|
||||
:to="`/machines?sites=${site.id}`"
|
||||
class="badge font-bold hover:opacity-80 transition-opacity"
|
||||
:style="site.color ? { backgroundColor: site.color + '30', color: site.color, borderColor: site.color + '50' } : {}"
|
||||
:class="!site.color ? 'badge-primary' : ''"
|
||||
>
|
||||
{{ site.machines?.length || 0 }}
|
||||
</span>
|
||||
{{ site.machines?.length || 0 }} machine{{ (site.machines?.length || 0) > 1 ? 's' : '' }}
|
||||
</NuxtLink>
|
||||
<button
|
||||
class="btn btn-ghost btn-xs btn-circle"
|
||||
@click="toggleSiteCollapse(site.id)"
|
||||
|
||||
@@ -15,6 +15,8 @@ export interface DataTableColumn {
|
||||
headerClass?: string
|
||||
/** Width hint (e.g. 'w-24', 'min-w-[10rem]') */
|
||||
width?: string
|
||||
/** Inline min-width style (e.g. '120px', '8rem'). Only effective with fixedLayout. */
|
||||
minWidth?: string
|
||||
/** Text alignment: 'left' (default), 'center', 'right' */
|
||||
align?: 'left' | 'center' | 'right'
|
||||
/** Hide on mobile (adds 'hidden sm:table-cell') */
|
||||
|
||||
Reference in New Issue
Block a user