Compare commits
2 Commits
61124cd9bb
...
b22c9b9cc5
| Author | SHA1 | Date |
|---|---|---|
|
|
b22c9b9cc5 | |
|
|
f494367683 |
|
|
@ -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'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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<string | null>('technical')
|
||||
const [activeTab, setActiveTab] = useState<string | null>('work-day')
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
@ -36,17 +54,17 @@ function OrganizationSettings() {
|
|||
<Box w="100%" display={'flex'} mt={15} ml={10}>
|
||||
<Tabs w="100%" value={activeTab} onChange={setActiveTab}>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="work-day">Work Day Setting</Tabs.Tab>
|
||||
<Tabs.Tab value="technical">Technical Setting</Tabs.Tab>
|
||||
<Tabs.Tab value="second">Setting 2</Tabs.Tab>
|
||||
<Tabs.Tab value="third">Setting 3</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="technical" pt="xs">
|
||||
<TechnicalSettingTab />
|
||||
<Tabs.Panel value="work-day" pt="xs">
|
||||
<WorkDaySettingTab />
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="second" pt="xs">
|
||||
Setting 2
|
||||
<Tabs.Panel value="technical" pt="xs">
|
||||
<TechnicalSettingTab />
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="third" pt="xs">
|
||||
|
|
@ -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<any>(null)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [isSaving, setIsSaving] = useState(false)
|
||||
const [selectedDate, setSelectedDate] = useState<Date | null>(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 (
|
||||
<Box>
|
||||
<LoadingOverlay visible={isLoading} />
|
||||
|
||||
<Title order={4} mb="xs">
|
||||
Set up Saturday as a working day.
|
||||
</Title>
|
||||
|
||||
<Paper withBorder p="lg" radius="md">
|
||||
<Grid>
|
||||
<Grid.Col span={12}>
|
||||
<DatePickerInput
|
||||
label="Saturday Work Start Date"
|
||||
description="Weeks starting from this date will include Saturday as a working day."
|
||||
placeholder="Select Date"
|
||||
value={selectedDate}
|
||||
onChange={setSelectedDate}
|
||||
valueFormat="DD/MM/YYYY"
|
||||
clearable={false}
|
||||
excludeDate={(date) => date.getDay() === 0}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
{selectedDate && (
|
||||
<Alert
|
||||
mt="md"
|
||||
variant="light"
|
||||
color="blue"
|
||||
icon={<IconInfoCircle size={16} />}
|
||||
>
|
||||
Starting from{' '}
|
||||
<Text span fw={500}>
|
||||
{dayjs(selectedDate).format('DD/MM/YYYY')}
|
||||
</Text>
|
||||
, Saturdays will be treated as working days in applicable weeks.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Group justify="flex-end" mt="lg" gap="sm">
|
||||
<Button variant="default" onClick={handleReset} disabled={isSaving}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleSave} loading={isSaving}>
|
||||
Save change
|
||||
</Button>
|
||||
</Group>
|
||||
</Paper>
|
||||
|
||||
<Paper withBorder p="sm" radius="md" mt="sm" bg="gray.0">
|
||||
<Text size="xs" c="dimmed">
|
||||
Setting type:{' '}
|
||||
<Code>{workDay?.c_type ?? 'SATURDAY_WORK_SCHEDULE'}</Code>
|
||||
</Text>
|
||||
</Paper>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default OrganizationSettings
|
||||
|
|
|
|||
Loading…
Reference in New Issue