Files
ytp-glm/src/routes/dashboard/+page.svelte

2331 lines
64 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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 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;
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 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: ""
};
$: 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
);
});
}
// Eğer goods_manager ise socket bağlantısı kur (GoodsManagerContent component'i kendi socket'ini kullanacak)
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/goods-managers")
]);
if (vehiclesRes.ok) {
const vehiclesData = await vehiclesRes.json();
vehicles = vehiclesData.vehicles || [];
}
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.goodsManagers?.filter((gm) => gm.is_active) || [];
if (!formData.goods_manager_id && goodsManagers.length) {
formData.goods_manager_id = goodsManagers[0].id;
}
}
} 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: goodsManagers[0]?.id || "",
notes: ""
};
}
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;
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;
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;
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;
showDevriçark = false;
showMonthlyReport = 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 && !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("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("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("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("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" && 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}
required
>
<option value="">Birlik Seçin</option>
{#each units as unit}
<option value={unit.id}>{unit.name}</option>
{/each}
</select>
</div>
<div class="form-group">
<label for="vehicle_id">Araç</label>
<select
id="vehicle_id"
class="form-select"
bind:value={formData.vehicle_id}
required
>
<option value="">Araç Seçin</option>
{#each vehicles as vehicle}
<option value={vehicle.id}
>{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}
>{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}
required
>
<option value="">Mal Sorumlusu Seçin</option>
{#each goodsManagers as manager}
<option value={manager.id}
>{manager.rank} {manager.full_name}</option
>
{/each}
</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>