2475 lines
69 KiB
Svelte
2475 lines
69 KiB
Svelte
<script>
|
||
import { onMount, onDestroy, tick } from "svelte";
|
||
import { goto } from "$app/navigation";
|
||
import { io } from "socket.io-client";
|
||
import VehiclesContent from "$lib/components/VehiclesContent.svelte";
|
||
import UnitsContent from "$lib/components/UnitsContent.svelte";
|
||
import PersonnelContent from "$lib/components/PersonnelContent.svelte";
|
||
import GoodsManagersContent from "$lib/components/GoodsManagersContent.svelte";
|
||
import GoodsManagerContent from "$lib/components/GoodsManagerContent.svelte";
|
||
import DevriçarkContent from "$lib/components/DevriçarkContent.svelte";
|
||
import MonthlyFuelReportContent from "$lib/components/MonthlyFuelReportContent.svelte";
|
||
|
||
let user = null;
|
||
let loading = true;
|
||
let currentTime = "";
|
||
let showMobileMenu = false;
|
||
let showFuelForm = false;
|
||
let showGoodsManager = false;
|
||
let showGoodsManagerVehicles = false;
|
||
let showVehicles = false;
|
||
let showUnits = false;
|
||
let showPersonnel = false;
|
||
let showGoodsManagers = false;
|
||
let showDevriçark = false;
|
||
let showMonthlyReport = false;
|
||
let socket = null;
|
||
|
||
// Admin state reset function
|
||
function resetAdminStates() {
|
||
showVehicles = false;
|
||
showUnits = false;
|
||
showPersonnel = false;
|
||
showGoodsManagers = false;
|
||
showFuelForm = false;
|
||
showGoodsManager = false;
|
||
showGoodsManagerVehicles = false;
|
||
showDevriçark = false;
|
||
showMonthlyReport = false;
|
||
}
|
||
|
||
// Fuel Manager için veriler
|
||
let fuelSummary = { benzin: 0, motorin: 0 };
|
||
let pendingSlips = [];
|
||
let approvedRejectedSlips = [];
|
||
let fuelLoading = true;
|
||
let vehicles = [];
|
||
let units = [];
|
||
let personnel = [];
|
||
let goodsManagers = [];
|
||
let filteredGoodsManagers = [];
|
||
let filteredVehicles = [];
|
||
let formError = "";
|
||
let formSuccess = "";
|
||
let isSubmitting = false;
|
||
|
||
let formData = {
|
||
date: new Date().toISOString().split("T")[0],
|
||
force_command: "1. Komutanlık",
|
||
unit_id: "",
|
||
vehicle_id: "",
|
||
fuel_type: "benzin",
|
||
liters: "",
|
||
km: "",
|
||
personnel_id: "",
|
||
goods_manager_id: "",
|
||
notes: ""
|
||
};
|
||
|
||
function setFormField(field, value) {
|
||
if (formData[field] === value) {
|
||
return;
|
||
}
|
||
formData = { ...formData, [field]: value };
|
||
}
|
||
|
||
$: displayPendingSlips = pendingSlips;
|
||
$: displayHistorySlips = approvedRejectedSlips;
|
||
|
||
onMount(async () => {
|
||
// localStorage'dan kullanıcı bilgisini al
|
||
const userData = localStorage.getItem("user");
|
||
if (!userData) {
|
||
goto("/");
|
||
return;
|
||
}
|
||
|
||
user = JSON.parse(userData);
|
||
loading = false;
|
||
|
||
// Zamanı güncelle
|
||
updateTime();
|
||
setInterval(updateTime, 1000);
|
||
|
||
// Eğer fuel_manager ise yakıt verilerini yükle ve socket bağlantısı kur
|
||
if (user.role === "fuel_manager") {
|
||
await loadFuelData();
|
||
|
||
// Socket.IO bağlantısı
|
||
socket = io("http://localhost:3000");
|
||
|
||
// Fiş durumu güncellendiğinde listeyi yenile
|
||
socket.on("fuel-slip-updated", (data) => {
|
||
console.log("Dashboard - fuel-slip-updated received:", data);
|
||
if (data.fuel_manager_id === user.id) {
|
||
loadFuelData();
|
||
formSuccess = `Fiş durumu güncellendi: ${data.status === "approved" ? "Onaylandı" : "Reddedildi"}`;
|
||
setTimeout(() => (formSuccess = ""), 3000);
|
||
}
|
||
});
|
||
|
||
socket.on("connect", () => {
|
||
console.log(
|
||
"Dashboard - Socket.IO connected for fuel_manager:",
|
||
socket.id
|
||
);
|
||
});
|
||
}
|
||
|
||
if (user.role === "goods_manager") {
|
||
console.log("Dashboard - goods_manager logged in, user:", user);
|
||
}
|
||
});
|
||
|
||
// Cleanup
|
||
onDestroy(() => {
|
||
if (socket) {
|
||
socket.disconnect();
|
||
}
|
||
});
|
||
|
||
async function loadFuelData() {
|
||
fuelLoading = true;
|
||
try {
|
||
const slipsResponse = await fetch("/api/fuel-slips");
|
||
if (slipsResponse.ok) {
|
||
const data = await slipsResponse.json();
|
||
const allSlips = data.fuelSlips || [];
|
||
|
||
// Sadece bu yakıt sorumlusunun onaylı fişlerini topla
|
||
const myApprovedSlips = allSlips.filter(
|
||
(slip) =>
|
||
slip.status === "approved" && slip.fuel_manager_id === user.id
|
||
);
|
||
fuelSummary = myApprovedSlips.reduce(
|
||
(summary, slip) => {
|
||
if (slip.fuel_type === "benzin") {
|
||
summary.benzin += slip.liters || 0;
|
||
} else if (slip.fuel_type === "motorin") {
|
||
summary.motorin += slip.liters || 0;
|
||
}
|
||
return summary;
|
||
},
|
||
{ benzin: 0, motorin: 0 }
|
||
);
|
||
|
||
// Sadece bu yakıt sorumlusunun fişlerini göster
|
||
const mySlips = allSlips.filter(
|
||
(slip) => slip.fuel_manager_id === user.id
|
||
);
|
||
pendingSlips = mySlips.filter((slip) => slip.status === "pending");
|
||
approvedRejectedSlips = mySlips.filter(
|
||
(slip) => slip.status !== "pending"
|
||
);
|
||
}
|
||
|
||
// Form için gerekli veriler
|
||
const [vehiclesRes, unitsRes, personnelRes, goodsManagersRes] =
|
||
await Promise.all([
|
||
fetch("/api/vehicles"),
|
||
fetch("/api/units"),
|
||
fetch("/api/fuel-personnel"),
|
||
fetch("/api/unit-personnel")
|
||
]);
|
||
|
||
if (vehiclesRes.ok) {
|
||
const vehiclesData = await vehiclesRes.json();
|
||
vehicles = vehiclesData.vehicles || [];
|
||
await syncVehicleSelection(formData.unit_id);
|
||
}
|
||
|
||
if (unitsRes.ok) {
|
||
const unitsData = await unitsRes.json();
|
||
units = unitsData.units || [];
|
||
}
|
||
|
||
if (personnelRes.ok) {
|
||
const personnelData = await personnelRes.json();
|
||
personnel =
|
||
personnelData.fuelPersonnel?.filter((p) => p.is_active) || [];
|
||
}
|
||
|
||
if (goodsManagersRes.ok) {
|
||
const goodsData = await goodsManagersRes.json();
|
||
goodsManagers =
|
||
goodsData.unitPersonnel?.filter((gm) => gm.is_active) || [];
|
||
syncGoodsManagerSelection();
|
||
}
|
||
} catch (err) {
|
||
console.error("Yakıt verileri yüklenemedi:", err);
|
||
formError = "Veriler yüklenirken bir hata oluştu.";
|
||
} finally {
|
||
fuelLoading = false;
|
||
}
|
||
}
|
||
|
||
function resetForm() {
|
||
formData = {
|
||
date: new Date().toISOString().split("T")[0],
|
||
force_command: "1. Komutanlık",
|
||
unit_id: "",
|
||
vehicle_id: "",
|
||
fuel_type: "benzin",
|
||
liters: "",
|
||
km: "",
|
||
personnel_id: "",
|
||
goods_manager_id: "",
|
||
notes: ""
|
||
};
|
||
syncGoodsManagerSelection("");
|
||
syncVehicleSelection("");
|
||
}
|
||
|
||
function getGoodsManagersByUnit(unitId) {
|
||
if (!unitId) return [];
|
||
const normalized = parseInt(unitId);
|
||
return goodsManagers.filter((manager) => manager.unit_id === normalized);
|
||
}
|
||
|
||
function syncGoodsManagerSelection(unitId = formData.unit_id) {
|
||
const candidates = getGoodsManagersByUnit(unitId);
|
||
filteredGoodsManagers = candidates;
|
||
|
||
if (!unitId || candidates.length === 0) {
|
||
setFormField("goods_manager_id", "");
|
||
return;
|
||
}
|
||
|
||
const hasCurrent = candidates.some(
|
||
(manager) =>
|
||
manager.id.toString() === (formData.goods_manager_id ?? "").toString()
|
||
);
|
||
|
||
if (!hasCurrent) {
|
||
setFormField("goods_manager_id", candidates[0].id.toString());
|
||
}
|
||
}
|
||
|
||
function getVehiclesByUnit(unitId) {
|
||
if (!unitId) {
|
||
return [];
|
||
}
|
||
|
||
const normalized = parseInt(unitId);
|
||
return vehicles.filter((vehicle) => vehicle.unit_id === normalized);
|
||
}
|
||
|
||
async function syncVehicleSelection(unitId = formData.unit_id) {
|
||
const candidates = getVehiclesByUnit(unitId);
|
||
filteredVehicles = candidates;
|
||
|
||
await tick();
|
||
|
||
if (!unitId || candidates.length === 0) {
|
||
setFormField("vehicle_id", "");
|
||
return;
|
||
}
|
||
|
||
const hasVehicle = candidates.some(
|
||
(vehicle) =>
|
||
vehicle.id.toString() === (formData.vehicle_id ?? "").toString()
|
||
);
|
||
|
||
if (!hasVehicle) {
|
||
setFormField("vehicle_id", candidates[0].id.toString());
|
||
}
|
||
}
|
||
|
||
$: if (formData.unit_id && filteredVehicles.length > 0) {
|
||
const hasVehicle = filteredVehicles.some(
|
||
(vehicle) =>
|
||
vehicle.id.toString() === (formData.vehicle_id ?? "").toString()
|
||
);
|
||
|
||
if (!hasVehicle) {
|
||
setFormField("vehicle_id", filteredVehicles[0].id.toString());
|
||
}
|
||
}
|
||
|
||
async function handleUnitChange(event) {
|
||
const value = event.target.value;
|
||
setFormField("unit_id", value);
|
||
syncGoodsManagerSelection(value);
|
||
await syncVehicleSelection(value);
|
||
}
|
||
|
||
async function handleCreateSlip() {
|
||
if (!user) return;
|
||
|
||
formError = "";
|
||
formSuccess = "";
|
||
|
||
const requiredFields = [
|
||
"date",
|
||
"force_command",
|
||
"unit_id",
|
||
"vehicle_id",
|
||
"fuel_type",
|
||
"liters",
|
||
"km",
|
||
"personnel_id",
|
||
"goods_manager_id"
|
||
];
|
||
for (const field of requiredFields) {
|
||
if (!formData[field]) {
|
||
formError = "Lütfen tüm zorunlu alanları doldurun.";
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (Number(formData.liters) <= 0 || Number(formData.km) < 0) {
|
||
formError = "Litre ve KM değerleri geçerli olmalıdır.";
|
||
return;
|
||
}
|
||
|
||
isSubmitting = true;
|
||
|
||
try {
|
||
const response = await fetch("/api/fuel-slips", {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
...formData,
|
||
fuel_manager_id: user.id
|
||
})
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (!response.ok) {
|
||
formError = data?.message || "Yakıt fişi oluşturulamadı.";
|
||
return;
|
||
}
|
||
|
||
formSuccess = "Yakıt fişi başarıyla oluşturuldu.";
|
||
resetForm();
|
||
await loadFuelData();
|
||
showFuelForm = false;
|
||
} catch (err) {
|
||
console.error("Yakıt fişi oluşturulamadı:", err);
|
||
formError = "Sunucuya ulaşılamadı.";
|
||
} finally {
|
||
isSubmitting = false;
|
||
}
|
||
}
|
||
|
||
function updateTime() {
|
||
const now = new Date();
|
||
const options = {
|
||
year: "numeric",
|
||
month: "long",
|
||
day: "numeric",
|
||
hour: "2-digit",
|
||
minute: "2-digit",
|
||
second: "2-digit"
|
||
};
|
||
currentTime = now.toLocaleDateString("tr-TR", options);
|
||
}
|
||
|
||
function handleLogout() {
|
||
localStorage.removeItem("user");
|
||
goto("/");
|
||
}
|
||
|
||
function getRoleDisplayName(role) {
|
||
switch (role) {
|
||
case "admin":
|
||
return '<i class="fas fa-user-shield"></i> Sistem Yöneticisi';
|
||
case "fuel_manager":
|
||
return '<i class="fas fa-gas-pump"></i> Yakıt Sorumlusu';
|
||
case "goods_manager":
|
||
return '<i class="fas fa-clipboard-check"></i> Mal Sorumlusu';
|
||
default:
|
||
return "Bilinmeyen Rol";
|
||
}
|
||
}
|
||
|
||
function getRoleBadgeClass(role) {
|
||
switch (role) {
|
||
case "admin":
|
||
return "role-admin";
|
||
case "fuel_manager":
|
||
return "role-fuel";
|
||
case "goods_manager":
|
||
return "role-goods";
|
||
default:
|
||
return "";
|
||
}
|
||
}
|
||
|
||
function getStatusClass(status) {
|
||
switch (status) {
|
||
case "pending":
|
||
return "status-pending";
|
||
case "approved":
|
||
return "status-approved";
|
||
case "rejected":
|
||
return "status-rejected";
|
||
default:
|
||
return "";
|
||
}
|
||
}
|
||
|
||
function getStatusLabel(status) {
|
||
switch (status) {
|
||
case "pending":
|
||
return '<i class="fas fa-clock"></i> Beklemede';
|
||
case "approved":
|
||
return '<i class="fas fa-check-circle"></i> Onaylı';
|
||
case "rejected":
|
||
return '<i class="fas fa-times-circle"></i> Reddedildi';
|
||
default:
|
||
return "Bilinmiyor";
|
||
}
|
||
}
|
||
|
||
function formatDate(value) {
|
||
const date = value ? new Date(value) : null;
|
||
return date ? date.toLocaleDateString("tr-TR") : "-";
|
||
}
|
||
|
||
function formatKm(value) {
|
||
return typeof value === "number"
|
||
? value.toLocaleString("tr-TR")
|
||
: value
|
||
? Number(value).toLocaleString("tr-TR")
|
||
: "-";
|
||
}
|
||
|
||
function formatLiters(value) {
|
||
return value ? `${Number(value).toFixed(0)}L` : "-";
|
||
}
|
||
|
||
function getFuelTypeLabel(type) {
|
||
return type === "benzin" ? "⛽ Benzin" : "🛢️ Motorin";
|
||
}
|
||
|
||
function navigateTo(page) {
|
||
if (page === "fuel-slips" && user?.role === "fuel_manager") {
|
||
showFuelForm = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "" && user?.role === "fuel_manager") {
|
||
showFuelForm = false;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "" && user?.role === "goods_manager") {
|
||
showGoodsManager = false;
|
||
showGoodsManagerVehicles = false;
|
||
showDevriçark = false;
|
||
showMonthlyReport = false;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "goods-manager" && user?.role === "goods_manager") {
|
||
console.log("🎯 Navigating to goods-manager, user:", user);
|
||
showGoodsManager = true;
|
||
showGoodsManagerVehicles = false;
|
||
showDevriçark = false;
|
||
showMonthlyReport = false;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "devriçark" && user?.role === "goods_manager") {
|
||
console.log("🎯 Navigating to devriçark, user:", user);
|
||
showGoodsManager = false;
|
||
showGoodsManagerVehicles = false;
|
||
showDevriçark = true;
|
||
showMonthlyReport = false;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "aylik-yakit-dokumu" && user?.role === "goods_manager") {
|
||
console.log("🎯 Navigating to aylik-yakit-dokumu, user:", user);
|
||
showGoodsManager = false;
|
||
showGoodsManagerVehicles = false;
|
||
showDevriçark = false;
|
||
showMonthlyReport = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "goods-manager-vehicles" && user?.role === "goods_manager") {
|
||
showGoodsManager = false;
|
||
showDevriçark = false;
|
||
showMonthlyReport = false;
|
||
showGoodsManagerVehicles = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "distribution-document" && user?.role === "fuel_manager") {
|
||
// Dağıtım belgesi sayfasına yönlendir (gelecekte oluşturulacak)
|
||
showMobileMenu = false;
|
||
alert("Dağıtım Belgesi özelliği yakında eklenecek.");
|
||
return;
|
||
}
|
||
|
||
showMobileMenu = false;
|
||
|
||
if (page === "goods-manager") {
|
||
if (user?.role === "goods_manager") {
|
||
console.log("🎯 Setting showGoodsManager to true");
|
||
showGoodsManager = true;
|
||
showFuelForm = false;
|
||
showMobileMenu = false;
|
||
return;
|
||
} else {
|
||
goto("/goods-manager");
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Admin page navigation for SPA
|
||
if (user?.role === "admin") {
|
||
// Hide all content first
|
||
showFuelForm = false;
|
||
showGoodsManager = false;
|
||
|
||
// 🎯 Ana Sayfa Case'i - Admin SPA içinde ana sayfaya dönüş
|
||
if (page === "") {
|
||
resetAdminStates(); // Tüm admin state'lerini false yap
|
||
showMobileMenu = false;
|
||
tick(); // Svelte reactivity'yi zorla
|
||
return; // goto çağrısı yapma, SPA içinde kal
|
||
}
|
||
|
||
if (page === "vehicles") {
|
||
resetAdminStates();
|
||
showVehicles = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "units") {
|
||
resetAdminStates();
|
||
showUnits = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "personnel") {
|
||
resetAdminStates();
|
||
showPersonnel = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
|
||
if (page === "goods-managers") {
|
||
resetAdminStates();
|
||
showGoodsManagers = true;
|
||
showMobileMenu = false;
|
||
return;
|
||
}
|
||
}
|
||
|
||
goto(`/dashboard/${page}`);
|
||
}
|
||
</script>
|
||
|
||
<div class="welcome-container">
|
||
<div class="container">
|
||
{#if loading}
|
||
<div class="text-center">
|
||
<div
|
||
class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"
|
||
></div>
|
||
<p class="mt-4">Yükleniyor...</p>
|
||
</div>
|
||
{:else if user}
|
||
<div class="dashboard-layout">
|
||
<!-- Sol Navigasyon Menüsü -->
|
||
<nav class="sidebar {showMobileMenu ? 'mobile-open' : ''}">
|
||
<div class="sidebar-header">
|
||
<h3 class="sidebar-title">
|
||
{#if user.role === "admin"}
|
||
Yönetim Paneli
|
||
{:else if user.role === "fuel_manager"}
|
||
Yakıt İşlemleri
|
||
{:else if user.role === "goods_manager"}
|
||
Onay Paneli
|
||
{/if}
|
||
</h3>
|
||
<button
|
||
class="mobile-close-btn"
|
||
on:click={() => (showMobileMenu = false)}>×</button
|
||
>
|
||
</div>
|
||
<ul class="nav-menu">
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("")}
|
||
class:active={user.role === "admin"
|
||
? !showVehicles &&
|
||
!showUnits &&
|
||
!showPersonnel &&
|
||
!showGoodsManagers
|
||
: user.role === "goods_manager"
|
||
? !showGoodsManager &&
|
||
!showGoodsManagerVehicles &&
|
||
!showDevriçark &&
|
||
!showMonthlyReport
|
||
: user.role !== "fuel_manager"
|
||
? !showFuelForm
|
||
: true}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||
<polyline points="9 22 9 12 15 12 15 22" />
|
||
</svg>
|
||
Ana Sayfa
|
||
</button>
|
||
</li>
|
||
|
||
{#if user.role === "admin"}
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("units")}
|
||
class:active={showUnits}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M3 21h18" />
|
||
<path d="M5 21V7l8-4v18" />
|
||
<path d="M19 21V11l-6-4" />
|
||
</svg>
|
||
Birlik Yönetimi
|
||
</button>
|
||
</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">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("personnel")}
|
||
class:active={showPersonnel}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||
<circle cx="9" cy="7" r="4" />
|
||
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
||
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||
</svg>
|
||
Yakıt Personeli
|
||
</button>
|
||
</li>
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("goods-managers")}
|
||
class:active={showGoodsManagers}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||
<circle cx="9" cy="7" r="4" />
|
||
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
||
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||
</svg>
|
||
Personel İşlemleri
|
||
</button>
|
||
</li>
|
||
{:else if user.role === "fuel_manager"}
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("fuel-slips")}
|
||
class:active={showFuelForm}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path
|
||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||
/>
|
||
<polyline points="14 2 14 8 20 8" />
|
||
<line x1="16" y1="13" x2="8" y2="13" />
|
||
<line x1="16" y1="17" x2="8" y2="17" />
|
||
<polyline points="10 9 9 9 8 9" />
|
||
</svg>
|
||
Yakıt Fişi Oluştur
|
||
</button>
|
||
</li>
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("distribution-document")}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path
|
||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||
/>
|
||
<polyline points="14 2 14 8 20 8" />
|
||
<line x1="12" y1="18" x2="12" y2="12" />
|
||
<line x1="9" y1="15" x2="15" y2="15" />
|
||
</svg>
|
||
Dağıtım Belgesi Oluştur
|
||
</button>
|
||
</li>
|
||
{:else if user.role === "goods_manager"}
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("goods-manager")}
|
||
class:active={showGoodsManager}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
|
||
<polyline points="22 4 12 14.01 9 11.01" />
|
||
</svg>
|
||
Atanan Fişler
|
||
</button>
|
||
</li>
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("goods-manager-vehicles")}
|
||
class:active={showGoodsManagerVehicles}
|
||
>
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M5 16l-1.5 3" />
|
||
<path d="M19 16l1.5 3" />
|
||
<path d="M7 16h10" />
|
||
<path d="M6 16v-6a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v6" />
|
||
<circle cx="7.5" cy="19.5" r="1.5" />
|
||
<circle cx="16.5" cy="19.5" r="1.5" />
|
||
</svg>
|
||
Araç Yönetimi
|
||
</button>
|
||
</li>
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("aylik-yakit-dokumu")}
|
||
class:active={showMonthlyReport}
|
||
>
|
||
<i class="fa-solid fa-list-ol"></i>
|
||
Aylık Yakıt Dökümü
|
||
</button>
|
||
</li>
|
||
<li class="nav-item">
|
||
<button
|
||
class="nav-btn"
|
||
on:click={() => navigateTo("devriçark")}
|
||
class:active={showDevriçark}
|
||
>
|
||
<i class="fa-regular fa-file-lines"></i>
|
||
Devriçark İşlemleri
|
||
</button>
|
||
</li>
|
||
{/if}
|
||
</ul>
|
||
</nav>
|
||
|
||
<!-- Ana İçerik Alanı -->
|
||
<div class="main-content">
|
||
<div class="welcome-card card">
|
||
<!-- Üst kısım: Kullanıcı bilgileri -->
|
||
<div class="user-header">
|
||
<div class="user-avatar">
|
||
<div class="avatar-circle">
|
||
{#if user.role === "admin"}
|
||
<i class="fa-solid fa-user-tie"></i>
|
||
{:else if user.role === "fuel_manager"}
|
||
<i class="fa-solid fa-gas-pump"></i>
|
||
{:else if user.role === "goods_manager"}
|
||
<i class="fa-solid fa-truck"></i>
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
<div class="user-info">
|
||
<h2 class="user-name">{user.full_name}</h2>
|
||
<div class="role-badge {getRoleBadgeClass(user.role)}">
|
||
{@html getRoleDisplayName(user.role)}
|
||
</div>
|
||
</div>
|
||
<div class="header-actions">
|
||
<button
|
||
class="btn mobile-menu-btn"
|
||
on:click={() => (showMobileMenu = !showMobileMenu)}
|
||
>
|
||
<svg
|
||
width="24"
|
||
height="24"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<line x1="3" y1="12" x2="21" y2="12" />
|
||
<line x1="3" y1="6" x2="21" y2="6" />
|
||
<line x1="3" y1="18" x2="21" y2="18" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Ayırıcı -->
|
||
<div class="divider"></div>
|
||
|
||
<!-- Sadece admin ve goods_manager için bilgilendirme -->
|
||
{#if user.role === "admin" && !showVehicles && !showUnits && !showPersonnel && !showGoodsManagers}
|
||
<!-- Karşılama mesajı -->
|
||
<div class="welcome-content">
|
||
<p class="welcome-message">
|
||
{#if user.role === "admin"}
|
||
Sisteme hoş geldiniz! Araç, birlik ve personel yönetimi
|
||
yapabilirsiniz.
|
||
{:else if user.role === "goods_manager"}
|
||
Hoş geldiniz! Size atanan yakıt fişlerini
|
||
onaylayabilirsiniz.
|
||
{/if}
|
||
</p>
|
||
|
||
<div class="current-time">
|
||
<svg
|
||
width="20"
|
||
height="20"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
class="inline mr-2"
|
||
>
|
||
<circle cx="12" cy="12" r="10" />
|
||
<polyline points="12 6 12 12 16 14" />
|
||
</svg>
|
||
{currentTime}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- İstatistikler Kartları -->
|
||
<div class="stats-grid">
|
||
<div class="stat-card card">
|
||
<div class="stat-icon fuel-icon">
|
||
<svg
|
||
width="32"
|
||
height="32"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path d="M3 3h18v18H3z" />
|
||
<path d="M7 7h10v10H7z" />
|
||
<path d="M11 3v18" />
|
||
<path d="M3 11h18" />
|
||
</svg>
|
||
</div>
|
||
<div class="stat-info">
|
||
<h3 class="stat-title">Yakıt İşlemleri</h3>
|
||
<p class="stat-value">Sistem Hazır</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card card">
|
||
<div class="stat-icon goods-icon">
|
||
<svg
|
||
width="32"
|
||
height="32"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path
|
||
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
|
||
/>
|
||
</svg>
|
||
</div>
|
||
<div class="stat-info">
|
||
<h3 class="stat-title">Mal Takibi</h3>
|
||
<p class="stat-value">Aktif</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card card">
|
||
<div class="stat-icon system-icon">
|
||
<svg
|
||
width="32"
|
||
height="32"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
|
||
<line x1="8" y1="21" x2="16" y2="21" />
|
||
<line x1="12" y1="17" x2="12" y2="21" />
|
||
</svg>
|
||
</div>
|
||
<div class="stat-info">
|
||
<h3 class="stat-title">Sistem Durumu</h3>
|
||
<p class="stat-value">✅ Çalışıyor</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bilgilendirme -->
|
||
<div class="info-section">
|
||
<div class="info-card card">
|
||
<h3 class="info-title">📋 Bilgilendirme</h3>
|
||
<div class="info-content">
|
||
{#if user.role === "admin"}
|
||
<ul class="info-list">
|
||
<li>
|
||
Araç, birlik ve personel yönetimi yapabilirsiniz
|
||
</li>
|
||
<li>Personel işlemlerini yönetebilirsiniz</li>
|
||
<li>Tüm kullanıcıları yönetebilirsiniz</li>
|
||
<li>Sistem ayarlarını yapılandırabilirsiniz</li>
|
||
<li>Raporları görüntüleyebilirsiniz</li>
|
||
</ul>
|
||
{:else if user.role === "goods_manager"}
|
||
<ul class="info-list">
|
||
<li>Araçların aldığı yakıtları takip edebilirsiniz</li>
|
||
<li>Onay/red işlemleri yapabilirsiniz</li>
|
||
<li>Ay sonu devriçark cetveli hazırlayabilirsiniz</li>
|
||
</ul>
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{:else if user.role === "goods_manager" && showGoodsManager}
|
||
<!-- Goods Manager Content -->
|
||
<GoodsManagerContent {user} />
|
||
{:else if user.role === "goods_manager" && showGoodsManagerVehicles}
|
||
<VehiclesContent {user} />
|
||
{:else if user.role === "goods_manager" && showMonthlyReport}
|
||
<!-- Monthly Fuel Report Content -->
|
||
<MonthlyFuelReportContent {user} />
|
||
{:else if user.role === "goods_manager" && showDevriçark}
|
||
<!-- Devriçark Content -->
|
||
<DevriçarkContent {user} />
|
||
{:else if user.role === "admin"}
|
||
<!-- Admin Dynamic Content -->
|
||
|
||
{#if showVehicles}
|
||
<VehiclesContent {user} />
|
||
{:else if showUnits}
|
||
<UnitsContent {user} />
|
||
{:else if showPersonnel}
|
||
<PersonnelContent {user} />
|
||
{:else if showGoodsManagers}
|
||
<GoodsManagersContent {user} />
|
||
{:else}
|
||
<!-- Admin Welcome Message (Default) -->
|
||
<div class="welcome-card card">
|
||
<div class="card-header">
|
||
<div class="card-icon">🚗</div>
|
||
<h3>Araç Yönetimi</h3>
|
||
</div>
|
||
<div class="card-content">
|
||
<p>
|
||
Yukarıdaki menüden Araç Yönetimi'ni seçerek araçları
|
||
yönetebilirsiniz.
|
||
</p>
|
||
<p
|
||
style="margin-top: 1rem; color: var(--primary-color); font-weight: 600;"
|
||
>
|
||
✅ Admin SPA yüklendi!
|
||
</p>
|
||
</div>
|
||
</div>
|
||
{/if}
|
||
{:else}
|
||
<!-- Fuel Manager ana görünümü -->
|
||
{#if formSuccess}
|
||
<div class="form-alert success-alert">
|
||
{formSuccess}
|
||
</div>
|
||
{/if}
|
||
|
||
{#if formError && showFuelForm}
|
||
<div class="form-alert error-alert">
|
||
{formError}
|
||
</div>
|
||
{/if}
|
||
|
||
{#if !showFuelForm}
|
||
<section class="fuel-summary-section">
|
||
<div class="fuel-summary-grid">
|
||
<div class="fuel-summary-card benzin">
|
||
<div class="summary-icon-wrapper">
|
||
<div class="summary-icon">⛽</div>
|
||
</div>
|
||
<div class="summary-info">
|
||
<h3 class="summary-title">Benzin</h3>
|
||
<p class="summary-amount">
|
||
{fuelLoading ? "..." : fuelSummary.benzin.toFixed(1)}
|
||
<span class="summary-unit">LT</span>
|
||
</p>
|
||
<span class="summary-label">Toplam Yakıt</span>
|
||
</div>
|
||
</div>
|
||
<div class="fuel-summary-card motorin">
|
||
<div class="summary-icon-wrapper">
|
||
<div class="summary-icon">🛢️</div>
|
||
</div>
|
||
<div class="summary-info">
|
||
<h3 class="summary-title">Motorin</h3>
|
||
<p class="summary-amount">
|
||
{fuelLoading ? "..." : fuelSummary.motorin.toFixed(1)}
|
||
<span class="summary-unit">LT</span>
|
||
</p>
|
||
<span class="summary-label">Toplam Yakıt</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="tables-section">
|
||
<div class="table-container">
|
||
<div class="fuel-table-header">
|
||
<h3 class="fuel-table-title">Onay Bekleyen Fişler</h3>
|
||
<span class="count-badge">{pendingSlips.length}</span>
|
||
</div>
|
||
{#if fuelLoading}
|
||
<div class="table-loader">Yükleniyor...</div>
|
||
{:else if pendingSlips.length === 0}
|
||
<div class="empty-table">
|
||
<div class="empty-table-icon">📄</div>
|
||
<p>Onay bekleyen fiş bulunmamaktadır.</p>
|
||
</div>
|
||
{:else}
|
||
<div class="table-wrapper">
|
||
<table class="fuel-table">
|
||
<thead>
|
||
<tr>
|
||
<th>S.No</th>
|
||
<th>Araç Plaka</th>
|
||
<th>Personel</th>
|
||
<th>Mal Sorumlusu</th>
|
||
<th>KM</th>
|
||
<th>Tarih</th>
|
||
<th>Yakıt Cinsi</th>
|
||
<th>Miktar</th>
|
||
<th>Durum</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{#each pendingSlips as slip, index}
|
||
<tr>
|
||
<td>{index + 1}</td>
|
||
<td>{slip.vehicle_info?.plate || "-"}</td>
|
||
<td>{slip.personnel_info?.full_name || "-"}</td>
|
||
<td
|
||
>{slip.goods_manager_info?.full_name ||
|
||
"-"}</td
|
||
>
|
||
<td>{formatKm(slip.km)}</td>
|
||
<td>{formatDate(slip.date)}</td>
|
||
<td>{getFuelTypeLabel(slip.fuel_type)}</td>
|
||
<td>{formatLiters(slip.liters)}</td>
|
||
<td>
|
||
<span
|
||
class={`status-badge ${getStatusClass(slip.status)}`}
|
||
title={slip.status === "rejected" &&
|
||
slip.approval_notes
|
||
? `Red Nedeni: ${slip.approval_notes}`
|
||
: ""}
|
||
>
|
||
{@html getStatusLabel(slip.status)}
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
{/each}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{/if}
|
||
</div>
|
||
|
||
<div class="table-container">
|
||
<div class="fuel-table-header">
|
||
<h3 class="fuel-table-title">İşlem Geçmişi</h3>
|
||
<span class="count-badge"
|
||
>{approvedRejectedSlips.length}</span
|
||
>
|
||
</div>
|
||
{#if fuelLoading}
|
||
<div class="table-loader">Yükleniyor...</div>
|
||
{:else if approvedRejectedSlips.length === 0}
|
||
<div class="empty-table">
|
||
<div class="empty-table-icon">🗂️</div>
|
||
<p>İşlenmiş fiş bulunmamaktadır.</p>
|
||
</div>
|
||
{:else}
|
||
<div class="table-wrapper">
|
||
<table class="fuel-table">
|
||
<thead>
|
||
<tr>
|
||
<th>S.No</th>
|
||
<th>Araç Plaka</th>
|
||
<th>Personel</th>
|
||
<th>Mal Sorumlusu</th>
|
||
<th>KM</th>
|
||
<th>Tarih</th>
|
||
<th>Yakıt Cinsi</th>
|
||
<th>Miktar</th>
|
||
<th>Durum</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{#each approvedRejectedSlips as slip, index}
|
||
<tr>
|
||
<td>{index + 1}</td>
|
||
<td>{slip.vehicle_info?.plate || "-"}</td>
|
||
<td>{slip.personnel_info?.full_name || "-"}</td>
|
||
<td
|
||
>{slip.goods_manager_info?.full_name ||
|
||
"-"}</td
|
||
>
|
||
<td>{formatKm(slip.km)}</td>
|
||
<td>{formatDate(slip.date)}</td>
|
||
<td>{getFuelTypeLabel(slip.fuel_type)}</td>
|
||
<td>{formatLiters(slip.liters)}</td>
|
||
<td>
|
||
<span
|
||
class={`status-badge ${getStatusClass(slip.status)}`}
|
||
title={slip.status === "rejected" &&
|
||
slip.approval_notes
|
||
? `Red Nedeni: ${slip.approval_notes}`
|
||
: ""}
|
||
>
|
||
{@html getStatusLabel(slip.status)}
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
{/each}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{/if}
|
||
</div>
|
||
</section>
|
||
{/if}
|
||
|
||
{#if showFuelForm}
|
||
<section class="fuel-form-section">
|
||
<div class="fuel-form-header">
|
||
<h3 class="fuel-form-title">
|
||
<svg
|
||
width="24"
|
||
height="24"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
style="display: inline-block; vertical-align: middle; margin-right: 0.5rem;"
|
||
>
|
||
<path
|
||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||
/>
|
||
<polyline points="14 2 14 8 20 8" />
|
||
<line x1="16" y1="13" x2="8" y2="13" />
|
||
<line x1="16" y1="17" x2="8" y2="17" />
|
||
<polyline points="10 9 9 9 8 9" />
|
||
</svg>
|
||
Yeni Yakıt Fişi Oluştur
|
||
</h3>
|
||
</div>
|
||
|
||
{#if formError}
|
||
<div class="form-alert error-alert">
|
||
{formError}
|
||
</div>
|
||
{/if}
|
||
|
||
<form
|
||
class="fuel-form"
|
||
on:submit|preventDefault={handleCreateSlip}
|
||
>
|
||
<div class="form-grid">
|
||
<div class="form-group">
|
||
<label for="force_command">Kuvvet Komutanlığı</label>
|
||
<input
|
||
id="force_command"
|
||
class="form-input"
|
||
type="text"
|
||
placeholder="1. Komutanlık"
|
||
bind:value={formData.force_command}
|
||
required
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="date">Tarih</label>
|
||
<input
|
||
id="date"
|
||
class="form-input"
|
||
type="date"
|
||
bind:value={formData.date}
|
||
required
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="unit_id">Birlik</label>
|
||
<select
|
||
id="unit_id"
|
||
class="form-select"
|
||
bind:value={formData.unit_id}
|
||
on:change={handleUnitChange}
|
||
required
|
||
>
|
||
<option value="">Birlik Seçin</option>
|
||
{#each units as unit}
|
||
<option value={unit.id.toString()}>{unit.name}</option>
|
||
{/each}
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="vehicle_id">Araç</label>
|
||
<select
|
||
id="vehicle_id"
|
||
class="form-select"
|
||
bind:value={formData.vehicle_id}
|
||
disabled={!formData.unit_id || filteredVehicles.length === 0}
|
||
required
|
||
>
|
||
<option value="" class="s-jZJiUkwef1J0">Araç Seçin</option>
|
||
{#if !formData.unit_id}
|
||
<option value="">Önce birlik seçin</option>
|
||
{:else if filteredVehicles.length === 0}
|
||
<option value="">Bu birliğe kayıtlı araç yok</option>
|
||
{/if}
|
||
{#each filteredVehicles as vehicle}
|
||
<option value={vehicle.id.toString()}>
|
||
{vehicle.brand} {vehicle.model} ({vehicle.plate})
|
||
</option>
|
||
{/each}
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="fuel_type">Yakıt Türü</label>
|
||
<select
|
||
id="fuel_type"
|
||
class="form-select"
|
||
bind:value={formData.fuel_type}
|
||
required
|
||
>
|
||
<option value="benzin">Benzin</option>
|
||
<option value="motorin">Motorin</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="liters">Litre</label>
|
||
<input
|
||
id="liters"
|
||
class="form-input"
|
||
type="number"
|
||
min="0.1"
|
||
step="0.1"
|
||
placeholder="45"
|
||
bind:value={formData.liters}
|
||
required
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="km">Kilometre</label>
|
||
<input
|
||
id="km"
|
||
class="form-input"
|
||
type="number"
|
||
min="0"
|
||
placeholder="125.420"
|
||
bind:value={formData.km}
|
||
required
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="personnel_id">Teslim Eden</label>
|
||
<select
|
||
id="personnel_id"
|
||
class="form-select"
|
||
bind:value={formData.personnel_id}
|
||
required
|
||
>
|
||
<option value="">Personel Seçin</option>
|
||
{#each personnel as person}
|
||
<option value={person.id.toString()}>
|
||
{person.rank} {person.full_name}
|
||
</option>
|
||
{/each}
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="goods_manager_id">Teslim Alan</label>
|
||
<select
|
||
id="goods_manager_id"
|
||
class="form-select"
|
||
bind:value={formData.goods_manager_id}
|
||
disabled={
|
||
!formData.unit_id ||
|
||
filteredGoodsManagers.length === 0
|
||
}
|
||
required
|
||
>
|
||
{#if !formData.unit_id}
|
||
<option value="">Önce birlik seçin</option>
|
||
{:else if filteredGoodsManagers.length === 0}
|
||
<option value="">
|
||
Bu birliğe atanmış personel yok
|
||
</option>
|
||
{:else}
|
||
<option value="">Mal Sorumlusu Seçin</option>
|
||
{#each filteredGoodsManagers as manager}
|
||
<option value={manager.id.toString()}>
|
||
{manager.rank} {manager.full_name}
|
||
</option>
|
||
{/each}
|
||
{/if}
|
||
</select>
|
||
</div>
|
||
<div class="form-group full-width">
|
||
<label for="notes">Notlar</label>
|
||
<textarea
|
||
id="notes"
|
||
class="form-textarea"
|
||
rows="2"
|
||
placeholder="Haftalık yakıt ikmali..."
|
||
bind:value={formData.notes}
|
||
></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="form-actions">
|
||
<button
|
||
type="button"
|
||
class="btn btn-secondary"
|
||
on:click={() => {
|
||
showFuelForm = false;
|
||
formError = "";
|
||
}}
|
||
>
|
||
<svg
|
||
width="16"
|
||
height="16"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<line x1="18" y1="6" x2="6" y2="18" />
|
||
<line x1="6" y1="6" x2="18" y2="18" />
|
||
</svg>
|
||
Vazgeç
|
||
</button>
|
||
<button
|
||
type="submit"
|
||
class="btn btn-primary"
|
||
disabled={isSubmitting}
|
||
>
|
||
{#if isSubmitting}
|
||
<span class="btn-spinner"></span>
|
||
Kaydediliyor...
|
||
{:else}
|
||
<svg
|
||
width="16"
|
||
height="16"
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
stroke-width="2"
|
||
>
|
||
<path
|
||
d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"
|
||
/>
|
||
<polyline points="17 21 17 13 7 13 7 21" />
|
||
<polyline points="7 3 7 8 15 8" />
|
||
</svg>
|
||
Fiş Oluştur
|
||
{/if}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
{/if}
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
<!-- main-content kapanış -->
|
||
</div>
|
||
<!-- dashboard-layout kapanış -->
|
||
{:else}
|
||
<div class="text-center">
|
||
<p>Oturum bulunamadı. Yönlendiriliyorsunuz...</p>
|
||
</div>
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.welcome-container {
|
||
min-height: 100vh;
|
||
background: #F2F3F7;
|
||
padding: 2rem var(--page-horizontal-padding);
|
||
}
|
||
|
||
:global(.welcome-container .container) {
|
||
width: 100%;
|
||
max-width: 1800px;
|
||
margin: 0;
|
||
margin-right: auto;
|
||
padding: 0;
|
||
}
|
||
|
||
.welcome-card {
|
||
max-width: 1600px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.user-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.user-avatar {
|
||
margin-right: 1.5rem;
|
||
}
|
||
|
||
.avatar-circle {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 50%;
|
||
background: var(--primary-color);
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 2.5rem;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.avatar-circle i {
|
||
font-size: 2.5rem;
|
||
}
|
||
|
||
.user-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.user-name {
|
||
font-size: 1.8rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.divider {
|
||
height: 1px;
|
||
background: var(--card-border-color);
|
||
margin: 2rem 0;
|
||
}
|
||
|
||
.welcome-content {
|
||
text-align: center;
|
||
padding: 2rem 0;
|
||
}
|
||
|
||
.welcome-icon {
|
||
color: var(--primary-color);
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.welcome-title {
|
||
font-size: 2.5rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.welcome-message {
|
||
font-size: 1.2rem;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 1.5rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.current-time {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--text-secondary);
|
||
font-size: 1rem;
|
||
margin-top: 1rem;
|
||
}
|
||
|
||
.stats-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||
gap: 1.5rem;
|
||
margin: 3rem 0;
|
||
}
|
||
|
||
.stat-card {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 1.5rem;
|
||
border: 1px solid #c9c8cb;
|
||
border-radius: 12px;
|
||
transition:
|
||
transform 0.3s ease,
|
||
box-shadow 0.3s ease;
|
||
}
|
||
|
||
.stat-icon {
|
||
width: 60px;
|
||
height: 60px;
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 1rem;
|
||
}
|
||
|
||
.fuel-icon {
|
||
background: rgba(37, 99, 235, 0.1);
|
||
color: #2563eb;
|
||
}
|
||
|
||
.goods-icon {
|
||
background: rgba(5, 150, 105, 0.1);
|
||
color: #059669;
|
||
}
|
||
|
||
.system-icon {
|
||
background: rgba(220, 38, 38, 0.1);
|
||
color: #dc2626;
|
||
}
|
||
|
||
.stat-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.stat-title {
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 1.4rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.info-section {
|
||
margin-top: 2rem;
|
||
}
|
||
|
||
.info-title {
|
||
font-size: 1.3rem;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.info-list {
|
||
list-style: none;
|
||
padding: 0;
|
||
}
|
||
|
||
.info-list li {
|
||
padding: 0.75rem 0;
|
||
border-bottom: 1px solid var(--card-border-color);
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.info-list li:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.info-list li::before {
|
||
content: "✓";
|
||
color: var(--primary-color);
|
||
font-weight: bold;
|
||
margin-right: 0.75rem;
|
||
}
|
||
|
||
/* Responsive tasarım */
|
||
@media (max-width: 768px) {
|
||
.user-header {
|
||
flex-direction: column;
|
||
text-align: center;
|
||
}
|
||
|
||
.user-avatar {
|
||
margin-right: 0;
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.avatar-circle {
|
||
width: 60px;
|
||
height: 60px;
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.welcome-title {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.stats-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.current-time {
|
||
flex-direction: column;
|
||
gap: 0.5rem;
|
||
}
|
||
}
|
||
|
||
/* Dashboard Layout */
|
||
.dashboard-layout {
|
||
display: flex;
|
||
gap: 2rem;
|
||
min-height: calc(100vh - 4rem);
|
||
padding: 0 var(--page-horizontal-padding);
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.sidebar {
|
||
width: 280px;
|
||
background: white;
|
||
border: 1px solid #c9c8cb;
|
||
border-radius: 12px;
|
||
padding: 1.5rem 1.5rem 1.5rem;
|
||
height: fit-content;
|
||
position: sticky;
|
||
top: 5rem;
|
||
}
|
||
|
||
.sidebar-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 2rem;
|
||
padding: 0 0 1rem 1.5rem;
|
||
border-bottom: 1px solid var(--card-border-color);
|
||
}
|
||
|
||
.sidebar-title {
|
||
font-size: 1.2rem;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
margin: 0;
|
||
}
|
||
|
||
.mobile-close-btn {
|
||
display: none;
|
||
background: none;
|
||
border: none;
|
||
font-size: 1.5rem;
|
||
color: var(--text-secondary);
|
||
cursor: pointer;
|
||
padding: 0.25rem;
|
||
}
|
||
|
||
.nav-menu {
|
||
list-style: none;
|
||
padding: 0 0 0 0;
|
||
margin: 0;
|
||
}
|
||
|
||
.nav-item {
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.nav-btn {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.75rem 1rem;
|
||
background: none;
|
||
border: none;
|
||
border-radius: 8px;
|
||
color: var(--text-secondary);
|
||
font-size: 0.95rem;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
text-align: left;
|
||
}
|
||
|
||
.nav-btn.active {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.main-content {
|
||
flex: 65;
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
gap: 1rem;
|
||
align-items: center;
|
||
}
|
||
|
||
.mobile-menu-btn {
|
||
display: none;
|
||
background: none;
|
||
border: 1px solid var(--card-border-color);
|
||
border-radius: 8px;
|
||
padding: 0.5rem;
|
||
cursor: pointer;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
/* Responsive Tasarım */
|
||
@media (max-width: 1024px) {
|
||
.dashboard-layout {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.sidebar {
|
||
width: 100%;
|
||
position: static;
|
||
display: none;
|
||
}
|
||
|
||
.sidebar.mobile-open {
|
||
display: block;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
z-index: 1000;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
padding: 0;
|
||
}
|
||
|
||
.sidebar.mobile-open > * {
|
||
background: white;
|
||
border-radius: 12px;
|
||
margin: 2rem var(--page-horizontal-padding);
|
||
max-height: 80vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.mobile-close-btn {
|
||
display: block;
|
||
}
|
||
|
||
.mobile-menu-btn {
|
||
display: block;
|
||
}
|
||
|
||
.header-actions {
|
||
flex-wrap: wrap;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.dashboard-layout {
|
||
padding: 0 var(--page-horizontal-padding);
|
||
}
|
||
|
||
.user-header {
|
||
flex-direction: column;
|
||
text-align: center;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.user-avatar {
|
||
margin-right: 0;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.avatar-circle {
|
||
width: 60px;
|
||
height: 60px;
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.avatar-circle i {
|
||
font-size: 1.75rem;
|
||
}
|
||
|
||
.welcome-title {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.stats-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.current-time {
|
||
flex-direction: column;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.sidebar.mobile-open > * {
|
||
margin: 1rem;
|
||
}
|
||
}
|
||
|
||
/* Animasyonlar */
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(20px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.welcome-card {
|
||
animation: fadeIn 0.6s ease-out;
|
||
}
|
||
|
||
.stat-card {
|
||
animation: fadeIn 0.8s ease-out;
|
||
}
|
||
|
||
.stat-card:nth-child(2) {
|
||
animation-delay: 0.1s;
|
||
}
|
||
|
||
.stat-card:nth-child(3) {
|
||
animation-delay: 0.2s;
|
||
}
|
||
|
||
.nav-item {
|
||
animation: fadeIn 0.5s ease-out;
|
||
}
|
||
|
||
.nav-item:nth-child(1) {
|
||
animation-delay: 0.1s;
|
||
}
|
||
.nav-item:nth-child(2) {
|
||
animation-delay: 0.2s;
|
||
}
|
||
.nav-item:nth-child(3) {
|
||
animation-delay: 0.3s;
|
||
}
|
||
.nav-item:nth-child(4) {
|
||
animation-delay: 0.4s;
|
||
}
|
||
|
||
/* Fuel Form Styles */
|
||
.fuel-form-section {
|
||
animation: slideDown 0.3s ease-out;
|
||
}
|
||
|
||
@keyframes slideDown {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-20px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.fuel-form-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 2rem;
|
||
padding-bottom: 1.5rem;
|
||
border-bottom: 2px solid #e5e7eb;
|
||
}
|
||
|
||
.fuel-form-title {
|
||
font-size: 1.75rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.fuel-form {
|
||
animation: fadeIn 0.4s ease-out 0.1s both;
|
||
}
|
||
|
||
.form-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||
gap: 1.5rem;
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.form-group.full-width {
|
||
grid-column: 1 / -1;
|
||
}
|
||
|
||
.form-group label {
|
||
display: block;
|
||
margin-bottom: 0.5rem;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.form-select,
|
||
.form-textarea {
|
||
width: 100%;
|
||
padding: 0.875rem 1rem;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 8px;
|
||
font-size: 0.95rem;
|
||
transition: all 0.2s ease;
|
||
background: white;
|
||
font-family: inherit;
|
||
}
|
||
|
||
.form-select:focus,
|
||
.form-textarea:focus,
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: var(--primary-color);
|
||
box-shadow: 0 0 0 3px rgba(108, 165, 227, 0.1);
|
||
}
|
||
|
||
.form-textarea {
|
||
resize: vertical;
|
||
min-height: 80px;
|
||
}
|
||
|
||
.form-actions {
|
||
display: flex;
|
||
gap: 1rem;
|
||
justify-content: flex-end;
|
||
padding-top: 2rem;
|
||
border-top: 2px solid #f3f4f6;
|
||
}
|
||
|
||
.btn-spinner {
|
||
width: 16px;
|
||
height: 16px;
|
||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||
border-top-color: white;
|
||
border-radius: 50%;
|
||
display: inline-block;
|
||
animation: spin 0.8s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.form-alert {
|
||
padding: 1rem 1.25rem;
|
||
border-radius: 8px;
|
||
margin-bottom: 1.5rem;
|
||
font-size: 0.9rem;
|
||
font-weight: 500;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
animation: slideDown 0.3s ease-out;
|
||
}
|
||
|
||
.success-alert {
|
||
background: #d1fae5;
|
||
color: #065f46;
|
||
border: 1px solid #6ee7b7;
|
||
}
|
||
|
||
.error-alert {
|
||
background: #fee2e2;
|
||
color: #991b1b;
|
||
border: 1px solid #fca5a5;
|
||
}
|
||
|
||
.success-alert::before {
|
||
content: "✓";
|
||
font-size: 1.25rem;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.error-alert::before {
|
||
content: "⚠";
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
/* Redirect Section Styles */
|
||
.redirect-section {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
min-height: 400px;
|
||
padding: 2rem 0;
|
||
}
|
||
|
||
.redirect-card {
|
||
text-align: center;
|
||
max-width: 500px;
|
||
padding: 3rem;
|
||
}
|
||
|
||
.redirect-icon {
|
||
color: var(--primary-color);
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.redirect-title {
|
||
font-size: 2rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.redirect-message {
|
||
font-size: 1.1rem;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 2rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.btn-large {
|
||
padding: 1rem 2rem;
|
||
font-size: 1.1rem;
|
||
font-weight: 600;
|
||
gap: 0.75rem;
|
||
}
|
||
|
||
.btn-large svg {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
|
||
/* Fuel Manager Summary Styles */
|
||
.fuel-summary-section {
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.fuel-summary-grid {
|
||
display: flex;
|
||
gap: 1.5rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.fuel-summary-card {
|
||
padding: 1.5rem 2rem;
|
||
border-radius: 16px;
|
||
border: 1px solid transparent;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1.5rem;
|
||
flex: 1;
|
||
min-width: 240px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.fuel-summary-card.benzin {
|
||
background: #ffedd5;
|
||
border-color: #fed7aa;
|
||
}
|
||
|
||
.fuel-summary-card.motorin {
|
||
background: #dbeafe;
|
||
border-color: #bfdbfe;
|
||
}
|
||
|
||
.summary-icon-wrapper {
|
||
width: 64px;
|
||
height: 64px;
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.fuel-summary-card.benzin .summary-icon-wrapper {
|
||
background: #fde047;
|
||
}
|
||
|
||
.fuel-summary-card.motorin .summary-icon-wrapper {
|
||
background: #93c5fd;
|
||
}
|
||
|
||
.summary-icon {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.summary-info {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.summary-title {
|
||
font-size: 0.875rem;
|
||
font-weight: 600;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 0.5rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.summary-amount {
|
||
font-size: 2rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin-bottom: 0.25rem;
|
||
line-height: 1;
|
||
}
|
||
|
||
.summary-unit {
|
||
font-size: 1rem;
|
||
color: var(--text-secondary);
|
||
margin-left: 0.25rem;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.summary-label {
|
||
font-size: 0.75rem;
|
||
color: var(--text-secondary);
|
||
display: block;
|
||
}
|
||
|
||
/* Tables Section Styles */
|
||
.tables-section {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: 2rem;
|
||
}
|
||
|
||
.table-container {
|
||
background: white;
|
||
border-radius: 12px;
|
||
border: 1px solid #c9c8cb;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.fuel-table-header {
|
||
padding: 1.5rem;
|
||
border-bottom: 1px solid var(--card-border-color);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.fuel-table-title {
|
||
font-size: 1.2rem;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
margin: 0;
|
||
}
|
||
|
||
.count-badge {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
padding: 0.25rem 0.75rem;
|
||
border-radius: 12px;
|
||
font-size: 0.8rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.table-wrapper {
|
||
overflow-x: auto;
|
||
border-radius: 12px;
|
||
border: 1px solid #e5e7eb;
|
||
}
|
||
|
||
.fuel-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
background: white;
|
||
}
|
||
|
||
.fuel-table th {
|
||
background: #f9fafb;
|
||
padding: 1rem 1.25rem;
|
||
text-align: left;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
border-bottom: 2px solid #e5e7eb;
|
||
white-space: nowrap;
|
||
font-size: 0.875rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.fuel-table th:first-child {
|
||
padding-left: 1.5rem;
|
||
border-top-left-radius: 12px;
|
||
}
|
||
|
||
.fuel-table th:last-child {
|
||
border-top-right-radius: 12px;
|
||
}
|
||
|
||
.fuel-table td {
|
||
padding: 1rem 1.25rem;
|
||
border-bottom: 1px solid #f3f4f6;
|
||
color: var(--text-color);
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.fuel-table td:first-child {
|
||
padding-left: 1.5rem;
|
||
font-weight: 600;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.fuel-table tbody tr {
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.fuel-table tbody tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.status-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
padding: 0.375rem 0.875rem;
|
||
border-radius: 20px;
|
||
font-size: 0.8rem;
|
||
font-weight: 600;
|
||
white-space: nowrap;
|
||
text-transform: capitalize;
|
||
}
|
||
|
||
.status-pending {
|
||
background: #fef3c7;
|
||
color: #92400e;
|
||
border: 1px solid #fcd34d;
|
||
}
|
||
|
||
.status-approved {
|
||
background: #d1fae5;
|
||
color: #065f46;
|
||
border: 1px solid #6ee7b7;
|
||
}
|
||
|
||
.status-rejected {
|
||
background: #fee2e2;
|
||
color: #991b1b;
|
||
border: 1px solid #fca5a5;
|
||
}
|
||
|
||
.empty-table {
|
||
padding: 3rem;
|
||
text-align: center;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.empty-table-icon {
|
||
font-size: 2rem;
|
||
margin-bottom: 1rem;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
/* Fuel Manager Responsive Design */
|
||
@media (max-width: 1024px) {
|
||
.fuel-summary-grid {
|
||
width: 100%;
|
||
}
|
||
|
||
.fuel-table {
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
.fuel-table th,
|
||
.fuel-table td {
|
||
padding: 0.75rem;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.fuel-summary-grid {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.fuel-summary-card {
|
||
min-width: auto;
|
||
}
|
||
|
||
.fuel-table {
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
.fuel-table th,
|
||
.fuel-table td {
|
||
padding: 0.5rem 0.75rem;
|
||
}
|
||
|
||
.fuel-table th:first-child,
|
||
.fuel-table td:first-child {
|
||
padding-left: 0.75rem;
|
||
}
|
||
|
||
.status-badge {
|
||
font-size: 0.7rem;
|
||
padding: 0.25rem 0.625rem;
|
||
}
|
||
|
||
.summary-icon-wrapper {
|
||
width: 56px;
|
||
height: 56px;
|
||
}
|
||
|
||
.summary-icon {
|
||
font-size: 1.75rem;
|
||
}
|
||
|
||
.summary-amount {
|
||
font-size: 1.5rem;
|
||
}
|
||
}
|
||
|
||
/* Goods Manager Content Styles */
|
||
.goods-manager-content {
|
||
padding: 0;
|
||
max-width: none;
|
||
margin: 0;
|
||
}
|
||
|
||
.content-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 2rem;
|
||
gap: 1rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.content-title {
|
||
font-size: 1.8rem;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin: 0;
|
||
}
|
||
|
||
.goods-manager-content .stats-badge {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
padding: 0.5rem 1rem;
|
||
border-radius: 20px;
|
||
font-size: 0.9rem;
|
||
font-weight: 600;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.goods-manager-content .count {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
padding: 0.25rem 0.5rem;
|
||
border-radius: 10px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.goods-manager-content .empty-state {
|
||
text-align: center;
|
||
padding: 3rem;
|
||
background: white;
|
||
border-radius: 12px;
|
||
border: 1px solid var(--card-border-color);
|
||
}
|
||
|
||
.goods-manager-content .empty-icon {
|
||
color: var(--text-secondary);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.goods-manager-content .empty-state h3 {
|
||
font-size: 1.5rem;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.goods-manager-content .empty-state p {
|
||
color: var(--text-secondary);
|
||
margin: 0;
|
||
}
|
||
</style>
|