296 lines
6.4 KiB
Vue
296 lines
6.4 KiB
Vue
<template>
|
||
<q-page
|
||
v-if="canReadUser"
|
||
class="ol-page with-bg"
|
||
>
|
||
|
||
<!-- 🔍 Sticky Filter -->
|
||
<div class="ol-filter-bar">
|
||
<div class="ol-filter-row">
|
||
|
||
<q-input
|
||
class="ol-filter-input ol-search"
|
||
dense
|
||
filled
|
||
clearable
|
||
v-model="store.filters.search"
|
||
label="Arama (Kullanıcı / Rol / Piyasa)"
|
||
debounce="300"
|
||
@update:model-value="store.fetchUsers"
|
||
>
|
||
<template #append>
|
||
<q-icon name="search" />
|
||
</template>
|
||
</q-input>
|
||
|
||
<q-toggle
|
||
v-model="store.filters.onlyActive"
|
||
label="Sadece Aktifler"
|
||
/>
|
||
|
||
<div class="ol-filter-actions">
|
||
<q-btn
|
||
v-if="canReadUser"
|
||
label="Yenile"
|
||
icon="refresh"
|
||
color="primary"
|
||
:loading="store.loading"
|
||
:disable="!canReadUser"
|
||
@click="store.fetchUsers"
|
||
/>
|
||
|
||
<q-btn
|
||
v-if="canWriteUser"
|
||
label="Yeni Kullanıcı"
|
||
icon="person_add"
|
||
color="primary"
|
||
outline
|
||
@click="goCreate"
|
||
/>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 📋 USER LIST TABLE -->
|
||
<q-table
|
||
title="Mevcut Kullanıcılar"
|
||
class="ol-table"
|
||
flat
|
||
bordered
|
||
dense
|
||
separator="cell"
|
||
row-key="id"
|
||
:rows="store.filteredUsers"
|
||
:columns="columns"
|
||
:loading="store.loading"
|
||
no-data-label="Kullanıcı bulunamadı"
|
||
:rows-per-page-options="[0]"
|
||
hide-bottom
|
||
>
|
||
|
||
|
||
<!-- 🔗 OPEN -->
|
||
<template #body-cell-open="props">
|
||
<q-td class="text-center">
|
||
<q-btn
|
||
v-if="canReadUser"
|
||
icon="open_in_new"
|
||
color="primary"
|
||
flat
|
||
round
|
||
dense
|
||
@click="openDetail(props.row.id)"
|
||
/>
|
||
</q-td>
|
||
</template>
|
||
|
||
<!-- ✅ DURUM -->
|
||
<template #body-cell-is_active="props">
|
||
<q-td class="text-center">
|
||
<q-icon
|
||
:name="props.row.is_active ? 'check_circle' : 'cancel'"
|
||
:color="props.row.is_active ? 'green' : 'red'"
|
||
size="18px"
|
||
/>
|
||
</q-td>
|
||
</template>
|
||
|
||
<!-- 👤 ROLLER -->
|
||
<template #body-cell-role_names="props">
|
||
<q-td>
|
||
<q-chip
|
||
v-for="r in splitNames(props.row.role_names)"
|
||
:key="r"
|
||
dense
|
||
color="primary"
|
||
text-color="white"
|
||
class="q-mr-xs"
|
||
>
|
||
{{ r }}
|
||
</q-chip>
|
||
</q-td>
|
||
</template>
|
||
|
||
<!-- 🏢 DEPARTMAN -->
|
||
<template #body-cell-department_names="props">
|
||
<q-td>
|
||
<q-chip
|
||
v-for="d in splitNames(props.row.department_names)"
|
||
:key="d"
|
||
dense
|
||
color="grey-7"
|
||
text-color="white"
|
||
class="q-mr-xs"
|
||
>
|
||
{{ d }}
|
||
</q-chip>
|
||
</q-td>
|
||
</template>
|
||
|
||
<!-- 🌍 PİYASALAR -->
|
||
<template #body-cell-piyasa_names="props">
|
||
<q-td class="ol-col-piyasa">
|
||
<div class="piyasa-wrap">
|
||
<q-chip
|
||
v-for="p in splitPiyasalar(props.row.piyasa_names)"
|
||
:key="p"
|
||
dense
|
||
outline
|
||
color="indigo"
|
||
class="piyasa-chip"
|
||
:title="p"
|
||
>
|
||
{{ p }}
|
||
</q-chip>
|
||
</div>
|
||
</q-td>
|
||
</template>
|
||
|
||
|
||
</q-table>
|
||
|
||
<!-- ❌ HATA -->
|
||
<q-banner v-if="store.error" class="bg-red text-white q-mt-sm">
|
||
❌ {{ store.error }}
|
||
</q-banner>
|
||
|
||
</q-page>
|
||
|
||
<q-page
|
||
v-else
|
||
class="q-pa-md flex flex-center"
|
||
>
|
||
<div class="text-negative text-subtitle1">
|
||
Bu module erisim yetkiniz yok.
|
||
</div>
|
||
</q-page>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { onMounted } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { useUserListStore } from 'src/stores/UserListStore'
|
||
import { usePermission } from 'src/composables/usePermission'
|
||
|
||
const { canRead, canWrite, canUpdate } = usePermission()
|
||
|
||
const canReadUser = canRead('user')
|
||
const canWriteUser = canWrite('user')
|
||
const canUpdateUser = canUpdate('user')
|
||
|
||
const router = useRouter()
|
||
const store = useUserListStore()
|
||
|
||
/* ==========================================================
|
||
📌 QTable Columns
|
||
========================================================== */
|
||
const columns = [
|
||
{ name: 'open', label: '', align: 'center' },
|
||
|
||
{
|
||
name: 'id',
|
||
label: 'No',
|
||
field: row => row.id,
|
||
sortable: true
|
||
},
|
||
|
||
{
|
||
name: 'code',
|
||
label: 'Kullanıcı',
|
||
field: row => row.code || '',
|
||
sortable: true,
|
||
sort: (a, b) => a.localeCompare(b, 'tr', { sensitivity: 'base' })
|
||
},
|
||
|
||
{
|
||
name: 'nebim_username',
|
||
label: 'Nebim',
|
||
field: row => row.nebim_username || '',
|
||
sortable: true,
|
||
sort: (a, b) => a.localeCompare(b, 'tr')
|
||
},
|
||
|
||
{
|
||
name: 'user_group_code',
|
||
label: 'Grup',
|
||
field: row => row.user_group_code || '',
|
||
sortable: true,
|
||
sort: (a, b) => a.localeCompare(b, 'tr')
|
||
},
|
||
|
||
{
|
||
name: 'is_active',
|
||
label: 'Durum',
|
||
field: row => row.is_active,
|
||
align: 'center',
|
||
sortable: true,
|
||
sort: (a, b) => Number(b) - Number(a)
|
||
},
|
||
|
||
{
|
||
name: 'role_names',
|
||
label: 'Roller',
|
||
field: row => row.role_names || '',
|
||
sortable: true,
|
||
sort: (a, b) => a.localeCompare(b, 'tr')
|
||
},
|
||
|
||
{
|
||
name: 'department_names',
|
||
label: 'Departmanlar',
|
||
field: row => row.department_names || '',
|
||
sortable: true,
|
||
sort: (a, b) => a.localeCompare(b, 'tr')
|
||
},
|
||
|
||
{
|
||
name: 'piyasa_names',
|
||
label: 'Piyasalar',
|
||
field: row => row.piyasa_names || '',
|
||
sortable: true,
|
||
sort: (a, b) => a.localeCompare(b, 'tr')
|
||
}
|
||
]
|
||
|
||
|
||
/* ==========================================================
|
||
HELPERS
|
||
========================================================== */
|
||
function splitNames(val) {
|
||
if (!val) return []
|
||
return val.split(',').map(v => v.trim())
|
||
}
|
||
|
||
function openDetail(id) {
|
||
const routeName = canUpdateUser.value ? 'user-edit' : 'user-view'
|
||
router.push({
|
||
name: routeName,
|
||
params: { id: String(id) }
|
||
})
|
||
}
|
||
|
||
|
||
|
||
function goCreate() {
|
||
if (!canWriteUser.value) return
|
||
router.push({ name: 'user-new' })
|
||
}
|
||
|
||
function splitPiyasalar (val) {
|
||
if (!val) return []
|
||
return val
|
||
.split(',')
|
||
.map(v => v.trim())
|
||
.filter(Boolean)
|
||
.slice(0, 24) // ✅ 6 satır × 4 kolon
|
||
}
|
||
|
||
|
||
onMounted(() => {
|
||
if (canReadUser.value) {
|
||
store.fetchUsers()
|
||
}
|
||
})
|
||
</script>
|