Mal Sorumlusu kaydetme mantığı değişti

This commit is contained in:
2025-11-08 14:34:55 +03:00
parent 4980095543
commit 495e6ae1a2
8 changed files with 690 additions and 533 deletions

View File

@@ -1,14 +1,14 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let user = null; export let user = null;
let goodsManagers = []; let personnel = [];
let units = []; let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
let showEditModal = false; let showEditModal = false;
let selectedManager = null; let selectedPersonnel = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
@@ -18,8 +18,6 @@
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '', unit_id: '',
username: '',
password: '',
is_active: true is_active: true
}; };
@@ -32,22 +30,22 @@
} }
user = JSON.parse(userData); user = JSON.parse(userData);
await loadGoodsManagers();
await loadUnits(); await loadUnits();
await loadPersonnel();
}); });
async function loadGoodsManagers() { async function loadPersonnel() {
try { try {
const response = await fetch('/api/goods-managers'); const response = await fetch('/api/fuel-personnel');
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
goodsManagers = data.goodsManagers; personnel = data.fuelPersonnel || [];
} else { } else {
error = 'Personel bilgileri yüklenemedi.'; error = 'Personel bilgileri yüklenemedi.';
} }
} catch (err) { } catch (err) {
error = 'Bağlantı hatası.'; error = 'Bağlantı hatası.';
console.error('Load goods managers error:', err); console.error('Load personnel error:', err);
} finally { } finally {
loading = false; loading = false;
} }
@@ -65,6 +63,11 @@
} }
} }
function getUnitName(unitId) {
const id = parseInt(unitId);
return units.find((unit) => unit.id === id)?.name || 'Belirtilmemiş';
}
function resetForm() { function resetForm() {
formData = { formData = {
full_name: '', full_name: '',
@@ -73,11 +76,9 @@
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '', unit_id: '',
username: '',
password: '',
is_active: true is_active: true
}; };
selectedManager = null; selectedPersonnel = null;
} }
function openAddModal() { function openAddModal() {
@@ -85,18 +86,16 @@
showAddModal = true; showAddModal = true;
} }
function openEditModal(manager) { function openEditModal(person) {
selectedManager = manager; selectedPersonnel = person;
formData = { formData = {
full_name: manager.full_name, full_name: person.full_name,
rank: manager.rank, rank: person.rank,
registration_number: manager.registration_number, registration_number: person.registration_number,
tc_kimlik: manager.tc_kimlik, tc_kimlik: person.tc_kimlik,
phone: manager.phone, phone: person.phone,
email: manager.email, unit_id: person.unit_id || '',
username: manager.username || '', is_active: person.is_active
password: '', // Şifre gösterilmez, değiştirilmek istenirse girilir
is_active: manager.is_active
}; };
showEditModal = true; showEditModal = true;
} }
@@ -107,8 +106,8 @@
resetForm(); resetForm();
} }
async function handleAddManager() { async function handleAddPersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username || !formData.password) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -118,18 +117,8 @@
return; return;
} }
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) {
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.';
return;
}
if (formData.password.length < 6) {
error = 'Şifre en az 6 karakter olmalıdır.';
return;
}
try { try {
const response = await fetch('/api/goods-managers', { const response = await fetch('/api/fuel-personnel', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -140,7 +129,7 @@
const data = await response.json(); const data = await response.json();
if (response.ok) { if (response.ok) {
await loadGoodsManagers(); await loadPersonnel();
closeModal(); closeModal();
error = ''; error = '';
} else { } else {
@@ -148,13 +137,13 @@
} }
} catch (err) { } catch (err) {
error = 'Bağlantı hatası.'; error = 'Bağlantı hatası.';
console.error('Add manager error:', err); console.error('Add personnel error:', err);
} }
} }
async function handleUpdateManager() { async function handleUpdatePersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Kullanıcı adı hariç tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -163,24 +152,14 @@
return; return;
} }
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) {
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.';
return;
}
if (formData.password && formData.password.trim().length > 0 && formData.password.length < 6) {
error = 'Şifre en az 6 karakter olmalıdır.';
return;
}
try { try {
const response = await fetch('/api/goods-managers', { const response = await fetch('/api/fuel-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
id: selectedManager.id, id: selectedPersonnel.id,
...formData ...formData
}), }),
}); });
@@ -188,7 +167,7 @@
const data = await response.json(); const data = await response.json();
if (response.ok) { if (response.ok) {
await loadGoodsManagers(); await loadPersonnel();
closeModal(); closeModal();
error = ''; error = '';
} else { } else {
@@ -196,63 +175,63 @@
} }
} catch (err) { } catch (err) {
error = 'Bağlantı hatası.'; error = 'Bağlantı hatası.';
console.error('Update manager error:', err); console.error('Update personnel error:', err);
} }
} }
async function handleDeleteManager(manager) { async function handleDeletePersonnel(person) {
if (!confirm(`${manager.rank} ${manager.full_name} personelini silmek istediğinizden emin misiniz?`)) { if (!confirm(`${person.rank} ${person.full_name} personelini silmek istediğinizden emin misiniz?`)) {
return; return;
} }
try { try {
const response = await fetch('/api/goods-managers', { const response = await fetch('/api/fuel-personnel', {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ id: manager.id }), body: JSON.stringify({ id: person.id }),
}); });
const data = await response.json(); const data = await response.json();
if (response.ok) { if (response.ok) {
await loadGoodsManagers(); await loadPersonnel();
error = ''; error = '';
} else { } else {
error = data.message || 'Personel silinemedi.'; error = data.message || 'Personel silinemedi.';
} }
} catch (err) { } catch (err) {
error = 'Bağlantı hatası.'; error = 'Bağlantı hatası.';
console.error('Delete manager error:', err); console.error('Delete personnel error:', err);
} }
} }
async function toggleManagerStatus(manager) { async function togglePersonnelStatus(person) {
try { try {
const response = await fetch('/api/goods-managers', { const response = await fetch('/api/fuel-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
id: manager.id, id: person.id,
...manager, ...person,
is_active: !manager.is_active is_active: !person.is_active
}), }),
}); });
const data = await response.json(); const data = await response.json();
if (response.ok) { if (response.ok) {
await loadGoodsManagers(); await loadPersonnel();
error = ''; error = '';
} else { } else {
error = data.message || 'Personel durumu güncellenemedi.'; error = data.message || 'Personel durumu güncellenemedi.';
} }
} catch (err) { } catch (err) {
error = 'Bağlantı hatası.'; error = 'Bağlantı hatası.';
console.error('Toggle manager status error:', err); console.error('Toggle personnel status error:', err);
} }
} }
</script> </script>
@@ -282,7 +261,7 @@
<div class="spinner"></div> <div class="spinner"></div>
<p>Yükleniyor...</p> <p>Yükleniyor...</p>
</div> </div>
{:else if goodsManagers.length === 0} {:else if personnel.length === 0}
<div class="empty-state"> <div class="empty-state">
<div class="empty-icon"> <div class="empty-icon">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -297,14 +276,14 @@
</div> </div>
{:else} {:else}
<div class="managers-grid"> <div class="managers-grid">
{#each goodsManagers as manager (manager.id)} {#each personnel as person (person.id)}
<div class="manager-card card {manager.is_active ? '' : 'inactive'}"> <div class="manager-card card {person.is_active ? '' : 'inactive'}">
<div class="manager-header"> <div class="manager-header">
<div class="manager-info"> <div class="manager-info">
<h3 class="manager-name">{manager.rank} {manager.full_name}</h3> <h3 class="manager-name">{person.rank} {person.full_name}</h3>
<div class="manager-status"> <div class="manager-status">
<span class="status-badge {manager.is_active ? 'active' : 'inactive'}"> <span class="status-badge {person.is_active ? 'active' : 'inactive'}">
{@html manager.is_active ? '<i class="fas fa-check"></i> Aktif' : '<i class="fas fa-times"></i> Pasif'} {@html person.is_active ? '<i class="fas fa-check"></i> Aktif' : '<i class="fas fa-times"></i> Pasif'}
</span> </span>
</div> </div>
</div> </div>
@@ -317,7 +296,7 @@
</div> </div>
<div class="detail-content"> <div class="detail-content">
<span class="detail-label">Sicil No:</span> <span class="detail-label">Sicil No:</span>
<span class="detail-value">{manager.registration_number}</span> <span class="detail-value">{person.registration_number}</span>
</div> </div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
@@ -326,7 +305,7 @@
</div> </div>
<div class="detail-content"> <div class="detail-content">
<span class="detail-label">TC Kimlik:</span> <span class="detail-label">TC Kimlik:</span>
<span class="detail-value">{manager.tc_kimlik}</span> <span class="detail-value">{person.tc_kimlik}</span>
</div> </div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
@@ -335,7 +314,7 @@
</div> </div>
<div class="detail-content"> <div class="detail-content">
<span class="detail-label">Birlik:</span> <span class="detail-label">Birlik:</span>
<span class="detail-value">{manager.unit_name || 'Belirtilmemiş'}</span> <span class="detail-value">{getUnitName(person.unit_id)}</span>
</div> </div>
</div> </div>
<div class="detail-item"> <div class="detail-item">
@@ -344,33 +323,24 @@
</div> </div>
<div class="detail-content"> <div class="detail-content">
<span class="detail-label">İrtibat:</span> <span class="detail-label">İrtibat:</span>
<span class="detail-value">{manager.phone}</span> <span class="detail-value">{person.phone}</span>
</div>
</div>
<div class="detail-item">
<div class="detail-icon">
<i class="fas fa-user"></i>
</div>
<div class="detail-content">
<span class="detail-label">Kullanıcı Adı:</span>
<span class="detail-value">{manager.username || 'Belirlenmemiş'}</span>
</div> </div>
</div> </div>
</div> </div>
<div class="manager-actions"> <div class="manager-actions">
<button class="btn btn-sm btn-secondary" on:click={() => openEditModal(manager)}> <button class="btn btn-sm btn-secondary" on:click={() => openEditModal(person)}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</svg> </svg>
Düzenle Düzenle
</button> </button>
<button <button
class="btn btn-sm {manager.is_active ? 'btn-warning' : 'btn-success'}" class="btn btn-sm {person.is_active ? 'btn-warning' : 'btn-success'}"
on:click={() => toggleManagerStatus(manager)} on:click={() => togglePersonnelStatus(person)}
> >
{#if manager.is_active} {#if person.is_active}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/> <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
<path d="M7 11V7a5 5 0 0 1 10 0v4"/> <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
@@ -385,7 +355,7 @@
Aktif Yap Aktif Yap
{/if} {/if}
</button> </button>
<button class="btn btn-sm btn-danger" on:click={() => handleDeleteManager(manager)}> <button class="btn btn-sm btn-danger" on:click={() => handleDeletePersonnel(person)}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="3 6 5 6 21 6"/> <polyline points="3 6 5 6 21 6"/>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/> <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
@@ -399,7 +369,7 @@
{/if} {/if}
</div> </div>
<!-- Mal Sorumlusu Ekle Modal --> <!-- Personel Ekle Modal -->
{#if showAddModal} {#if showAddModal}
<div class="modal-overlay" on:click={closeModal}> <div class="modal-overlay" on:click={closeModal}>
<div class="modal" on:click|stopPropagation> <div class="modal" on:click|stopPropagation>
@@ -407,7 +377,7 @@
<h2>Yeni Personel Ekle</h2> <h2>Yeni Personel Ekle</h2>
<button class="modal-close" on:click={closeModal}>×</button> <button class="modal-close" on:click={closeModal}>×</button>
</div> </div>
<form on:submit|preventDefault={handleAddManager} class="modal-form"> <form on:submit|preventDefault={handleAddPersonnel} class="modal-form">
<div class="form-group"> <div class="form-group">
<label for="full_name">Adı Soyadı</label> <label for="full_name">Adı Soyadı</label>
<input <input
@@ -478,31 +448,6 @@
{/each} {/each}
</select> </select>
</div> </div>
<div class="form-group">
<label for="username">Kullanıcı Adı</label>
<input
id="username"
type="text"
class="form-input"
bind:value={formData.username}
placeholder="ibrahim.kara"
required
/>
<small style="color: var(--text-secondary); font-size: 0.8rem; margin-top: 0.25rem; display: block;">
Bu kullanıcı adı ile sisteme giriş yapabilecek.
</small>
</div>
<div class="form-group">
<label for="password">Şifre</label>
<input
id="password"
type="password"
class="form-input"
bind:value={formData.password}
placeholder="En az 6 karakter"
required
/>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button> <button type="submit" class="btn btn-primary">Kaydet</button>
@@ -512,7 +457,7 @@
</div> </div>
{/if} {/if}
<!-- Mal Sorumlusu Düzenle Modal --> <!-- Personel Düzenle Modal -->
{#if showEditModal} {#if showEditModal}
<div class="modal-overlay" on:click={closeModal}> <div class="modal-overlay" on:click={closeModal}>
<div class="modal" on:click|stopPropagation> <div class="modal" on:click|stopPropagation>
@@ -520,7 +465,7 @@
<h2>Personel Düzenle</h2> <h2>Personel Düzenle</h2>
<button class="modal-close" on:click={closeModal}>×</button> <button class="modal-close" on:click={closeModal}>×</button>
</div> </div>
<form on:submit|preventDefault={handleUpdateManager} class="modal-form"> <form on:submit|preventDefault={handleUpdatePersonnel} class="modal-form">
<div class="form-group"> <div class="form-group">
<label for="edit-full_name">Adı Soyadı</label> <label for="edit-full_name">Adı Soyadı</label>
<input <input
@@ -591,33 +536,6 @@
{/each} {/each}
</select> </select>
</div> </div>
<div class="form-group">
<label for="edit-username">Kullanıcı Adı</label>
<input
id="edit-username"
type="text"
class="form-input"
bind:value={formData.username}
placeholder="ibrahim.kara"
required
/>
<small style="color: var(--text-secondary); font-size: 0.8rem; margin-top: 0.25rem; display: block;">
Bu kullanıcı adı ile sisteme giriş yapabilecek.
</small>
</div>
<div class="form-group">
<label for="edit-password">Yeni Şifre (Opsiyonel)</label>
<input
id="edit-password"
type="password"
class="form-input"
bind:value={formData.password}
placeholder="Değiştirmek için yeni şifre girin"
/>
<small style="color: var(--text-secondary); font-size: 0.8rem; margin-top: 0.25rem; display: block;">
Boş bırakırsanız mevcut şifre korunur.
</small>
</div>
<div class="form-group"> <div class="form-group">
<label class="checkbox-label"> <label class="checkbox-label">
<input <input
@@ -1023,4 +941,4 @@
text-align: left; text-align: left;
} }
} }
</style> </style>

