Intranet AppService Meal

This commit is contained in:
Sedat ÖZTÜRK 2025-10-29 16:11:03 +03:00
parent e67b8220ec
commit ef4e84f7f6
14 changed files with 262 additions and 199 deletions

View file

@ -13,5 +13,7 @@ public class IntranetDashboardDto
public ExpensesDto Expenses { get; set; } = new ExpensesDto(); public ExpensesDto Expenses { get; set; } = new ExpensesDto();
public List<FileItemDto> Documents { get; set; } = []; public List<FileItemDto> Documents { get; set; } = [];
public List<AnnouncementDto> Announcements { get; set; } = []; public List<AnnouncementDto> Announcements { get; set; } = [];
public List<ShuttleRouteDto> ShuttleRoutes { get; set; } = [];
public List<MealDto> Meals { get; set; } = [];
} }

View file

@ -0,0 +1,15 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Kurs.Platform.Intranet;
public class MealDto : FullAuditedEntityDto<Guid>
{
public Guid? TenantId { get; set; }
public Guid? BranchId { get; set; }
public DateTime Date { get; set; }
public string Type { get; set; }
public decimal TotalCalorie { get; set; }
public string[] Materials { get; set; }
}

View file

@ -0,0 +1,17 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Kurs.Platform.Intranet;
public class ShuttleRouteDto : FullAuditedEntityDto<Guid>
{
public Guid? TenantId { get; set; }
public string Type { get; set; } // Örn: "Servis", "Transfer", "Ring"
public string Name { get; set; } // Hat adı veya açıklaması
public string DepartureTime { get; set; } // Kalkış saati
public string ArrivalTime { get; set; } // Varış saati
public int Capacity { get; set; } // Toplam kapasite
public int Available { get; set; } // Mevcut boş koltuk sayısı
public string[] Route { get; set; } // JSON veya metin formatında güzergah bilgisi
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using ClosedXML;
using Kurs.Platform.BlobStoring; using Kurs.Platform.BlobStoring;
using Kurs.Platform.Entities; using Kurs.Platform.Entities;
using Kurs.Platform.FileManagement; using Kurs.Platform.FileManagement;
@ -30,6 +31,8 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
private readonly IRepository<Expense, Guid> _expenseRepository; private readonly IRepository<Expense, Guid> _expenseRepository;
private readonly IRepository<Announcement, Guid> _announcementRepository; private readonly IRepository<Announcement, Guid> _announcementRepository;
private readonly IRepository<Department, Guid> _departmentRepository; private readonly IRepository<Department, Guid> _departmentRepository;
private readonly IRepository<ShuttleRoute, Guid> _shuttleRouteRepository;
private readonly IRepository<Meal, Guid> _mealRepository;
public IntranetAppService( public IntranetAppService(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
@ -43,7 +46,9 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
IRepository<Training, Guid> trainingRepository, IRepository<Training, Guid> trainingRepository,
IRepository<Expense, Guid> expenseRepository, IRepository<Expense, Guid> expenseRepository,
IRepository<Announcement, Guid> announcementRepository, IRepository<Announcement, Guid> announcementRepository,
IRepository<Department, Guid> departmentRepository IRepository<Department, Guid> departmentRepository,
IRepository<ShuttleRoute, Guid> shuttleRouteRepository,
IRepository<Meal, Guid> mealRepository
) )
{ {
_currentTenant = currentTenant; _currentTenant = currentTenant;
@ -58,6 +63,8 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
_expenseRepository = expenseRepository; _expenseRepository = expenseRepository;
_announcementRepository = announcementRepository; _announcementRepository = announcementRepository;
_departmentRepository = departmentRepository; _departmentRepository = departmentRepository;
_shuttleRouteRepository = shuttleRouteRepository;
_mealRepository = mealRepository;
} }
public async Task<IntranetDashboardDto> GetIntranetDashboardAsync() public async Task<IntranetDashboardDto> GetIntranetDashboardAsync()
@ -71,10 +78,78 @@ public class IntranetAppService : PlatformAppService, IIntranetAppService
Trainings = await GetTrainingsAsync(), Trainings = await GetTrainingsAsync(),
Expenses = await GetExpensesAsync(), Expenses = await GetExpensesAsync(),
Documents = await GetIntranetDocumentsAsync(BlobContainerNames.Intranet), Documents = await GetIntranetDocumentsAsync(BlobContainerNames.Intranet),
Announcements = await GetAnnouncementsAsync() Announcements = await GetAnnouncementsAsync(),
ShuttleRoutes = await GetShuttleRoutesAsync(),
Meals = await GetMealsAsync()
}; };
} }
private async Task<List<MealDto>> GetMealsAsync()
{
// Bu haftanın başlangıç ve bitiş tarihlerini hesapla
var today = DateTime.Now.Date;
var dayOfWeek = (int)today.DayOfWeek;
// Pazartesi'yi haftanın başı olarak kabul ediyoruz (ISO 8601)
var weekStart = today.AddDays(-(dayOfWeek == 0 ? 6 : dayOfWeek - 1));
var weekEnd = weekStart.AddDays(6);
// Sadece bu haftanın yemeklerini getir
var meals = await _mealRepository.GetListAsync(m =>
m.Date >= weekStart && m.Date <= weekEnd);
var mealDtos = new List<MealDto>();
foreach (var meal in meals)
{
var dto = ObjectMapper.Map<Meal, MealDto>(meal);
if (!string.IsNullOrEmpty(meal.Materials))
{
dto.Materials = meal.Materials
.Split('|', StringSplitOptions.RemoveEmptyEntries)
.Select(r => r.Trim())
.ToArray();
}
else
{
dto.Materials = [];
}
mealDtos.Add(dto);
}
return mealDtos;
}
private async Task<List<ShuttleRouteDto>> GetShuttleRoutesAsync()
{
var shuttleRoutes = await _shuttleRouteRepository.GetListAsync();
var shuttleRouteDtos = new List<ShuttleRouteDto>();
foreach (var shuttleRoute in shuttleRoutes)
{
var dto = ObjectMapper.Map<ShuttleRoute, ShuttleRouteDto>(shuttleRoute);
// Route string'ini array'e çevir (pipe ile ayrılmış)
if (!string.IsNullOrEmpty(shuttleRoute.Route))
{
dto.Route = shuttleRoute.Route
.Split('|', StringSplitOptions.RemoveEmptyEntries)
.Select(r => r.Trim())
.ToArray();
}
else
{
dto.Route = [];
}
shuttleRouteDtos.Add(dto);
}
return shuttleRouteDtos;
}
private async Task<List<AnnouncementDto>> GetAnnouncementsAsync() private async Task<List<AnnouncementDto>> GetAnnouncementsAsync()
{ {
var announcements = await _announcementRepository var announcements = await _announcementRepository

View file

@ -17,7 +17,14 @@ public class IntranetAutoMapperProfile : Profile
CreateMap<Currency, CurrencyDto>(); CreateMap<Currency, CurrencyDto>();
CreateMap<Expense, ExpenseDto>(); CreateMap<Expense, ExpenseDto>();
CreateMap<Meal, MealDto>()
.ForMember(dest => dest.Materials, opt => opt.Ignore());
CreateMap<Announcement, AnnouncementDto>() CreateMap<Announcement, AnnouncementDto>()
.ForMember(dest => dest.Departments, opt => opt.Ignore()); // Manuel olarak set ediliyor .ForMember(dest => dest.Departments, opt => opt.Ignore());
CreateMap<ShuttleRoute, ShuttleRouteDto>()
.ForMember(dest => dest.Route, opt => opt.Ignore());
} }
} }

