diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/CategoryController.php b/BACKEND/Modules/Admin/app/Http/Controllers/CategoryController.php index 0150d30..408787a 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/CategoryController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/CategoryController.php @@ -3,6 +3,7 @@ namespace Modules\Admin\app\Http\Controllers; use App\Http\Controllers\Controller; +use Carbon\Carbon; use Illuminate\Http\Request; use Modules\Admin\app\Models\Category; @@ -29,4 +30,45 @@ class CategoryController extends Controller $data = Category::where('c_type', '=', $type)->where('c_active', '=', 1)->select('id', 'c_code', 'c_name', 'c_value', 'c_type')->get(); return $data; } + + public function workDays() + { + $saturday_work_schedules = Category::where('c_type', 'SATURDAY_WORK_SCHEDULE') + ->get(); + + return response()->json([ + 'data' => $saturday_work_schedules, + 'status' => true + ]); + } + + public function updateWorkDays(Request $request) + { + $request->validate([ + 'c_code' => 'required|date_format:d-m-Y', + ]); + + $schedule = Category::where('c_type', 'SATURDAY_WORK_SCHEDULE')->first(); + + if (!$schedule) { + $schedule = Category::create([ + 'c_type' => 'SATURDAY_WORK_SCHEDULE', + 'c_name' => "Ngày bắt đầu làm việc thứ 7 trong năm", + 'c_code' => $request->c_code, + 'c_value' => Carbon::now()->year, + 'c_active' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } else { + $schedule->update([ + 'c_code' => $request->c_code, + ]); + } + + return response()->json([ + 'status' => true, + 'message' => 'Saturday work schedule updated successfully' + ]); + } } diff --git a/BACKEND/Modules/Admin/app/Models/Category.php b/BACKEND/Modules/Admin/app/Models/Category.php index 11a4424..356d346 100644 --- a/BACKEND/Modules/Admin/app/Models/Category.php +++ b/BACKEND/Modules/Admin/app/Models/Category.php @@ -8,4 +8,12 @@ use Illuminate\Database\Eloquent\Model; class Category extends Model { use HasFactory; + + protected $fillable = [ + 'c_type', + 'c_name', + 'c_code', + 'c_value', + 'c_active', + ]; } diff --git a/BACKEND/Modules/Admin/routes/api.php b/BACKEND/Modules/Admin/routes/api.php index c555911..dc662b2 100755 --- a/BACKEND/Modules/Admin/routes/api.php +++ b/BACKEND/Modules/Admin/routes/api.php @@ -149,6 +149,8 @@ Route::middleware('api') 'prefix' => 'category', ], function () { Route::get('/get-list-master', [CategoryController::class, 'getListMaster']); + Route::get('/work-days', [CategoryController::class, 'workDays']); + Route::put('/update-work-days', [CategoryController::class, 'updateWorkDays']); }); Route::group([ diff --git a/FRONTEND/src/api/Admin.ts b/FRONTEND/src/api/Admin.ts index 1de63ba..822388b 100755 --- a/FRONTEND/src/api/Admin.ts +++ b/FRONTEND/src/api/Admin.ts @@ -35,6 +35,8 @@ export const updateWorkingDays = //Category export const getListMaster = API_URL + 'v1/admin/category/get-list-master' +export const getWorkDay = API_URL + 'v1/admin/category/work-days' +export const updateWorkDay = API_URL + 'v1/admin/category/update-work-days' //LeaveManagement export const getLeaveManagement = API_URL + 'v1/admin/leave-management' diff --git a/FRONTEND/src/pages/OrganizationSettings/OrganizationSettings.tsx b/FRONTEND/src/pages/OrganizationSettings/OrganizationSettings.tsx index 718f301..fae84e4 100644 --- a/FRONTEND/src/pages/OrganizationSettings/OrganizationSettings.tsx +++ b/FRONTEND/src/pages/OrganizationSettings/OrganizationSettings.tsx @@ -1,28 +1,46 @@ import { useEffect, useState } from 'react' import { + Alert, Box, Button, + Code, Dialog, Flex, + Grid, Group, Loader, + LoadingOverlay, Modal, + Paper, Select, Tabs, Text, TextInput, + Title, } from '@mantine/core' import classes from './OrganizationSettings.module.css' import DataTableAll from '@/components/DataTable/DataTable' -import { get, post } from '@/rtk/helpers/apiService' +import { get, post, put } from '@/rtk/helpers/apiService' import { notifications } from '@mantine/notifications' -import { createTechnical, deleteTechnical, listTechnical } from '@/api/Admin' +import { + createTechnical, + deleteTechnical, + getWorkDay, + listTechnical, + updateWorkDay, +} from '@/api/Admin' import { useForm } from '@mantine/form' import { Xdelete } from '@/rtk/helpers/CRUD' import moment from 'moment' +import { DatePickerInput } from '@mantine/dates' +import { IconInfoCircle } from '@tabler/icons-react' +import dayjs from 'dayjs' +import customParseFormat from 'dayjs/plugin/customParseFormat' + +dayjs.extend(customParseFormat) function OrganizationSettings() { - const [activeTab, setActiveTab] = useState('technical') + const [activeTab, setActiveTab] = useState('work-day') return (
@@ -36,17 +54,17 @@ function OrganizationSettings() { + Work Day Setting Technical Setting - Setting 2 Setting 3 - - + + - - Setting 2 + + @@ -100,8 +118,8 @@ const TechnicalSettingTab = () => { ? row?.level === 1 ? { backgroundColor: '#d9d2e9' } : row?.level === 2 - ? { backgroundColor: '#ffd966' } - : { backgroundColor: '#cfe2f3' } + ? { backgroundColor: '#ffd966' } + : { backgroundColor: '#cfe2f3' } : { backgroundColor: '' } } fw={500} @@ -330,4 +348,126 @@ const TechnicalSettingTab = () => { ) } +const WorkDaySettingTab = () => { + const [workDay, setWorkDay] = useState(null) + const [isLoading, setIsLoading] = useState(false) + const [isSaving, setIsSaving] = useState(false) + const [selectedDate, setSelectedDate] = useState(null) + + useEffect(() => { + getWorkDays() + }, []) + + const getWorkDays = async () => { + try { + setIsLoading(true) + const res = await get(getWorkDay, {}) + if (res.status && res.data?.length > 0) { + const item = res.data[0] + setWorkDay(item) + const parsed = dayjs(item.c_code, 'DD-MM-YYYY').toDate() + setSelectedDate(parsed) + } + } catch (error: any) { + notifications.show({ + title: 'Error', + message: error.message ?? error, + color: 'red', + }) + } finally { + setIsLoading(false) + } + } + + const handleSave = async () => { + if (!selectedDate) return + try { + setIsSaving(true) + const payload = { + c_code: dayjs(selectedDate).format('DD-MM-YYYY'), + } + const res = await put(`${updateWorkDay}`, payload) + if (res.status) { + notifications.show({ + title: 'Success', + message: res.message, + color: 'green', + }) + } + } catch (error: any) { + notifications.show({ + title: 'Error', + message: error.message ?? error, + color: 'red', + }) + } finally { + setIsSaving(false) + } + } + + const handleReset = () => { + if (!workDay) return + const parsed = dayjs(workDay.c_code, 'DD-MM-YYYY').toDate() + setSelectedDate(parsed) + } + + return ( + + + + + Set up Saturday as a working day. + + + + + + date.getDay() === 0} + /> + + + + {selectedDate && ( + } + > + Starting from{' '} + + {dayjs(selectedDate).format('DD/MM/YYYY')} + + , Saturdays will be treated as working days in applicable weeks. + + )} + + + + + + + + + + Setting type:{' '} + {workDay?.c_type ?? 'SATURDAY_WORK_SCHEDULE'} + + + + ) +} + export default OrganizationSettings