View File

@@ -4,7 +4,8 @@
// Props // Props
export let user = null; export let user = null;
let personnel = []; let personnel = [];
let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -12,20 +13,34 @@
let selectedPersonnel = null; let selectedPersonnel = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
is_active: true unit_id: '',
}; is_active: true
};
onMount(async () => { onMount(async () => {
await loadPersonnel(); await loadUnits();
}); await loadPersonnel();
});
async function loadPersonnel() { async function loadUnits() {
try {
const response = await fetch('/api/units');
if (response.ok) {
const data = await response.json();
units = data.units || [];
}
} catch (err) {
console.error('Load units error:', err);
}
}
async function loadPersonnel() {
try { try {
const response = await fetch('/api/fuel-personnel'); const response = await fetch('/api/fuel-personnel');
if (response.ok) { if (response.ok) {
@@ -42,35 +57,37 @@
} }
} }
function resetForm() { function resetForm() {
formData = { formData = {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
is_active: true unit_id: '',
}; is_active: true
selectedPersonnel = null; };
} selectedPersonnel = null;
}
function openAddModal() { function openAddModal() {
resetForm(); resetForm();
showAddModal = true; showAddModal = true;
} }
function openEditModal(person) { function openEditModal(person) {
selectedPersonnel = person; selectedPersonnel = person;
formData = { formData = {
full_name: person.full_name, full_name: person.full_name,
rank: person.rank, rank: person.rank,
registration_number: person.registration_number, registration_number: person.registration_number,
tc_kimlik: person.tc_kimlik, tc_kimlik: person.tc_kimlik,
phone: person.phone, phone: person.phone,
is_active: person.is_active unit_id: person.unit_id || '',
}; is_active: person.is_active
showEditModal = true; };
} showEditModal = true;
}
function closeModal() { function closeModal() {
showAddModal = false; showAddModal = false;
@@ -79,10 +96,10 @@
} }
async function handleAddPersonnel() { async function handleAddPersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
@@ -114,10 +131,10 @@
} }
async function handleUpdatePersonnel() { async function handleUpdatePersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
@@ -371,22 +388,36 @@
required required
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="phone">İrtibat Numarası</label> <label for="phone">İrtibat Numarası</label>
<input <input
id="phone" id="phone"
type="tel" type="tel"
class="form-input" class="form-input"
bind:value={formData.phone} bind:value={formData.phone}
placeholder="05321234567" placeholder="05321234567"
required required
/> />
</div> </div>
<div class="modal-actions"> <div class="form-group">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <label for="unit_id">Birlik</label>
<button type="submit" class="btn btn-primary">Kaydet</button> <select
</div> id="unit_id"
</form> class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button>
</div>
</form>
</div> </div>
</div> </div>
{/if} {/if}
@@ -445,22 +476,36 @@
required required
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="edit-phone">İrtibat Numarası</label> <label for="edit-phone">İrtibat Numarası</label>
<input <input
id="edit-phone" id="edit-phone"
type="tel" type="tel"
class="form-input" class="form-input"
bind:value={formData.phone} bind:value={formData.phone}
placeholder="05321234567" placeholder="05321234567"
required required
/> />
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="checkbox-label"> <label for="edit-unit_id">Birlik</label>
<input <select
type="checkbox" id="edit-unit_id"
bind:checked={formData.is_active} class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group">
<label class="checkbox-label">
<input
type="checkbox"
bind:checked={formData.is_active}
/> />
<span class="checkmark"></span> <span class="checkmark"></span>
Personel Aktif Personel Aktif
@@ -877,4 +922,4 @@
font-size: 0.8rem; font-size: 0.8rem;
} }
} }
</style> </style>