View file

@ -275,7 +275,7 @@ public class BranchSeedManager : DomainService
var mealLog = CreateLog(nameof(Meal)); var mealLog = CreateLog(nameof(Meal));
foreach (var item in items.Meals) foreach (var item in items.Meals)
{ {
var exists = await _mealRepository.AnyAsync(x => x.Date == item.Date && x.Type == item.Type && x.BranchId == branchId); var exists = await _mealRepository.AnyAsync(x => x.Date == item.Date && x.BranchId == branchId);
if (!exists) if (!exists)
{ {
await _mealRepository.InsertAsync(new() await _mealRepository.InsertAsync(new()
@ -283,7 +283,6 @@ public class BranchSeedManager : DomainService
TenantId = tenantId, TenantId = tenantId,
BranchId = branchId, BranchId = branchId,
Date = item.Date, Date = item.Date,
Type = item.Type,
TotalCalorie = item.TotalCalorie, TotalCalorie = item.TotalCalorie,
Materials = item.Materials Materials = item.Materials
}, autoSave: true); }, autoSave: true);

View file

@ -811,29 +811,33 @@
], ],
"Meals": [ "Meals": [
{ {
"date": "01-10-2025", "date": "2025-10-27",
"type": "lunch", "type": "lunch",
"totalCalorie": 650, "totalCalorie": 650,
"materials": "Mercimek Çorbası|Tavuk Şinitzel|Bulgur Pilavı|Salata|Meyve" "materials": "Mercimek Çorbası|Tavuk Şinitzel|Bulgur Pilavı|Salata|Meyve"
}, },
{ {
"date": "02-10-2025", "date": "2025-10-28",
"type": "lunch", "type": "lunch",
"totalCalorie": 450,
"materials": "Domates Çorbası|Etli Kuru Fasulye|Pilav|Turşu|Komposto" "materials": "Domates Çorbası|Etli Kuru Fasulye|Pilav|Turşu|Komposto"
}, },
{ {
"date": "03-10-2025", "date": "2025-10-29",
"type": "lunch", "type": "lunch",
"totalCalorie": 660,
"materials": "Tarator|Köfte|Patates Püresi|Salata|Meyve" "materials": "Tarator|Köfte|Patates Püresi|Salata|Meyve"
}, },
{ {
"date": "04-10-2025", "date": "2025-10-30",
"type": "lunch", "type": "lunch",
"totalCalorie": 350,
"materials": "Yoğurtlu Kabak Salatası|Fırında Levrek|Kuskus|Roka Salatası|Meyve" "materials": "Yoğurtlu Kabak Salatası|Fırında Levrek|Kuskus|Roka Salatası|Meyve"
}, },
{ {
"date": "05-10-2025", "date": "2025-10-31",
"type": "lunch", "type": "lunch",
"totalCalorie": 490,
"materials": "Mercimek Çorbası|Tavuk Şinitzel|Bulgur Pilavı|Salata|Meyve" "materials": "Mercimek Çorbası|Tavuk Şinitzel|Bulgur Pilavı|Salata|Meyve"
} }
] ]

