add switch corporate & fix table & fix policy
This commit is contained in:
@@ -7,7 +7,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class CorporateController extends Controller
|
class CorporateManageController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
@@ -18,8 +18,6 @@ class CorporateController extends Controller
|
|||||||
$userLogin = Auth::user();
|
$userLogin = Auth::user();
|
||||||
$corporate = $userLogin->managedCorporates()->select(['corporates.id', 'corporates.name'])->get();
|
$corporate = $userLogin->managedCorporates()->select(['corporates.id', 'corporates.name'])->get();
|
||||||
|
|
||||||
// corporate policy, all member list, notification
|
|
||||||
|
|
||||||
return response()->json($corporate);
|
return response()->json($corporate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ use Illuminate\Routing\Controller;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Modules\Client\Transformers\DashboardResources;
|
use Modules\Client\Transformers\DashboardResources;
|
||||||
|
|
||||||
class DashboardController extends Controller
|
class CorporatePolicyController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
@@ -20,7 +20,7 @@ class DashboardController extends Controller
|
|||||||
$currentCorporate = $user->managedCorporates()
|
$currentCorporate = $user->managedCorporates()
|
||||||
->with(['currentPolicy', 'employees'])
|
->with(['currentPolicy', 'employees'])
|
||||||
->find($corporate_id);
|
->find($corporate_id);
|
||||||
|
|
||||||
$data = DashboardResources::make($currentCorporate);
|
$data = DashboardResources::make($currentCorporate);
|
||||||
|
|
||||||
return response()->json($data);
|
return response()->json($data);
|
||||||
@@ -15,17 +15,13 @@ class DivisionController extends Controller
|
|||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
* @return Renderable
|
* @return Renderable
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request, $corporate_id)
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$division = CorporateDivision::query()
|
||||||
|
->where('corporate_id', $corporate_id)
|
||||||
$corporate = $user->managedCorporates()->where('active', 1)->first();
|
|
||||||
|
|
||||||
$benefits = CorporateDivision::query()
|
|
||||||
->where('corporate_id', $corporate->id)
|
|
||||||
->get(['id', 'name']);
|
->get(['id', 'name']);
|
||||||
|
|
||||||
return $benefits;
|
return response()->json($division);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Models\Member;
|
|||||||
use Illuminate\Contracts\Support\Renderable;
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
|
use Modules\Client\Transformers\MemberResources;
|
||||||
|
|
||||||
class MemberController extends Controller
|
class MemberController extends Controller
|
||||||
{
|
{
|
||||||
@@ -14,29 +15,25 @@ class MemberController extends Controller
|
|||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
* @return Renderable
|
* @return Renderable
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request, $corporate_id)
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$limit = $request->has('per_page') ? $request->per_page : 10;
|
||||||
|
|
||||||
$corporate = $user->managedCorporates()->first();
|
|
||||||
// $plans =
|
|
||||||
|
|
||||||
$members = Member::query()
|
$members = Member::query()
|
||||||
->whereHas('employeds', function($corporateEmployee) use ($corporate) {
|
->whereHas('employeds', function ($corporateEmployee) use ($corporate_id) {
|
||||||
$corporateEmployee->where('corporate_id', $corporate->id);
|
$corporateEmployee->where('corporate_id', $corporate_id);
|
||||||
});
|
})->when($request->input('division'), function ($division, $division_id) {
|
||||||
if ($request->has('search')) {
|
$division->whereHas('division', function ($corporateEmployee) use ($division_id) {
|
||||||
$members
|
$corporateEmployee->where('division_id', $division_id);
|
||||||
->where('member_id', 'like', "%" . $request->search . "%")
|
});
|
||||||
->orWhere('payor_id', 'like', "%" . $request->search . "%")
|
})->when($request->input('search'), function ($query, $search) {
|
||||||
->orWhere('name', 'like', "%" . $request->search . "%");
|
$query->where('member_id', 'like', "%" . $search . "%")
|
||||||
}
|
->orWhere('name', 'like', "%" . $search . "%");
|
||||||
|
})->when($request->has('orderBy'), function ($query) use ($request) {
|
||||||
|
$query->orderBy($request->orderBy, $request->order);
|
||||||
|
})->paginate($limit);
|
||||||
|
|
||||||
$members = $members->paginate();
|
return response()->json(Helper::paginateResources(MemberResources::collection($members)));
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'members' => Helper::paginateResources($members)
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Modules\Client\Http\Controllers\Api\AuthController;
|
use Modules\Client\Http\Controllers\Api\AuthController;
|
||||||
use Modules\Client\Http\Controllers\Api\CorporateController;
|
use Modules\Client\Http\Controllers\Api\CorporateManageController;
|
||||||
use Modules\Client\Http\Controllers\Api\DashboardController;
|
use Modules\Client\Http\Controllers\Api\CorporatePolicyController;
|
||||||
use Modules\Client\Http\Controllers\Api\DivisionController;
|
use Modules\Client\Http\Controllers\Api\DivisionController;
|
||||||
use Modules\Client\Http\Controllers\Api\MemberController;
|
use Modules\Client\Http\Controllers\Api\MemberController;
|
||||||
use Modules\Client\Http\Controllers\Api\UserController;
|
use Modules\Client\Http\Controllers\Api\UserController;
|
||||||
@@ -28,19 +28,13 @@ Route::prefix('client')->group(function () {
|
|||||||
Route::middleware('auth:sanctum')->group(function () {
|
Route::middleware('auth:sanctum')->group(function () {
|
||||||
|
|
||||||
Route::post('logout', [AuthController::class, 'logout'])->name('logout');
|
Route::post('logout', [AuthController::class, 'logout'])->name('logout');
|
||||||
Route::get('user', [UserController::class, 'index']);
|
Route::get('user', [UserController::class, 'index']);
|
||||||
|
|
||||||
Route::prefix('{corporate_id}')->group(function() {
|
Route::get('corporate-manage', [CorporateManageController::class, 'index']);
|
||||||
Route::get('asd', function ($corporate_id) {
|
Route::prefix('{corporate_id}')->group(function () {
|
||||||
return $corporate_id;
|
Route::get('policy', [CorporatePolicyController::class, 'index']);
|
||||||
|
Route::get('division', [DivisionController::class, 'index']);
|
||||||
|
Route::get('members', [MemberController::class, 'index']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Route::get('dashboard', [DashboardController::class, 'index']);
|
|
||||||
Route::get('corporate', [CorporateController::class, 'index']);
|
|
||||||
Route::get('corporate/{corporate_id}', [CorporateController::class, 'show']);
|
|
||||||
Route::get('division', [DivisionController::class, 'index']);
|
|
||||||
Route::get('members', [MemberController::class, 'index']);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,9 +16,13 @@ class MemberResources extends JsonResource
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'memberId' => $this->member_id,
|
'memberId' => $this->member_id,
|
||||||
'full_name' => $this->full_name,
|
'fullName' => $this->full_name,
|
||||||
'division' => $this->division->name,
|
'division' => $this->division->name,
|
||||||
'employeeLimit' => '',
|
'limit' => [
|
||||||
|
'current' => 2000000,
|
||||||
|
'total' => 4000000,
|
||||||
|
'percentage' => (2000000 / 4000000) * 100
|
||||||
|
],
|
||||||
'status' => $this->active
|
'status' => $this->active
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,11 +183,6 @@ class Member extends Model
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function corporateEmployee()
|
|
||||||
// {
|
|
||||||
// return $this->hasOne(CorporateEmployee::class, 'member_id');
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function division()
|
public function division()
|
||||||
{
|
{
|
||||||
return $this->hasOneThrough(CorporateDivision::class, CorporateEmployee::class, 'member_id', 'id', 'id', 'division_id');
|
return $this->hasOneThrough(CorporateDivision::class, CorporateEmployee::class, 'member_id', 'id', 'id', 'division_id');
|
||||||
|
|||||||
8
frontend/client-portal/src/contexts/UserCurrentCorporate.tsx
Executable file
8
frontend/client-portal/src/contexts/UserCurrentCorporate.tsx
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
const UserCurrentCorporateContext = createContext({
|
||||||
|
corporateValue: '',
|
||||||
|
setCorporateValue: (value: string) => Promise<void>,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { UserCurrentCorporateContext };
|
||||||
48
frontend/client-portal/src/layouts/dashboard/header/CorporatePopover.tsx
Executable file
48
frontend/client-portal/src/layouts/dashboard/header/CorporatePopover.tsx
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';
|
||||||
|
import { useContext, useEffect, useState } from 'react';
|
||||||
|
import { UserCurrentCorporateContext } from '../../../contexts/UserCurrentCorporate';
|
||||||
|
import axios from '../../../utils/axios';
|
||||||
|
|
||||||
|
/* ---------------------------------- types --------------------------------- */
|
||||||
|
type CorporateDataProps = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
export default function CorporatePopover() {
|
||||||
|
const { corporateValue, setCorporateValue } = useContext(UserCurrentCorporateContext);
|
||||||
|
const [corporateData, setCorporateData] = useState([]);
|
||||||
|
|
||||||
|
const handleCorporateChange = (event: SelectChangeEvent) => {
|
||||||
|
setCorporateValue(event.target.value as string);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
// @ts-ignore
|
||||||
|
const corporateManages = await axios.get(`/corporate-manage`);
|
||||||
|
setCorporateData(corporateManages.data);
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<InputLabel id="simple-corporate-select-lable">Corporate</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="simple-corporate-select-lable"
|
||||||
|
id="corporate-select-lable"
|
||||||
|
value={corporateValue}
|
||||||
|
label="Corporate"
|
||||||
|
defaultValue={corporateValue}
|
||||||
|
onChange={handleCorporateChange}
|
||||||
|
>
|
||||||
|
{corporateData.map((row: CorporateDataProps, index) => (
|
||||||
|
<MenuItem key={index} value={row.id}>
|
||||||
|
{row.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import AccountPopover from './AccountPopover';
|
|||||||
import LanguagePopover from './LanguagePopover';
|
import LanguagePopover from './LanguagePopover';
|
||||||
import ContactsPopover from './ContactsPopover';
|
import ContactsPopover from './ContactsPopover';
|
||||||
import NotificationsPopover from './NotificationsPopover';
|
import NotificationsPopover from './NotificationsPopover';
|
||||||
|
import CorporatePopover from './CorporatePopover';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -92,6 +93,7 @@ export default function DashboardHeader({
|
|||||||
<Box sx={{ flexGrow: 1 }} />
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
|
|
||||||
<Stack direction="row" alignItems="center" spacing={{ xs: 0.5, sm: 1.5 }}>
|
<Stack direction="row" alignItems="center" spacing={{ xs: 0.5, sm: 1.5 }}>
|
||||||
|
<CorporatePopover />
|
||||||
<LanguagePopover />
|
<LanguagePopover />
|
||||||
<NotificationsPopover />
|
<NotificationsPopover />
|
||||||
<ContactsPopover />
|
<ContactsPopover />
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import { HEADER, NAVBAR } from '../../config';
|
|||||||
import DashboardHeader from './header';
|
import DashboardHeader from './header';
|
||||||
import NavbarVertical from './navbar/NavbarVertical';
|
import NavbarVertical from './navbar/NavbarVertical';
|
||||||
import NavbarHorizontal from './navbar/NavbarHorizontal';
|
import NavbarHorizontal from './navbar/NavbarHorizontal';
|
||||||
|
import useLocalStorage from '../../hooks/useLocalStorage';
|
||||||
|
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||||
|
import useAuth from '../../hooks/useAuth';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -47,6 +50,7 @@ export default function DashboardLayout() {
|
|||||||
const { collapseClick, isCollapse } = useCollapseDrawer();
|
const { collapseClick, isCollapse } = useCollapseDrawer();
|
||||||
|
|
||||||
const { themeLayout } = useSettings();
|
const { themeLayout } = useSettings();
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
const isDesktop = useResponsive('up', 'lg');
|
const isDesktop = useResponsive('up', 'lg');
|
||||||
|
|
||||||
@@ -54,6 +58,12 @@ export default function DashboardLayout() {
|
|||||||
|
|
||||||
const verticalLayout = themeLayout === 'vertical';
|
const verticalLayout = themeLayout === 'vertical';
|
||||||
|
|
||||||
|
const [corporateValue, setCorporateValue] = useLocalStorage(
|
||||||
|
'corporateValue',
|
||||||
|
`${user.corporate.id}`
|
||||||
|
);
|
||||||
|
const value = { corporateValue, setCorporateValue };
|
||||||
|
|
||||||
if (verticalLayout) {
|
if (verticalLayout) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -86,19 +96,21 @@ export default function DashboardLayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<UserCurrentCorporateContext.Provider value={value}>
|
||||||
sx={{
|
<Box
|
||||||
display: { lg: 'flex' },
|
sx={{
|
||||||
minHeight: { lg: 1 },
|
display: { lg: 'flex' },
|
||||||
}}
|
minHeight: { lg: 1 },
|
||||||
>
|
}}
|
||||||
<DashboardHeader isCollapse={isCollapse} onOpenSidebar={() => setOpen(true)} />
|
>
|
||||||
|
<DashboardHeader isCollapse={isCollapse} onOpenSidebar={() => setOpen(true)} />
|
||||||
|
|
||||||
<NavbarVertical isOpenSidebar={open} onCloseSidebar={() => setOpen(false)} />
|
<NavbarVertical isOpenSidebar={open} onCloseSidebar={() => setOpen(false)} />
|
||||||
|
|
||||||
<MainStyle collapseClick={collapseClick}>
|
<MainStyle collapseClick={collapseClick}>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</MainStyle>
|
</MainStyle>
|
||||||
</Box>
|
</Box>
|
||||||
|
</UserCurrentCorporateContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
// @mui
|
// @mui
|
||||||
import {
|
import { Typography, Container, Grid } from '@mui/material';
|
||||||
Typography,
|
|
||||||
Container,
|
|
||||||
Grid,
|
|
||||||
FormControl,
|
|
||||||
InputLabel,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
} from '@mui/material';
|
|
||||||
// hooks
|
// hooks
|
||||||
import useSettings from '../../hooks/useSettings';
|
import useSettings from '../../hooks/useSettings';
|
||||||
// components
|
// components
|
||||||
@@ -16,11 +8,10 @@ import Page from '../../components/Page';
|
|||||||
import CardNotification from '../../sections/dashboard/CardNotification';
|
import CardNotification from '../../sections/dashboard/CardNotification';
|
||||||
import CardBalance from '../../sections/dashboard/CardBalance';
|
import CardBalance from '../../sections/dashboard/CardBalance';
|
||||||
import TableList from '../../sections/dashboard/TableList';
|
import TableList from '../../sections/dashboard/TableList';
|
||||||
import { useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import axios from '../../utils/axios';
|
import axios from '../../utils/axios';
|
||||||
import { Stack } from '@mui/system';
|
import { Stack } from '@mui/system';
|
||||||
import { SelectChangeEvent } from '@mui/material/Select';
|
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||||
import useAuth from '../../hooks/useAuth';
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -35,12 +26,7 @@ const itemList = [
|
|||||||
|
|
||||||
/* ---------------------------------- types --------------------------------- */
|
/* ---------------------------------- types --------------------------------- */
|
||||||
|
|
||||||
type CorporateDataProps = {
|
type PolicyProps = {
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type CardBalanceProps = {
|
|
||||||
myLimit: {
|
myLimit: {
|
||||||
balance: number;
|
balance: number;
|
||||||
total: number;
|
total: number;
|
||||||
@@ -54,42 +40,35 @@ type CardBalanceProps = {
|
|||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------------ default data ------------------------------ */
|
||||||
|
const defaultPolicyData = {
|
||||||
|
myLimit: {
|
||||||
|
balance: 0,
|
||||||
|
total: 0,
|
||||||
|
percentage: 0,
|
||||||
|
},
|
||||||
|
lockLimit: {
|
||||||
|
balance: 0,
|
||||||
|
percentage: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const { themeStretch } = useSettings();
|
const { themeStretch } = useSettings();
|
||||||
const { user } = useAuth();
|
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||||
const [currentCorporate, setCurrentCorporate] = useState({id: 1});
|
|
||||||
|
|
||||||
// @ts-ignore
|
// const [tableData, setTableData] = useState([]);
|
||||||
const [corporateValue, setCorporateValue] = useState(`${user.corporate.id}`);
|
const [policyData, setPolicyData] = useState<PolicyProps>(defaultPolicyData);
|
||||||
const [corporateData, setCorporateData] = useState([]);
|
|
||||||
const [tableData, setTableData] = useState([]);
|
|
||||||
const [policyData, setPolicyData] = useState<CardBalanceProps>({
|
|
||||||
myLimit: {
|
|
||||||
balance: 0,
|
|
||||||
total: 0,
|
|
||||||
percentage: 0,
|
|
||||||
},
|
|
||||||
lockLimit: {
|
|
||||||
balance: 0,
|
|
||||||
percentage: 0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleCorporateChange = (event: SelectChangeEvent) => {
|
|
||||||
setCorporateValue(event.target.value as string);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const corporates = await axios.get(`${currentCorporate.id}/dashboard`);
|
setPolicyData(defaultPolicyData);
|
||||||
const dashboard = await axios.get(`${currentCorporate.id}/dashboard`);
|
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||||
|
const dashboard = await axios.get(`${corporateValue}/policy`);
|
||||||
console.log(dashboard);
|
|
||||||
|
|
||||||
setCorporateData(corporates.data);
|
|
||||||
setPolicyData(dashboard.data.policy);
|
setPolicyData(dashboard.data.policy);
|
||||||
})();
|
})();
|
||||||
}, [user, corporateValue]);
|
}, [corporateValue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title="Dashboard">
|
<Page title="Dashboard">
|
||||||
@@ -98,24 +77,6 @@ export default function Dashboard() {
|
|||||||
<Typography variant="h3" component="h1" paragraph>
|
<Typography variant="h3" component="h1" paragraph>
|
||||||
Dashboard
|
Dashboard
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<InputLabel id="simple-corporate-select-lable">Corporate</InputLabel>
|
|
||||||
<Select
|
|
||||||
labelId="simple-corporate-select-lable"
|
|
||||||
id="corporate-select-lable"
|
|
||||||
value={corporateValue}
|
|
||||||
label="Corporate"
|
|
||||||
defaultValue={corporateValue}
|
|
||||||
onChange={handleCorporateChange}
|
|
||||||
>
|
|
||||||
{corporateData.map((row: CorporateDataProps, index) => (
|
|
||||||
<MenuItem key={index} value={row.id}>
|
|
||||||
{row.name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
|
|||||||
@@ -83,11 +83,7 @@ export default function Login() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<VerifyCodeForm
|
<VerifyCodeForm emailOrPhone={emailOrPhone} />
|
||||||
setEmailOrPhoneForm={setEmailOrPhoneForm}
|
|
||||||
setLoginOrVerifyCode={setLoginOrVerifyCode}
|
|
||||||
emailOrPhone={emailOrPhone}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack sx={{ marginTop: 5 }} spacing={1} alignItems="center">
|
<Stack sx={{ marginTop: 5 }} spacing={1} alignItems="center">
|
||||||
<Typography>Tidak mendapatkan kode?</Typography>
|
<Typography>Tidak mendapatkan kode?</Typography>
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import useAuth from '../../../hooks/useAuth';
|
|||||||
|
|
||||||
type VerifyCodeFormProps = {
|
type VerifyCodeFormProps = {
|
||||||
emailOrPhone: string;
|
emailOrPhone: string;
|
||||||
setEmailOrPhoneForm: Function;
|
|
||||||
setLoginOrVerifyCode: Function;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type FormValuesProps = {
|
type FormValuesProps = {
|
||||||
@@ -39,11 +37,7 @@ type responseProps = {
|
|||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
export default function VerifyCodeForm({
|
export default function VerifyCodeForm({ emailOrPhone }: VerifyCodeFormProps) {
|
||||||
emailOrPhone,
|
|
||||||
setEmailOrPhoneForm,
|
|
||||||
setLoginOrVerifyCode,
|
|
||||||
}: VerifyCodeFormProps) {
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { validateOtp } = useAuth();
|
const { validateOtp } = useAuth();
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import Iconify from '../../components/Iconify';
|
|||||||
// React
|
// React
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
// utils
|
// utils
|
||||||
import { fCurrency } from '../../utils/formatNumber';
|
import { fCurrency, fSplit } from '../../utils/formatNumber';
|
||||||
/* -------------------------------- sections -------------------------------- */
|
/* -------------------------------- sections -------------------------------- */
|
||||||
import DialogTopUpLimit from './DialogTopUpLimit';
|
import DialogTopUpLimit from './DialogTopUpLimit';
|
||||||
import DialogClaimSubmitMember from './DialogClaimSubmitMember';
|
import DialogClaimSubmitMember from './DialogClaimSubmitMember';
|
||||||
@@ -97,7 +97,7 @@ export default function CardBalance(props: CardBalanceProps) {
|
|||||||
{fCurrency(myLimit ? myLimit.balance : 0)}
|
{fCurrency(myLimit ? myLimit.balance : 0)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography sx={{ typography: 'caption', color: '#919EAB' }}>
|
<Typography sx={{ typography: 'caption', color: '#919EAB' }}>
|
||||||
/ {myLimit ? myLimit.total : 0}
|
/ {fSplit(myLimit ? myLimit.total : 0)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ export default function CardBalance(props: CardBalanceProps) {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
||||||
{lockLimit ? lockLimit.balance : 0} / {myLimit ? myLimit.total : 0}
|
{fSplit(lockLimit ? lockLimit.balance : 0)} / {fSplit(myLimit ? myLimit.total : 0)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* ---------------------------------- @mui ---------------------------------- */
|
/* ---------------------------------- @mui ---------------------------------- */
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
import {
|
import {
|
||||||
Paper,
|
Paper,
|
||||||
Table,
|
Table,
|
||||||
@@ -19,19 +20,25 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
SelectChangeEvent,
|
SelectChangeEvent,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
LinearProgress,
|
||||||
|
linearProgressClasses,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { visuallyHidden } from '@mui/utils';
|
import { visuallyHidden } from '@mui/utils';
|
||||||
import { Add as AddIcon } from '@mui/icons-material';
|
import { Add as AddIcon } from '@mui/icons-material';
|
||||||
/* ---------------------------------- axios --------------------------------- */
|
/* ---------------------------------- axios --------------------------------- */
|
||||||
import axios from '../../utils/axios';
|
import axios from '../../utils/axios';
|
||||||
/* ---------------------------------- react --------------------------------- */
|
/* ---------------------------------- react --------------------------------- */
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useContext, useEffect, useRef, useState } from 'react';
|
||||||
/* -------------------------------- component ------------------------------- */
|
/* -------------------------------- component ------------------------------- */
|
||||||
import Iconify from '../../components/Iconify';
|
import Iconify from '../../components/Iconify';
|
||||||
import BaseTablePagination from '../../components/BaseTablePagination';
|
import BaseTablePagination from '../../components/BaseTablePagination';
|
||||||
/* ---------------------------------- theme --------------------------------- */
|
/* ---------------------------------- theme --------------------------------- */
|
||||||
import palette from '../../theme/palette';
|
import palette from '../../theme/palette';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||||
|
import { fSplit } from '../../utils/formatNumber';
|
||||||
|
|
||||||
/* ---------------------------------- types --------------------------------- */
|
/* ---------------------------------- types --------------------------------- */
|
||||||
type PaginationTableProps = {
|
type PaginationTableProps = {
|
||||||
@@ -46,11 +53,15 @@ type PaginationTableProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type DataTableProps = {
|
type DataTableProps = {
|
||||||
name: string;
|
fullName: string;
|
||||||
member_id: string;
|
memberId: string;
|
||||||
division: string;
|
division: string;
|
||||||
limit: string;
|
limit: {
|
||||||
status: string;
|
current: number;
|
||||||
|
total: number;
|
||||||
|
percentage: number;
|
||||||
|
};
|
||||||
|
status: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Order = 'asc' | 'desc';
|
type Order = 'asc' | 'desc';
|
||||||
@@ -74,6 +85,20 @@ type DivisionDataProps = {
|
|||||||
};
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* --------------------------------- styled --------------------------------- */
|
||||||
|
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 6,
|
||||||
|
[`&.${linearProgressClasses.colorPrimary}`]: {
|
||||||
|
backgroundColor: '#D1F1F1',
|
||||||
|
},
|
||||||
|
[`& .${linearProgressClasses.bar}`]: {
|
||||||
|
borderRadius: 6,
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* -------------------------- enchanced table head -------------------------- */
|
/* -------------------------- enchanced table head -------------------------- */
|
||||||
const headCells: readonly HeadCell[] = [
|
const headCells: readonly HeadCell[] = [
|
||||||
{
|
{
|
||||||
@@ -92,16 +117,16 @@ const headCells: readonly HeadCell[] = [
|
|||||||
id: 'division',
|
id: 'division',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
label: 'Divisi',
|
label: 'Divisi',
|
||||||
isSort: true,
|
isSort: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'limit',
|
id: 'limit',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
label: 'Limit',
|
label: 'Limit',
|
||||||
isSort: true,
|
isSort: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'status',
|
id: 'active',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
isSort: true,
|
isSort: true,
|
||||||
@@ -150,14 +175,9 @@ function EnhancedTableHead({ order, orderBy, onRequestSort }: EnhancedTableProps
|
|||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
export default function TableList(props: any) {
|
export default function TableList(props: any) {
|
||||||
const [order, setOrder] = useState<Order>('asc');
|
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||||
const [orderBy, setOrderBy] = useState('name');
|
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [dataTable, setDataTable] = useState([]);
|
const [dataTable, setDataTable] = useState([]);
|
||||||
const [page, setPage] = useState(0);
|
|
||||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
|
||||||
const [appliedParams, setAppliedParams] = useState({});
|
|
||||||
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
|
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
|
||||||
current_page: 0,
|
current_page: 0,
|
||||||
from: 0,
|
from: 0,
|
||||||
@@ -169,6 +189,15 @@ export default function TableList(props: any) {
|
|||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const [appliedParams, setAppliedParams] = useState({});
|
||||||
|
|
||||||
|
const [order, setOrder] = useState<Order>('asc');
|
||||||
|
const [orderBy, setOrderBy] = useState('name');
|
||||||
|
const [page, setPage] = useState(0);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||||
|
|
||||||
/* ------------------------------- handle sort ------------------------------ */
|
/* ------------------------------- handle sort ------------------------------ */
|
||||||
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
||||||
const isAsc = orderBy === property && order === 'asc';
|
const isAsc = orderBy === property && order === 'asc';
|
||||||
@@ -211,9 +240,15 @@ export default function TableList(props: any) {
|
|||||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]);
|
if (searchText === '') {
|
||||||
|
searchParams.delete('search');
|
||||||
|
const params = Object.fromEntries([...searchParams.entries()]);
|
||||||
|
setAppliedParams(params);
|
||||||
|
} else {
|
||||||
|
const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]);
|
||||||
|
setAppliedParams(params);
|
||||||
|
}
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
setAppliedParams(params);
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -275,7 +310,7 @@ export default function TableList(props: any) {
|
|||||||
(async () => {
|
(async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const division = await axios.get('/division');
|
const division = await axios.get(`${corporateValue}/division`);
|
||||||
setDivisionData(division.data);
|
setDivisionData(division.data);
|
||||||
|
|
||||||
const params =
|
const params =
|
||||||
@@ -283,19 +318,17 @@ export default function TableList(props: any) {
|
|||||||
? appliedParams
|
? appliedParams
|
||||||
: Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]);
|
: Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]);
|
||||||
|
|
||||||
const response = await axios.get('/dashboard', {
|
const corporateMembers = await axios.get(`${corporateValue}/members`, {
|
||||||
params: params,
|
params,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
setSearchParams(params);
|
setSearchParams(params);
|
||||||
// setDataTable(response.data.data);
|
setDataTable(corporateMembers.data.data);
|
||||||
// setPaginationTable(response.data.meta);
|
// setPaginationTable(response.data.meta);
|
||||||
// setRowsPerPage(response.data.meta.per_page);
|
// setRowsPerPage(response.data.meta.per_page);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
})();
|
})();
|
||||||
}, [appliedParams, searchParams, order, orderBy, setSearchParams]);
|
}, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
@@ -388,12 +421,23 @@ export default function TableList(props: any) {
|
|||||||
) : dataTable.length >= 1 ? (
|
) : dataTable.length >= 1 ? (
|
||||||
dataTable.map((row: DataTableProps, index) => (
|
dataTable.map((row: DataTableProps, index) => (
|
||||||
<TableRow key={index}>
|
<TableRow key={index}>
|
||||||
<TableCell align="left">{row.member_id}</TableCell>
|
<TableCell align="left">{row.memberId}</TableCell>
|
||||||
<TableCell align="center">{row.name}</TableCell>
|
<TableCell align="center">{row.fullName}</TableCell>
|
||||||
<TableCell align="center">{row.division}</TableCell>
|
<TableCell align="center">{row.division}</TableCell>
|
||||||
<TableCell align="center">{row.limit}</TableCell>
|
<TableCell align="center" width={170}>
|
||||||
|
<Stack>
|
||||||
|
<BorderLinearProgress
|
||||||
|
variant="determinate"
|
||||||
|
value={row.limit.percentage}
|
||||||
|
sx={{ mb: 1 }}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
||||||
|
{fSplit(row.limit.current)} / {fSplit(row.limit.total)}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</TableCell>
|
||||||
<TableCell align="center">
|
<TableCell align="center">
|
||||||
{row.status.toLowerCase() === 'active' ? (
|
{row.status === 1 ? (
|
||||||
<Button
|
<Button
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: 'rgba(84, 214, 44, 0.16)',
|
backgroundColor: 'rgba(84, 214, 44, 0.16)',
|
||||||
@@ -405,7 +449,7 @@ export default function TableList(props: any) {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{row.status}
|
Active
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
@@ -419,7 +463,7 @@ export default function TableList(props: any) {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{row.status}
|
Inactive
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ export function fCurrency(number: string | number) {
|
|||||||
return numeral(number).format('$0,0');
|
return numeral(number).format('$0,0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fSplit(number: string | number) {
|
||||||
|
return numeral(number).format('0,0');
|
||||||
|
}
|
||||||
|
|
||||||
export function fPercent(number: number) {
|
export function fPercent(number: number) {
|
||||||
return numeral(number / 100).format('0.0%');
|
return numeral(number / 100).format('0.0%');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user