View File

@@ -12,19 +12,21 @@
let selectedUnit = null; let selectedUnit = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
name: '', name: '',
address: '', address: '',
stk: '', stk: '',
btk: '', btk: '',
commander: { commander: {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '' phone: '',
} username: '',
}; password: ''
}
};
onMount(async () => { onMount(async () => {
await loadUnits(); await loadUnits();
@@ -53,16 +55,18 @@
address: '', address: '',
stk: '', stk: '',
btk: '', btk: '',
commander: { commander: {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '' phone: '',
} username: '',
}; password: ''
selectedUnit = null; }
} };
selectedUnit = null;
}
function openAddModal() { function openAddModal() {
resetForm(); resetForm();
@@ -71,15 +75,23 @@
function openEditModal(unit) { function openEditModal(unit) {
selectedUnit = unit; selectedUnit = unit;
formData = { formData = {
name: unit.name, name: unit.name,
address: unit.address, address: unit.address,
stk: unit.stk, stk: unit.stk,
btk: unit.btk, btk: unit.btk,
commander: { ...unit.commander } commander: {
}; full_name: unit.commander.full_name,
showEditModal = true; rank: unit.commander.rank,
} registration_number: unit.commander.registration_number,
tc_kimlik: unit.commander.tc_kimlik,
phone: unit.commander.phone,
username: unit.commander.username || '',
password: unit.commander.password || ''
}
};
showEditModal = true;
}
function closeModal() { function closeModal() {
showAddModal = false; showAddModal = false;
@@ -94,10 +106,10 @@
} }
const { commander } = formData; const { commander } = formData;
if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone) { if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone || !commander.username || !commander.password) {
error = 'Birlik sorumlusunun tüm bilgileri zorunludur.'; error = 'Mal sorumlusunun tüm bilgileri zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(commander.tc_kimlik)) { if (!/^[0-9]{11}$/.test(commander.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
@@ -135,10 +147,10 @@
} }
const { commander } = formData; const { commander } = formData;
if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone) { if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone || !commander.username || !commander.password) {
error = 'Birlik sorumlusunun tüm bilgileri zorunludur.'; error = 'Mal sorumlusunun tüm bilgileri zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(commander.tc_kimlik)) { if (!/^[0-9]{11}$/.test(commander.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
@@ -358,8 +370,8 @@
</div> </div>
</div> </div>
<div class="form-section"> <div class="form-section">
<h3>Birlik Sorumlusu</h3> <h3>Mal Sorumlusu</h3>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="commander-name">Adı Soyadı</label> <label for="commander-name">Adı Soyadı</label>
@@ -408,19 +420,43 @@
/> />
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="commander-tc">TC Kimlik Numarası</label> <label for="commander-tc">TC Kimlik Numarası</label>
<input <input
id="commander-tc" id="commander-tc"
type="text" type="text"
class="form-input" class="form-input"
bind:value={formData.commander.tc_kimlik} bind:value={formData.commander.tc_kimlik}
placeholder="12345678901" placeholder="12345678901"
maxlength="11" maxlength="11"
required required
/> />
</div> </div>
</div> <div class="form-row">
<div class="form-group">
<label for="commander-username">Kullanıcı Adı</label>
<input
id="commander-username"
type="text"
class="form-input"
bind:value={formData.commander.username}
placeholder="kullanici_adi"
required
/>
</div>
<div class="form-group">
<label for="commander-password">Şifre</label>
<input
id="commander-password"
type="password"
class="form-input"
bind:value={formData.commander.password}
placeholder="En az 6 karakter"
required
/>
</div>
</div>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
@@ -490,8 +526,8 @@
</div> </div>
</div> </div>
<div class="form-section"> <div class="form-section">
<h3>Birlik Sorumlusu</h3> <h3>Mal Sorumlusu</h3>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="edit-commander-name">Adı Soyadı</label> <label for="edit-commander-name">Adı Soyadı</label>
@@ -540,19 +576,43 @@
/> />
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="edit-commander-tc">TC Kimlik Numarası</label> <label for="edit-commander-tc">TC Kimlik Numarası</label>
<input <input
id="edit-commander-tc" id="edit-commander-tc"
type="text" type="text"
class="form-input" class="form-input"
bind:value={formData.commander.tc_kimlik} bind:value={formData.commander.tc_kimlik}
placeholder="12345678901" placeholder="12345678901"
maxlength="11" maxlength="11"
required required
/> />
</div> </div>
</div> <div class="form-row">
<div class="form-group">
<label for="edit-commander-username">Kullanıcı Adı</label>
<input
id="edit-commander-username"
type="text"
class="form-input"
bind:value={formData.commander.username}
placeholder="kullanici_adi"
required
/>
</div>
<div class="form-group">
<label for="edit-commander-password">Şifre</label>
<input
id="edit-commander-password"
type="password"
class="form-input"
bind:value={formData.commander.password}
placeholder="En az 6 karakter"
required
/>
</div>
</div>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
@@ -920,4 +980,4 @@
flex-direction: column; flex-direction: column;
} }
} }
</style> </style>