View file

@ -90,6 +90,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
private readonly IRepository<SocialPollOption, Guid> _socialPollOptionRepository; private readonly IRepository<SocialPollOption, Guid> _socialPollOptionRepository;
private readonly IRepository<SocialComment, Guid> _socialCommentRepository; private readonly IRepository<SocialComment, Guid> _socialCommentRepository;
private readonly IRepository<SocialLike, Guid> _socialLikeRepository; private readonly IRepository<SocialLike, Guid> _socialLikeRepository;
private readonly IRepository<Meal, Guid> _mealMenuRepository;
public TenantDataSeeder( public TenantDataSeeder(
IRepository<IdentityUser, Guid> repositoryUser, IRepository<IdentityUser, Guid> repositoryUser,
@ -163,7 +164,8 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
IRepository<SocialMedia, Guid> socialMediaRepository, IRepository<SocialMedia, Guid> socialMediaRepository,
IRepository<SocialPollOption, Guid> socialPollOptionRepository, IRepository<SocialPollOption, Guid> socialPollOptionRepository,
IRepository<SocialComment, Guid> socialCommentRepository, IRepository<SocialComment, Guid> socialCommentRepository,
IRepository<SocialLike, Guid> socialLikeRepository IRepository<SocialLike, Guid> socialLikeRepository,
IRepository<Meal, Guid> mealMenuRepository
) )
{ {
_repositoryUser = repositoryUser; _repositoryUser = repositoryUser;
@ -239,6 +241,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
_socialPollOptionRepository = socialPollOptionRepository; _socialPollOptionRepository = socialPollOptionRepository;
_socialCommentRepository = socialCommentRepository; _socialCommentRepository = socialCommentRepository;
_socialLikeRepository = socialLikeRepository; _socialLikeRepository = socialLikeRepository;
_mealMenuRepository = mealMenuRepository;
} }
private static IConfigurationRoot BuildConfiguration() private static IConfigurationRoot BuildConfiguration()

View file

