2026-09-05 00:18:39 +03:30
|
|
|
|
<script setup lang="ts">
|
2026-09-10 01:22:24 +03:30
|
|
|
|
import UiFilterBar from '@/components/ui/UiFilterBar.vue';
|
2026-09-05 00:18:39 +03:30
|
|
|
|
import UiIcon from '@/components/UiIcon.vue';
|
2026-09-10 01:22:24 +03:30
|
|
|
|
import UiSegmented from '@/components/ui/UiSegmented.vue';
|
|
|
|
|
|
import UiSelect from '@/components/ui/UiSelect.vue';
|
2026-09-05 00:18:39 +03:30
|
|
|
|
|
|
|
|
|
|
export type PipelineViewMode = 'kanban' | 'list';
|
|
|
|
|
|
|
2026-09-09 13:12:13 +03:30
|
|
|
|
withDefaults(
|
|
|
|
|
|
defineProps<{
|
|
|
|
|
|
pipelineName: string;
|
|
|
|
|
|
pipelineOptions: Array<{ id: string; name: string }>;
|
|
|
|
|
|
canCreate?: boolean;
|
2026-09-15 19:13:30 +03:30
|
|
|
|
icon?: 'briefcase' | 'grid';
|
|
|
|
|
|
createOptionLabel?: string;
|
|
|
|
|
|
showAmountFilters?: boolean;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
}>(),
|
2026-09-15 19:13:30 +03:30
|
|
|
|
{
|
|
|
|
|
|
canCreate: false,
|
|
|
|
|
|
icon: 'briefcase',
|
2026-10-06 20:51:50 +03:30
|
|
|
|
createOptionLabel: 'مسیر فروش جدید…',
|
2026-09-15 19:13:30 +03:30
|
|
|
|
showAmountFilters: true,
|
|
|
|
|
|
},
|
2026-09-09 13:12:13 +03:30
|
|
|
|
);
|
2026-09-05 00:18:39 +03:30
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
2026-09-09 13:12:13 +03:30
|
|
|
|
create: [];
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}>();
|
2026-09-09 13:12:13 +03:30
|
|
|
|
|
2026-09-10 01:22:24 +03:30
|
|
|
|
const viewMode = defineModel<PipelineViewMode>('viewMode', { required: true });
|
|
|
|
|
|
const search = defineModel<string>('search', { default: '' });
|
|
|
|
|
|
const selectedPipelineId = defineModel<string>('selectedPipelineId', { required: true });
|
|
|
|
|
|
const amountMin = defineModel<string>('amountMin', { default: '' });
|
|
|
|
|
|
const amountMax = defineModel<string>('amountMax', { default: '' });
|
|
|
|
|
|
|
|
|
|
|
|
const viewOptions = [
|
2026-10-06 20:51:50 +03:30
|
|
|
|
{ value: 'kanban' as const, label: 'نمای ستونی', icon: 'grid' as const },
|
2026-09-10 01:22:24 +03:30
|
|
|
|
{ value: 'list' as const, label: 'نمای لیست', icon: 'list' as const },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
2026-09-09 13:12:13 +03:30
|
|
|
|
function onPick(value: string) {
|
|
|
|
|
|
if (value === '__create__') {
|
|
|
|
|
|
emit('create');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-09-10 01:22:24 +03:30
|
|
|
|
selectedPipelineId.value = value;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
}
|
2026-09-05 00:18:39 +03:30
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<header class="toolbar" dir="rtl">
|
|
|
|
|
|
<div class="title-block">
|
|
|
|
|
|
<span class="brand-ico" aria-hidden="true">
|
2026-09-15 19:13:30 +03:30
|
|
|
|
<UiIcon :name="icon" :size="18" />
|
2026-09-05 00:18:39 +03:30
|
|
|
|
</span>
|
2026-09-09 13:12:13 +03:30
|
|
|
|
<h1>{{ pipelineName }}</h1>
|
2026-09-05 00:18:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-09-10 01:22:24 +03:30
|
|
|
|
<UiSegmented v-model="viewMode" :options="viewOptions">
|
|
|
|
|
|
<template #icon="{ option }">
|
|
|
|
|
|
<UiIcon :name="option.icon ?? 'grid'" :size="16" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</UiSegmented>
|
2026-09-05 00:18:39 +03:30
|
|
|
|
|
2026-09-15 19:13:30 +03:30
|
|
|
|
<UiSelect
|
2026-09-10 01:22:24 +03:30
|
|
|
|
class="pipeline-pick"
|
|
|
|
|
|
:model-value="selectedPipelineId"
|
|
|
|
|
|
@update:model-value="onPick"
|
|
|
|
|
|
>
|
|
|
|
|
|
<option
|
|
|
|
|
|
v-for="opt in pipelineOptions"
|
|
|
|
|
|
:key="opt.id"
|
|
|
|
|
|
:value="opt.id"
|
2026-09-05 00:18:39 +03:30
|
|
|
|
>
|
2026-09-10 01:22:24 +03:30
|
|
|
|
{{ opt.name }}
|
|
|
|
|
|
</option>
|
2026-09-15 19:13:30 +03:30
|
|
|
|
<option v-if="canCreate" value="__create__">{{ createOptionLabel }}</option>
|
2026-09-10 01:22:24 +03:30
|
|
|
|
</UiSelect>
|
2026-09-05 00:18:39 +03:30
|
|
|
|
|
2026-09-15 19:13:30 +03:30
|
|
|
|
<div class="excel-actions">
|
|
|
|
|
|
<slot name="excel" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<UiFilterBar
|
|
|
|
|
|
v-model:search="search"
|
|
|
|
|
|
class="filters"
|
|
|
|
|
|
:show-filters="showAmountFilters"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template v-if="showAmountFilters">
|
|
|
|
|
|
<label class="field">
|
|
|
|
|
|
<span>حداقل مبلغ</span>
|
|
|
|
|
|
<input v-model="amountMin" type="number" min="0" placeholder="۰" />
|
|
|
|
|
|
</label>
|
|
|
|
|
|
<label class="field">
|
|
|
|
|
|
<span>حداکثر مبلغ</span>
|
|
|
|
|
|
<input v-model="amountMax" type="number" min="0" placeholder="—" />
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</template>
|
2026-09-10 01:22:24 +03:30
|
|
|
|
</UiFilterBar>
|
2026-09-05 00:18:39 +03:30
|
|
|
|
</header>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.toolbar {
|
|
|
|
|
|
display: flex;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
flex-wrap: nowrap;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
align-items: center;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
gap: 0.55rem;
|
|
|
|
|
|
margin-bottom: 0.85rem;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
width: 100%;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.title-block {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.55rem;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
min-width: 0;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.brand-ico {
|
2026-09-10 01:22:24 +03:30
|
|
|
|
width: var(--control-h);
|
|
|
|
|
|
height: var(--control-h);
|
|
|
|
|
|
border-radius: var(--radius);
|
2026-09-05 00:18:39 +03:30
|
|
|
|
display: grid;
|
|
|
|
|
|
place-items: center;
|
2026-09-10 01:22:24 +03:30
|
|
|
|
background: var(--accent-deep);
|
2026-09-05 00:18:39 +03:30
|
|
|
|
color: #fff;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
flex: 0 0 auto;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
h1 {
|
|
|
|
|
|
margin: 0;
|
2026-09-10 01:22:24 +03:30
|
|
|
|
font-size: 1.15rem;
|
2026-09-12 01:33:07 +03:30
|
|
|
|
font-weight: 600;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
color: var(--ink);
|
2026-09-09 13:12:13 +03:30
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pipeline-pick {
|
2026-09-09 13:12:13 +03:30
|
|
|
|
flex: 0 1 13rem;
|
2026-09-10 01:22:24 +03:30
|
|
|
|
min-width: 8.5rem;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-15 19:13:30 +03:30
|
|
|
|
.excel-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 0.4rem;
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.excel-actions :deep(.btn-ghost-sm) {
|
|
|
|
|
|
border: 1px solid #e2e8f0;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
color: #0f766e;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
padding: 0.45rem 0.75rem;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
font-size: 0.85rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font: inherit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-10 01:22:24 +03:30
|
|
|
|
.filters {
|
|
|
|
|
|
flex: 1 1 12rem;
|
2026-09-09 13:12:13 +03:30
|
|
|
|
min-width: 0;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-10 01:22:24 +03:30
|
|
|
|
.field {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
gap: 0.3rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.field span {
|
|
|
|
|
|
font-size: 0.8rem;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-09 13:12:13 +03:30
|
|
|
|
@container pipeline (max-width: 720px) {
|
2026-09-05 00:18:39 +03:30
|
|
|
|
.toolbar {
|
2026-09-09 13:12:13 +03:30
|
|
|
|
flex-wrap: wrap;
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.title-block {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-10 01:22:24 +03:30
|
|
|
|
.pipeline-pick,
|
2026-09-15 19:13:30 +03:30
|
|
|
|
.excel-actions,
|
2026-09-10 01:22:24 +03:30
|
|
|
|
.filters {
|
2026-09-09 13:12:13 +03:30
|
|
|
|
flex: 1 1 100%;
|
|
|
|
|
|
}
|
2026-09-05 00:18:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
</style>
|