View File

@@ -539,27 +539,6 @@
</li> </li>
{#if user.role === "admin"} {#if user.role === "admin"}
<li class="nav-item">
<button
class="nav-btn"
on:click={() => navigateTo("vehicles")}
class:active={showVehicles}
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path d="M19 9l-7 7-7-7" />
<rect x="11" y="5" width="2" height="14" />
<path d="M5 5v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V5" />
</svg>
Araç Yönetimi
</button>
</li>
<li class="nav-item"> <li class="nav-item">
<button <button
class="nav-btn" class="nav-btn"
@@ -581,6 +560,27 @@
Birlik Yönetimi Birlik Yönetimi
</button> </button>
</li> </li>
<li class="nav-item">
<button
class="nav-btn"
on:click={() => navigateTo("vehicles")}
class:active={showVehicles}
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path d="M19 9l-7 7-7-7" />
<rect x="11" y="5" width="2" height="14" />
<path d="M5 5v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V5" />
</svg>
Araç Yönetimi
</button>
</li>
<li class="nav-item"> <li class="nav-item">
<button <button
class="nav-btn" class="nav-btn"
@@ -759,7 +759,7 @@
<line x1="3" y1="18" x2="21" y2="18" /> <line x1="3" y1="18" x2="21" y2="18" />
</svg> </svg>
</button> </button>
</div> </div>
</div> </div>
<!-- Ayırıcı --> <!-- Ayırıcı -->

View File

@@ -11,7 +11,7 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
let user = null; let user = null;
let goodsManagers = []; let personnel = [];
let units = []; let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
@@ -19,18 +19,16 @@
let showEditModal = false; let showEditModal = false;
let selectedManager = null; let selectedManager = null;
// Form değişkenleri // Form değişkenleri
let formData = { let formData = {
full_name: '', full_name: '',
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '', unit_id: '',
username: '', is_active: true
password: '', };
is_active: true
};
onMount(async () => { onMount(async () => {
const userData = localStorage.getItem('user'); const userData = localStorage.getItem('user');
@@ -39,75 +37,76 @@
return; return;
} }
user = JSON.parse(userData); user = JSON.parse(userData);
await loadGoodsManagers(); await loadUnits();
await loadUnits(); await loadGoodsManagers();
}); });
async function loadGoodsManagers() { async function loadGoodsManagers() {
try { try {
const response = await fetch('/api/goods-managers'); const response = await fetch('/api/fuel-personnel');
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
goodsManagers = data.goodsManagers; personnel = data.fuelPersonnel || [];
} else { } else {
error = 'Personel bilgileri yüklenemedi.'; error = 'Personel bilgileri yüklenemedi.';
}
} catch (err) {
error = 'Bağlantı hatası.';
console.error('Load goods managers error:', err);
} finally {
loading = false;
} }
} catch (err) {
error = 'Bağlantı hatası.';
console.error('Load personnel error:', err);
} finally {
loading = false;
} }
}
async function loadUnits() { async function loadUnits() {
try { try {
const response = await fetch('/api/units'); const response = await fetch('/api/units');
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
units = data.units || []; units = data.units || [];
}
} catch (err) {
console.error('Load units error:', err);
} }
} catch (err) {
console.error('Load units error:', err);
} }
}
function resetForm() { function getUnitName(unitId) {
formData = { const id = parseInt(unitId);
full_name: '', return units.find((unit) => unit.id === id)?.name || 'Belirtilmemiş';
rank: '', }
registration_number: '',
tc_kimlik: '', function resetForm() {
phone: '', formData = {
unit_id: '', full_name: '',
username: '', rank: '',
password: '', registration_number: '',
is_active: true tc_kimlik: '',
}; phone: '',
selectedManager = null; unit_id: '',
} is_active: true
};
selectedManager = null;
}
function openAddModal() { function openAddModal() {
resetForm(); resetForm();
showAddModal = true; showAddModal = true;
} }
function openEditModal(manager) { function openEditModal(manager) {
selectedManager = manager; selectedManager = manager;
formData = { formData = {
full_name: manager.full_name, full_name: manager.full_name,
rank: manager.rank, rank: manager.rank,
registration_number: manager.registration_number, registration_number: manager.registration_number,
tc_kimlik: manager.tc_kimlik, tc_kimlik: manager.tc_kimlik,
phone: manager.phone, phone: manager.phone,
email: manager.email, unit_id: manager.unit_id || '',
username: manager.username || '', is_active: manager.is_active
password: '', // Şifre gösterilmez, değiştirilmek istenirse girilir };
is_active: manager.is_active showEditModal = true;
}; }
showEditModal = true;
}
function closeModal() { function closeModal() {
showAddModal = false; showAddModal = false;
@@ -115,32 +114,22 @@
resetForm(); resetForm();
} }
async function handleAddManager() { async function handleAddManager() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username || !formData.password) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
return; return;
} }
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) { try {
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.'; const response = await fetch('/api/fuel-personnel', {
return; method: 'POST',
} headers: {
'Content-Type': 'application/json',
if (formData.password.length < 6) {
error = 'Şifre en az 6 karakter olmalıdır.';
return;
}
try {
const response = await fetch('/api/goods-managers', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}, },
body: JSON.stringify(formData), body: JSON.stringify(formData),
}); });
@@ -160,36 +149,26 @@
} }
} }
async function handleUpdateManager() { async function handleUpdateManager() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Kullanıcı adı hariç tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) { if (!/^[0-9]{11}$/.test(formData.tc_kimlik)) {
error = 'TC Kimlik numarası 11 haneli olmalıdır.'; error = 'TC Kimlik numarası 11 haneli olmalıdır.';
return; return;
} }
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) { try {
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.'; const response = await fetch('/api/fuel-personnel', {
return; method: 'PUT',
} headers: {
'Content-Type': 'application/json',
if (formData.password && formData.password.trim().length > 0 && formData.password.length < 6) { },
error = 'Şifre en az 6 karakter olmalıdır.'; body: JSON.stringify({
return; id: selectedManager.id,
} ...formData
try {
const response = await fetch('/api/goods-managers', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: selectedManager.id,
...formData
}), }),
}); });
@@ -214,7 +193,7 @@
} }
try { try {
const response = await fetch('/api/goods-managers', { const response = await fetch('/api/fuel-personnel', {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -238,7 +217,7 @@
async function toggleManagerStatus(manager) { async function toggleManagerStatus(manager) {
try { try {
const response = await fetch('/api/goods-managers', { const response = await fetch('/api/fuel-personnel', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -301,7 +280,7 @@
<div class="spinner"></div> <div class="spinner"></div>
<p>Yükleniyor...</p> <p>Yükleniyor...</p>
</div> </div>
{:else if goodsManagers.length === 0} {:else if personnel.length === 0}
<div class="empty-state"> <div class="empty-state">
<div class="empty-icon"> <div class="empty-icon">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -316,7 +295,7 @@
</div> </div>
{:else} {:else}
<div class="managers-grid"> <div class="managers-grid">
{#each goodsManagers as manager (manager.id)} {#each personnel as manager (manager.id)}
<div class="manager-card card {manager.is_active ? '' : 'inactive'}"> <div class="manager-card card {manager.is_active ? '' : 'inactive'}">
<div class="manager-header"> <div class="manager-header">
<div class="manager-info"> <div class="manager-info">
@@ -338,18 +317,14 @@
<span class="detail-label">🆔 TC Kimlik:</span> <span class="detail-label">🆔 TC Kimlik:</span>
<span class="detail-value">{manager.tc_kimlik}</span> <span class="detail-value">{manager.tc_kimlik}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="detail-label">🏢 Birlik:</span> <span class="detail-label">🏢 Birlik:</span>
<span class="detail-value">{manager.unit_name || 'Belirtilmemiş'}</span> <span class="detail-value">{getUnitName(manager.unit_id)}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="detail-label">📱 İrtibat:</span> <span class="detail-label">📱 İrtibat:</span>
<span class="detail-value">{manager.phone}</span> <span class="detail-value">{manager.phone}</span>
</div> </div>
<div class="detail-item">
<span class="detail-label">👤 Kullanıcı Adı:</span>
<span class="detail-value">{manager.username || 'Belirlenmemiş'}</span>
</div>
</div> </div>
<div class="manager-actions"> <div class="manager-actions">
@@ -393,7 +368,7 @@
{/if} {/if}
</div> </div>
<!-- Mal Sorumlusu Ekle Modal --> <!-- Personel Ekle Modal -->
{#if showAddModal} {#if showAddModal}
<div class="modal-overlay" on:click={closeModal}> <div class="modal-overlay" on:click={closeModal}>
<div class="modal" on:click|stopPropagation> <div class="modal" on:click|stopPropagation>
@@ -472,31 +447,6 @@
{/each} {/each}
</select> </select>
</div> </div>
<div class="form-group">
<label for="username">Kullanıcı Adı</label>
<input
id="username"
type="text"
class="form-input"
bind:value={formData.username}
placeholder="ibrahim.kara"
required
/>
<small style="color: var(--text-secondary); font-size: 0.8rem; margin-top: 0.25rem; display: block;">
Bu kullanıcı adı ile sisteme giriş yapabilecek.
</small>
</div>
<div class="form-group">
<label for="password">Şifre</label>
<input
id="password"
type="password"
class="form-input"
bind:value={formData.password}
placeholder="En az 6 karakter"
required
/>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button> <button type="submit" class="btn btn-primary">Kaydet</button>
@@ -585,33 +535,6 @@
{/each} {/each}
</select> </select>
</div> </div>
<div class="form-group">
<label for="edit-username">Kullanıcı Adı</label>
<input
id="edit-username"
type="text"
class="form-input"
bind:value={formData.username}
placeholder="ibrahim.kara"
required
/>
<small style="color: var(--text-secondary); font-size: 0.8rem; margin-top: 0.25rem; display: block;">
Bu kullanıcı adı ile sisteme giriş yapabilecek.
</small>
</div>
<div class="form-group">
<label for="edit-password">Yeni Şifre (Opsiyonel)</label>
<input
id="edit-password"
type="password"
class="form-input"
bind:value={formData.password}
placeholder="Değiştirmek için yeni şifre girin"
/>
<small style="color: var(--text-secondary); font-size: 0.8rem; margin-top: 0.25rem; display: block;">
Boş bırakırsanız mevcut şifre korunur.
</small>
</div>
<div class="form-group"> <div class="form-group">
<label class="checkbox-label"> <label class="checkbox-label">
<input <input
@@ -974,4 +897,4 @@
text-align: left; text-align: left;
} }
} }
</style> </style>

View File

@@ -12,6 +12,7 @@
let user = null; let user = null;
let personnel = []; let personnel = [];
let units = [];
let loading = true; let loading = true;
let error = ''; let error = '';
let showAddModal = false; let showAddModal = false;
@@ -25,6 +26,7 @@
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '',
is_active: true is_active: true
}; };
@@ -36,9 +38,25 @@
} }
user = JSON.parse(userData); user = JSON.parse(userData);
await loadUnits();
await loadPersonnel(); await loadPersonnel();
}); });
async function loadUnits() {
try {
const response = await fetch('/api/units');
if (response.ok) {
const data = await response.json();
units = data.units;
} else {
error = 'Birlik listesi yüklenemedi.';
}
} catch (err) {
error = 'Bağlantı hatası.';
console.error('Load units error:', err);
}
}
async function loadPersonnel() { async function loadPersonnel() {
try { try {
const response = await fetch('/api/fuel-personnel'); const response = await fetch('/api/fuel-personnel');
@@ -63,6 +81,7 @@
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '', phone: '',
unit_id: '',
is_active: true is_active: true
}; };
selectedPersonnel = null; selectedPersonnel = null;
@@ -81,6 +100,7 @@
registration_number: person.registration_number, registration_number: person.registration_number,
tc_kimlik: person.tc_kimlik, tc_kimlik: person.tc_kimlik,
phone: person.phone, phone: person.phone,
unit_id: person.unit_id || '',
is_active: person.is_active is_active: person.is_active
}; };
showEditModal = true; showEditModal = true;
@@ -93,7 +113,7 @@
} }
async function handleAddPersonnel() { async function handleAddPersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -128,7 +148,7 @@
} }
async function handleUpdatePersonnel() { async function handleUpdatePersonnel() {
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone) { if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id) {
error = 'Tüm alanlar zorunludur.'; error = 'Tüm alanlar zorunludur.';
return; return;
} }
@@ -236,7 +256,7 @@
</svg> </svg>
Geri Geri
</button> </button>
<h1 class="page-title">Yakıt Personeli</h1> <h1 class="page-title">Personel İşlemleri</h1>
</div> </div>
<button class="btn btn-primary" on:click={openAddModal}> <button class="btn btn-primary" on:click={openAddModal}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -269,7 +289,7 @@
</svg> </svg>
</div> </div>
<h3>Henüz Personel Yok</h3> <h3>Henüz Personel Yok</h3>
<p>Sisteme yakıt personeli eklemek için "Yeni Personel Ekle" butonuna tıklayın.</p> <p>Sisteme birlik personeli eklemek için "Yeni Personel Ekle" butonuna tıklayın.</p>
<button class="btn btn-primary" on:click={openAddModal}> <button class="btn btn-primary" on:click={openAddModal}>
İlk Personeli Ekle İlk Personeli Ekle
</button> </button>
@@ -425,6 +445,20 @@
required required
/> />
</div> </div>
<div class="form-group">
<label for="unit_id">Birlik</label>
<select
id="unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button> <button type="button" class="btn btn-secondary" on:click={closeModal}>İptal</button>
<button type="submit" class="btn btn-primary">Kaydet</button> <button type="submit" class="btn btn-primary">Kaydet</button>
@@ -499,6 +533,20 @@
required required
/> />
</div> </div>
<div class="form-group">
<label for="edit-unit_id">Birlik</label>
<select
id="edit-unit_id"
class="form-input"
bind:value={formData.unit_id}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group"> <div class="form-group">
<label class="checkbox-label"> <label class="checkbox-label">
<input <input