@ -1,118 +1,16 @@
import { AnnouncementDto, DocumentDto, EventDto, ExpenseDto, ReservationDto, TrainingDto, VisitorDto } from '@/proxy/intranet/models'
import { mockEmployees } from './mockEmployees'
import { import {
Certificate, AnnouncementDto,
MealMenu, CertificateDto,
ShuttleRoute, DocumentDto,
Survey, EventDto,
SocialPost, ExpenseDto,
} from '@/types/intranet' ReservationDto,
ShuttleRouteDto,
export const mockMealMenus: MealMenu[] = [ TrainingDto,
{ VisitorDto,
id: 'menu1', } from '@/proxy/intranet/models'
date: new Date('2025-10-27'), import { mockEmployees } from './mockEmployees'
dayOfWeek: 'Pazartesi', import { Survey, SocialPost } from '@/types/intranet'
meals: [
{
type: 'lunch',
items: ['Mercimek Çorbası', 'Tavuk Şinitzel', 'Bulgur Pilavı', 'Salata', 'Meyve'],
calories: 650,
},
],
},
{
id: 'menu2',
date: new Date('2025-10-28'),
dayOfWeek: 'Salı',
meals: [
{
type: 'lunch',
items: ['Yayla Çorbası', 'Köfte', 'Patates Püresi', 'Cacık', 'Ayran'],
calories: 720,
},
],
},
{
id: 'menu3',
date: new Date('2025-10-29'),
dayOfWeek: 'Çarşamba',
meals: [
{
type: 'lunch',
items: ['Domates Çorbası', 'Etli Kuru Fasulye', 'Pilav', 'Turşu', 'Komposto'],
calories: 680,
},
],
},
{
id: 'menu4',
date: new Date('2025-10-30'),
dayOfWeek: 'Perşembe',
meals: [
{
type: 'lunch',
items: ['Tarhana Çorbası', 'Fırın Tavuk', 'Makarna', 'Yeşil Salata', 'Sütlaç'],
calories: 700,
},
],
},
{
id: 'menu5',
date: new Date('2025-10-31'),
dayOfWeek: 'Cuma',
meals: [
{
type: 'lunch',
items: ['Ezogelin Çorbası', 'Balık', 'Bulgur Pilavı', 'Salata', 'Meyve'],
calories: 620,
},
],
},
]
export const mockShuttleRoutes: ShuttleRoute[] = [
{
id: 'shuttle1',
name: 'Kadıköy - Ofis',
route: ['Kadıköy İskele', 'Bostancı', 'Acıbadem', 'Kozyatağı', 'Ofis'],
departureTime: '07:30',
arrivalTime: '08:45',
capacity: 25,
available: 3,
type: 'morning',
},
{
id: 'shuttle2',
name: 'Üsküdar - Ofis',
route: ['Üsküdar Meydanı', 'Kısıklı', 'Bulgurlu', 'Ümraniye', 'Ofis'],
departureTime: '07:45',
arrivalTime: '08:50',
capacity: 25,
available: 8,
type: 'morning',
},
{
id: 'shuttle3',
name: 'Ofis - Kadıköy',
route: ['Ofis', 'Kozyatağı', 'Acıbadem', 'Bostancı', 'Kadıköy İskele'],
departureTime: '18:00',
arrivalTime: '19:15',
capacity: 25,
available: 5,
type: 'evening',
},
{
id: 'shuttle4',
name: 'Ofis - Üsküdar',
route: ['Ofis', 'Ümraniye', 'Bulgurlu', 'Kısıklı', 'Üsküdar Meydanı'],
departureTime: '18:15',
arrivalTime: '19:20',
capacity: 25,
available: 12,
type: 'evening',
},
]
export const mockSurveys: Survey[] = [ export const mockSurveys: Survey[] = [
{ {
@ -750,7 +648,7 @@ export const mockTrainings: TrainingDto[] = [
}, },
] ]
export const mockCertificates: Certificate[] = [ export const mockCertificates: CertificateDto[] = [
{ {
id: 'cert1', id: 'cert1',
employee: mockEmployees[0], employee: mockEmployees[0],
@ -1031,3 +929,46 @@ export const mockAnnouncements: AnnouncementDto[] = [
attachments: [{ name: 'Bilgi_Guvenligi_Politikasi_v2.pdf', url: '#', size: '2.4 MB' }], attachments: [{ name: 'Bilgi_Guvenligi_Politikasi_v2.pdf', url: '#', size: '2.4 MB' }],
}, },
] ]
export const mockShuttleRoutes: ShuttleRouteDto[] = [
{
id: 'shuttle1',
name: 'Kadıköy - Ofis',
route: ['Kadıköy İskele', 'Bostancı', 'Acıbadem', 'Kozyatağı', 'Ofis'],
departureTime: '07:30',
arrivalTime: '08:45',
capacity: 25,
available: 3,
type: 'morning',
},
{
id: 'shuttle2',
name: 'Üsküdar - Ofis',
route: ['Üsküdar Meydanı', 'Kısıklı', 'Bulgurlu', 'Ümraniye', 'Ofis'],
departureTime: '07:45',
arrivalTime: '08:50',
capacity: 25,
available: 8,
type: 'morning',
},
{
id: 'shuttle3',
name: 'Ofis - Kadıköy',
route: ['Ofis', 'Kozyatağı', 'Acıbadem', 'Bostancı', 'Kadıköy İskele'],
departureTime: '18:00',
arrivalTime: '19:15',
capacity: 25,
available: 5,
type: 'evening',
},
{
id: 'shuttle4',
name: 'Ofis - Üsküdar',
route: ['Ofis', 'Ümraniye', 'Bulgurlu', 'Kısıklı', 'Üsküdar Meydanı'],
departureTime: '18:15',
arrivalTime: '19:20',
capacity: 25,
available: 12,
type: 'evening',
},
]

View file

@ -23,9 +23,9 @@ export interface IntranetDashboardDto {
expenses: ExpensesDto expenses: ExpensesDto
documents: DocumentDto[] documents: DocumentDto[]
announcements: AnnouncementDto[] announcements: AnnouncementDto[]
shuttleRoutes: ShuttleRouteDto[]
meals: MealDto[]
// surveys: Survey[] // surveys: Survey[]
// mealMenu: MealMenu[]
// shuttleRoutes: ShuttleRoute[]
// priorityTasks: TaskDto[] // priorityTasks: TaskDto[]
} }
@ -230,6 +230,17 @@ export interface DocumentDto {
childCount: number childCount: number
} }
// Sertifika
export interface CertificateDto {
id: string
employee: EmployeeDto
trainingTitle: string
issueDate: Date
expiryDate?: Date
certificateUrl: string
score?: number
}
// Duyuru // Duyuru
export interface AnnouncementDto { export interface AnnouncementDto {
id: string id: string
@ -247,3 +258,25 @@ export interface AnnouncementDto {
departments?: string[] departments?: string[]
attachments?: { name: string; url: string; size: string }[] attachments?: { name: string; url: string; size: string }[]
} }
// Servis
export interface ShuttleRouteDto {
id: string
name: string
route: string[]
departureTime: string
arrivalTime: string
capacity: number
available: number
type: string
}
// Yemek Menüsü
export interface MealDto {
id: string
branchId: string
date: Date
type: 'breakfast' | 'lunch' | 'dinner'
totalCalorie?: number
materials: string[]
}

View file

@ -17,41 +17,6 @@ export interface Task {
comments: number comments: number
} }
// Sertifika
export interface Certificate {
id: string
employee: EmployeeDto
trainingTitle: string
issueDate: Date
expiryDate?: Date
certificateUrl: string
score?: number
}
// Yemek Menüsü
export interface MealMenu {
id: string
date: Date
dayOfWeek: string
meals: {
type: 'breakfast' | 'lunch' | 'dinner'
items: string[]
calories?: number
}[]
}
// Servis
export interface ShuttleRoute {
id: string
name: string
route: string[]
departureTime: string
arrivalTime: string
capacity: number
available: number
type: 'morning' | 'evening'
}
// Anket // Anket
export interface Survey { export interface Survey {
id: string id: string

View file

@ -11,7 +11,6 @@ import UpcomingEvents from './widgets/UpcomingEvents'
import RecentDocuments from './widgets/RecentDocuments' import RecentDocuments from './widgets/RecentDocuments'
import PriorityTasks from './widgets/PriorityTasks' import PriorityTasks from './widgets/PriorityTasks'
import MealWeeklyMenu from './widgets/MealWeeklyMenu' import MealWeeklyMenu from './widgets/MealWeeklyMenu'
import ShuttleSchedule from './widgets/ShuttleSchedule'
import LeaveManagement from './widgets/LeaveManagement' import LeaveManagement from './widgets/LeaveManagement'
import OvertimeManagement from './widgets/OvertimeManagement' import OvertimeManagement from './widgets/OvertimeManagement'
import ExpenseManagement from './widgets/ExpenseManagement' import ExpenseManagement from './widgets/ExpenseManagement'
@ -36,6 +35,7 @@ import { usePermission } from '@/utils/hooks/usePermission'
import { AnnouncementDto, IntranetDashboardDto } from '@/proxy/intranet/models' import { AnnouncementDto, IntranetDashboardDto } from '@/proxy/intranet/models'
import { intranetService } from '@/services/intranet.service' import { intranetService } from '@/services/intranet.service'
import Announcements from './widgets/Announcements' import Announcements from './widgets/Announcements'
import ShuttleRoute from './widgets/ShuttleRoute'
dayjs.locale('tr') dayjs.locale('tr')
dayjs.extend(relativeTime) dayjs.extend(relativeTime)
@ -125,7 +125,7 @@ const IntranetDashboard: React.FC = () => {
}, },
{ id: 'priority-tasks', permission: 'App.Projects.Tasks.Widget', column: 'right' }, { id: 'priority-tasks', permission: 'App.Projects.Tasks.Widget', column: 'right' },
{ id: 'meal-weekly-menu', permission: 'App.Intranet.Meal.Widget', column: 'right' }, { id: 'meal-weekly-menu', permission: 'App.Intranet.Meal.Widget', column: 'right' },
{ id: 'shuttle-schedule', permission: 'App.Intranet.ShuttleRoute.Widget', column: 'right' }, { id: 'shuttle-route', permission: 'App.Intranet.ShuttleRoute.Widget', column: 'right' },
{ id: 'leave-management', permission: 'App.Hr.Leave.Widget', column: 'right' }, { id: 'leave-management', permission: 'App.Hr.Leave.Widget', column: 'right' },
{ id: 'overtime-management', permission: 'App.Hr.Overtime.Widget', column: 'right' }, { id: 'overtime-management', permission: 'App.Hr.Overtime.Widget', column: 'right' },
] ]
@ -275,17 +275,23 @@ const IntranetDashboard: React.FC = () => {
case 'documents': case 'documents':
return <RecentDocuments documents={intranetDashboard?.documents || []} /> return <RecentDocuments documents={intranetDashboard?.documents || []} />
case 'announcements': case 'announcements':
return <Announcements announcements={intranetDashboard?.announcements || []} onAnnouncementClick={setSelectedAnnouncement} /> return (
<Announcements
announcements={intranetDashboard?.announcements || []}
onAnnouncementClick={setSelectedAnnouncement}
/>
)
case 'shuttle-route':
return <ShuttleRoute shuttleRoutes={intranetDashboard?.shuttleRoutes || []} />
case 'meal-weekly-menu':
return <MealWeeklyMenu meals={intranetDashboard?.meals || []} />
case 'active-surveys': case 'active-surveys':
return <ActiveSurveys onTakeSurvey={handleTakeSurvey} /> return <ActiveSurveys onTakeSurvey={handleTakeSurvey} />
case 'social-wall': case 'social-wall':
return <SocialWall /> return <SocialWall />
case 'priority-tasks': case 'priority-tasks':
return <PriorityTasks /> return <PriorityTasks />
case 'meal-weekly-menu':
return <MealWeeklyMenu />
case 'shuttle-schedule':
return <ShuttleSchedule />
case 'leave-management': case 'leave-management':
return <LeaveManagement onNewLeave={() => setShowLeaveModal(true)} /> return <LeaveManagement onNewLeave={() => setShowLeaveModal(true)} />
case 'overtime-management': case 'overtime-management':

View file

@ -2,19 +2,19 @@ import React from 'react'
import { FaUtensils } from 'react-icons/fa' import { FaUtensils } from 'react-icons/fa'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import isBetween from 'dayjs/plugin/isBetween' import isBetween from 'dayjs/plugin/isBetween'
import { mockMealMenus } from '../../../mocks/mockIntranet'
import { Badge } from '@/components/ui' import { Badge } from '@/components/ui'
import { MealDto } from '@/proxy/intranet/models'
dayjs.extend(isBetween) dayjs.extend(isBetween)
const MealWeeklyMenu: React.FC = () => { const MealWeeklyMenu: React.FC<{ meals: MealDto[] }> = ({ meals }) => {
const mealWeekMenus = mockMealMenus.filter((menu) => { // const mealWeekMenus = meals.filter((menu) => {
const menuDate = dayjs(menu.date) // const menuDate = dayjs(menu.date)
const today = dayjs() // const today = dayjs()
const weekStart = today.startOf('week') // const weekStart = today.startOf('week')
const weekEnd = today.endOf('week') // const weekEnd = today.endOf('week')
return menuDate.isBetween(weekStart, weekEnd, null, '[]') // return menuDate.isBetween(weekStart, weekEnd, null, '[]')
}) // })
return ( return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700"> <div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
@ -26,9 +26,9 @@ const MealWeeklyMenu: React.FC = () => {
</h2> </h2>
</div> </div>
</div> </div>
{mealWeekMenus.length > 0 ? ( {meals.length > 0 ? (
<div className="divide-y divide-gray-200 dark:divide-gray-700"> <div className="divide-y divide-gray-200 dark:divide-gray-700">
{mealWeekMenus.map((menu) => { {meals.map((menu) => {
const isToday = dayjs(menu.date).isSame(dayjs(), 'day') const isToday = dayjs(menu.date).isSame(dayjs(), 'day')
return ( return (
<div <div
@ -40,7 +40,7 @@ const MealWeeklyMenu: React.FC = () => {
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="text-sm font-semibold text-gray-900 dark:text-white"> <h3 className="text-sm font-semibold text-gray-900 dark:text-white">
{dayjs(menu.date).format('DD MMMM')} {menu.dayOfWeek} {dayjs(menu.date).format('DD MMMM')} {dayjs(menu.date).format('dddd')}
</h3> </h3>
{isToday && ( {isToday && (
<span className="text-xs bg-orange-500 text-white px-2 py-0.5 rounded-full"> <span className="text-xs bg-orange-500 text-white px-2 py-0.5 rounded-full">
@ -48,15 +48,15 @@ const MealWeeklyMenu: React.FC = () => {
</span> </span>
)} )}
</div> </div>
{menu.meals[0]?.calories && ( {menu.totalCalorie && (
<div className="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400"> <div className="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400">
{menu.meals[0].calories} kcal {menu.totalCalorie} kcal
</div> </div>
)} )}
</div> </div>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{menu.meals[0]?.items.map((item, idx) => ( {menu.materials.map((item, idx) => (
<Badge key={idx} content={item} className='p-1 bg-red-500' /> <Badge key={idx} content={item} className="p-1 bg-red-500" />
))} ))}
</div> </div>
</div> </div>

View file

@ -1,10 +1,10 @@
import React from 'react' import React from 'react'
import { FaTruck } from 'react-icons/fa' import { FaTruck } from 'react-icons/fa'
import { mockShuttleRoutes } from '../../../mocks/mockIntranet' import { ShuttleRouteDto } from '@/proxy/intranet/models'
const ShuttleSchedule: React.FC = () => { const ShuttleRoute: React.FC<{ shuttleRoutes: ShuttleRouteDto[] }> = ({ shuttleRoutes }) => {
const morningShuttles = mockShuttleRoutes.filter((s) => s.type === 'morning') const morningShuttles = shuttleRoutes.filter((s) => s.type === 'morning')
const eveningShuttles = mockShuttleRoutes.filter((s) => s.type === 'evening') const eveningShuttles = shuttleRoutes.filter((s) => s.type === 'evening')
return ( return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700"> <div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
@ -42,9 +42,7 @@ const ShuttleSchedule: React.FC = () => {
</div> </div>
</div> </div>
<div className="flex items-center justify-between text-xs"> <div className="flex items-center justify-between text-xs">
<span className="text-gray-600 dark:text-gray-400"> <span className="text-gray-600 dark:text-gray-400">{shuttle.arrivalTime}</span>
{shuttle.arrivalTime}
</span>
<span <span
className={`px-2 py-1 rounded-full ${ className={`px-2 py-1 rounded-full ${
shuttle.available > 5 shuttle.available > 5
@ -89,9 +87,7 @@ const ShuttleSchedule: React.FC = () => {
</div> </div>
</div> </div>
<div className="flex items-center justify-between text-xs"> <div className="flex items-center justify-between text-xs">
<span className="text-gray-600 dark:text-gray-400"> <span className="text-gray-600 dark:text-gray-400">{shuttle.arrivalTime}</span>
{shuttle.arrivalTime}
</span>
<span <span
className={`px-2 py-1 rounded-full ${ className={`px-2 py-1 rounded-full ${
shuttle.available > 5 shuttle.available > 5
@ -113,4 +109,4 @@ const ShuttleSchedule: React.FC = () => {
) )
} }
export default ShuttleSchedule export default ShuttleRoute