adding a table component
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
headers: {
|
||||
type: Array,
|
||||
default: () => ['Author', 'Function', 'Status', 'Employed', 'Action'],
|
||||
},
|
||||
/**
|
||||
* Each row: {
|
||||
* image?: string — avatar URL (falls back to initials)
|
||||
* initials?: string — shown when no image
|
||||
* color?: string — gradient color for initials avatar
|
||||
* name: string
|
||||
* email: string
|
||||
* position: [string, string] — [label, sublabel]
|
||||
* status: boolean — true = Online, false = Offline
|
||||
* date: string
|
||||
* action: { label, route }
|
||||
* }
|
||||
*/
|
||||
rows: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const avatarGradients = {
|
||||
primary: 'bg-gradient-primary shadow-primary',
|
||||
secondary: 'bg-gradient-secondary shadow-secondary',
|
||||
success: 'bg-gradient-success shadow-success',
|
||||
warning: 'bg-gradient-warning shadow-warning',
|
||||
danger: 'bg-gradient-danger shadow-danger',
|
||||
info: 'bg-gradient-info shadow-info',
|
||||
dark: 'bg-gradient-dark shadow-dark',
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-soft-md">
|
||||
|
||||
<!-- Optional slot for a card header (title, actions, etc.) -->
|
||||
<div v-if="$slots.header" class="border-b border-gray-100 px-6 py-4">
|
||||
<slot name="header" />
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left text-sm">
|
||||
<thead>
|
||||
<tr class="border-b border-gray-100">
|
||||
<th
|
||||
v-for="(header, i) in headers"
|
||||
:key="header"
|
||||
class="px-6 py-3 text-xs font-bold uppercase tracking-wide text-secondary"
|
||||
:class="i > 1 ? 'text-center' : ''"
|
||||
>
|
||||
{{ header }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(row, i) in rows"
|
||||
:key="i"
|
||||
:class="i < rows.length - 1 ? 'border-b border-gray-100' : ''"
|
||||
>
|
||||
<!-- Author: avatar + name + email -->
|
||||
<td class="px-6 py-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Photo avatar -->
|
||||
<img
|
||||
v-if="row.image"
|
||||
:src="row.image"
|
||||
:alt="row.name"
|
||||
class="h-9 w-9 shrink-0 rounded-xl object-cover"
|
||||
/>
|
||||
<!-- Initials avatar -->
|
||||
<div
|
||||
v-else
|
||||
class="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-xs font-bold text-white"
|
||||
:class="avatarGradients[row.color] ?? avatarGradients.dark"
|
||||
>
|
||||
{{ row.initials ?? row.name?.slice(0, 2).toUpperCase() }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="font-medium text-dark">{{ row.name }}</p>
|
||||
<p class="text-xs text-secondary">{{ row.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Position: two-line label -->
|
||||
<td class="px-6 py-3">
|
||||
<p class="font-medium text-dark">{{ row.position?.[0] ?? '—' }}</p>
|
||||
<p class="text-xs text-secondary">{{ row.position?.[1] ?? '' }}</p>
|
||||
</td>
|
||||
|
||||
<!-- Status badge -->
|
||||
<td class="px-6 py-3 text-center">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium"
|
||||
:class="row.status
|
||||
? 'bg-success/10 text-success'
|
||||
: 'bg-gray-100 text-secondary'"
|
||||
>
|
||||
<span
|
||||
class="h-1.5 w-1.5 rounded-full"
|
||||
:class="row.status ? 'bg-success' : 'bg-gray-400'"
|
||||
/>
|
||||
{{ row.status ? 'Online' : 'Offline' }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<!-- Date -->
|
||||
<td class="px-6 py-3 text-center text-xs text-secondary">
|
||||
{{ row.date }}
|
||||
</td>
|
||||
|
||||
<!-- Action -->
|
||||
<td class="px-6 py-3 text-center">
|
||||
<a
|
||||
:href="row.action?.route ?? '#'"
|
||||
class="text-xs font-medium text-secondary no-underline transition-colors hover:text-primary"
|
||||
>
|
||||
{{ row.action?.label ?? 'Edit' }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Optional slot for pagination or footer -->
|
||||
<div v-if="$slots.footer" class="border-t border-gray-100 px-6 py-4">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user