diff --git a/Modules/Internal/Http/Controllers/Api/CorporateBenefitController.php b/Modules/Internal/Http/Controllers/Api/CorporateBenefitController.php index 3648c21f..f4362852 100644 --- a/Modules/Internal/Http/Controllers/Api/CorporateBenefitController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateBenefitController.php @@ -108,18 +108,15 @@ class CorporateBenefitController extends Controller { $corporateBenefit = CorporateBenefit::findOrFail($id); + $request->validate([ - 'code' => [ + 'budget' => [ 'required', - Rule::unique('corporate_plans')->where('corporate_id', $corporate_id)->ignore($corporateBenefit->id) ], - 'name' => 'required' ]); $corporateBenefit->fill([ - 'code' => $request->code, - 'name' => $request->name, - 'active' => $request->active, + 'budget' => $request->budget, ])->save(); return $corporateBenefit; diff --git a/Modules/Internal/Http/Controllers/Api/CorporateController.php b/Modules/Internal/Http/Controllers/Api/CorporateController.php index e63fb754..fb53bd26 100644 --- a/Modules/Internal/Http/Controllers/Api/CorporateController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateController.php @@ -381,13 +381,15 @@ class CorporateController extends Controller public function activation(Request $request, $corporate_id) { $request->validate([ - 'active' => 'required' + 'active' => 'required', + 'reason' => 'required' ]); // abort(404); $corporate = Corporate::findOrFail($corporate_id); $corporate->active = $request->active == '1'; + $corporate->reason = $request->reason; if ($corporate->save()) { return response()->json([ diff --git a/Modules/Internal/Http/Controllers/Api/CorporatePlanController.php b/Modules/Internal/Http/Controllers/Api/CorporatePlanController.php index bcf8c232..a71309a1 100644 --- a/Modules/Internal/Http/Controllers/Api/CorporatePlanController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporatePlanController.php @@ -34,7 +34,7 @@ class CorporatePlanController extends Controller // abort(404); $plan = CorporatePlan::findOrFail($plan_id); - $plan->active = $request->active == '1'; + $plan->active = $request->active == 1 ? 0 : 1; $plan->reason = $request->reason; if ($plan->save()) { @@ -110,21 +110,21 @@ class CorporatePlanController extends Controller public function update(Request $request, $corporate_id, $id) { $corporatePlan = CorporatePlan::findOrFail($id); + $request->validate([ 'code' => [ 'required', - Rule::unique('corporate_plans')->where('corporate_id', $corporate_id)->ignore($corporatePlan->id) + // Rule::unique('corporate_plans')->where('corporate_id', $corporate_id)->ignore($corporatePlan->id) ], - 'name' => 'required' ]); - $corporatePlan->fill([ 'code' => $request->code, - 'name' => $request->name, - 'active' => $request->active, - 'description' => $request->description + 'corporate_plan_id' => $request->plan, + 'service_code' => $request->service, + 'type' => $request->type, + 'limit_rules' => $request->limit ])->save(); - + return $corporatePlan; } diff --git a/Modules/Internal/Http/Controllers/Api/CorporateServiceController.php b/Modules/Internal/Http/Controllers/Api/CorporateServiceController.php index 87892a76..bffaca9e 100644 --- a/Modules/Internal/Http/Controllers/Api/CorporateServiceController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateServiceController.php @@ -144,7 +144,7 @@ class CorporateServiceController extends Controller // ->with('configs', 'service') ->first(); $corporateService->fill([ - 'status' => $request->status == 'active' ? 'active' : 'inactive', + 'status' => $request->status == 'active' ? 'inactive' : 'active', 'reason' => $request->reason ]); $corporateService->save(); diff --git a/Modules/Internal/Http/Controllers/Api/ServiceController.php b/Modules/Internal/Http/Controllers/Api/ServiceController.php new file mode 100644 index 00000000..221b3fd9 --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/ServiceController.php @@ -0,0 +1,86 @@ +get(); + + if (empty($service)) { + return response(['message' => 'Tidak ada data'], 404); + } else { + return response(['message' => 'Data ditemukan', "status" => 200, 'data' => $service]); + } + } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function create() + { + return view('internal::create'); + } + + /** + * Store a newly created resource in storage. + * @param Request $request + * @return Renderable + */ + public function store(Request $request) + { + // + } + + /** + * Show the specified resource. + * @param int $id + * @return Renderable + */ + public function show($id) + { + return view('internal::show'); + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + return view('internal::edit'); + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + // + } +} diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index fc2603d3..2377549d 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -31,6 +31,7 @@ use Modules\Internal\Http\Controllers\Api\OptionController; use Modules\Internal\Http\Controllers\Api\OrganizationController; use Modules\Internal\Http\Controllers\Api\PlanController; use Modules\Internal\Http\Controllers\Api\ProvinceController; +use Modules\Internal\Http\Controllers\Api\ServiceController; use Modules\Internal\Http\Controllers\Api\PrescriptionController; use Modules\Internal\Http\Controllers\Api\SpecialityController; use Modules\Internal\Http\Controllers\Api\VillageController; @@ -201,6 +202,7 @@ Route::prefix('internal')->group(function () { }); Route::get('province', [ProvinceController::class, 'index']); + Route::get('service', [ServiceController::class, 'index']); Route::get('city', [CityController::class, 'index']); Route::get('district', [DistrictController::class, 'index']); Route::get('village', [VillageController::class, 'index']); diff --git a/Modules/Internal/Transformers/CorporateServiceConfigResource.php b/Modules/Internal/Transformers/CorporateServiceConfigResource.php index a9d9589b..1ea2c8e7 100644 --- a/Modules/Internal/Transformers/CorporateServiceConfigResource.php +++ b/Modules/Internal/Transformers/CorporateServiceConfigResource.php @@ -41,38 +41,97 @@ class CorporateServiceConfigResource extends JsonResource ]; $list_msc = $this->corporateServiceSpecialities->map(function ($speciality) { - return explode(',', $speciality->exclusions->first()->rules->where('name', 'msc')->first()->values ?? ''); - })->map(function ($item) { + $exclusions = $speciality->exclusions->first(); + + if ($exclusions) { + $rules = $exclusions->rules->where('name', 'msc')->first(); + + if ($rules) { + $values = $rules->values ?? ''; + $item = explode(',', $values); + } else { + // Handle case where 'rules' with name 'msc' is not found + $item = []; + } + } else { + // Handle case where 'exclusions' is not found + $item = []; + } + return [ 'm' => in_array('m', $item), 's' => in_array('s', $item), 'c' => in_array('c', $item), ]; }); - + $list_gender = $this->corporateServiceSpecialities->map(function ($speciality) { - // dd($speciality->exclusions->first()->rules); - return explode(',', $speciality->exclusions->first()->rules->where('name', 'gender')->first()->values ?? ''); - })->map(function ($item) { - + $exclusions = $speciality->exclusions->first(); + + if ($exclusions) { + $rules = $exclusions->rules->where('name', 'gender')->first(); + + if ($rules) { + $values = $rules->values ?? ''; + $item = explode(',', $values); + } else { + // Handle case where 'rules' with name 'gender' is not found + $item = []; + } + } else { + // Handle case where 'exclusions' is not found + $item = []; + } + return [ 'male' => in_array('male', $item), 'female' => in_array('female', $item), ]; }); + $min_age = $this->corporateServiceSpecialities->map(function ($speciality) { - return $speciality->exclusions->first()->rules->where('name', 'min_age')->first()->values ?? ''; + $exclusions = $speciality->exclusions->first(); + + if ($exclusions) { + $rules = $exclusions->rules->where('name', 'min_age')->first(); + + if ($rules) { + return $rules->values ?? ''; + } + } + + return ''; }); - + $max_age = $this->corporateServiceSpecialities->map(function ($speciality) { - return $speciality->exclusions->first()->rules->where('name', 'max_age')->first()->values ?? ''; + $exclusions = $speciality->exclusions->first(); + + if ($exclusions) { + $rules = $exclusions->rules->where('name', 'max_age')->first(); + + if ($rules) { + return $rules->values ?? ''; + } + } + + return ''; }); - + $plan = $this->corporateServiceSpecialities->map(function ($speciality) { - return $speciality->exclusions->first()->rules->where('name', 'plan')->first()->values ?? null; + $exclusions = $speciality->exclusions->first(); + + if ($exclusions) { + $rules = $exclusions->rules->where('name', 'plan')->first(); + + if ($rules) { + return $rules->values ?? null; + } + } + + return null; }); - + $data['exclusions'] = $data['exclusions']->map(function ($item, $key) use ( $list_msc, $list_gender, diff --git a/app/Models/CorporatePlan.php b/app/Models/CorporatePlan.php index ca27e624..818e1255 100644 --- a/app/Models/CorporatePlan.php +++ b/app/Models/CorporatePlan.php @@ -18,6 +18,10 @@ class CorporatePlan extends Model 'code', 'name', 'description', + 'corporate_plan_id', + 'service_code', + 'type', + 'limit_rules', 'active', 'reason' ]; diff --git a/frontend/client-portal/src/pages/ClaimSubmit/List.tsx b/frontend/client-portal/src/pages/ClaimSubmit/List.tsx index 620ec685..9b63bdc8 100644 --- a/frontend/client-portal/src/pages/ClaimSubmit/List.tsx +++ b/frontend/client-portal/src/pages/ClaimSubmit/List.tsx @@ -105,24 +105,7 @@ export default function List() { setSearchText: setSearchText, handleSearchSubmit: handleSearchSubmit, }; - - /* ------------------------------------------------------------------------- */ - /*-------------------------------- handlle checkbox ------------------------ */ - const handleCheckboxChange = async (event: React.FormEvent) => { - // Anda bisa menambahkan logika di sini - if (event.target.checked) { - // Checkbox dicentang - console.log('Checkbox dicentang'); - // Tambahkan kode lain yang ingin Anda jalankan saat checkbox dicentang - } else { - // Checkbox tidak dicentang - console.log('Checkbox tidak dicentang'); - // Tambahkan kode lain yang ingin Anda jalankan saat checkbox tidak dicentang - } - }; - - /* -------------------------------- headCell -------------------------------- */ - + return ( diff --git a/frontend/dashboard/src/@types/corporates.ts b/frontend/dashboard/src/@types/corporates.ts index 5484f2ce..8d39037c 100644 --- a/frontend/dashboard/src/@types/corporates.ts +++ b/frontend/dashboard/src/@types/corporates.ts @@ -12,6 +12,10 @@ export type Corporate = { divisions?: Division[]; employees?: Employee[]; current_policy?: Policy; + corporate_plans_count: number; + corporate_benefits_count: number; + employees_count: number; + }; export type Division = { @@ -39,14 +43,19 @@ export type Policy = { minimal_stop_service_net: number; start: string | Date; end: string | Date; + limit_balance: number; } export type CorporatePlan = { id: number; corporate_id: number; code: string; + service_code: string; + limit_rules: number; + corporate_plan_id: number; name: string; description: string | null; + type: number; active: boolean | number; } @@ -101,6 +110,7 @@ export type Plan = { currency: string; max_surgery_reinstatement_days: string; max_surgery_periode_days: string; + active: number } export type CorporateBenefit = { @@ -113,6 +123,7 @@ export type CorporateBenefit = { } export type Benefit = { + id : number; service_code : string; plan_code : string; benefit_code : string; @@ -170,6 +181,11 @@ export type Benefit = { currency : string; show_benefit_item : string; show_benefit_value : string; + plan : Plan; + benefit: Benefit; + corporate_benefit_code: string; + active: number; + limit_free_tc: number; } export type CorporateService = { @@ -189,3 +205,7 @@ export type MasterExclusion = { code: string; description?: string; } + +export type CorporateId = { + corporate_id?: number +} diff --git a/frontend/dashboard/src/components/DialogUpdateStatus.tsx b/frontend/dashboard/src/components/DialogUpdateStatus.tsx new file mode 100644 index 00000000..71b8f908 --- /dev/null +++ b/frontend/dashboard/src/components/DialogUpdateStatus.tsx @@ -0,0 +1,208 @@ +import * as Yup from 'yup'; +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { Dialog, DialogTitle, DialogContent, Stack, Typography, IconButton, Grid } from '@mui/material'; +import CloseIcon from '@mui/icons-material/Close'; +import { ReactElement } from 'react'; +import Iconify from './Iconify'; +import { Card } from '@mui/material'; +import { FormProvider, RHFTextField, RHFSwitch, RHFSelect } from './hook-form'; +import { Button } from '@mui/material'; +import { LoadingButton } from '@mui/lab'; +import axios from '@/utils/axios'; +import { enqueueSnackbar } from 'notistack'; + +// ---------------------------------------------------------------------- + +type DataContent = { + code: string; + name: string; + id: number; + status: string +}; + +type MuiDialogProps = { + title?: { + name?: string; + icon?: string; + }; + openDialog: boolean; + setOpenDialog: Function; + content?: ReactElement; + maxWidth?: string; + data?: DataContent | undefined; + description: string; +}; + +type FormValuesProps = { + value: string; + active: boolean; +}; + + +// ---------------------------------------------------------------------- + +const DialogUpdateStatus = ({ title, openDialog, setOpenDialog, data, maxWidth, content }: MuiDialogProps) => { + const NewCorporateSchema = Yup.object().shape({ + reason: Yup.string().required('Corporate Status is required'), + }); + + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + }); + + const { + reset, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + + useEffect(() => { + if (openDialog === false) { + reset(); + } + }, [openDialog, reset]); + + const handleClose = () => { + setOpenDialog(false); + }; + + const handleUpdate = (id: number, status: number) => { + axios + .put(`/corporates/${id}/activation`, { + // service_code: service.service_code, + active: status, + }) + .then((res) => { + handleClose() + window.location.reload(); + }) + .catch((error) => { + // console.log('asdasd', error.response.data.message) + enqueueSnackbar( + error.response.data.message ?? error.message ?? 'Failed Processing Request', + { variant: 'error' } + ); + }); + } + let maxWidthDialog = 'md'; + + if (maxWidth) { + maxWidthDialog = maxWidth; + } + + const onSubmit = async (row : any) => { + console.log('test') + }; + + return ( + + + + {title?.icon ? ( + + + {title?.name} + + ) : ( + {title?.name ? title?.name : ''} + )} + + + + + + + + {/* + {description} + + + + + Code + + + {data?.code} + + + Corporate Name + + + {data?.name} + + + + + + Reason for update* + + + + + + + + + + + + + + + {data?.status == 1 ? + + : } + + */} + {content} + + + + ); +}; + +export default DialogUpdateStatus; diff --git a/frontend/dashboard/src/components/Label.tsx b/frontend/dashboard/src/components/Label.tsx new file mode 100644 index 00000000..c633ec4f --- /dev/null +++ b/frontend/dashboard/src/components/Label.tsx @@ -0,0 +1,98 @@ +// @mui +import { alpha, Theme, useTheme, styled } from '@mui/material/styles'; +import { BoxProps } from '@mui/material'; +// theme +import { ColorSchema } from '../theme/palette'; + +// ---------------------------------------------------------------------- + +type LabelColor = 'default' | 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'; + +type LabelVariant = 'filled' | 'outlined' | 'ghost'; + +const RootStyle = styled('span')( + ({ + theme, + ownerState, + }: { + theme: Theme; + ownerState: { + color: LabelColor; + variant: LabelVariant; + }; + }) => { + const isLight = theme.palette.mode === 'light'; + const { color, variant } = ownerState; + + const styleFilled = (color: ColorSchema) => ({ + color: theme.palette[color].contrastText, + backgroundColor: theme.palette[color].main, + }); + + const styleOutlined = (color: ColorSchema) => ({ + color: theme.palette[color].main, + backgroundColor: 'transparent', + border: `1px solid ${theme.palette[color].main}`, + }); + + const styleGhost = (color: ColorSchema) => ({ + color: theme.palette[color][isLight ? 'dark' : 'light'], + backgroundColor: alpha(theme.palette[color].main, 0.16), + }); + + return { + height: 22, + minWidth: 22, + lineHeight: 0, + borderRadius: 6, + // cursor: 'default', + alignItems: 'center', + whiteSpace: 'nowrap', + display: 'inline-flex', + justifyContent: 'center', + padding: theme.spacing(0, 1), + color: theme.palette.grey[800], + fontSize: theme.typography.pxToRem(12), + fontFamily: theme.typography.fontFamily, + backgroundColor: theme.palette.grey[300], + fontWeight: theme.typography.fontWeightBold, + + ...(color !== 'default' + ? { + ...(variant === 'filled' && { ...styleFilled(color) }), + ...(variant === 'outlined' && { ...styleOutlined(color) }), + ...(variant === 'ghost' && { ...styleGhost(color) }), + } + : { + ...(variant === 'outlined' && { + backgroundColor: 'transparent', + color: theme.palette.text.primary, + border: `1px solid ${theme.palette.grey[500_32]}`, + }), + ...(variant === 'ghost' && { + color: isLight ? theme.palette.text.secondary : theme.palette.common.white, + backgroundColor: theme.palette.grey[500_16], + }), + }), + }; + } +); + +// ---------------------------------------------------------------------- + +interface Props extends BoxProps { + color?: LabelColor; + variant?: LabelVariant; +} + +export default function Label({ color = 'default', variant = 'ghost', children, sx }: Props) { + const theme = useTheme(); + + return ( + + {children} + + ); +} + + diff --git a/frontend/dashboard/src/components/ThemeColorPresets.tsx b/frontend/dashboard/src/components/ThemeColorPresets.tsx index 03d43c43..56c57c2d 100644 --- a/frontend/dashboard/src/components/ThemeColorPresets.tsx +++ b/frontend/dashboard/src/components/ThemeColorPresets.tsx @@ -21,7 +21,7 @@ export default function ThemeColorPresets({ children }: Props) { ...defaultTheme, palette: { ...defaultTheme.palette, - primary: setColor, + // primary: setColor, }, customShadows: { ...defaultTheme.customShadows, diff --git a/frontend/dashboard/src/pages/Corporates/Benefit/Create.tsx b/frontend/dashboard/src/pages/Corporates/Benefit/Create.tsx index 5e9fccdf..628f6588 100644 --- a/frontend/dashboard/src/pages/Corporates/Benefit/Create.tsx +++ b/frontend/dashboard/src/pages/Corporates/Benefit/Create.tsx @@ -2,21 +2,43 @@ import * as Yup from 'yup'; import { yupResolver } from "@hookform/resolvers/yup"; import { Card, Collapse, Divider, Grid, Stack, Typography } from "@mui/material"; import { useForm } from "react-hook-form"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs"; import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from "../../../components/hook-form"; import Page from "../../../components/Page"; import useSettings from "../../../hooks/useSettings"; import CorporateTabNavigations from "../CorporateTabNavigations"; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; import DivisionsList from "./List"; -import { useMemo, useState } from 'react'; +import FormEdit from "./Form"; +import { useEffect, useMemo, useState } from 'react'; +import { Benefit } from '@/@types/corporates'; +import axios from '@/utils/axios'; export default function Divisions() { const { themeStretch } = useSettings(); - const { corporate_id } = useParams(); + const { corporate_id, benefit_id } = useParams(); + const [ currentCorporateBenefit, setCurrentCorporateBenefit ] = useState(); + const navigate = useNavigate(); + const isEdit = !!benefit_id; + useEffect(() => { + console.log(benefit_id); + if (isEdit) { + axios.get('/corporates/'+corporate_id+'/corporate-benefits/'+benefit_id+'/edit') + .then((res) => { + setCurrentCorporateBenefit(res.data); + }) + .catch((err) => { + if (err.response.status === 404) { + navigate('/404'); + } + }) + } + }, [corporate_id, benefit_id]); + const NewDivisionSchema = Yup.object().shape({ name: Yup.string().required('Name is required'), @@ -51,97 +73,12 @@ export default function Divisions() { console.log(data); }; - const [open, setOpen] = useState(false); - const benefits = [ - { - 'category' : 'General Practitioner', - 'childs' : [ - { - 'name' : 'External Doctor Online', - 'code' : 'gp-external-doctor-online' - }, - { - 'name' : 'External Doctor Offline', - 'code' : 'gp-external-doctor-offline' - }, - { - 'name' : 'Internal Doctor Online', - 'code' : 'gp-internal-doctor-online' - }, - { - 'name' : 'Internal Doctor Offline', - 'code' : 'gp-internal-doctor-offline' - }, - ] - }, - { - 'category' : 'Specialist', - 'childs' : [ - { - 'name' : 'External Doctor Online', - 'code' : 'sp-external-doctor-online' - }, - { - 'name' : 'External Doctor Offline', - 'code' : 'sp-external-doctor-offline' - }, - { - 'name' : 'Internal Doctor Online', - 'code' : 'sp-internal-doctor-online' - }, - { - 'name' : 'Internal Doctor Offline', - 'code' : 'sp-internal-doctor-offline' - }, - ] - }, - { - 'category' : 'Medicines', - 'childs' : [ - { - 'name' : 'Vitamins', - 'code' : 'medicines-vitamins' - }, - { - 'name' : 'Delivery Fee', - 'code' : 'medicines-delivery-fee' - }, - ] - }, - ]; - - const products = [ - { - 'name' : 'Inpatient', - 'code' : 'IP', - }, - { - 'name' : 'Outpatient', - 'code' : 'OP', - }, - { - 'name' : 'Dental', - 'code' : 'DT', - }, - { - 'name' : 'Dental', - 'code' : 'DTL', - }, - { - 'name' : 'Matternity', - 'code' : 'MT', - }, - { - 'name' : 'Special Benefit', - 'code' : 'SB', - }, - ]; return ( - + /> */} - +{/* @@ -235,7 +172,17 @@ export default function Divisions() { - + */} + + navigate(`/corporates/${corporate_id}/benefit`)} + sx={{ cursor: 'pointer' }} + /> + + Edit Plan + + + ); } diff --git a/frontend/dashboard/src/pages/Corporates/Benefit/Form.tsx b/frontend/dashboard/src/pages/Corporates/Benefit/Form.tsx index 85050511..89317b32 100644 --- a/frontend/dashboard/src/pages/Corporates/Benefit/Form.tsx +++ b/frontend/dashboard/src/pages/Corporates/Benefit/Form.tsx @@ -1,7 +1,7 @@ import * as Yup from 'yup'; import { LoadingButton } from '@mui/lab'; -import { Box, Card, Grid, Stack, Typography } from '@mui/material'; -import { CorporatePlan } from '../../../@types/corporates'; +import { Box, Button, Card, Grid, Stack, Typography } from '@mui/material'; +import { Benefit } from '../../../@types/corporates'; import { FormProvider, RHFSwitch, RHFTextField } from '../../../components/hook-form'; import { useEffect, useMemo } from 'react'; import { useForm } from 'react-hook-form'; @@ -12,39 +12,36 @@ import axios from '../../../utils/axios'; type Props = { isEdit: boolean; - currentCorporatePlan?: CorporatePlan; + currentCorporateBenefit?: Benefit; }; -export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Props) { +export default function CorporateBenefitForm({ isEdit, currentCorporateBenefit }: Props) { const { enqueueSnackbar } = useSnackbar(); const navigate = useNavigate(); - const { corporate_id } = useParams(); + const { corporate_id, benefit_id } = useParams(); - const NewCorporatePlanSchema = Yup.object().shape({ - name: Yup.string().required('Name is required'), - code: Yup.string().required('Corporate Code is required'), + const NewCorporateBenefitSchema = Yup.object().shape({ + budget: Yup.string().required('Budget is required'), }); const defaultValues = useMemo( () => ({ - name: currentCorporatePlan?.name || '', - code: currentCorporatePlan?.code || '', - active: currentCorporatePlan?.active === 1 ? true : false, + budget: currentCorporateBenefit?.budget || '', }), - [currentCorporatePlan] + [currentCorporateBenefit] ); useEffect(() => { - if (isEdit && currentCorporatePlan) { + if (isEdit && currentCorporateBenefit) { reset(defaultValues); } if (!isEdit) { reset(defaultValues); } - }, [isEdit, currentCorporatePlan]); + }, [isEdit, currentCorporateBenefit]); const methods = useForm({ - resolver: yupResolver(NewCorporatePlanSchema), + resolver: yupResolver(NewCorporateBenefitSchema), defaultValues, }); @@ -81,12 +78,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop }); } else { await axios - .put('/corporate/' + corporate_id + '/divisions/' + currentCorporatePlan?.id, data) + .put('/corporates/' + corporate_id + '/corporate-benefits/' + benefit_id, data) .then((res) => { enqueueSnackbar('Division updated successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/divisions/', { replace: true }); + navigate('/corporates/' + corporate_id + '/benefits', { replace: true }); }) .catch(({ response }) => { enqueueSnackbar('Update Failed : ' + response.data.message, { variant: 'error' }); @@ -95,30 +92,44 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop }; return ( + - + ASO/Budget - - - - - - - - - ASO/Budget - - + + + + + Save + + ); diff --git a/frontend/dashboard/src/pages/Corporates/Benefit/Index.tsx b/frontend/dashboard/src/pages/Corporates/Benefit/Index.tsx index 54cac928..5070058e 100644 --- a/frontend/dashboard/src/pages/Corporates/Benefit/Index.tsx +++ b/frontend/dashboard/src/pages/Corporates/Benefit/Index.tsx @@ -44,10 +44,10 @@ export default function Divisions() { ]} /> - + {/* */} - + {/* */} ); } diff --git a/frontend/dashboard/src/pages/Corporates/Benefit/List.tsx b/frontend/dashboard/src/pages/Corporates/Benefit/List.tsx index 46f9c5be..cbbfbf12 100644 --- a/frontend/dashboard/src/pages/Corporates/Benefit/List.tsx +++ b/frontend/dashboard/src/pages/Corporates/Benefit/List.tsx @@ -35,11 +35,14 @@ import AddIcon from '@mui/icons-material/Add'; import UploadIcon from '@mui/icons-material/Upload'; import CancelIcon from '@mui/icons-material/Cancel'; import HistoryIcon from '@mui/icons-material/History'; +import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined'; +import FindInPageOutlinedIcon from '@mui/icons-material/FindInPageOutlined'; + // hooks import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react'; import useSettings from '../../../hooks/useSettings'; -import {Link, useParams, useSearchParams } from 'react-router-dom'; +import {Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'; // components import { @@ -64,12 +67,19 @@ import BasePagination from '../../../components/BasePagination'; import { enqueueSnackbar } from 'notistack'; import { LoadingButton } from '@mui/lab'; import DialogLog from './sections/DialogLog'; +import Label from '@/components/Label'; +import TableMoreMenu from '@/components/table/TableMoreMenu'; +import { Edit } from '@mui/icons-material'; +import { fData, fNumber } from '@/utils/formatNumber'; +import DialogUpdateStatus from '@/components/DialogUpdateStatus'; export default function PlanList() { const { themeStretch } = useSettings(); const { corporate_id } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); const [importResult, setImportResult] = useState(null); + + const navigate = useNavigate() const [openDialog, setOpenDialog] = useState(false); const [isDialog, setIsDialog] = useState(''); @@ -302,84 +312,141 @@ export default function PlanList() { }; } + type DataContent = { + code: string; + name: string; + id: number; + status: string|number; + }; + + // Generate the every row of the table + const [isDialogOpen, setDialogOpen] = useState(false) + let titles = { + name: 'Update Status', + icon: '-' + } + const [dataValue, setDataValue] = useState(''); + const [dataDescription, setDescriptionValue] = useState(''); + const [url, setUrl] = useState(''); + function Row(props: { row: ReturnType }) { const { row } = props; const [open, setOpen] = React.useState(false); const [openEdit, setOpenEdit] = React.useState(false); - const handleActivate = (model: any, status: string) => { - axios - .put(`/benefits/${row.id}/activation`, { - // service_code: service.service_code, - active: status == 'active', - }) - .then((res) => { - setDataTableData({ - ...dataTableData, - data: dataTableData.data.map((model) => { - let updatedModel = model; - if (row.id == model.id) { - updatedModel.active = res.data.benefit.active; - } - return updatedModel; - }), - }); - }) - .catch((error) => { - // console.log('asdasd', error.response.data.message) - enqueueSnackbar( - error.response.data.message ?? error.message ?? 'Failed Processing Request', - { variant: 'error' } - ); - }); + // const handleActivate = (model: any, status: string) => { + // axios + // .put(`/benefits/${row.id}/activation`, { + // // service_code: service.service_code, + // active: status == 'active', + // }) + // .then((res) => { + // setDataTableData({ + // ...dataTableData, + // data: dataTableData.data.map((model) => { + // let updatedModel = model; + // if (row.id == model.id) { + // updatedModel.active = res.data.benefit.active; + // } + // return updatedModel; + // }), + // }); + // }) + // .catch((error) => { + // // console.log('asdasd', error.response.data.message) + // enqueueSnackbar( + // error.response.data.message ?? error.message ?? 'Failed Processing Request', + // { variant: 'error' } + // ); + // }); + // }; + + + const handleActivate = (isOpen: boolean, dataValue: DataContent) => { + setDialogOpen(isOpen) + setDataValue(dataValue) + setDescriptionValue('Are you sure to inactive this service ?') + setUrl(url) }; + let frequency_period_name: string + switch (row.max_frequency_period) { + case '1' : + frequency_period_name = 'Daily Visit'; + break; + case '2': + frequency_period_name = 'Weekly'; + break; + case '3': + frequency_period_name = 'Monthly'; + break; + case '4': + frequency_period_name = 'Yearly'; + break; + case '5': + frequency_period_name = 'Disability'; + break; + case '6': + frequency_period_name = 'Visit'; + break; + default: + frequency_period_name = 'Policy Period'; + } + return ( *': { borderBottom: 'unset' } }}> - + {/* setOpen(!open)}> {open ? : } - + */} {row.plan?.service_code} {row.plan?.code} {row.benefit?.code} {row.corporate_benefit_code} {row.benefit?.description} + { fNumber(row.limit_amount)} + { row.max_frequency_period} {row.active == 1 && ( - + // )} {row.active != 1 && ( - + )} - + {/* + */} + + + setOpen(!open) }> + + Detail + + navigate(`/corporates/${corporate_id}/benefits/${row.id}/edit`) }> + + Edit + + navigate(`/corporates/${corporate_id}/benefits/${row.id}/history`)}> + + History + + handleActivate(true, {code: row.code, name: row.service_code, id:row.id, status: row.active}) }> + + Update Status + + + } /> - + {/* - + */} {/* COLLAPSIBLE ROW */} - {open == true ? ( - openEdit == false ? ( - - - - - - ASO/Budget + + {open == true ? ( + openEdit == false ? ( + + + + + + ASO/Budget + + + : {row.budget ? row.budget : '-'} + + + Budget Condition + + + : {row.budget_conditions ? row.budget_conditions : '-'} + + + Budget Code + + + : {row.budget_code ? row.budget_code : '-'} + + + Primary benefit + + + : {row.primary_benefit_code ? row.primary_benefit_code : '-'} + + + Benefit Mode + + + : {row.benefit_mode ? row.benefit_mode : '-'} + + + Room Class + + + : {row.room_class_coverage ? row.room_class_coverage : '-'} + + + Max Bed + + + : {row.max_bed_coverage ? row.max_bed_coverage : '-'} + + + Tolerance Paramater + + + : {row.tolerance_parameter ? row.tolerance_parameter : '-'} + + + Max. Room Class + + + : {row.max_room_class ? row.max_room_class : '-'} + + + Limit Value + + + : {row.limit_amount ? fNumber(row.limit_amount) : '-'} + + + Area + + + : {row.area_limit ? row.area_limit : '-'} + + + Shared Benefit With + + + : {row.shared_benefit ? row.shared_benefit : '-'} + + + Shared Benefit Type + + + : {row.shared_benefit_type ? row.shared_benefit_type : '-'} + + + MSC + + + : {row.msc ? row.msc : '-'} + + + Gender + + + : {row.genders ? row.genders : '-'} + + + Min Age + + + : {row.min_age ? row.min_age : '-'} + + + Max Age + + + : {row.max_age ? row.max_age : '-'} + + + Freq. Period + + + : {row.max_frequency_period ? frequency_period_name : '-'} + + + Daily Frequency + + + : {row.daily_frequency ? row.daily_frequency : '-'} + + + Weekly Frequency + + + : {row.weekly_frequency ? row.weekly_frequency : '-'} + + + Monthly Frequency + + + : {row.monthly_frequency ? row.monthly_frequency : '-'} + + + Yearly Frequency + + + : {row.yearly_frequency ? row.yearly_frequency : '-'} + + + Custom Duration + + + : {row.custom_frequency_days ? row.custom_frequency_days : '-'} + + + Custom Duration Value + + + : {row.custom_duration_value ? row.custom_duration_value : '-'} + + + Cashless, Reimbursement + + + : {row.allowed_transaction_types ? row.allowed_transaction_types : '-'} + + + High Plan Factor + + + : {row.high_plan_factor ? row.high_plan_factor : '-'} + - - : {row.budget ? row.budget : '-'} - - - Budget Condition - - - : {row.budget_conditions ? row.budget_conditions : '-'} - - - Budget Code - - - : {row.budget_code ? row.budget_code : '-'} - - - Primary benefit - - - : {row.primary_benefit_code ? row.primary_benefit_code : '-'} - - - Benefit Mode - - - : {row.benefit_mode ? row.benefit_mode : '-'} - - - Room Class - - - : {row.room_class_coverage ? row.room_class_coverage : '-'} - - - Max Bed - - - : {row.max_bed_coverage ? row.max_bed_coverage : '-'} - - - Tolerance Paramater - - - : {row.tolerance_parameter ? row.tolerance_parameter : '-'} - - - Max. Room Class - - - : {row.max_room_class ? row.max_room_class : '-'} - - - Limit Value - - - : {row.limit_amount ? row.limit_amount : '-'} - - - Area - - - : {row.area_limit ? row.area_limit : '-'} - - - Shared Benefit With - - - : {row.shared_benefit ? row.shared_benefit : '-'} - - - Shared Benefit Type - - - : {row.shared_benefit_type ? row.shared_benefit_type : '-'} - - - MSC - - - : {row.msc ? row.msc : '-'} - - - Gender - - - : {row.genders ? row.genders : '-'} - - - Min Age - - - : {row.min_age ? row.min_age : '-'} - - - Max Age - - - : {row.max_age ? row.max_age : '-'} - - - Freq. Period - - - : {row.max_frequency_period ? row.max_frequency_period : '-'} - - - Daily Frequency - - - : {row.daily_frequency ? row.daily_frequency : '-'} - - - Weekly Frequency - - - : {row.weekly_frequency ? row.weekly_frequency : '-'} - - - Monthly Frequency - - - : {row.monthly_frequency ? row.monthly_frequency : '-'} - - - Yearly Frequency - - - : {row.yearly_frequency ? row.yearly_frequency : '-'} - - - Custom Duration - - - : {row.custom_frequency_days ? row.custom_frequency_days : '-'} - - - Custom Duration Value - - - : {row.custom_duration_value ? row.custom_duration_value : '-'} - - - Cashless, Reimbursement - - - : {row.allowed_transaction_types ? row.allowed_transaction_types : '-'} - - - High Plan Factor - - - : {row.high_plan_factor ? row.high_plan_factor : '-'} + + + + + Pre Post Treatment + + + : {row.pre_post_treatment ? row.pre_post_treatment : '-'} + + + Pre Treatment + + + : {row.pre_treatment_days ? row.pre_treatment_days : '-'} + + + Post Treatment + + + : {row.post_treatment_days ? row.post_treatment_days : '-'} + + + Layer Type 1 + + + : {row.layer_type_1 ? row.layer_type_1 : '-'} + + + Layer Value 1 + + + : {row.layer_value_1 ? row.layer_value_1 : '-'} + + + Layer Type 2 + + + : {row.layer_type_2 ? row.layer_type_2 : '-'} + + + Layer Value 2 + + + : {row.layer_value_2 ? row.layer_value_2 : '-'} + + + Cashless (%) + + + : {row.cashless_percentage ? row.cashless_percentage : '-'} + + + Reimburse (%) + + + : {row.reimbursement_percentage ? row.reimbursement_percentage : '-'} + + + Digital (%) + + + : {row.digital_percentage ? row.digital_percentage : '-'} + + + CoShareM (%) + + + : {row.co_share_m_percentage ? row.co_share_m_percentage : '-'} + + + CoShareS (%) + + + : {row.co_share_s_percentage ? row.co_share_s_percentage : '-'} + + + CoShareC (%) + + + : {row.co_share_c_percentage ? row.co_share_c_percentage : '-'} + + + Cashless Deductible + + + : {row.cashless_deductible ? row.cashless_deductible : '-'} + + + Reimbursement Deductible + + + : {row.reimbursement_deductible ? row.reimbursement_deductible : '-'} + + + Digital Deductible + + + : {row.digital_deductible ? row.digital_deductible : '-'} + + + DeductibleM + + + : {row.co_share_m_deductible ? row.co_share_m_deductible : '-'} + + + DeductibleS + + + : {row.co_share_s_deductible ? row.co_share_s_deductible : '-'} + + + DeductibleC + + + : {row.co_share_c_deductible ? row.co_share_c_deductible : '-'} + + + Prorate Type + + + : {row.prorate_type ? row.prorate_type : '-'} + + + Prorate Lookup + + + : {row.prorate_lookup ? row.prorate_lookup : '-'} + + + Max Days for Disability + + + : {row.max_days_for_disability ? row.max_days_for_disability : '-'} + + + Max Periode of Disability + + + : {row.max_period_for_disability ? row.max_period_for_disability : '-'} + + + Limit Free TC + + + : {row.limit_free_tc ? row.limit_free_tc : '-'} + + + Currency + + + : {row.currency ? row.currency : '-'} + + + Show Benefit Item + + + : {row.show_benefit_item ? row.show_benefit_item : '-'} + + + Show Benefit Value + + + : {row.show_benefit_value ? row.show_benefit_value : '-'} + - - - - Pre Post Treatment - - - : {row.pre_post_treatment ? row.pre_post_treatment : '-'} - - - Pre Treatment - - - : {row.pre_treatment_days ? row.pre_treatment_days : '-'} - - - Post Treatment - - - : {row.post_treatment_days ? row.post_treatment_days : '-'} - - - Layer Type 1 - - - : {row.layer_type_1 ? row.layer_type_1 : '-'} - - - Layer Value 1 - - - : {row.layer_value_1 ? row.layer_value_1 : '-'} - - - Layer Type 2 - - - : {row.layer_type_2 ? row.layer_type_2 : '-'} - - - Layer Value 2 - - - : {row.layer_value_2 ? row.layer_value_2 : '-'} - - - Cashless (%) - - - : {row.cashless_percentage ? row.cashless_percentage : '-'} - - - Reimburse (%) - - - : {row.reimbursement_percentage ? row.reimbursement_percentage : '-'} - - - Digital (%) - - - : {row.digital_percentage ? row.digital_percentage : '-'} - - - CoShareM (%) - - - : {row.co_share_m_percentage ? row.co_share_m_percentage : '-'} - - - CoShareS (%) - - - : {row.co_share_s_percentage ? row.co_share_s_percentage : '-'} - - - CoShareC (%) - - - : {row.co_share_c_percentage ? row.co_share_c_percentage : '-'} - - - Cashless Deductible - - - : {row.cashless_deductible ? row.cashless_deductible : '-'} - - - Reimbursement Deductible - - - : {row.reimbursement_deductible ? row.reimbursement_deductible : '-'} - - - Digital Deductible - - - : {row.digital_deductible ? row.digital_deductible : '-'} - - - DeductibleM - - - : {row.co_share_m_deductible ? row.co_share_m_deductible : '-'} - - - DeductibleS - - - : {row.co_share_s_deductible ? row.co_share_s_deductible : '-'} - - - DeductibleC - - - : {row.co_share_c_deductible ? row.co_share_c_deductible : '-'} - - - Prorate Type - - - : {row.prorate_type ? row.prorate_type : '-'} - - - Prorate Lookup - - - : {row.prorate_lookup ? row.prorate_lookup : '-'} - - - Max Days for Disability - - - : {row.max_days_for_disability ? row.max_days_for_disability : '-'} - - - Max Periode of Disability - - - : {row.max_period_for_disability ? row.max_period_for_disability : '-'} - - - Limit Free TC - - - : {row.limit_free_tc ? row.limit_free_tc : '-'} - - - Currency - - - : {row.currency ? row.currency : '-'} - - - Show Benefit Item - - - : {row.show_benefit_item ? row.show_benefit_item : '-'} - - - Show Benefit Value - - - : {row.show_benefit_value ? row.show_benefit_value : '-'} - - - - - - ) : ( -
- ) - ) : null} + + ) : ( + + ) + ) : null} + {/* @@ -803,17 +894,106 @@ export default function PlanList() { loadDataTableData(); }, []); + + const getContent = () => ( + <> + + Are you sure to {dataValue?.status == 1 ? 'inactive' : 'active'} this service ? + + + + + Code + + + {dataValue?.code} + + + Service Name + + + {dataValue?.name} + + + + + + Reason for update* + + + + + + + + + + + + + + {dataValue?.status == 1? + + Inactive + + : + + Active + + + + } + + + + + + ); + return ( - - {/* The Main Table */} - - +
+ - + {/* */} Service @@ -829,15 +1009,20 @@ export default function PlanList() { Detail Benefit - + + Limit Benefit + + + Limit Frequency + Status - Action + - + {dataTableIsLoading ? ( @@ -864,8 +1049,7 @@ export default function PlanList() {
- -
+ {isDialog === 'edit' && ( )} + {/* */}
); } diff --git a/frontend/dashboard/src/pages/Corporates/Benefit/sections/History.tsx b/frontend/dashboard/src/pages/Corporates/Benefit/sections/History.tsx index fd329b53..7cd79003 100644 --- a/frontend/dashboard/src/pages/Corporates/Benefit/sections/History.tsx +++ b/frontend/dashboard/src/pages/Corporates/Benefit/sections/History.tsx @@ -85,7 +85,7 @@ export default function CustomizedAccordions() { (panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => { setExpanded(newExpanded ? panel : false); }; - const pageTitle = 'Audittrail Corporate'; + const pageTitle = 'Corporate Dashboard'; const { themeStretch } = useSettings(); @@ -121,11 +121,11 @@ export default function CustomizedAccordions() { }, { name: corporate?.name ?? '-', - href: '/corporate/' + corporate_id + '/plans', + href: '/corporates/' + corporate_id + '/benefits', }, { - name: 'Audittrail Corporate', - href: '/corporate/' + corporate_id + '/plans', + name: 'Benefit', + href: '/corporates/' + corporate_id + '/benefits', }, ]} /> diff --git a/frontend/dashboard/src/pages/Corporates/CorporatePlan/CreateUpdate.tsx b/frontend/dashboard/src/pages/Corporates/CorporatePlan/CreateUpdate.tsx index 8768616f..a063274d 100644 --- a/frontend/dashboard/src/pages/Corporates/CorporatePlan/CreateUpdate.tsx +++ b/frontend/dashboard/src/pages/Corporates/CorporatePlan/CreateUpdate.tsx @@ -8,6 +8,9 @@ import axios from '../../../utils/axios'; import { useSnackbar } from 'notistack'; import CorporatePlanForm from './Form'; import { CorporatePlan } from '../../../@types/corporates'; +import { Stack } from "@mui/system"; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; +import { Typography } from "@mui/material"; @@ -36,8 +39,8 @@ export default function PlanCreate() { return ( - + /> */} + + navigate(`/corporates/${corporate_id}/plans`)} + sx={{ cursor: 'pointer' }} + /> + + Edit Plan + + diff --git a/frontend/dashboard/src/pages/Corporates/CorporatePlan/Form.tsx b/frontend/dashboard/src/pages/Corporates/CorporatePlan/Form.tsx index 145980be..da07687f 100644 --- a/frontend/dashboard/src/pages/Corporates/CorporatePlan/Form.tsx +++ b/frontend/dashboard/src/pages/Corporates/CorporatePlan/Form.tsx @@ -1,6 +1,6 @@ import * as Yup from 'yup'; import { LoadingButton } from '@mui/lab'; -import { Card, Grid, Stack, Typography } from '@mui/material'; +import { Card, Grid, Stack, Typography, Button } from '@mui/material'; import { CorporatePlan } from '../../../@types/corporates'; import { FormProvider, RHFEditor, RHFSwitch, RHFTextField } from '../../../components/hook-form'; import { useEffect, useMemo, useState } from 'react'; @@ -22,16 +22,22 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop const { corporate_id } = useParams(); const NewCorporatePlanSchema = Yup.object().shape({ - name: Yup.string().required('Name is required'), code: Yup.string().required('Corporate Code is required'), + service: Yup.string().required('Corporate Service is required'), + plan: Yup.string().required('Corporate Plan is required'), + type: Yup.string().required('Corporate Type is required'), + limit: Yup.string().required('Corporate Limit is required'), }); const defaultValues = useMemo( () => ({ - name: currentCorporatePlan?.name || '', + // name: currentCorporatePlan?.name || '', code: currentCorporatePlan?.code || '', - active: currentCorporatePlan?.active || true, - description: currentCorporatePlan?.description || '', + // active: currentCorporatePlan?.active || true, + type: currentCorporatePlan?.type || '', + limit: currentCorporatePlan?.limit_rules || '', + service: currentCorporatePlan?.service_code || '', + plan: currentCorporatePlan?.corporate_plan_id || '', }), [currentCorporatePlan] ); @@ -62,14 +68,15 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop } = methods; const onSubmit = async (data: any) => { + console.log(data); if (!isEdit) { await axios - .post('/corporate/' + corporate_id + '/corporate-plans', data) + .post('/corporates/' + corporate_id + '/corporate-plans', data) .then((res) => { enqueueSnackbar('Corporate Plan created successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/corporate-plans', { replace: true }); + navigate(`/corporates/${corporate_id}/plans`, { replace: true }); }) .catch(({ response }) => { if (response.status === 422) { @@ -83,12 +90,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop }); } else { await axios - .put('/corporate/' + corporate_id + '/corporate-plans/' + currentCorporatePlan?.id, data) + .put('/corporates/' + corporate_id + '/corporate-plans/' + currentCorporatePlan?.id, data) .then((res) => { enqueueSnackbar('Corporate Plan updated successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/corporate-plans/', { replace: true }); + navigate('/corporates/' + corporate_id + '/plans', { replace: true }); }) .catch(({ response }) => { enqueueSnackbar('Update Failed : ' + response.data.message, { variant: 'error' }); @@ -98,12 +105,34 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop return ( - - - + + + + Service* + + + + Plan* + + + + Code* + + + + Type* + + + + Plan Limit* + + + + {/* Corporate Plan Detail + @@ -122,17 +151,35 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop fullWidth={true} loading={isSubmitting} > - Create Corporate Plan + { isEdit ? 'Update' : 'Create'} Corporate Plan - + */} - - - - - - + + + + + Save + + ); } diff --git a/frontend/dashboard/src/pages/Corporates/DialogUpdateStatus.tsx b/frontend/dashboard/src/pages/Corporates/DialogUpdateStatus.tsx new file mode 100644 index 00000000..2a1bd19d --- /dev/null +++ b/frontend/dashboard/src/pages/Corporates/DialogUpdateStatus.tsx @@ -0,0 +1,189 @@ +import * as Yup from 'yup'; +import { enqueueSnackbar, useSnackbar } from 'notistack'; +import { useNavigate } from 'react-router-dom'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +// @mui +import { styled } from '@mui/material/styles'; +import { LoadingButton } from '@mui/lab'; +import { Box, Button, Grid, Stack, Typography, Chip, Autocomplete } from '@mui/material'; +import { CorporateService } from '../../@types/corporates'; +// components +import { FormProvider, RHFTextField, RHFSwitch, RHFSelect } from '../../components/hook-form'; +import axios from '../../utils/axios'; +import { LaravelPaginatedData } from '../../@types/paginated-data'; + +// import { Contact } from '../../../../@types/contact'; +import { Link, useParams, useSearchParams } from 'react-router-dom'; + +// @mui +// components +import MuiDialog from '../../components/MuiDialog'; +// React +import { ReactElement } from 'react'; + +// ---------------------------------------------------------------------- + +const HeaderStyle = styled('header')(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + padding: theme.spacing(2), + justifyContent: 'space-between', +})); + +type DataContent = { + info: string; + date: string; + time: string; +}; + +type MuiDialogProps = { + title?: { + name?: string; + icon?: string; + }; + openDialog: boolean; + setOpenDialog: Function; + content?: ReactElement; + id: number; +}; + +type FormValuesProps = { + value: string; + active: boolean; +}; + +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- + +const DialogUpdateStatus = ({ title, openDialog, setOpenDialog, id }: MuiDialogProps) => { + const NewCorporateSchema = Yup.object().shape({ + reason: Yup.string().required('Corporate Status is required'), + }); + + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + }); + + const { + reset, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + + useEffect(() => { + if (openDialog === false) { + reset(); + } + }, [openDialog, reset]); + + const handleActivate = (id: number, status: string) => { + axios + .put(`/corporates/${id}/activation`, { + active: status == 'active', + }) + .then((res) => { + console.log(res) + enqueueSnackbar( + 'Succes', + { variant: 'success' } + ); + }) + .catch((error) => { + // console.log('asdasd', error.response.data.message) + enqueueSnackbar( + error.response.data.message ?? error.message ?? 'Failed Processing Request', + { variant: 'error' } + ); + }); + }; + + const onSubmit = async (row : ReturnType) => { + try { + handleActivate(1, 'active') + } catch (error: any) { + + } + + const ascent = document?.querySelector('ascent'); + if (ascent != null) { + ascent.innerHTML = ''; + } + }; + + function createData(corporateService: CorporateService): CorporateService { + return { + ...corporateService, + }; + } + + const getContent = (props: { row: ReturnType }) => ( + + + + + + + + + + + + + + + + + + + Save + + + + + + + + ); + + return ( + + ); +}; + +export default DialogUpdateStatus; \ No newline at end of file diff --git a/frontend/dashboard/src/pages/Corporates/Form.tsx b/frontend/dashboard/src/pages/Corporates/Form.tsx index b739a98c..d349d07f 100644 --- a/frontend/dashboard/src/pages/Corporates/Form.tsx +++ b/frontend/dashboard/src/pages/Corporates/Form.tsx @@ -496,7 +496,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) { - Corporate Profile + Corporate Profile Corporate Profile* @@ -627,7 +627,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) { {/* Policy Detail */} - Policy Detail + Policy Detail @@ -733,7 +733,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) { )} {/* Type contrack */} - + {/* @@ -806,18 +806,32 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) { - + */} - - - {!isEdit ? 'Save New Corporate' : 'Save Corporate'} - + + + + + Save + + diff --git a/frontend/dashboard/src/pages/Corporates/History.tsx b/frontend/dashboard/src/pages/Corporates/History.tsx index 09c0cdf1..777d52e8 100644 --- a/frontend/dashboard/src/pages/Corporates/History.tsx +++ b/frontend/dashboard/src/pages/Corporates/History.tsx @@ -139,7 +139,7 @@ export default function CustomizedAccordions() { aria-controls={`panel${index}d-content`} id={`panel${index}d-header`} > - {`Data has ${item.action} by ${item.user_id} on ${fDateTime(item.updated_at)}`} + {`Data has ${item.action} by ${item.user_id} on ${fDateTime(item.updated_at)}`} diff --git a/frontend/dashboard/src/pages/Corporates/Index.tsx b/frontend/dashboard/src/pages/Corporates/Index.tsx index 689a144b..11c2936e 100644 --- a/frontend/dashboard/src/pages/Corporates/Index.tsx +++ b/frontend/dashboard/src/pages/Corporates/Index.tsx @@ -24,24 +24,33 @@ import { Typography, Badge, Stack, + Dialog, } from '@mui/material'; +import * as Yup from 'yup'; + + +// icon import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; import PublishIcon from '@mui/icons-material/Publish'; import AddIcon from '@mui/icons-material/Add'; import HistoryIcon from '@mui/icons-material/History'; import MoreVertIcon from '@mui/icons-material/MoreVert'; +import FindInPageOutlinedIcon from '@mui/icons-material/FindInPageOutlined'; import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; +import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined'; // hooks import useSettings from '../../hooks/useSettings'; // components import Page from '../../components/Page'; +import DialogUpdateStatus from '../../components/DialogUpdateStatus'; import axios from '../../utils/axios'; import useAuth from '../../hooks/useAuth'; +import { useForm } from 'react-hook-form' import { Link, NavLink as RouterLink, useNavigate, useSearchParams } from 'react-router-dom'; -import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import React, { ChangeEvent, ReactElement, useEffect, useRef, useState } from 'react'; import { Theme, useTheme } from '@mui/material/styles'; import { Corporate } from '../../@types/corporates'; import { LaravelPaginatedData } from '../../@types/paginated-data'; @@ -51,11 +60,14 @@ import { fCurrency } from '../../utils/formatNumber'; import { enqueueSnackbar } from 'notistack'; import { fDate } from '@/utils/formatTime'; import Popover from '@mui/material/Popover'; -import PopupState, { bindTrigger, bindPopover } from 'material-ui-popup-state'; import ButtonStyles from '../../theme/overrides/Button'; import TableMoreMenu from '@/components/table/TableMoreMenu'; import Iconify from '@/components/Iconify'; +import Label from '@/components/Label'; +import { FormProvider, RHFSelect } from '@/components/hook-form'; +import { LoadingButton } from '@mui/lab'; +import { yupResolver } from '@hookform/resolvers/yup'; export default function Corporates() { @@ -63,12 +75,37 @@ export default function Corporates() { const [searchParams, setSearchParams] = useSearchParams(); const navigate = useNavigate() + // Type + type DataContent = { + code: string; + name: string; + id: string; + status: string|number; + }; + + type MuiDialogProps = { + title?: { + name?: string; + icon?: string; + }; + openDialog: boolean; + setOpenDialog: Function; + content?: ReactElement; + data?: DataContent[]; + }; + + type FormValuesProps = { + value: string; + active: boolean; + }; + // Called on every row to map the data to the columns function createData(corporate: Corporate): Corporate { return { ...corporate, }; } + // Dummy Default Data const [dataTableIsLoading, setDataTableLoading] = React.useState(true); @@ -161,6 +198,8 @@ export default function Corporates() { typeof value === 'string' ? value.split(',') : value ); }; + + // END FILTER SELECT // Component Search Input @@ -258,7 +297,7 @@ export default function Corporates() { Import */} - @@ -274,36 +313,154 @@ export default function Corporates() { // Component Row // Generate the every row of the table + const [isDialogOpen, setDialogOpen] = useState(false) + let titles = { + name: 'Update Status', + icon: '-' + } + const [dataValue, setDataValue] = useState(); + const [dataDescription, setDescriptionValue] = useState(''); + + + const NewCorporateSchema = Yup.object().shape({ + reason: Yup.string().required('Reason Edit is required'), + }); + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + }); + + const { + reset, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + const onSubmit = async (row : any) => { + try { + console.log(dataValue) + handleUpdate(dataValue.id, dataValue.status, row.reason) + } catch (error: any) { + console.log('data gagal'); + } + + const ascent = document?.querySelector('ascent'); + if (ascent != null) { + ascent.innerHTML = ''; + } + }; + + const handleUpdate = (id: string, active: number, reason: string) => { + axios + .put(`/corporates/${id}/activation`, { + active: active, + reason: reason + }) + .then((res) => { + window.location.reload(); + }); + } + + + const getContent = () => ( + <> + + Are you sure to {dataValue?.status == 1 ? 'inactive' : 'active'} this service ? + + + + + Code + + + {dataValue?.code} + + + Corporate Name + + + {dataValue?.name} + + + + + + Reason for update* + + + + + + + + + + + + + + {dataValue?.status == 1 ? + + Inactive + + : + + Active + + + + } + + + + + + ); + function Row(props: { row: ReturnType }) { const { row } = props; const [open, setOpen] = React.useState(false); const navigate = useNavigate() - const handleActivate = (model: any, status: string) => { - axios - .put(`/corporates/${row.id}/activation`, { - // service_code: service.service_code, - active: status == 'active', - }) - .then((res) => { - setDataTableData({ - ...dataTableData, - data: dataTableData.data.map((model) => { - let updatedModel = model; - if (row.id == model.id) { - updatedModel.active = res.data.corporate.active; - } - return updatedModel; - }), - }); - }) - .catch((error) => { - // console.log('asdasd', error.response.data.message) - enqueueSnackbar( - error.response.data.message ?? error.message ?? 'Failed Processing Request', - { variant: 'error' } - ); - }); + + const handleActivate = (isOpen: boolean, dataValue: DataContent) => { + setDialogOpen(isOpen) + setDataValue(dataValue) + setDescriptionValue('Are you sure to inactive this coporate ?') }; return ( @@ -318,31 +475,37 @@ export default function Corporates() { {row.name} {row.active == 1 && ( - + + // )} {row.active != 1 && ( - + + // )} - + {/* + + Import + {handleGetTemplate('plan-benefit')}}>Download Template + {handleGetData('data-plan-benefit')}}>Download Plans & Benefit + + + {/*

kjasndkjandskjasndkjansdkjansd

*/} - - - Import - {handleGetTemplate('plan-benefit')}}>Download Template - {handleGetData('data-plan-benefit')}}>Download Plans & Benefit - +
)} @@ -286,47 +407,51 @@ export default function CorporatePlanList() { }; } + type DataContent = { + code: string; + name: string; + id: number; + status: string|number; + }; + + type FormValuesProps = { + value: string; + active: boolean; + }; + // Generate the every row of the table + const [isDialogOpen, setDialogOpen] = useState(false) + let titles = { + name: 'Update Status', + icon: '-' + } + const [dataValue, setDataValue] = useState(''); + const [dataDescription, setDescriptionValue] = useState(''); + const [url, setUrl] = useState(''); + function Row(props: { row: ReturnType }) { const { row } = props; const [open, setOpen] = React.useState(false); - const handleActivate = (model: any, status: string) => { - axios - .put(`/plans/${row.id}/activation`, { - // service_code: service.service_code, - active: status == 'active', - }) - .then((res) => { - setDataTableData({ - ...dataTableData, - data: dataTableData.data.map((model) => { - let updatedModel = model; - if (row.id == model.id) { - updatedModel.active = res.data.plan.active; - } - return updatedModel; - }), - }); - }) - .catch((error) => { - // console.log('asdasd', error.response.data.message) - enqueueSnackbar( - error.response.data.message ?? error.message ?? 'Failed Processing Request', - { variant: 'error' } - ); - }); + const handleActivate = (isOpen: boolean, dataValue: DataContent) => { + setDialogOpen(isOpen) + setDataValue(dataValue) + setDescriptionValue('Are you sure to inactive this service ?') + setUrl(url) }; - + return ( - *': { borderBottom: 'unset' } }}> - - setOpen(!open)}> + + {/* */} + {/* setOpen(!open)}> {open ? : } - + */} + {/* */} + + {row.service_code} - {row.service_code} + {row.corporate_plan_id} {row.code} {row.type} @@ -334,41 +459,27 @@ export default function CorporatePlanList() { {row.limit_rules} - {row.active == 1 && ( - - )} - {row.active != 1 && ( - - )} + {row.active == 1 ? + : + } - - - - - + + navigate(`/corporates/${corporate_id}/corporate-plans/${row.id}/edit`)}> + + Edit + + navigate(`/corporates/${corporate_id}/plans/${row.id}/history`)}> + + History + + handleActivate(true, {code: row.code, name: row.service_code, id:row.id, status: row.active})}> + + Update Status + + + } /> {/* COLLAPSIBLE ROW */} @@ -689,6 +800,20 @@ export default function CorporatePlanList() { fontWeight: 'bold', }; + + const onSubmit = async (row : any) => { + try { + handleUpdate(dataValue.status, dataValue.id, row.reason) + } catch (error: any) { + console.log('data gagal'); + } + + const ascent = document?.querySelector('ascent'); + if (ascent != null) { + ascent.innerHTML = ''; + } + }; + const applyFilter = async (searchFilter: string) => { await loadDataTableData({ search: searchFilter }); setSearchParams({ search: searchFilter }); @@ -704,17 +829,134 @@ export default function CorporatePlanList() { loadDataTableData(); }, []); + const NewCorporateSchema = Yup.object().shape({ + reason: Yup.string().required('Reason Edit is required'), + }); + + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + }); + + + const { + reset, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + const handleUpdate = (active: number, id: number, reason:string) => { + console.log(active) + axios + .put(`/plans/${id}/activation`, { + active: active, + reason: reason + }) + .then((res) => { + window.location.reload(); + }); +} + + const getContent = () => ( + <> + + Are you sure to {dataValue?.status == 1 ? 'inactive' : 'active'} this service ? + + + + + Code + + + {dataValue?.code} + + + Service Name + + + {dataValue?.name} + + + + + + Reason for update* + + + + + + + + + + + + + + {dataValue?.status == 1? + + Inactive + + : + + Active + + + + } + + + + + + ); + return ( - + {/* */} {/* The Main Table */} - + - + - + {/* */} Service @@ -737,7 +979,7 @@ export default function CorporatePlanList() { Action - + {dataTableIsLoading ? ( @@ -765,7 +1007,7 @@ export default function CorporatePlanList() { - + {/* */} {isDialog === 'edit' && ( )} + + ); } diff --git a/frontend/dashboard/src/pages/Corporates/Plan/sections/History.tsx b/frontend/dashboard/src/pages/Corporates/Plan/sections/History.tsx index c1f372cf..03f6d685 100644 --- a/frontend/dashboard/src/pages/Corporates/Plan/sections/History.tsx +++ b/frontend/dashboard/src/pages/Corporates/Plan/sections/History.tsx @@ -121,11 +121,11 @@ export default function CustomizedAccordions() { }, { name: corporate?.name ?? '-', - href: '/corporate/' + corporate_id + '/plans', + href: '/corporates/' + corporate_id + '/plans', }, { - name: 'Audittrail Corporate', - href: '/corporate/' + corporate_id + '/plans', + name: 'Corporate Dashboard', + href: '/corporates/' + corporate_id + '/plans', }, ]} /> diff --git a/frontend/dashboard/src/pages/Corporates/Services/Create.tsx b/frontend/dashboard/src/pages/Corporates/Services/Create.tsx index 26f21c96..4a4a7517 100644 --- a/frontend/dashboard/src/pages/Corporates/Services/Create.tsx +++ b/frontend/dashboard/src/pages/Corporates/Services/Create.tsx @@ -44,7 +44,7 @@ import { RHFCustomMultiCheckbox, } from '../../../components/hook-form'; import { Controller, useForm } from 'react-hook-form'; -import { useParams } from 'react-router-dom'; +import { useParams, useNavigate } from 'react-router-dom'; import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; import Page from '../../../components/Page'; import useSettings from '../../../hooks/useSettings'; @@ -150,6 +150,8 @@ export default function Divisions() { }); }; + const navigate = useNavigate(); + const handleConfigExclusion = ( event: ChangeEvent, service: any, @@ -378,580 +380,584 @@ export default function Divisions() { }, { name: corporate?.name ?? '-', - href: '/corporate/' + corporate_id, + href: '/corporates/' + corporate_id, }, { name: 'Services', - href: '/corporate/' + corporate_id + '/services', + href: '/corporates/' + corporate_id + '/services', }, { name: service_code ?? '-', - href: '/corporate/' + corporate_id + '/services/' + service_code, + href: '/corporates/' + corporate_id + '/services/' + service_code, }, ]} /> - - {/* */} - - - -
- - - - General Practitioner - - - - - - External Doctor - Internal Doctor - - - - { - handleConfigChange(event, service); - }} - name="gp_external_doctor_online" - /> - } - label="Online" - /> - - - { - handleConfigChange(event, service); - }} - name="gp_external_doctor_offline" - /> - } - label="Offline" - /> - - - { - handleConfigChange(event, service); - }} - name="gp_internal_doctor_online" - /> - } - label="Online" - /> - - - { - handleConfigChange(event, service); - }} - name="gp_internal_doctor_offline" - /> - } - label="Offline" - /> - - - -
-
+ + + + General Practitioner* + + + External Doctor + - - - - - - Specialist Practitioner - - - - - - External Doctor - Internal Doctor - - - - { - handleConfigChange(event, service); - }} - name="sp_external_doctor_online" - /> - } - label="Online" - /> - - - { - handleConfigChange(event, service); - }} - name="sp_external_doctor_offline" - /> - } - label="Offline" - /> - - - { - handleConfigChange(event, service); - }} - name="sp_internal_doctor_online" - /> - } - label="Online" - /> - - - { - handleConfigChange(event, service); - }} - name="sp_internal_doctor_offline" - /> - } - label="Offline" - /> - - - - - { - setSpecialityModal(true); - }} - > - - - - {(service.selected_specialities && service.selected_specialities != '') - ? Object.keys(service.selected_specialities).length + ' Spesialis Diijinkan : {' + Object.values(service.selected_specialities).join(', ') + '}' - : 'Tidak Ada Spesialis yang diijinkan'} - - - - -
-
+ + Internal Doctor + - { - setSpecialityModal(false); - }} - sx={{ - '& .MuiDialog-paper': { - width: '100%', - maxWidth: 1500, - maxHeight: 750, - bgcolor: 'background.paper', - boxShadow: 24, - }, - }} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > - - - - Specialities - - - - - - - - - - - Covered - Nama Spesialisasi - MSC - Gender - - Min Age - - - Max Age - - Plan - - - - - {specialities.map((row: any, index: any) => ( - - - { - handleToggleSpeciality(event, service, row); - }} - /> - - - {row.name} - - - - - item.speciality_id == row.id && item.msc?.m == '1' - )} - onChange={(event) => { - handleConfigExclusion(event, service, row, 'm', 'msc'); - }} - /> - } - label="Member" - /> - - item.speciality_id == row.id && item.msc?.s == '1' - )} - onChange={(event) => { - handleConfigExclusion(event, service, row, 's', 'msc'); - }} - /> - } - label="Spouse" - /> - - item.speciality_id == row.id && item.msc?.c == '1' - )} - onChange={(event) => { - handleConfigExclusion(event, service, row, 'c', 'msc'); - }} - /> - } - label="Child" - /> - - - - - - item.speciality_id == row.id && - item.gender?.male == '1' - )} - onChange={(event) => { - handleConfigExclusion( - event, - service, - row, - 'male', - 'gender' - ); - }} - /> - } - label="Male" - /> - - item.speciality_id == row.id && - item.gender?.female == '1' - )} - onChange={(event) => { - handleConfigExclusion( - event, - service, - row, - 'female', - 'gender' - ); - }} - /> - } - label="Female" - /> - - + {/* Dokter external online */} + + { + handleConfigChange(event, service); + }} + name="gp_external_doctor_online" + /> + } + label="Online" + /> + + {/* Dokter internal online */} + + { + handleConfigChange(event, service); + }} + name="gp_internal_doctor_online" + /> + } + label="Online" + /> + + {/* Dokter internal offline */} + + { + handleConfigChange(event, service); + }} + name="gp_internal_doctor_offline" + /> + } + label="Offline" + /> + - - - item.speciality_id == row.id - )?.min_age - } - onChange={(event) => { - handleMinAge(event); - handleChange(index, event, 'min_age', row.id); - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - handleConfigExclusion( - event, - service, - row, - minAge, - 'min_age' - ); - } - }} - /> - - - - item.speciality_id == row.id - )?.max_age - } - onChange={(event) => { - handleMaxAge(event); - handleChange(index, event, 'max_age', row.id); - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - handleConfigExclusion( - event, - service, - row, - maxAge, - 'max_age' - ); - } - }} - /> - - - option.label} - defaultValue={ - convertToArray( - service.exclusions.find( - (item: { speciality_id: any }) => - item.speciality_id == row.id - )?.plan - ) || [] - } - isOptionEqualToValue={(option, value) => - option.value === value.value - } - onChange={(event, value) => { - handlePlanChange(event, value); - handleChange(index, event, 'plan', row.id, value); - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - handleConfigExclusion( - event, - service, - row, - valuePlan, - 'plan' - ); - } - }} - renderInput={(params) => ( - - )} - /> - - - - - - ))} - -
-
-
-
-
- - - - - - - Medicine - - - - - - - { - handleConfigChange(event, service); - }} - name="vitamins" - /> - } - label="Vitamins" - /> - - - { - handleConfigChange(event, service); - }} - name="delivery_fee" - /> - } - label="Delivery Fee" - /> - - - - - -
-
- - - - - - - Free Admin Fee - - - - - - - { - handleConfigChange(event, service); - }} - name="general_practitioner_fee" - /> - } - label="General Practitioner" - /> - - - { - handleConfigChange(event, service); - }} - name="specialist_practitioner_fee" - /> - } - label="Specialist Practitioner" - /> - - - - - -
-
-
- - {/* */} + {/* Dokter external offline */} + + { + handleConfigChange(event, service); + }} + name="gp_external_doctor_offline" + /> + } + label="Offline" + /> + +
+ + {/* Specialist Practitioner* */} + + + + Specialist Practitioner* + + + + + + External Doctor + + + + Internal Doctor + + + {/* Dokter external online */} + + { + handleConfigChange(event, service); + }} + name="sp_external_doctor_online" + /> + } + label="Online" + /> + + {/* Dokter internal online */} + + { + handleConfigChange(event, service); + }} + name="sp_internal_doctor_online" + /> + } + label="Online" + /> + + {/* Dokter internal offline */} + + { + handleConfigChange(event, service); + }} + name="sp_internal_doctor_offline" + /> + } + label="Offline" + /> + + + {/* Dokter external offline */} + + { + handleConfigChange(event, service); + }} + name="sp_external_doctor_offline" + /> + } + label="Offline" + /> + + + + + {/* Medicine */} + + + + Medicine* + + {/* Medicine */} + + { + handleConfigChange(event, service); + }} + name="vitamins" + /> + } + label="Suplemen" + /> + + {/* Dokter internal online */} + + { + handleConfigChange(event, service); + }} + name="delivery_fee" + /> + } + label="Delivery Fee" + /> + + + + + {/* Free Admin Fee* */} + + + + Free Admin Fee* + + + { + handleConfigChange(event, service); + }} + name="general_practitioner_fee" + /> + } + label="General Practitioner" + /> + + + { + handleConfigChange(event, service); + }} + name="specialist_practitioner_fee" + /> + } + label="Specialist Practitioner" + /> + + + + + {/* */} + + + { + setSpecialityModal(false); + }} + sx={{ + '& .MuiDialog-paper': { + width: '100%', + maxWidth: '90%', + maxHeight: '90%', + bgcolor: 'background.paper', + boxShadow: 24, + }, + }} + aria-labelledby="modal-modal-title" + aria-describedby="modal-modal-description" + > + + + + Specialities + + + + + + + + + + + + + + + Specialitation + MSC + Gender + + Min Age + + + Max Age + + Plan + + + + + {specialities.map((row: any, index: any) => ( + + + { + handleToggleSpeciality(event, service, row); + }} + /> + + + {row.name} + + + + + item.speciality_id == row.id && item.msc?.m == '1' + )} + onChange={(event) => { + handleConfigExclusion(event, service, row, 'm', 'msc'); + }} + /> + } + label="Member" + /> + + item.speciality_id == row.id && item.msc?.s == '1' + )} + onChange={(event) => { + handleConfigExclusion(event, service, row, 's', 'msc'); + }} + /> + } + label="Spouse" + /> + + item.speciality_id == row.id && item.msc?.c == '1' + )} + onChange={(event) => { + handleConfigExclusion(event, service, row, 'c', 'msc'); + }} + /> + } + label="Child" + /> + + + + + + item.speciality_id == row.id && + item.gender?.male == '1' + )} + onChange={(event) => { + handleConfigExclusion( + event, + service, + row, + 'male', + 'gender' + ); + }} + /> + } + label="Male" + /> + + item.speciality_id == row.id && + item.gender?.female == '1' + )} + onChange={(event) => { + handleConfigExclusion( + event, + service, + row, + 'female', + 'gender' + ); + }} + /> + } + label="Female" + /> + + + + + + item.speciality_id == row.id + )?.min_age + } + onChange={(event) => { + handleMinAge(event); + handleChange(index, event, 'min_age', row.id); + }} + onKeyDown={(event) => { + if (event.key === 'Enter') { + handleConfigExclusion( + event, + service, + row, + minAge, + 'min_age' + ); + } + }} + /> + + + + item.speciality_id == row.id + )?.max_age + } + onChange={(event) => { + handleMaxAge(event); + handleChange(index, event, 'max_age', row.id); + }} + onKeyDown={(event) => { + if (event.key === 'Enter') { + handleConfigExclusion( + event, + service, + row, + maxAge, + 'max_age' + ); + } + }} + /> + + + option.label} + defaultValue={ + convertToArray( + service.exclusions.find( + (item: { speciality_id: any }) => + item.speciality_id == row.id + )?.plan + ) || [] + } + isOptionEqualToValue={(option, value) => + option.value === value.value + } + onChange={(event, value) => { + handlePlanChange(event, value); + handleChange(index, event, 'plan', row.id, value); + }} + onKeyDown={(event) => { + if (event.key === 'Enter') { + handleConfigExclusion( + event, + service, + row, + valuePlan, + 'plan' + ); + } + }} + renderInput={(params) => ( + + )} + /> + + + + + + ))} + +
+
+
+
+
+
+
+ {/*
*/} + + + + + + + diff --git a/frontend/dashboard/src/pages/Corporates/Services/List.tsx b/frontend/dashboard/src/pages/Corporates/Services/List.tsx index 55d2c285..307f2f2f 100644 --- a/frontend/dashboard/src/pages/Corporates/Services/List.tsx +++ b/frontend/dashboard/src/pages/Corporates/Services/List.tsx @@ -30,17 +30,21 @@ import { Checkbox, FormControlLabel, Tooltip, + Divider, + Grid, } from '@mui/material'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; import AddIcon from '@mui/icons-material/Add'; import UploadIcon from '@mui/icons-material/Upload'; import CancelIcon from '@mui/icons-material/Cancel'; +import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; +import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined'; import HistoryIcon from '@mui/icons-material/History'; // hooks import React, { ChangeEvent, Component, useEffect, useMemo, useRef, useState } from 'react'; import useSettings from '../../../hooks/useSettings'; -import { Link, useParams, useSearchParams } from 'react-router-dom'; +import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'; // components import axios from '../../../utils/axios'; import { LaravelPaginatedData } from '../../../@types/paginated-data'; @@ -48,11 +52,17 @@ import { Icd } from '../../../@types/diagnosis'; import BasePagination from '../../../components/BasePagination'; import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; -import { RHFCheckbox } from '../../../components/hook-form'; -import { CheckBox } from '@mui/icons-material'; +import { FormProvider, RHFTextField, RHFSwitch, RHFSelect } from '../../../components/hook-form'; +import { Add, CheckBox } from '@mui/icons-material'; import { CorporateService } from '../../../@types/corporates'; import { number } from 'yup/lib/locale'; import DialogLog from './sections/DialogLog'; +import TableMoreMenu from '@/components/table/TableMoreMenu'; +import Label from '@/components/Label'; +import DialogUpdateStatus from '@/components/DialogUpdateStatus'; +import palette from '@/theme/palette'; +import { enqueueSnackbar } from 'notistack'; +import { LoadingButton } from '@mui/lab'; export default function List() { const { themeStretch } = useSettings(); @@ -154,9 +164,39 @@ export default function List() { } // Generate the every row of the table + type DataContent = { + code: string; + name: string; + id: string; + status: string|number; + }; + + type DataType = { + code: string; + name: string; + id: string; + } + + type FormValuesProps = { + value: string; + active: boolean; + }; + + const [isDialogOpen, setDialogOpen] = useState(false) + let titles = { + name: 'Update Status', + icon: '-' + } + const [dataValue, setDataValue] = useState(''); + const [dataDescription, setDescriptionValue] = useState(''); + const [url, setUrl] = useState(''); + + // const { id, service_code, status } = data; + function Row(props: { row: ReturnType }) { const { row } = props; const [open, setOpen] = React.useState(false); + const navigate = useNavigate() const handleConfigChange = (event: ChangeEvent, service: any) => { console.log(event.target.name, event.target.checked, service); @@ -168,85 +208,67 @@ export default function List() { }); }; - const handleActivate = (service: any, status: string) => { - axios - .put(`/corporates/${corporate_id}/services/${service.service_code}`, { - service_code: service.service_code, - status, - reason:service.reason - }) - .then((res) => { - setDataTableData({ - ...dataTableData, - data: dataTableData.data.map((service) => { - let updatedService = service; - if (row.id == service.id) { - updatedService.status = res.data.status; - } - return updatedService; - }), - }); - }); + // const handleActivate = (service: any, status: string) => { + // axios + // .put(`/corporates/${corporate_id}/services/${service.service_code}`, { + // service_code: service.service_code, + // status, + // reason:service.reason + // }) + // .then((res) => { + // setDataTableData({ + // ...dataTableData, + // data: dataTableData.data.map((service) => { + // let updatedService = service; + // if (row.id == service.id) { + // updatedService.status = res.data.status; + // } + // return updatedService; + // }), + // }); + // }); + // }; + + const handleActivate = (isOpen: boolean, dataValue: DataContent) => { + setDialogOpen(isOpen) + setDataValue(dataValue) + setDescriptionValue('Are you sure to inactive this service ?') + setUrl(url) }; return ( - *': { borderBottom: 'unset' } }}> - {/* - setOpen(!open)} - > - {open ? : } - - */} + + + + {row.service_code} {row.name} + + {row.status == 'active' ? + : + } + - - {row.status == 'active' && ( - - )} - {row.status == 'inactive' && ( - - )} - - - - - - - - - - - - + + + navigate(`/corporates/${row.corporate_id}/services/${row.service_code}`)}> + + Config + + navigate(`/corporates/${corporate_id}/services/${row.id}/history`)}> + + History + + handleActivate(true, {code: row.service_code, name: row.name, id:corporate_id, status: row.status})}> + + Update Status + + + } /> + {/* COLLAPSIBLE ROW */} {false && ( @@ -682,6 +704,20 @@ export default function List() { fontWeight: 'bold', }; + const onSubmit = async (row : any) => { + try { + handleUpdate(dataValue.status, dataValue.code, row.reason) + } catch (error: any) { + console.log('data gagal'); + } + + const ascent = document?.querySelector('ascent'); + if (ascent != null) { + ascent.innerHTML = ''; + } + }; + + const applyFilter = async (searchFilter: any) => { await loadDataTableData({ search: searchFilter }); setSearchParams({ search: searchFilter }); @@ -697,32 +733,146 @@ export default function List() { loadDataTableData(); }, []); + const NewCorporateSchema = Yup.object().shape({ + reason: Yup.string().required('Reason Edit is required'), + }); + + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + }); + + const { + reset, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + const handleUpdate = (active: string, service_code: string, reason:string) => { + console.log(active) + axios + .put(`/corporates/${corporate_id}/services/${service_code}`, { + service_code: service_code, + status: active, + reason: reason + }) + .then((res) => { + window.location.reload(); + }); + } + + const getContent = () => ( + <> + + Are you sure to {dataValue?.status == 'active' ? 'inactive' : 'active'} this service ? + + + + + Code + + + {dataValue?.code} + + + Service Name + + + {dataValue?.name} + + + + + + Reason for update* + + + + + + + + + + + + + + {dataValue?.status == 'active' ? + + Inactive + + : + + Active + + + + } + + + + + + ); + return ( - - {/* The Main Table */} - + - {/* */} - + + Code - + Service - - + Status - - Action + + {/* Action */} - + {dataTableIsLoading ? ( @@ -750,16 +900,27 @@ export default function List() { - - {isDialog === 'edit' && ( + {/* {isDialog === 'edit' && ( - )} + )} */} + + + + ); } diff --git a/frontend/dashboard/src/pages/Corporates/Services/sections/History.tsx b/frontend/dashboard/src/pages/Corporates/Services/sections/History.tsx index 5e7f7675..b3c74418 100644 --- a/frontend/dashboard/src/pages/Corporates/Services/sections/History.tsx +++ b/frontend/dashboard/src/pages/Corporates/Services/sections/History.tsx @@ -121,11 +121,11 @@ export default function CustomizedAccordions() { }, { name: corporate?.name ?? '-', - href: '/corporate/' + corporate_id + '/services', + href: '/corporates/' + corporate_id + '/services', }, { name: 'Audittrail Corporate', - href: '/corporate/' + corporate_id + '/benefits', + href: '/corporates/' + corporate_id + '/benefits', }, ]} /> diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index e51ed3b7..74ee0341 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -135,6 +135,10 @@ export default function Router() { path: ':corporate_id/benefits/:benefit_id/history', element: , }, + { + path: ':corporate_id/benefits/:benefit_id/edit', + element: , + }, { path: ':corporate_id/members', element: , @@ -440,6 +444,9 @@ const CorporateBenefits = Loadable( const CorporateBenefitsHistory = Loadable( lazy(() => import('../pages/Corporates/Benefit/sections/History')) ); +const CorporateBenefitsEdit = Loadable( + lazy(() => import('../pages/Corporates/Benefit/Create')) +); const CorporatePlanCreate = Loadable( lazy(() => import('../pages/Corporates/CorporatePlan/CreateUpdate')) diff --git a/frontend/dashboard/src/theme/overrides/Table.ts b/frontend/dashboard/src/theme/overrides/Table.ts index d5266c91..d4249380 100644 --- a/frontend/dashboard/src/theme/overrides/Table.ts +++ b/frontend/dashboard/src/theme/overrides/Table.ts @@ -25,7 +25,7 @@ export default function Table(theme: Theme) { color: theme.palette.text.secondary, backgroundColor: theme.palette.background.neutral, '&:first-of-type': { - // paddingLeft: theme.spacing(3), + paddingLeft: theme.spacing(3), borderTopLeftRadius: theme.shape.borderRadius, borderBottomLeftRadius: theme.shape.borderRadius, boxShadow: `inset 8px 0 0 ${theme.palette.background.paper}`, @@ -44,6 +44,7 @@ export default function Table(theme: Theme) { body: { '&:first-of-type': { paddingLeft: theme.spacing(3), + // borderBottom: 'none', }, '&:last-of-type': { paddingRight: theme.spacing(3), diff --git a/frontend/dashboard/src/theme/palette.ts b/frontend/dashboard/src/theme/palette.ts index cc7367af..38249bc1 100644 --- a/frontend/dashboard/src/theme/palette.ts +++ b/frontend/dashboard/src/theme/palette.ts @@ -62,11 +62,11 @@ declare module '@mui/material' { // SETUP COLORS const PRIMARY = { - lighter: '#C8FACD', - light: '#5BE584', - main: '#00AB55', - dark: '#007B55', - darker: '#005249', + lighter: '#D0FBEC', + light: '#70EAD5', + main: '#19BBBB', + dark: '#0C7186', + darker: '#043C59', }; const SECONDARY = { lighter: '#D6E4FF', diff --git a/frontend/hospital-portal/src/components/ThemeColorPresets.tsx b/frontend/hospital-portal/src/components/ThemeColorPresets.tsx index 4f267027..c4145f07 100644 --- a/frontend/hospital-portal/src/components/ThemeColorPresets.tsx +++ b/frontend/hospital-portal/src/components/ThemeColorPresets.tsx @@ -21,7 +21,7 @@ export default function ThemeColorPresets({ children }: Props) { ...defaultTheme, palette: { ...defaultTheme.palette, - primary: setColor, + // primary: setColor, }, customShadows: { ...defaultTheme.customShadows,