perosnel işlemleri change
This commit is contained in:
208
src/data/units.js
Normal file
208
src/data/units.js
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
import { json } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
// Geçici veritabanı simülasyonu
|
||||||
|
let units = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '1. Motorlu Piyade Tugayı',
|
||||||
|
address: 'Mecidiyeköy, Şişli/İstanbul',
|
||||||
|
stk: 'STK-12345',
|
||||||
|
btk: 'BTK-67890',
|
||||||
|
commander: {
|
||||||
|
full_name: 'Mehmet Yılmaz',
|
||||||
|
rank: 'Yüzbaşı',
|
||||||
|
registration_number: '123456',
|
||||||
|
tc_kimlik: '12345678901',
|
||||||
|
phone: '05321234567'
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '2. Zırhlı Tabur',
|
||||||
|
address: 'Havran, Balıkesir',
|
||||||
|
stk: 'STK-54321',
|
||||||
|
btk: 'BTK-09876',
|
||||||
|
commander: {
|
||||||
|
full_name: 'Ali Kaya',
|
||||||
|
rank: 'Binbaşı',
|
||||||
|
registration_number: '654321',
|
||||||
|
tc_kimlik: '98765432109',
|
||||||
|
phone: '05337654321'
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: '3. Komutanlık',
|
||||||
|
address: 'Çankaya, Ankara',
|
||||||
|
stk: 'STK-11111',
|
||||||
|
btk: 'BTK-22222',
|
||||||
|
commander: {
|
||||||
|
full_name: 'Hasan Demir',
|
||||||
|
rank: 'Üsteğmen',
|
||||||
|
registration_number: '111111',
|
||||||
|
tc_kimlik: '11111111111',
|
||||||
|
phone: '05321111111'
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let nextId = 4;
|
||||||
|
|
||||||
|
// GET - Tüm birlikleri listele
|
||||||
|
export async function GET({ request }) {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
return json({ units });
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST - Yeni birlik ekle
|
||||||
|
export async function POST({ request }) {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
stk,
|
||||||
|
btk,
|
||||||
|
commander
|
||||||
|
} = await request.json();
|
||||||
|
|
||||||
|
// Validasyon
|
||||||
|
if (!name || !address || !stk || !btk || !commander) {
|
||||||
|
return json({ message: 'Tüm alanlar zorunludur.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Komutan validasyonu
|
||||||
|
const { full_name, rank, registration_number, tc_kimlik, phone } = commander;
|
||||||
|
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) {
|
||||||
|
return json({ message: 'Birlik sorumlusunun tüm bilgileri zorunludur.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TC Kimlik numarası validasyonu
|
||||||
|
if (!/^[0-9]{11}$/.test(tc_kimlik)) {
|
||||||
|
return json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yeni birlik oluştur
|
||||||
|
const newUnit = {
|
||||||
|
id: nextId++,
|
||||||
|
name: name.trim(),
|
||||||
|
address: address.trim(),
|
||||||
|
stk: stk.trim().toUpperCase(),
|
||||||
|
btk: btk.trim().toUpperCase(),
|
||||||
|
commander: {
|
||||||
|
full_name: full_name.trim(),
|
||||||
|
rank: rank.trim(),
|
||||||
|
registration_number: registration_number.trim(),
|
||||||
|
tc_kimlik: tc_kimlik.trim(),
|
||||||
|
phone: phone.trim()
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
units.push(newUnit);
|
||||||
|
|
||||||
|
return json({
|
||||||
|
message: 'Birlik başarıyla eklendi.',
|
||||||
|
unit: newUnit
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return json({ message: 'Sunucu hatası.' }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT - Birlik güncelle
|
||||||
|
export async function PUT({ request }) {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
stk,
|
||||||
|
btk,
|
||||||
|
commander
|
||||||
|
} = await request.json();
|
||||||
|
|
||||||
|
// Validasyon
|
||||||
|
if (!id || !name || !address || !stk || !btk || !commander) {
|
||||||
|
return json({ message: 'Tüm alanlar zorunludur.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Komutan validasyonu
|
||||||
|
const { full_name, rank, registration_number, tc_kimlik, phone } = commander;
|
||||||
|
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) {
|
||||||
|
return json({ message: 'Birlik sorumlusunun tüm bilgileri zorunludur.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TC Kimlik numarası validasyonu
|
||||||
|
if (!/^[0-9]{11}$/.test(tc_kimlik)) {
|
||||||
|
return json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik bul
|
||||||
|
const unitIndex = units.findIndex(u => u.id === parseInt(id));
|
||||||
|
if (unitIndex === -1) {
|
||||||
|
return json({ message: 'Birlik bulunamadı.' }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik güncelle
|
||||||
|
units[unitIndex] = {
|
||||||
|
...units[unitIndex],
|
||||||
|
name: name.trim(),
|
||||||
|
address: address.trim(),
|
||||||
|
stk: stk.trim().toUpperCase(),
|
||||||
|
btk: btk.trim().toUpperCase(),
|
||||||
|
commander: {
|
||||||
|
full_name: full_name.trim(),
|
||||||
|
rank: rank.trim(),
|
||||||
|
registration_number: registration_number.trim(),
|
||||||
|
tc_kimlik: tc_kimlik.trim(),
|
||||||
|
phone: phone.trim()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return json({
|
||||||
|
message: 'Birlik başarıyla güncellendi.',
|
||||||
|
unit: units[unitIndex]
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return json({ message: 'Sunucu hatası.' }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE - Birlik sil
|
||||||
|
export async function DELETE({ request }) {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { id } = await request.json();
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return json({ message: 'Birlik ID zorunludur.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik bul
|
||||||
|
const unitIndex = units.findIndex(u => u.id === parseInt(id));
|
||||||
|
if (unitIndex === -1) {
|
||||||
|
return json({ message: 'Birlik bulunamadı.' }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik sil
|
||||||
|
const deletedUnit = units.splice(unitIndex, 1)[0];
|
||||||
|
|
||||||
|
return json({
|
||||||
|
message: 'Birlik başarıyla silindi.',
|
||||||
|
unit: deletedUnit
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return json({ message: 'Sunucu hatası.' }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
let user = null;
|
let user = null;
|
||||||
let goodsManagers = [];
|
let goodsManagers = [];
|
||||||
|
let units = [];
|
||||||
let loading = true;
|
let loading = true;
|
||||||
let error = '';
|
let error = '';
|
||||||
let showAddModal = false;
|
let showAddModal = false;
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
registration_number: '',
|
registration_number: '',
|
||||||
tc_kimlik: '',
|
tc_kimlik: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
email: '',
|
unit_id: '',
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
is_active: true
|
is_active: true
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
|
|
||||||
user = JSON.parse(userData);
|
user = JSON.parse(userData);
|
||||||
await loadGoodsManagers();
|
await loadGoodsManagers();
|
||||||
|
await loadUnits();
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadGoodsManagers() {
|
async function loadGoodsManagers() {
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
goodsManagers = data.goodsManagers;
|
goodsManagers = data.goodsManagers;
|
||||||
} else {
|
} else {
|
||||||
error = 'Mal sorumluları yüklenemedi.';
|
error = 'Personel bilgileri yüklenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -51,6 +53,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
formData = {
|
formData = {
|
||||||
full_name: '',
|
full_name: '',
|
||||||
@@ -58,7 +72,7 @@
|
|||||||
registration_number: '',
|
registration_number: '',
|
||||||
tc_kimlik: '',
|
tc_kimlik: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
email: '',
|
unit_id: '',
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
is_active: true
|
is_active: true
|
||||||
@@ -94,7 +108,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleAddManager() {
|
async function handleAddManager() {
|
||||||
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.email || !formData.username || !formData.password) {
|
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username || !formData.password) {
|
||||||
error = 'Tüm alanlar zorunludur.';
|
error = 'Tüm alanlar zorunludur.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -104,12 +118,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(formData.email)) {
|
|
||||||
error = 'Geçersiz e-posta formatı.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) {
|
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.';
|
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.';
|
||||||
return;
|
return;
|
||||||
@@ -136,7 +144,7 @@
|
|||||||
closeModal();
|
closeModal();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu eklenemedi.';
|
error = data.message || 'Personel eklenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -145,7 +153,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleUpdateManager() {
|
async function handleUpdateManager() {
|
||||||
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.email || !formData.username) {
|
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username) {
|
||||||
error = 'Kullanıcı adı hariç tüm alanlar zorunludur.';
|
error = 'Kullanıcı adı hariç tüm alanlar zorunludur.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -155,12 +163,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(formData.email)) {
|
|
||||||
error = 'Geçersiz e-posta formatı.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) {
|
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.';
|
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.';
|
||||||
return;
|
return;
|
||||||
@@ -190,7 +192,7 @@
|
|||||||
closeModal();
|
closeModal();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu güncellenemedi.';
|
error = data.message || 'Personel güncellenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -199,7 +201,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleDeleteManager(manager) {
|
async function handleDeleteManager(manager) {
|
||||||
if (!confirm(`${manager.rank} ${manager.full_name} mal sorumlusunu silmek istediğinizden emin misiniz?`)) {
|
if (!confirm(`${manager.rank} ${manager.full_name} personelini silmek istediğinizden emin misiniz?`)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +220,7 @@
|
|||||||
await loadGoodsManagers();
|
await loadGoodsManagers();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu silinemedi.';
|
error = data.message || 'Personel silinemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -246,7 +248,7 @@
|
|||||||
await loadGoodsManagers();
|
await loadGoodsManagers();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu durumu güncellenemedi.';
|
error = data.message || 'Personel durumu güncellenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -258,14 +260,14 @@
|
|||||||
<div class="goods-managers-content">
|
<div class="goods-managers-content">
|
||||||
<div class="content-header">
|
<div class="content-header">
|
||||||
<div class="header-left">
|
<div class="header-left">
|
||||||
<h1 class="page-title">Mal Sorumluları</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">
|
||||||
<line x1="12" y1="5" x2="12" y2="19"/>
|
<line x1="12" y1="5" x2="12" y2="19"/>
|
||||||
<line x1="5" y1="12" x2="19" y2="12"/>
|
<line x1="5" y1="12" x2="19" y2="12"/>
|
||||||
</svg>
|
</svg>
|
||||||
Yeni Mal Sorumlusu Ekle
|
Yeni Personel Ekle
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -290,11 +292,8 @@
|
|||||||
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3>Henüz Mal Sorumlusu Yok</h3>
|
<h3>Henüz Personel Yok</h3>
|
||||||
<p>Sisteme mal sorumlusu eklemek için "Yeni Mal Sorumlusu Ekle" butonuna tıklayın.</p>
|
<p>Sisteme personel eklemek için "Yeni Personel Ekle" butonuna tıklayın.</p>
|
||||||
<button class="btn btn-primary" on:click={openAddModal}>
|
|
||||||
İlk Mal Sorumlusunu Ekle
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="managers-grid">
|
<div class="managers-grid">
|
||||||
@@ -321,8 +320,8 @@
|
|||||||
<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">📧 E-posta:</span>
|
<span class="detail-label">🏢 Birlik:</span>
|
||||||
<span class="detail-value">{manager.email}</span>
|
<span class="detail-value">{manager.unit_name || 'Belirtilmemiş'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">📱 İrtibat:</span>
|
<span class="detail-label">📱 İrtibat:</span>
|
||||||
@@ -380,7 +379,7 @@
|
|||||||
<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>
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2>Yeni Mal Sorumlusu 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={handleAddManager} class="modal-form">
|
||||||
@@ -441,15 +440,18 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email">E-posta</label>
|
<label for="unit_id">Birlik</label>
|
||||||
<input
|
<select
|
||||||
id="email"
|
id="unit_id"
|
||||||
type="email"
|
|
||||||
class="form-input"
|
class="form-input"
|
||||||
bind:value={formData.email}
|
bind:value={formData.unit_id}
|
||||||
placeholder="ali.veli@mil.tr"
|
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
|
<option value="">Birlik Seçiniz</option>
|
||||||
|
{#each units as unit}
|
||||||
|
<option value={unit.id}>{unit.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">Kullanıcı Adı</label>
|
<label for="username">Kullanıcı Adı</label>
|
||||||
@@ -490,7 +492,7 @@
|
|||||||
<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>
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2>Mal Sorumlusu 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={handleUpdateManager} class="modal-form">
|
||||||
@@ -551,15 +553,18 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="edit-email">E-posta</label>
|
<label for="edit-unit_id">Birlik</label>
|
||||||
<input
|
<select
|
||||||
id="edit-email"
|
id="edit-unit_id"
|
||||||
type="email"
|
|
||||||
class="form-input"
|
class="form-input"
|
||||||
bind:value={formData.email}
|
bind:value={formData.unit_id}
|
||||||
placeholder="ali.veli@mil.tr"
|
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
|
<option value="">Birlik Seçiniz</option>
|
||||||
|
{#each units as unit}
|
||||||
|
<option value={unit.id}>{unit.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="edit-username">Kullanıcı Adı</label>
|
<label for="edit-username">Kullanıcı Adı</label>
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let goodsManagers = [
|
|||||||
registration_number: 'GM001',
|
registration_number: 'GM001',
|
||||||
tc_kimlik: '12345678901',
|
tc_kimlik: '12345678901',
|
||||||
phone: '05321234567',
|
phone: '05321234567',
|
||||||
email: 'ali.veli@mil.tr',
|
unit_id: 1,
|
||||||
|
unit_name: '1. Komutanlık',
|
||||||
username: 'goods',
|
username: 'goods',
|
||||||
password: 'goods123',
|
password: 'goods123',
|
||||||
is_active: true,
|
is_active: true,
|
||||||
@@ -23,7 +24,8 @@ let goodsManagers = [
|
|||||||
registration_number: 'GM002',
|
registration_number: 'GM002',
|
||||||
tc_kimlik: '98765432101',
|
tc_kimlik: '98765432101',
|
||||||
phone: '05339876543',
|
phone: '05339876543',
|
||||||
email: 'ibrahim.kara@mil.tr',
|
unit_id: 2,
|
||||||
|
unit_name: '2. Komutanlık',
|
||||||
username: 'ibrahim_kara',
|
username: 'ibrahim_kara',
|
||||||
password: 'kara123',
|
password: 'kara123',
|
||||||
is_active: true,
|
is_active: true,
|
||||||
@@ -36,7 +38,8 @@ let goodsManagers = [
|
|||||||
registration_number: '2022/21345',
|
registration_number: '2022/21345',
|
||||||
tc_kimlik: '12312321312',
|
tc_kimlik: '12312321312',
|
||||||
phone: '05537746067',
|
phone: '05537746067',
|
||||||
email: 'ibo@gmail.com',
|
unit_id: 3,
|
||||||
|
unit_name: '3. Komutanlık',
|
||||||
username: 'fatih',
|
username: 'fatih',
|
||||||
password: 'fat123',
|
password: 'fat123',
|
||||||
is_active: true,
|
is_active: true,
|
||||||
@@ -75,7 +78,8 @@ export function addGoodsManager(managerData) {
|
|||||||
registration_number,
|
registration_number,
|
||||||
tc_kimlik,
|
tc_kimlik,
|
||||||
phone,
|
phone,
|
||||||
email,
|
unit_id,
|
||||||
|
unit_name,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
is_active = true
|
is_active = true
|
||||||
@@ -83,7 +87,7 @@ export function addGoodsManager(managerData) {
|
|||||||
|
|
||||||
// Validasyonlar
|
// Validasyonlar
|
||||||
if (!full_name || !rank || !registration_number || !tc_kimlik ||
|
if (!full_name || !rank || !registration_number || !tc_kimlik ||
|
||||||
!phone || !email || !username || !password) {
|
!phone || !unit_id || !unit_name || !username || !password) {
|
||||||
throw new Error('Tüm alanlar zorunludur.');
|
throw new Error('Tüm alanlar zorunludur.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,11 +95,6 @@ export function addGoodsManager(managerData) {
|
|||||||
throw new Error('TC Kimlik numarası 11 haneli olmalıdır.');
|
throw new Error('TC Kimlik numarası 11 haneli olmalıdır.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(email)) {
|
|
||||||
throw new Error('Geçersiz e-posta formatı.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tekrar kontrolü
|
// Tekrar kontrolü
|
||||||
const existingByReg = goodsManagers.find(m =>
|
const existingByReg = goodsManagers.find(m =>
|
||||||
m.registration_number.toLowerCase() === registration_number.toLowerCase()
|
m.registration_number.toLowerCase() === registration_number.toLowerCase()
|
||||||
@@ -109,13 +108,6 @@ export function addGoodsManager(managerData) {
|
|||||||
throw new Error('Bu TC Kimlik numarası zaten kayıtlı.');
|
throw new Error('Bu TC Kimlik numarası zaten kayıtlı.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingByEmail = goodsManagers.find(m =>
|
|
||||||
m.email.toLowerCase() === email.toLowerCase()
|
|
||||||
);
|
|
||||||
if (existingByEmail) {
|
|
||||||
throw new Error('Bu e-posta adresi zaten kayıtlı.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingByUsername = goodsManagers.find(m =>
|
const existingByUsername = goodsManagers.find(m =>
|
||||||
m.username.toLowerCase() === username.toLowerCase()
|
m.username.toLowerCase() === username.toLowerCase()
|
||||||
);
|
);
|
||||||
@@ -139,7 +131,8 @@ export function addGoodsManager(managerData) {
|
|||||||
registration_number: registration_number.trim().toUpperCase(),
|
registration_number: registration_number.trim().toUpperCase(),
|
||||||
tc_kimlik: tc_kimlik.trim(),
|
tc_kimlik: tc_kimlik.trim(),
|
||||||
phone: phone.trim(),
|
phone: phone.trim(),
|
||||||
email: email.trim().toLowerCase(),
|
unit_id: parseInt(unit_id),
|
||||||
|
unit_name: unit_name.trim(),
|
||||||
username: username.trim().toLowerCase(),
|
username: username.trim().toLowerCase(),
|
||||||
password: password.trim(), // Gerçek uygulamada hash'lenmelidir
|
password: password.trim(), // Gerçek uygulamada hash'lenmelidir
|
||||||
is_active: Boolean(is_active),
|
is_active: Boolean(is_active),
|
||||||
@@ -163,7 +156,8 @@ export function updateGoodsManager(id, updateData) {
|
|||||||
registration_number,
|
registration_number,
|
||||||
tc_kimlik,
|
tc_kimlik,
|
||||||
phone,
|
phone,
|
||||||
email,
|
unit_id,
|
||||||
|
unit_name,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
is_active
|
is_active
|
||||||
@@ -171,7 +165,7 @@ export function updateGoodsManager(id, updateData) {
|
|||||||
|
|
||||||
// Validasyonlar
|
// Validasyonlar
|
||||||
if (!id || !full_name || !rank || !registration_number || !tc_kimlik ||
|
if (!id || !full_name || !rank || !registration_number || !tc_kimlik ||
|
||||||
!phone || !email || !username) {
|
!phone || !unit_id || !unit_name || !username) {
|
||||||
throw new Error('Tüm alanlar zorunludur.');
|
throw new Error('Tüm alanlar zorunludur.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,11 +173,6 @@ export function updateGoodsManager(id, updateData) {
|
|||||||
throw new Error('TC Kimlik numarası 11 haneli olmalıdır.');
|
throw new Error('TC Kimlik numarası 11 haneli olmalıdır.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(email)) {
|
|
||||||
throw new Error('Geçersiz e-posta formatı.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tekrar kontrolü (diğer managerlar için)
|
// Tekrar kontrolü (diğer managerlar için)
|
||||||
const existingByReg = goodsManagers.find(m =>
|
const existingByReg = goodsManagers.find(m =>
|
||||||
m.id !== parseInt(id) && m.registration_number.toLowerCase() === registration_number.toLowerCase()
|
m.id !== parseInt(id) && m.registration_number.toLowerCase() === registration_number.toLowerCase()
|
||||||
@@ -199,13 +188,6 @@ export function updateGoodsManager(id, updateData) {
|
|||||||
throw new Error('Bu TC Kimlik numarası başka bir mal sorumlusunda kullanılıyor.');
|
throw new Error('Bu TC Kimlik numarası başka bir mal sorumlusunda kullanılıyor.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingByEmail = goodsManagers.find(m =>
|
|
||||||
m.id !== parseInt(id) && m.email.toLowerCase() === email.toLowerCase()
|
|
||||||
);
|
|
||||||
if (existingByEmail) {
|
|
||||||
throw new Error('Bu e-posta adresi başka bir mal sorumlusunda kullanılıyor.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingByUsername = goodsManagers.find(m =>
|
const existingByUsername = goodsManagers.find(m =>
|
||||||
m.id !== parseInt(id) && m.username.toLowerCase() === username.toLowerCase()
|
m.id !== parseInt(id) && m.username.toLowerCase() === username.toLowerCase()
|
||||||
);
|
);
|
||||||
@@ -229,7 +211,8 @@ export function updateGoodsManager(id, updateData) {
|
|||||||
registration_number: registration_number.trim().toUpperCase(),
|
registration_number: registration_number.trim().toUpperCase(),
|
||||||
tc_kimlik: tc_kimlik.trim(),
|
tc_kimlik: tc_kimlik.trim(),
|
||||||
phone: phone.trim(),
|
phone: phone.trim(),
|
||||||
email: email.trim().toLowerCase(),
|
unit_id: parseInt(unit_id),
|
||||||
|
unit_name: unit_name.trim(),
|
||||||
username: username.trim().toLowerCase(),
|
username: username.trim().toLowerCase(),
|
||||||
is_active: Boolean(is_active)
|
is_active: Boolean(is_active)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export async function POST({ request }) {
|
|||||||
registration_number,
|
registration_number,
|
||||||
tc_kimlik,
|
tc_kimlik,
|
||||||
phone,
|
phone,
|
||||||
email,
|
unit_id,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
is_active = true
|
is_active = true
|
||||||
@@ -40,14 +40,14 @@ export async function POST({ request }) {
|
|||||||
registration_number,
|
registration_number,
|
||||||
tc_kimlik,
|
tc_kimlik,
|
||||||
phone,
|
phone,
|
||||||
email,
|
unit_id,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
is_active
|
is_active
|
||||||
});
|
});
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
message: 'Mal sorumlusu başarıyla eklendi.',
|
message: 'Personel başarıyla eklendi.',
|
||||||
goodsManager: newManager
|
goodsManager: newManager
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ export async function PUT({ request }) {
|
|||||||
registration_number,
|
registration_number,
|
||||||
tc_kimlik,
|
tc_kimlik,
|
||||||
phone,
|
phone,
|
||||||
email,
|
unit_id,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
is_active
|
is_active
|
||||||
@@ -86,14 +86,14 @@ export async function PUT({ request }) {
|
|||||||
registration_number,
|
registration_number,
|
||||||
tc_kimlik,
|
tc_kimlik,
|
||||||
phone,
|
phone,
|
||||||
email,
|
unit_id,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
is_active
|
is_active
|
||||||
});
|
});
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
message: 'Mal sorumlusu başarıyla güncellendi.',
|
message: 'Personel başarıyla güncellendi.',
|
||||||
goodsManager: updatedManager
|
goodsManager: updatedManager
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -532,7 +532,7 @@
|
|||||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
|
||||||
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
||||||
</svg>
|
</svg>
|
||||||
Mal Sorumluları
|
Personel İşlemleri
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{:else if user.role === 'fuel_manager'}
|
{:else if user.role === 'fuel_manager'}
|
||||||
@@ -703,7 +703,7 @@
|
|||||||
{#if user.role === 'admin'}
|
{#if user.role === 'admin'}
|
||||||
<ul class="info-list">
|
<ul class="info-list">
|
||||||
<li>Araç, birlik ve personel yönetimi yapabilirsiniz</li>
|
<li>Araç, birlik ve personel yönetimi yapabilirsiniz</li>
|
||||||
<li>Mal sorumluları ekleyebilir, düzenleyebilirsiniz</li>
|
<li>Personel işlemlerini yönetebilirsiniz</li>
|
||||||
<li>Tüm kullanıcıları yönetebilirsiniz</li>
|
<li>Tüm kullanıcıları yönetebilirsiniz</li>
|
||||||
<li>Sistem ayarlarını yapılandırabilirsiniz</li>
|
<li>Sistem ayarlarını yapılandırabilirsiniz</li>
|
||||||
<li>Raporları görüntüleyebilirsiniz</li>
|
<li>Raporları görüntüleyebilirsiniz</li>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
let user = null;
|
let user = null;
|
||||||
let goodsManagers = [];
|
let goodsManagers = [];
|
||||||
|
let units = [];
|
||||||
let loading = true;
|
let loading = true;
|
||||||
let error = '';
|
let error = '';
|
||||||
let showAddModal = false;
|
let showAddModal = false;
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
registration_number: '',
|
registration_number: '',
|
||||||
tc_kimlik: '',
|
tc_kimlik: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
email: '',
|
unit_id: '',
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
is_active: true
|
is_active: true
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
|
|
||||||
user = JSON.parse(userData);
|
user = JSON.parse(userData);
|
||||||
await loadGoodsManagers();
|
await loadGoodsManagers();
|
||||||
|
await loadUnits();
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadGoodsManagers() {
|
async function loadGoodsManagers() {
|
||||||
@@ -49,7 +51,7 @@
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
goodsManagers = data.goodsManagers;
|
goodsManagers = data.goodsManagers;
|
||||||
} else {
|
} else {
|
||||||
error = 'Mal sorumluları yüklenemedi.';
|
error = 'Personel bilgileri yüklenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -59,6 +61,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
formData = {
|
formData = {
|
||||||
full_name: '',
|
full_name: '',
|
||||||
@@ -66,7 +80,7 @@
|
|||||||
registration_number: '',
|
registration_number: '',
|
||||||
tc_kimlik: '',
|
tc_kimlik: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
email: '',
|
unit_id: '',
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
is_active: true
|
is_active: true
|
||||||
@@ -102,7 +116,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleAddManager() {
|
async function handleAddManager() {
|
||||||
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.email || !formData.username || !formData.password) {
|
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username || !formData.password) {
|
||||||
error = 'Tüm alanlar zorunludur.';
|
error = 'Tüm alanlar zorunludur.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -112,12 +126,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(formData.email)) {
|
|
||||||
error = 'Geçersiz e-posta formatı.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) {
|
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.';
|
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.';
|
||||||
return;
|
return;
|
||||||
@@ -144,7 +152,7 @@
|
|||||||
closeModal();
|
closeModal();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu eklenemedi.';
|
error = data.message || 'Personel eklenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -153,7 +161,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleUpdateManager() {
|
async function handleUpdateManager() {
|
||||||
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.email || !formData.username) {
|
if (!formData.full_name || !formData.rank || !formData.registration_number || !formData.tc_kimlik || !formData.phone || !formData.unit_id || !formData.username) {
|
||||||
error = 'Kullanıcı adı hariç tüm alanlar zorunludur.';
|
error = 'Kullanıcı adı hariç tüm alanlar zorunludur.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -163,12 +171,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(formData.email)) {
|
|
||||||
error = 'Geçersiz e-posta formatı.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^[a-zA-Z0-9]{3,20}$/.test(formData.username)) {
|
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.';
|
error = 'Kullanıcı adı 3-20 karakter arası olmalı ve sadece harf ve rakam içermelidir.';
|
||||||
return;
|
return;
|
||||||
@@ -198,7 +200,7 @@
|
|||||||
closeModal();
|
closeModal();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu güncellenemedi.';
|
error = data.message || 'Personel güncellenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -207,7 +209,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleDeleteManager(manager) {
|
async function handleDeleteManager(manager) {
|
||||||
if (!confirm(`${manager.rank} ${manager.full_name} mal sorumlusunu silmek istediğinizden emin misiniz?`)) {
|
if (!confirm(`${manager.rank} ${manager.full_name} personelini silmek istediğinizden emin misiniz?`)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +228,7 @@
|
|||||||
await loadGoodsManagers();
|
await loadGoodsManagers();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu silinemedi.';
|
error = data.message || 'Personel silinemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -254,7 +256,7 @@
|
|||||||
await loadGoodsManagers();
|
await loadGoodsManagers();
|
||||||
error = '';
|
error = '';
|
||||||
} else {
|
} else {
|
||||||
error = data.message || 'Mal sorumlusu durumu güncellenemedi.';
|
error = data.message || 'Personel durumu güncellenemedi.';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = 'Bağlantı hatası.';
|
error = 'Bağlantı hatası.';
|
||||||
@@ -277,14 +279,14 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Geri
|
Geri
|
||||||
</button>
|
</button>
|
||||||
<h1 class="page-title">Mal Sorumluları</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">
|
||||||
<line x1="12" y1="5" x2="12" y2="19"/>
|
<line x1="12" y1="5" x2="12" y2="19"/>
|
||||||
<line x1="5" y1="12" x2="19" y2="12"/>
|
<line x1="5" y1="12" x2="19" y2="12"/>
|
||||||
</svg>
|
</svg>
|
||||||
Yeni Mal Sorumlusu Ekle
|
Yeni Personel Ekle
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -309,11 +311,8 @@
|
|||||||
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3>Henüz Mal Sorumlusu Yok</h3>
|
<h3>Henüz Personel Yok</h3>
|
||||||
<p>Sisteme mal sorumlusu eklemek için "Yeni Mal Sorumlusu Ekle" butonuna tıklayın.</p>
|
<p>Sisteme personel eklemek için "Yeni Personel Ekle" butonuna tıklayın.</p>
|
||||||
<button class="btn btn-primary" on:click={openAddModal}>
|
|
||||||
İlk Mal Sorumlusunu Ekle
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="managers-grid">
|
<div class="managers-grid">
|
||||||
@@ -340,8 +339,8 @@
|
|||||||
<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">📧 E-posta:</span>
|
<span class="detail-label">🏢 Birlik:</span>
|
||||||
<span class="detail-value">{manager.email}</span>
|
<span class="detail-value">{manager.unit_name || 'Belirtilmemiş'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">📱 İrtibat:</span>
|
<span class="detail-label">📱 İrtibat:</span>
|
||||||
@@ -399,7 +398,7 @@
|
|||||||
<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>
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2>Yeni Mal Sorumlusu 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={handleAddManager} class="modal-form">
|
||||||
@@ -460,15 +459,18 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email">E-posta</label>
|
<label for="unit_id">Birlik</label>
|
||||||
<input
|
<select
|
||||||
id="email"
|
id="unit_id"
|
||||||
type="email"
|
|
||||||
class="form-input"
|
class="form-input"
|
||||||
bind:value={formData.email}
|
bind:value={formData.unit_id}
|
||||||
placeholder="ali.veli@mil.tr"
|
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
|
<option value="">Birlik Seçiniz</option>
|
||||||
|
{#each units as unit}
|
||||||
|
<option value={unit.id}>{unit.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">Kullanıcı Adı</label>
|
<label for="username">Kullanıcı Adı</label>
|
||||||
@@ -504,12 +506,12 @@
|
|||||||
</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>
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2>Mal Sorumlusu 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={handleUpdateManager} class="modal-form">
|
||||||
@@ -570,15 +572,18 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="edit-email">E-posta</label>
|
<label for="edit-unit_id">Birlik</label>
|
||||||
<input
|
<select
|
||||||
id="edit-email"
|
id="edit-unit_id"
|
||||||
type="email"
|
|
||||||
class="form-input"
|
class="form-input"
|
||||||
bind:value={formData.email}
|
bind:value={formData.unit_id}
|
||||||
placeholder="ali.veli@mil.tr"
|
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
|
<option value="">Birlik Seçiniz</option>
|
||||||
|
{#each units as unit}
|
||||||
|
<option value={unit.id}>{unit.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="edit-username">Kullanıcı Adı</label>
|
<label for="edit-username">Kullanıcı Adı</label>
|
||||||
|
|||||||
350
src/server.js
350
src/server.js
@@ -7,6 +7,63 @@ import bcrypt from 'bcrypt';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
|
import {
|
||||||
|
getGoodsManagers,
|
||||||
|
addGoodsManager,
|
||||||
|
updateGoodsManager,
|
||||||
|
deleteGoodsManager
|
||||||
|
} from './lib/data/goodsManagers.js';
|
||||||
|
|
||||||
|
// Units veritabanı
|
||||||
|
let units = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '1. Motorlu Piyade Tugayı',
|
||||||
|
address: 'Mecidiyeköy, Şişli/İstanbul',
|
||||||
|
stk: 'STK-12345',
|
||||||
|
btk: 'BTK-67890',
|
||||||
|
commander: {
|
||||||
|
full_name: 'Mehmet Yılmaz',
|
||||||
|
rank: 'Yüzbaşı',
|
||||||
|
registration_number: '123456',
|
||||||
|
tc_kimlik: '12345678901',
|
||||||
|
phone: '05321234567'
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '2. Zırhlı Tabur',
|
||||||
|
address: 'Havran, Balıkesir',
|
||||||
|
stk: 'STK-54321',
|
||||||
|
btk: 'BTK-09876',
|
||||||
|
commander: {
|
||||||
|
full_name: 'Ali Kaya',
|
||||||
|
rank: 'Binbaşı',
|
||||||
|
registration_number: '654321',
|
||||||
|
tc_kimlik: '98765432109',
|
||||||
|
phone: '05337654321'
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: '3. Komutanlık',
|
||||||
|
address: 'Çankaya, Ankara',
|
||||||
|
stk: 'STK-11111',
|
||||||
|
btk: 'BTK-22222',
|
||||||
|
commander: {
|
||||||
|
full_name: 'Hasan Demir',
|
||||||
|
rank: 'Üsteğmen',
|
||||||
|
registration_number: '111111',
|
||||||
|
tc_kimlik: '11111111111',
|
||||||
|
phone: '05321111111'
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let nextUnitId = 4;
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const server = createServer(app);
|
const server = createServer(app);
|
||||||
@@ -20,7 +77,7 @@ const io = new Server(server, {
|
|||||||
// Export io for use in other modules
|
// Export io for use in other modules
|
||||||
export { io };
|
export { io };
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3002;
|
||||||
|
|
||||||
// ES Module equivalent of __dirname
|
// ES Module equivalent of __dirname
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
@@ -254,6 +311,297 @@ app.get('/api/users', (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Units API endpoint'leri
|
||||||
|
|
||||||
|
// GET - Tüm birlikleri listele
|
||||||
|
app.get('/api/units', (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
res.json({ units });
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST - Yeni birlik ekle
|
||||||
|
app.post('/api/units', (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
stk,
|
||||||
|
btk,
|
||||||
|
commander
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
// Validasyon
|
||||||
|
if (!name || !address || !stk || !btk || !commander) {
|
||||||
|
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Komutan validasyonu
|
||||||
|
const { full_name, rank, registration_number, tc_kimlik, phone } = commander;
|
||||||
|
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) {
|
||||||
|
return res.status(400).json({ message: 'Birlik sorumlusunun tüm bilgileri zorunludur.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TC Kimlik numarası validasyonu
|
||||||
|
if (!/^[0-9]{11}$/.test(tc_kimlik)) {
|
||||||
|
return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yeni birlik oluştur
|
||||||
|
const newUnit = {
|
||||||
|
id: nextUnitId++,
|
||||||
|
name: name.trim(),
|
||||||
|
address: address.trim(),
|
||||||
|
stk: stk.trim().toUpperCase(),
|
||||||
|
btk: btk.trim().toUpperCase(),
|
||||||
|
commander: {
|
||||||
|
full_name: full_name.trim(),
|
||||||
|
rank: rank.trim(),
|
||||||
|
registration_number: registration_number.trim(),
|
||||||
|
tc_kimlik: tc_kimlik.trim(),
|
||||||
|
phone: phone.trim()
|
||||||
|
},
|
||||||
|
created_at: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
units.push(newUnit);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Birlik başarıyla eklendi.',
|
||||||
|
unit: newUnit
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Sunucu hatası.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// PUT - Birlik güncelle
|
||||||
|
app.put('/api/units', (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
stk,
|
||||||
|
btk,
|
||||||
|
commander
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
// Validasyon
|
||||||
|
if (!id || !name || !address || !stk || !btk || !commander) {
|
||||||
|
return res.status(400).json({ message: 'Tüm alanlar zorunludur.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Komutan validasyonu
|
||||||
|
const { full_name, rank, registration_number, tc_kimlik, phone } = commander;
|
||||||
|
if (!full_name || !rank || !registration_number || !tc_kimlik || !phone) {
|
||||||
|
return res.status(400).json({ message: 'Birlik sorumlusunun tüm bilgileri zorunludur.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TC Kimlik numarası validasyonu
|
||||||
|
if (!/^[0-9]{11}$/.test(tc_kimlik)) {
|
||||||
|
return res.status(400).json({ message: 'TC Kimlik numarası 11 haneli olmalıdır.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik bul
|
||||||
|
const unitIndex = units.findIndex(u => u.id === parseInt(id));
|
||||||
|
if (unitIndex === -1) {
|
||||||
|
return res.status(404).json({ message: 'Birlik bulunamadı.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik güncelle
|
||||||
|
units[unitIndex] = {
|
||||||
|
...units[unitIndex],
|
||||||
|
name: name.trim(),
|
||||||
|
address: address.trim(),
|
||||||
|
stk: stk.trim().toUpperCase(),
|
||||||
|
btk: btk.trim().toUpperCase(),
|
||||||
|
commander: {
|
||||||
|
full_name: full_name.trim(),
|
||||||
|
rank: rank.trim(),
|
||||||
|
registration_number: registration_number.trim(),
|
||||||
|
tc_kimlik: tc_kimlik.trim(),
|
||||||
|
phone: phone.trim()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Birlik başarıyla güncellendi.',
|
||||||
|
unit: units[unitIndex]
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Sunucu hatası.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// DELETE - Birlik sil
|
||||||
|
app.delete('/api/units', (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { id } = req.body;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.status(400).json({ message: 'Birlik ID zorunludur.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik bul
|
||||||
|
const unitIndex = units.findIndex(u => u.id === parseInt(id));
|
||||||
|
if (unitIndex === -1) {
|
||||||
|
return res.status(404).json({ message: 'Birlik bulunamadı.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birlik sil
|
||||||
|
const deletedUnit = units.splice(unitIndex, 1)[0];
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Birlik başarıyla silindi.',
|
||||||
|
unit: deletedUnit
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Sunucu hatası.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Goods Managers API endpoint'leri
|
||||||
|
|
||||||
|
// GET - Tüm mal sorumlularını listele
|
||||||
|
app.get('/api/goods-managers', (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
try {
|
||||||
|
const goodsManagers = getGoodsManagers();
|
||||||
|
res.json({ goodsManagers });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Mal sorumluları alınırken hata oluştu.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// POST - Yeni mal sorumlusu ekle
|
||||||
|
app.post('/api/goods-managers', async (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
full_name,
|
||||||
|
rank,
|
||||||
|
registration_number,
|
||||||
|
tc_kimlik,
|
||||||
|
phone,
|
||||||
|
unit_id,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
is_active = true
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const newManager = addGoodsManager({
|
||||||
|
full_name,
|
||||||
|
rank,
|
||||||
|
registration_number,
|
||||||
|
tc_kimlik,
|
||||||
|
phone,
|
||||||
|
unit_id,
|
||||||
|
unit_name: units.find(u => u.id === parseInt(unit_id))?.name || 'Bilinmeyen Birlik',
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
is_active
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Personel başarıyla eklendi.',
|
||||||
|
goodsManager: newManager
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
if (error.message.includes('zorunludur') ||
|
||||||
|
error.message.includes('zaten kayıtlı') ||
|
||||||
|
error.message.includes('Geçersiz') ||
|
||||||
|
error.message.includes('karakter')) {
|
||||||
|
return res.status(400).json({ message: error.message });
|
||||||
|
}
|
||||||
|
res.status(500).json({ message: 'Sunucu hatası.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// PUT - Mal sorumlusu güncelle
|
||||||
|
app.put('/api/goods-managers', async (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
full_name,
|
||||||
|
rank,
|
||||||
|
registration_number,
|
||||||
|
tc_kimlik,
|
||||||
|
phone,
|
||||||
|
unit_id,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
is_active
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const updatedManager = updateGoodsManager(id, {
|
||||||
|
full_name,
|
||||||
|
rank,
|
||||||
|
registration_number,
|
||||||
|
tc_kimlik,
|
||||||
|
phone,
|
||||||
|
unit_id,
|
||||||
|
unit_name: units.find(u => u.id === parseInt(unit_id))?.name || 'Bilinmeyen Birlik',
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
is_active
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Personel başarıyla güncellendi.',
|
||||||
|
goodsManager: updatedManager
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
if (error.message.includes('zorunludur') ||
|
||||||
|
error.message.includes('bulunamadı') ||
|
||||||
|
error.message.includes('zaten kayıtlı') ||
|
||||||
|
error.message.includes('Geçersiz') ||
|
||||||
|
error.message.includes('karakter')) {
|
||||||
|
return res.status(error.message.includes('bulunamadı') ? 404 : 400).json({ message: error.message });
|
||||||
|
}
|
||||||
|
res.status(500).json({ message: 'Sunucu hatası.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// DELETE - Mal sorumlusu sil
|
||||||
|
app.delete('/api/goods-managers', async (req, res) => {
|
||||||
|
// Yetki kontrolü (temporary - will be implemented with proper session)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { id } = req.body;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.status(400).json({ message: 'Mal sorumlusu ID zorunludur.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedManager = deleteGoodsManager(id);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: 'Mal sorumlusu başarıyla silindi.',
|
||||||
|
goodsManager: deletedManager
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
if (error.message.includes('bulunamadı')) {
|
||||||
|
return res.status(404).json({ message: error.message });
|
||||||
|
}
|
||||||
|
res.status(500).json({ message: 'Sunucu hatası.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Socket.IO bağlantıları
|
// Socket.IO bağlantıları
|
||||||
io.on('connection', (socket) => {
|
io.on('connection', (socket) => {
|
||||||
console.log('✅ Bir kullanıcı bağlandı:', socket.id);
|
console.log('✅ Bir kullanıcı bağlandı:', socket.id);
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ import { defineConfig } from 'vite';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()],
|
plugins: [sveltekit()],
|
||||||
server: {
|
server: {
|
||||||
port: 5173
|
port: 5173,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:3002',
|
||||||
|
changeOrigin: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user