View File

@@ -29,7 +29,9 @@
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '' phone: '',
username: '',
password: ''
} }
}; };
@@ -72,7 +74,9 @@
rank: '', rank: '',
registration_number: '', registration_number: '',
tc_kimlik: '', tc_kimlik: '',
phone: '' phone: '',
username: '',
password: ''
} }
}; };
selectedUnit = null; selectedUnit = null;
@@ -90,7 +94,15 @@
address: unit.address, address: unit.address,
stk: unit.stk, stk: unit.stk,
btk: unit.btk, btk: unit.btk,
commander: { ...unit.commander } commander: {
full_name: unit.commander.full_name,
rank: unit.commander.rank,
registration_number: unit.commander.registration_number,
tc_kimlik: unit.commander.tc_kimlik,
phone: unit.commander.phone,
username: unit.commander.username || '',
password: unit.commander.password || ''
}
}; };
showEditModal = true; showEditModal = true;
} }
@@ -108,8 +120,8 @@
} }
const { commander } = formData; const { commander } = formData;
if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone) { if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone || !commander.username || !commander.password) {
error = 'Birlik sorumlusunun tüm bilgileri zorunludur.'; error = 'Mal sorumlusunun tüm bilgileri zorunludur.';
return; return;
} }
@@ -149,8 +161,8 @@
} }
const { commander } = formData; const { commander } = formData;
if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone) { if (!commander.full_name || !commander.rank || !commander.registration_number || !commander.tc_kimlik || !commander.phone || !commander.username || !commander.password) {
error = 'Birlik sorumlusunun tüm bilgileri zorunludur.'; error = 'Mal sorumlusunun tüm bilgileri zorunludur.';
return; return;
} }
@@ -289,7 +301,7 @@
</div> </div>
<div class="commander-section"> <div class="commander-section">
<h4 class="commander-title">Birlik Sorumlusu</h4> <h4 class="commander-title">Mal Sorumlusu</h4>
<div class="commander-info"> <div class="commander-info">
<div class="commander-details"> <div class="commander-details">
<p class="commander-name">{unit.commander.rank} {unit.commander.full_name}</p> <p class="commander-name">{unit.commander.rank} {unit.commander.full_name}</p>
@@ -382,7 +394,7 @@
</div> </div>
<div class="form-section"> <div class="form-section">
<h3>Birlik Sorumlusu</h3> <h3>Mal Sorumlusu</h3>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="commander-name">Adı Soyadı</label> <label for="commander-name">Adı Soyadı</label>
@@ -443,6 +455,30 @@
required required
/> />
</div> </div>
<div class="form-row">
<div class="form-group">
<label for="commander-username">Kullanıcı Adı</label>
<input
id="commander-username"
type="text"
class="form-input"
bind:value={formData.commander.username}
placeholder="kullanici_adi"
required
/>
</div>
<div class="form-group">
<label for="commander-password">Şifre</label>
<input
id="commander-password"
type="password"
class="form-input"
bind:value={formData.commander.password}
placeholder="şifre123"
required
/>
</div>
</div>
</div> </div>
<div class="modal-actions"> <div class="modal-actions">
@@ -514,7 +550,7 @@
</div> </div>
<div class="form-section"> <div class="form-section">
<h3>Birlik Sorumlusu</h3> <h3>Mal Sorumlusu</h3>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="edit-commander-name">Adı Soyadı</label> <label for="edit-commander-name">Adı Soyadı</label>
@@ -575,6 +611,30 @@
required required
/> />
</div> </div>
<div class="form-row">
<div class="form-group">
<label for="edit-commander-username">Kullanıcı Adı</label>
<input
id="edit-commander-username"
type="text"
class="form-input"
bind:value={formData.commander.username}
placeholder="kullanici_adi"
required
/>
</div>
<div class="form-group">
<label for="edit-commander-password">Şifre</label>
<input
id="edit-commander-password"
type="password"
class="form-input"
bind:value={formData.commander.password}
placeholder="şifre123"
required
/>
</div>
</div>
</div> </div>
<div class="modal-actions"> <div class="modal-actions">

