Add row selection, bulk delete, row numbers and page size picker to tables; redesign person profile header

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-05 20:00:21 +03:30
co-authored by Cursor
parent 71b3a7255a
commit 48de552f36
15 changed files with 565 additions and 79 deletions
+53 -4
View File
@@ -2,6 +2,7 @@
import { computed } from 'vue';
import UiButton from './UiButton.vue';
import UiIcon from '@/components/UiIcon.vue';
import { toFaDigits } from '@/lib/jalali';
const props = withDefaults(
defineProps<{
@@ -9,6 +10,8 @@ const props = withDefaults(
totalPages?: number;
totalItems?: number;
pageSize?: number;
/** با مقداردهی، انتخاب «تعداد در صفحه» نمایش داده می‌شود */
pageSizeOptions?: number[];
}>(),
{
page: 1,
@@ -17,6 +20,7 @@ const props = withDefaults(
const emit = defineEmits<{
'update:page': [page: number];
'update:pageSize': [size: number];
change: [page: number];
}>();
@@ -28,22 +32,45 @@ const effectiveTotalPages = computed(() => {
return 1;
});
const showSizePicker = computed(() => Boolean(props.pageSizeOptions?.length && props.pageSize));
function goTo(p: number) {
if (p < 1 || p > effectiveTotalPages.value || p === props.page) return;
emit('update:page', p);
emit('change', p);
}
function onSizeChange(e: Event) {
const size = Number((e.target as HTMLSelectElement).value);
if (!size || size === props.pageSize) return;
emit('update:pageSize', size);
if (props.page !== 1) {
emit('update:page', 1);
emit('change', 1);
}
}
</script>
<template>
<nav v-if="effectiveTotalPages > 1 || totalItems !== undefined" class="ui-pagination" aria-label="صفحه‌بندی">
<nav
v-if="effectiveTotalPages > 1 || totalItems !== undefined || showSizePicker"
class="ui-pagination"
aria-label="صفحه‌بندی"
>
<div class="pagination-info">
<span v-if="totalItems !== undefined">
مجموع: <strong>{{ totalItems }}</strong> مورد
مجموع: <strong>{{ toFaDigits(totalItems.toLocaleString('en-US')) }}</strong> مورد
</span>
<span v-if="effectiveTotalPages > 1" class="page-count">
(صفحه {{ page }} از {{ effectiveTotalPages }})
(صفحه {{ toFaDigits(page) }} از {{ toFaDigits(effectiveTotalPages) }})
</span>
<label v-if="showSizePicker" class="size-picker">
<span>نمایش</span>
<select :value="pageSize" @change="onSizeChange">
<option v-for="n in pageSizeOptions" :key="n" :value="n">{{ toFaDigits(n) }}</option>
</select>
<span>در هر صفحه</span>
</label>
</div>
<div v-if="effectiveTotalPages > 1" class="pagination-controls">
@@ -69,7 +96,7 @@ function goTo(p: number) {
</UiButton>
<span class="current-indicator">
{{ page }} / {{ effectiveTotalPages }}
{{ toFaDigits(page) }} / {{ toFaDigits(effectiveTotalPages) }}
</span>
<UiButton
@@ -112,6 +139,7 @@ function goTo(p: number) {
color: var(--muted);
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--sp-2);
}
@@ -119,6 +147,27 @@ function goTo(p: number) {
color: var(--muted-light);
}
.size-picker {
display: inline-flex;
align-items: center;
gap: 0.35rem;
margin-inline-start: var(--sp-2);
font-size: var(--fs-xs);
}
.size-picker select {
height: 30px;
min-width: 3.6rem;
padding: 0 0.45rem;
border: 1px solid var(--line);
border-radius: 8px;
background: #fff;
font: inherit;
font-size: var(--fs-sm);
color: var(--ink);
cursor: pointer;
}
.pagination-controls {
display: inline-flex;
align-items: center;