View File

@@ -396,7 +396,7 @@ app.get('/api/units', (req, res) => {
}); });
// POST - Yeni birlik ekle // POST - Yeni birlik ekle
app.post('/api/units', (req, res) => { app.post('/api/units', async (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session) // Yetki kontrolü (temporary - will be implemented with proper session)
try { try {
@@ -414,9 +414,9 @@ app.post('/api/units', (req, res) => {
} }
// Komutan validasyonu // Komutan validasyonu
const { full_name, rank, registration_number, tc_kimlik, phone } = commander; const { full_name, rank, registration_number, tc_kimlik, phone, username, password } = commander;
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) { if (!full_name || !rank || !registration_number || !tc_kimlik || !phone || !username || !password) {
return res.status(400).json({ message: 'Birlik sorumlusunun tüm bilgileri zorunludur.' }); return res.status(400).json({ message: 'Mal sorumlusunun tüm bilgileri zorunludur.' });
} }
// TC Kimlik numarası validasyonu // TC Kimlik numarası validasyonu
@@ -436,11 +436,44 @@ app.post('/api/units', (req, res) => {
rank: rank.trim(), rank: rank.trim(),
registration_number: registration_number.trim(), registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(), tc_kimlik: tc_kimlik.trim(),
phone: phone.trim() phone: phone.trim(),
username: username.trim(),
password: password.trim()
}, },
created_at: new Date().toISOString() created_at: new Date().toISOString()
}; };
// Mal sorumlusu için kullanıcı oluştur
try {
const hashedPassword = await bcrypt.hash(password, 10);
// Kullanıcı adı benzersizliğini kontrol et
const existingUser = await new Promise((resolve, reject) => {
db.get('SELECT id FROM users WHERE username = ?', [username], (err, row) => {
if (err) reject(err);
else resolve(row);
});
});
if (existingUser) {
return res.status(400).json({ message: 'Bu kullanıcı adı zaten kullanımda.' });
}
// Mal sorumlusu kullanıcı olarak ekle
await new Promise((resolve, reject) => {
db.run('INSERT INTO users (username, password, role, full_name) VALUES (?, ?, ?, ?)',
[username, hashedPassword, 'goods_manager', full_name], (err) => {
if (err) reject(err);
else resolve();
});
});
console.log(`✅ Mal sorumlusu kullanıcı oluşturuldu: ${username}`);
} catch (userError) {
console.error('❌ Mal sorumlusu kullanıcı oluşturma hatası:', userError);
return res.status(500).json({ message: 'Mal sorumlusu kullanıcı oluşturulamadı.' });
}
units.push(newUnit); units.push(newUnit);
res.json({ res.json({
@@ -454,7 +487,7 @@ app.post('/api/units', (req, res) => {
}); });
// PUT - Birlik güncelle // PUT - Birlik güncelle
app.put('/api/units', (req, res) => { app.put('/api/units', async (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session) // Yetki kontrolü (temporary - will be implemented with proper session)
try { try {
@@ -473,9 +506,9 @@ app.put('/api/units', (req, res) => {
} }
// Komutan validasyonu // Komutan validasyonu
const { full_name, rank, registration_number, tc_kimlik, phone } = commander; const { full_name, rank, registration_number, tc_kimlik, phone, username, password } = commander;
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) { if (!full_name || !rank || !registration_number || !tc_kimlik || !phone || !username || !password) {
return res.status(400).json({ message: 'Birlik sorumlusunun tüm bilgileri zorunludur.' }); return res.status(400).json({ message: 'Mal sorumlusunun tüm bilgileri zorunludur.' });
} }
// TC Kimlik numarası validasyonu // TC Kimlik numarası validasyonu
@@ -490,21 +523,52 @@ app.put('/api/units', (req, res) => {
} }
// Birlik güncelle // Birlik güncelle
const updatedCommander = {
full_name: full_name.trim(),
rank: rank.trim(),
registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(),
phone: phone.trim(),
username: username.trim(),
password: password.trim()
};
units[unitIndex] = { units[unitIndex] = {
...units[unitIndex], ...units[unitIndex],
name: name.trim(), name: name.trim(),
address: address.trim(), address: address.trim(),
stk: stk.trim().toUpperCase(), stk: stk.trim().toUpperCase(),
btk: btk.trim().toUpperCase(), btk: btk.trim().toUpperCase(),
commander: { commander: updatedCommander
full_name: full_name.trim(),
rank: rank.trim(),
registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(),
phone: phone.trim()
}
}; };
// Eğer kullanıcı adı veya şifre değişmişse, kullanıcıyı güncelle
const oldCommander = units[unitIndex].commander;
if (oldCommander.username !== username || password !== oldCommander.password) {
try {
const hashedPassword = await bcrypt.hash(password, 10);
// Kullanıcıyı güncelle
await new Promise((resolve, reject) => {
db.run('UPDATE users SET username = ?, password = ?, full_name = ? WHERE username = ?',
[username, hashedPassword, full_name, oldCommander.username], (err) => {
if (err) reject(err);
else resolve();
});
});
console.log(`✅ Mal sorumlusu kullanıcı güncellendi: ${username}`);
} catch (userError) {
console.error('❌ Mal sorumlusu kullanıcı güncelleme hatası:', userError);
// Kullanıcı güncellenemezse, birlik güncellemesi geri alınsın
units[unitIndex] = {
...units[unitIndex],
commander: oldCommander
};
return res.status(500).json({ message: 'Mal sorumlusu kullanıcı güncellenemedi.' });
}
}
res.json({ res.json({
message: 'Birlik başarıyla güncellendi.', message: 'Birlik başarıyla güncellendi.',
unit: units[unitIndex] unit: units[unitIndex]
@@ -687,7 +751,7 @@ app.get('/api/fuel-personnel', (req, res) => {
}); });
// POST - Yeni yakıt personeli ekle // POST - Yeni yakıt personeli ekle
app.post('/api/fuel-personnel', (req, res) => { app.post('/api/fuel-personnel', async (req, res) => {
// Yetki kontrolü (temporary - will be implemented with proper session) // Yetki kontrolü (temporary - will be implemented with proper session)
try { try {
@@ -697,11 +761,12 @@ app.post('/api/fuel-personnel', (req, res) => {
registration_number, registration_number,
tc_kimlik, tc_kimlik,
phone, phone,
unit_id,
is_active = true is_active = true
} = req.body; } = req.body;
// Validasyon // Validasyon
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) { if (!full_name || !rank || !registration_number || !tc_kimlik || !phone || !unit_id) {
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' }); return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
} }
@@ -734,10 +799,46 @@ app.post('/api/fuel-personnel', (req, res) => {
registration_number: registration_number.trim(), registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(), tc_kimlik: tc_kimlik.trim(),
phone: phone.trim(), phone: phone.trim(),
unit_id: parseInt(unit_id),
is_active: Boolean(is_active), is_active: Boolean(is_active),
created_at: new Date().toISOString() created_at: new Date().toISOString()
}; };
// Birlik personeli için kullanıcı oluştur
try {
// Kullanıcı adını TC kimlik numarasından oluştur
const username = `bp_${tc_kimlik}`;
const defaultPassword = tc_kimlik.substring(0, 6); // İlk 6 hane varsayılan şifre
const hashedPassword = await bcrypt.hash(defaultPassword, 10);
// Kullanıcı adı benzersizliğini kontrol et
const existingUser = await new Promise((resolve, reject) => {
db.get('SELECT id FROM users WHERE username = ?', [username], (err, row) => {
if (err) reject(err);
else resolve(row);
});
});
if (existingUser) {
return res.status(400).json({ message: 'Bu personel için zaten kullanıcı hesabı mevcut.' });
}
// Birlik personeli olarak kullanıcı ekle
await new Promise((resolve, reject) => {
db.run('INSERT INTO users (username, password, role, full_name) VALUES (?, ?, ?, ?)',
[username, hashedPassword, 'birlik_personeli', full_name], (err) => {
if (err) reject(err);
else resolve();
});
});
console.log(`✅ Birlik personeli kullanıcı oluşturuldu: ${username}`);
} catch (userError) {
console.error('❌ Birlik personeli kullanıcı oluşturma hatası:', userError);
return res.status(500).json({ message: 'Personel için kullanıcı hesabı oluşturulamadı.' });
}
fuelPersonnel.push(newPersonnel); fuelPersonnel.push(newPersonnel);
res.json({ res.json({
@@ -762,11 +863,12 @@ app.put('/api/fuel-personnel', (req, res) => {
registration_number, registration_number,
tc_kimlik, tc_kimlik,
phone, phone,
unit_id,
is_active is_active
} = req.body; } = req.body;
// Validasyon // Validasyon
if (!id || !full_name || !rank || !registration_number || !tc_kimlik || !phone) { if (!id || !full_name || !rank || !registration_number || !tc_kimlik || !phone || !unit_id) {
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' }); return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
} }
@@ -805,6 +907,7 @@ app.put('/api/fuel-personnel', (req, res) => {
registration_number: registration_number.trim(), registration_number: registration_number.trim(),
tc_kimlik: tc_kimlik.trim(), tc_kimlik: tc_kimlik.trim(),
phone: phone.trim(), phone: phone.trim(),
unit_id: parseInt(unit_id),
is_active: Boolean(is_active) is_active: Boolean(is_active)
}; };