Merge branch 'feature/client-portal-dashboard' into staging
This commit is contained in:
@@ -3,50 +3,26 @@
|
|||||||
namespace Modules\Client\Http\Controllers\Api;
|
namespace Modules\Client\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Member;
|
use App\Services\CorporateMemberService;
|
||||||
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;
|
use Modules\Client\Transformers\Dashboard\MemberResources;
|
||||||
|
|
||||||
class CorporateMemberController extends Controller
|
class CorporateMemberController extends Controller
|
||||||
{
|
{
|
||||||
|
public function __construct(public CorporateMemberService $corporateMemberService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
* @return Renderable
|
* @return Renderable
|
||||||
*/
|
*/
|
||||||
public function index(Request $request, $corporate_id)
|
public function index(Request $request, $corporate_id)
|
||||||
{
|
{
|
||||||
$limit = $request->has('per_page') ? $request->per_page : 10;
|
$members = $this->corporateMemberService->getAllDashboardMembers($corporate_id, $request);
|
||||||
|
|
||||||
$members = Member::query()
|
|
||||||
->whereHas('employeds', function ($corporateEmployee) use ($corporate_id) {
|
|
||||||
$corporateEmployee->where('corporate_id', $corporate_id);
|
|
||||||
})->when($request->input('search'), function ($query, $search) {
|
|
||||||
$query->where('member_id', 'like', "%" . $search . "%")
|
|
||||||
->orWhere('name', 'like', "%" . $search . "%");
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($request->input('claimMember') === 'false') {
|
|
||||||
$members = $members->when($request->input('division'), function ($division, $division_id) {
|
|
||||||
$division->whereHas('division', function ($corporateEmployee) use ($division_id) {
|
|
||||||
$corporateEmployee->where('division_id', $division_id);
|
|
||||||
});
|
|
||||||
})->when($request->has('orderBy'), function ($query) use ($request) {
|
|
||||||
$query->orderBy($request->orderBy, $request->order);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// else {
|
|
||||||
// $members = $members->get();
|
|
||||||
|
|
||||||
// return response()->json(MemberResources::collection($members));
|
|
||||||
// }
|
|
||||||
$members->with('currentPlan');
|
|
||||||
$members->withSum('claims', 'total_claim');
|
|
||||||
|
|
||||||
$members = $members->paginate($limit);
|
|
||||||
// return $members;
|
|
||||||
|
|
||||||
return response()->json(Helper::paginateResources(MemberResources::collection($members)));
|
return response()->json(Helper::paginateResources(MemberResources::collection($members)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
namespace Modules\Client\Http\Controllers\Api;
|
namespace Modules\Client\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\Helper;
|
||||||
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 Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Modules\Client\Transformers\DashboardResources;
|
use Modules\Client\Transformers\Dashboard\LimitResources;
|
||||||
|
|
||||||
class CorporatePolicyController extends Controller
|
class CorporatePolicyController extends Controller
|
||||||
{
|
{
|
||||||
@@ -16,14 +17,13 @@ class CorporatePolicyController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request, $corporate_id)
|
public function index(Request $request, $corporate_id)
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$currentCorporate = Auth::user()->managedCorporates()
|
||||||
$currentCorporate = $user->managedCorporates()
|
|
||||||
->with(['currentPolicy', 'employees'])
|
->with(['currentPolicy', 'employees'])
|
||||||
->find($corporate_id);
|
->find($corporate_id);
|
||||||
|
|
||||||
$data = DashboardResources::make($currentCorporate);
|
$data = LimitResources::make($currentCorporate);
|
||||||
|
|
||||||
return response()->json($data);
|
return Helper::responseJson($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Client\Transformers;
|
namespace Modules\Client\Transformers\Dashboard;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
class DashboardResources extends JsonResource
|
class LimitResources extends JsonResource
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Transform the resource into an array.
|
* Transform the resource into an array.
|
||||||
@@ -22,17 +21,15 @@ class DashboardResources extends JsonResource
|
|||||||
$lockPercentage = (int)$this->currentPolicy->minimal_stop_service_percentage;
|
$lockPercentage = (int)$this->currentPolicy->minimal_stop_service_percentage;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'policy' => [
|
'myLimit' => [
|
||||||
'myLimit' => [
|
'balance' => $myLimitBalance,
|
||||||
'balance' => $myLimitBalance,
|
'total' => $myLimitTotal,
|
||||||
'total' => $myLimitTotal,
|
'percentage' => $myLimitTotal ? round(($myLimitBalance / $myLimitTotal) * 100, 2) : 0,
|
||||||
'percentage' => $myLimitTotal ? (($myLimitBalance / $myLimitTotal) * 100) : 0,
|
|
||||||
],
|
|
||||||
'lockLimit' => [
|
|
||||||
'balance' => $lockBalance,
|
|
||||||
'percentage' => $lockPercentage
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
|
'lockLimit' => [
|
||||||
|
'balance' => $lockBalance,
|
||||||
|
'percentage' => $lockPercentage
|
||||||
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Client\Transformers;
|
namespace Modules\Client\Transformers\Dashboard;
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
@@ -18,15 +18,13 @@ class MemberResources extends JsonResource
|
|||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'memberId' => $this->member_id,
|
'memberId' => $this->member_id,
|
||||||
'fullName' => $this->full_name,
|
'fullName' => $this->full_name,
|
||||||
$this->mergeWhen($request->input('claimMember') === 'false', [
|
'division' => $this->division_name ?? '',
|
||||||
'division' => $this->division->name ?? '',
|
|
||||||
'status' => $this->active
|
|
||||||
]),
|
|
||||||
'limit' => [
|
'limit' => [
|
||||||
'current' => $this->claims_sum_total_claim,
|
'current' => $this->claims_sum_total_claim,
|
||||||
'total' => $this->currentPlan->limit_rules ?? 0,
|
'total' => $this->currentPlan->limit_rules ?? 0,
|
||||||
'percentage' => (!empty($this->currentPlan->limit_rules ?? 0)) ? (($this->claims_sum_total_claim / $this->currentPlan->limit_rules) * 100) : 0
|
'percentage' => (!empty($this->currentPlan->limit_rules ?? 0)) ? (($this->claims_sum_total_claim / $this->currentPlan->limit_rules) * 100) : 0
|
||||||
],
|
],
|
||||||
|
'status' => $this->active,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
49
app/Services/CorporateMemberService.php
Normal file
49
app/Services/CorporateMemberService.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\Member;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class CorporateMemberService
|
||||||
|
{
|
||||||
|
public function getAllDashboardMembers(int $corporateId, Request $request)
|
||||||
|
{
|
||||||
|
$limit = $request->has('perPage') ? $request->input('perPage') : 10;
|
||||||
|
|
||||||
|
return Member::query()
|
||||||
|
->select(['members.id', 'members.person_id', 'members.member_id', 'members.name', 'members.name_prefix', 'members.name_suffix', 'corporate_divisions.name AS division_name', 'members.active'])
|
||||||
|
->leftJoin('corporate_employees', 'members.id', '=', 'corporate_employees.member_id')
|
||||||
|
->leftJoin('corporate_divisions', 'corporate_employees.division_id', '=', 'corporate_divisions.id')
|
||||||
|
->with('currentPlan')
|
||||||
|
->withSum('claims', 'total_claim')
|
||||||
|
->whereHas('employeds', function (Builder $corporateEmployee) use ($corporateId) {
|
||||||
|
$corporateEmployee->where('corporate_id', $corporateId);
|
||||||
|
})
|
||||||
|
->when($request->input('search'), function (Builder $query, $search) {
|
||||||
|
$query->where('member_id', 'like', "%" . $search . "%")
|
||||||
|
->orWhere('name', 'like', "%" . $search . "%");
|
||||||
|
})
|
||||||
|
->when($request->input('division'), function (Builder $division, $division_id) {
|
||||||
|
$division->whereHas('division', function ($corporateEmployee) use ($division_id) {
|
||||||
|
$corporateEmployee->where('division_id', $division_id);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
->when($request->has('orderBy'), function (Builder $query) use ($request) {
|
||||||
|
$orderBy = match ($request->orderBy) {
|
||||||
|
'memberId' => 'member_id',
|
||||||
|
'fullName' => 'name',
|
||||||
|
'status' => 'active',
|
||||||
|
default => ''
|
||||||
|
};
|
||||||
|
|
||||||
|
if (in_array($orderBy, ['member_id', 'name', 'active'])) {
|
||||||
|
$query->getQuery()->orderBy($orderBy, $request->order);
|
||||||
|
} elseif ($request->orderBy === 'division') {
|
||||||
|
$query->getQuery()->orderBy('corporate_divisions.name', $request->order);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->paginate($limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ return [
|
|||||||
'collation' => 'utf8mb4_unicode_ci',
|
'collation' => 'utf8mb4_unicode_ci',
|
||||||
'prefix' => '',
|
'prefix' => '',
|
||||||
'prefix_indexes' => true,
|
'prefix_indexes' => true,
|
||||||
'strict' => true,
|
'strict' => env('DB_STRICT', true),
|
||||||
'engine' => null,
|
'engine' => null,
|
||||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||||
@@ -145,7 +145,7 @@ return [
|
|||||||
|
|
||||||
'options' => [
|
'options' => [
|
||||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'default' => [
|
'default' => [
|
||||||
|
|||||||
@@ -37,80 +37,81 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@date-io/date-fns": "^2.15.0",
|
"@date-io/date-fns": "^2.16.0",
|
||||||
"@emotion/cache": "^11.10.3",
|
"@emotion/cache": "^11.10.5",
|
||||||
"@emotion/react": "^11.10.0",
|
"@emotion/react": "^11.10.6",
|
||||||
"@emotion/styled": "^11.10.0",
|
"@emotion/styled": "^11.10.6",
|
||||||
"@hookform/resolvers": "^2.9.7",
|
"@hookform/resolvers": "^2.9.11",
|
||||||
"@iconify/react": "^3.2.2",
|
"@iconify/react": "^3.2.2",
|
||||||
"@mui/icons-material": "^5.10.2",
|
"@mui/icons-material": "^5.11.11",
|
||||||
"@mui/lab": "5.0.0-alpha.80",
|
"@mui/lab": "5.0.0-alpha.80",
|
||||||
"@mui/material": "^5.10.2",
|
"@mui/material": "^5.11.14",
|
||||||
"@mui/system": "^5.10.2",
|
"@mui/system": "^5.11.14",
|
||||||
"@mui/utils": "^5.10.16",
|
"@mui/utils": "^5.11.13",
|
||||||
"@mui/x-data-grid": "^5.16.0",
|
"@mui/x-data-grid": "^5.17.26",
|
||||||
"@mui/x-date-pickers": "5.0.0-beta.2",
|
"@mui/x-date-pickers": "5.0.0-beta.2",
|
||||||
"@vitejs/plugin-react": "^1.3.2",
|
"@vitejs/plugin-react": "^1.3.2",
|
||||||
"apexcharts": "^3.36.3",
|
"apexcharts": "^3.37.2",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"change-case": "^4.1.2",
|
"change-case": "^4.1.2",
|
||||||
"csstype": "^3.1.0",
|
"csstype": "^3.1.1",
|
||||||
"date-fns": "^2.29.2",
|
"date-fns": "^2.29.3",
|
||||||
"framer-motion": "^6.5.1",
|
"framer-motion": "^6.5.1",
|
||||||
"highlight.js": "^11.6.0",
|
"highlight.js": "^11.7.0",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"jsx-runtime": "^1.2.0",
|
"jsx-runtime": "^1.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"notistack": "^3.0.0-alpha.7",
|
"notistack": "^3.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
|
"pusher-js": "^8.0.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-apexcharts": "^1.4.0",
|
"react-apexcharts": "^1.4.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-dropzone": "^14.2.2",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-helmet-async": "^1.3.0",
|
"react-helmet-async": "^1.3.0",
|
||||||
"react-hook-form": "^7.34.2",
|
"react-hook-form": "^7.43.7",
|
||||||
"react-intersection-observer": "^8.34.0",
|
"react-intersection-observer": "^8.34.0",
|
||||||
"react-lazy-load-image-component": "^1.5.5",
|
"react-lazy-load-image-component": "^1.5.6",
|
||||||
"react-number-format": "^5.1.1",
|
"react-number-format": "^5.1.4",
|
||||||
"react-quill": "2.0.0-beta.4",
|
"react-quill": "2.0.0-beta.4",
|
||||||
"react-router": "^6.3.0",
|
"react-router": "^6.9.0",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.9.0",
|
||||||
"simplebar": "^5.3.8",
|
"simplebar": "^5.3.9",
|
||||||
"simplebar-react": "^2.4.1",
|
"simplebar-react": "^2.4.3",
|
||||||
"stylis": "^4.1.1",
|
"stylis": "^4.1.3",
|
||||||
"stylis-plugin-rtl": "^2.1.1",
|
"stylis-plugin-rtl": "^2.1.1",
|
||||||
"vite": "^3.0.9",
|
"vite": "^3.2.5",
|
||||||
"vite-plugin-svgr": "^2.2.1",
|
"vite-plugin-svgr": "^2.4.0",
|
||||||
"yup": "^0.32.11"
|
"yup": "^0.32.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.18.13",
|
"@babel/core": "^7.21.3",
|
||||||
"@babel/eslint-parser": "^7.18.9",
|
"@babel/eslint-parser": "^7.21.3",
|
||||||
"@babel/plugin-syntax-flow": "^7.18.6",
|
"@babel/plugin-syntax-flow": "^7.18.6",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.18.10",
|
"@babel/plugin-transform-react-jsx": "^7.21.0",
|
||||||
"@types/lodash": "^4.14.184",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "^0.2.0",
|
||||||
"@types/react": "^17.0.48",
|
"@types/react": "^17.0.53",
|
||||||
"@types/react-dom": "^17.0.17",
|
"@types/react-dom": "^17.0.19",
|
||||||
"@types/react-lazy-load-image-component": "^1.5.2",
|
"@types/react-lazy-load-image-component": "^1.5.2",
|
||||||
"@types/stylis": "^4.0.2",
|
"@types/stylis": "^4.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.35.1",
|
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||||
"@typescript-eslint/parser": "^5.35.1",
|
"@typescript-eslint/parser": "^5.56.0",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.36.0",
|
||||||
"eslint-config-airbnb": "19.0.4",
|
"eslint-config-airbnb": "19.0.4",
|
||||||
"eslint-config-airbnb-typescript": "^16.2.0",
|
"eslint-config-airbnb-typescript": "^16.2.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
"eslint-config-react-app": "7.0.0",
|
"eslint-config-react-app": "7.0.0",
|
||||||
"eslint-import-resolver-typescript": "^2.7.1",
|
"eslint-import-resolver-typescript": "^2.7.1",
|
||||||
"eslint-plugin-flowtype": "^8.0.3",
|
"eslint-plugin-flowtype": "^8.0.3",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-jsx-a11y": "6.5.1",
|
"eslint-plugin-jsx-a11y": "6.5.1",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.31.0",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "4.3.0",
|
"eslint-plugin-react-hooks": "4.3.0",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.8.6",
|
||||||
"typescript": "^4.8.2",
|
"typescript": "^4.9.5",
|
||||||
"vite-plugin-pwa": "^0.12.3"
|
"vite-plugin-pwa": "^0.12.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3369
frontend/client-portal/pnpm-lock.yaml
generated
3369
frontend/client-portal/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
11
frontend/client-portal/src/@types/policy.ts
Normal file
11
frontend/client-portal/src/@types/policy.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export type PolicyProps = {
|
||||||
|
myLimit: {
|
||||||
|
balance: number;
|
||||||
|
total: number;
|
||||||
|
percentage: number;
|
||||||
|
};
|
||||||
|
lockLimit: {
|
||||||
|
balance: number;
|
||||||
|
percentage: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
66
frontend/client-portal/src/@types/table.ts
Normal file
66
frontend/client-portal/src/@types/table.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { Dispatch, SetStateAction } from 'react';
|
||||||
|
|
||||||
|
/* ------------------------------- pagination ------------------------------- */
|
||||||
|
export type PaginationTableProps = {
|
||||||
|
current_page: number;
|
||||||
|
from: number;
|
||||||
|
last_page: number;
|
||||||
|
links: [];
|
||||||
|
path: string;
|
||||||
|
per_page: number;
|
||||||
|
to: number;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ---------------------------------- order --------------------------------- */
|
||||||
|
export type Order = 'asc' | 'desc';
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* --------------------------------- filter --------------------------------- */
|
||||||
|
export type DivisionDataProps = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------------- headcell -------------------------------- */
|
||||||
|
export type HeadCell<DataType> = {
|
||||||
|
id: Extract<keyof DataType, string>;
|
||||||
|
align: string;
|
||||||
|
label: string;
|
||||||
|
isSort: boolean;
|
||||||
|
width?: number;
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------- row ---------------------------------- */
|
||||||
|
export type TableListProps<DataType> = {
|
||||||
|
headCells?: HeadCell<DataType>[];
|
||||||
|
rows?: Array<DataType>;
|
||||||
|
paginations: {
|
||||||
|
page: number;
|
||||||
|
setPage: Dispatch<SetStateAction<number>>;
|
||||||
|
rowsPerPage: number;
|
||||||
|
setRowsPerPage: Dispatch<SetStateAction<number>>;
|
||||||
|
paginationTable: PaginationTableProps;
|
||||||
|
setPaginationTable: Dispatch<SetStateAction<PaginationTableProps>>;
|
||||||
|
};
|
||||||
|
orders: {
|
||||||
|
order: Order;
|
||||||
|
setOrder: Dispatch<SetStateAction<Order>>;
|
||||||
|
orderBy: string;
|
||||||
|
setOrderBy: Dispatch<SetStateAction<string>>;
|
||||||
|
};
|
||||||
|
loadings: {
|
||||||
|
isLoading: boolean;
|
||||||
|
setIsLoading: Dispatch<SetStateAction<boolean>>;
|
||||||
|
};
|
||||||
|
params: {
|
||||||
|
searchParams: URLSearchParams;
|
||||||
|
setSearchParams: any;
|
||||||
|
appliedParams: {};
|
||||||
|
setAppliedParams: Dispatch<SetStateAction<{}>>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
289
frontend/client-portal/src/components/Table.tsx
Normal file
289
frontend/client-portal/src/components/Table.tsx
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
/* ---------------------------------- @mui ---------------------------------- */
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import {
|
||||||
|
Paper,
|
||||||
|
Table as TableContent,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TextField,
|
||||||
|
Button,
|
||||||
|
TableSortLabel,
|
||||||
|
Box,
|
||||||
|
Card,
|
||||||
|
Grid,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Select,
|
||||||
|
MenuItem,
|
||||||
|
SelectChangeEvent,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
LinearProgress,
|
||||||
|
linearProgressClasses,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { visuallyHidden } from '@mui/utils';
|
||||||
|
/* ---------------------------------- axios --------------------------------- */
|
||||||
|
import axios from '../utils/axios';
|
||||||
|
/* ---------------------------------- react --------------------------------- */
|
||||||
|
import { useContext, useEffect, useState } from 'react';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
/* -------------------------------- component ------------------------------- */
|
||||||
|
import BaseTablePagination from './BaseTablePagination';
|
||||||
|
/* ---------------------------------- theme --------------------------------- */
|
||||||
|
import palette from '../theme/palette';
|
||||||
|
/* ---------------------------------- utils --------------------------------- */
|
||||||
|
import { UserCurrentCorporateContext } from '../contexts/UserCurrentCorporate';
|
||||||
|
import { fSplit } from '../utils/formatNumber';
|
||||||
|
/* ---------------------------------- types --------------------------------- */
|
||||||
|
import { DivisionDataProps, Order, PaginationTableProps, TableListProps } from '../@types/table';
|
||||||
|
|
||||||
|
/* --------------------------------- styled --------------------------------- */
|
||||||
|
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 6,
|
||||||
|
[`&.${linearProgressClasses.colorPrimary}`]: {
|
||||||
|
backgroundColor: '#D1F1F1',
|
||||||
|
},
|
||||||
|
[`& .${linearProgressClasses.bar}`]: {
|
||||||
|
borderRadius: 6,
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
export default function Table<T>({
|
||||||
|
headCells,
|
||||||
|
rows,
|
||||||
|
paginations,
|
||||||
|
orders,
|
||||||
|
loadings,
|
||||||
|
params,
|
||||||
|
}: TableListProps<T>) {
|
||||||
|
/* ------------------------------- handle sort ------------------------------ */
|
||||||
|
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
||||||
|
const isAsc = orders?.orderBy === property && orders?.order === 'asc';
|
||||||
|
|
||||||
|
orders?.setOrder(isAsc ? 'desc' : 'asc');
|
||||||
|
orders?.setOrderBy(property);
|
||||||
|
const parameters = Object.fromEntries([
|
||||||
|
...params.searchParams.entries(),
|
||||||
|
['order', isAsc ? 'desc' : 'asc'],
|
||||||
|
['orderBy', property],
|
||||||
|
]);
|
||||||
|
params.setAppliedParams(parameters);
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------- enchanced table head -------------------------- */
|
||||||
|
const EnhancedTableHead = () => {
|
||||||
|
const createSortHandler = (property: string) => (event: React.MouseEvent<unknown>) => {
|
||||||
|
handleRequestSort(event, property);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
{headCells &&
|
||||||
|
headCells.map((headCell, index) => (
|
||||||
|
<TableCell
|
||||||
|
key={index}
|
||||||
|
sortDirection={orders?.orderBy === headCell.id ? orders.order : false}
|
||||||
|
// @ts-ignore
|
||||||
|
align={headCell.align}
|
||||||
|
sx={{ padding: 2 }}
|
||||||
|
width={headCell.width ? headCell.width : 'auto'}
|
||||||
|
>
|
||||||
|
{headCell.isSort ? (
|
||||||
|
<TableSortLabel
|
||||||
|
active={orders?.orderBy === headCell.id}
|
||||||
|
direction={orders?.orderBy === headCell.id ? orders.order : 'asc'}
|
||||||
|
onClick={createSortHandler(headCell.id)}
|
||||||
|
>
|
||||||
|
{headCell.label}
|
||||||
|
{orders?.orderBy === headCell.id ? (
|
||||||
|
<Box component="span" sx={visuallyHidden}>
|
||||||
|
{orders.order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
</TableSortLabel>
|
||||||
|
) : (
|
||||||
|
headCell.label
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------- division field ----------------------------- */
|
||||||
|
// const [divisionValue, setDivisionValue] = useState('all');
|
||||||
|
// const [divisionData, setDivisionData] = useState([]);
|
||||||
|
|
||||||
|
// const handleDivisionChange = (event: SelectChangeEvent) => {
|
||||||
|
// setDivisionValue(event.target.value as string);
|
||||||
|
|
||||||
|
// if (event.target.value === 'all') {
|
||||||
|
// searchParams.delete('division');
|
||||||
|
// const params = Object.fromEntries([...searchParams.entries()]);
|
||||||
|
// setAppliedParams(params);
|
||||||
|
// } else {
|
||||||
|
// const params = Object.fromEntries([
|
||||||
|
// ...searchParams.entries(),
|
||||||
|
// ['division', event.target.value as string],
|
||||||
|
// ]);
|
||||||
|
// setAppliedParams(params);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------------ Search field ------------------------------ */
|
||||||
|
// const [searchText, setSearchText] = useState('');
|
||||||
|
|
||||||
|
// const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
// event.preventDefault();
|
||||||
|
// setIsLoading(true);
|
||||||
|
// 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));
|
||||||
|
// setIsLoading(false);
|
||||||
|
// };
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------ button change pagination ------------------------ */
|
||||||
|
const onPageChangeHandle = async (
|
||||||
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
|
newPage: number
|
||||||
|
) => {
|
||||||
|
const parameters = Object.fromEntries([
|
||||||
|
...params.searchParams.entries(),
|
||||||
|
['page', newPage + 1],
|
||||||
|
]);
|
||||||
|
paginations.setPage(newPage);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
params.setAppliedParams(parameters);
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* --------------------------- row page per limit --------------------------- */
|
||||||
|
const onRowsPerPageChangeHandle = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
params.searchParams.delete('page');
|
||||||
|
const parameters = Object.fromEntries([
|
||||||
|
...params.searchParams.entries(),
|
||||||
|
['per_page', parseInt(event.target.value, 10)],
|
||||||
|
]);
|
||||||
|
|
||||||
|
paginations.setPage(0);
|
||||||
|
paginations.setRowsPerPage(parseInt(event.target.value, 10));
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
params.setAppliedParams(parameters);
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<Grid container>
|
||||||
|
{/* Field 1 */}
|
||||||
|
{/* <Grid item xs={12} paddingX="24px" paddingY="20px">
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} lg={3} xl={2}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel id="simple-division-select-lable">Division</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="simple-division-select-lable"
|
||||||
|
id="division-select-lable"
|
||||||
|
value={divisionValue}
|
||||||
|
label="Division"
|
||||||
|
onChange={handleDivisionChange}
|
||||||
|
>
|
||||||
|
<MenuItem value="all">All</MenuItem>
|
||||||
|
{divisionData.map((row: DivisionDataProps, index) => (
|
||||||
|
<MenuItem key={index} value={row.id}>
|
||||||
|
{row.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} lg={9} xl={10}>
|
||||||
|
<form onSubmit={handleSearchSubmit}>
|
||||||
|
<TextField
|
||||||
|
id="search-input"
|
||||||
|
label="Search"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={(event) => setSearchText(event.target.value)}
|
||||||
|
value={searchText}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid> */}
|
||||||
|
{/* End Field 1 */}
|
||||||
|
{/* Field 2 */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
{/* Table */}
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<TableContent aria-label="collapsible table" size="small">
|
||||||
|
{/* Table Header */}
|
||||||
|
<EnhancedTableHead />
|
||||||
|
{/* End Table Header */}
|
||||||
|
{/* Table Body */}
|
||||||
|
<TableBody>
|
||||||
|
{loadings.isLoading ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={headCells?.length} align="center">
|
||||||
|
Loading . . .
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : rows && rows.length >= 1 ? (
|
||||||
|
rows.map((row, rowIndex) => (
|
||||||
|
<TableRow key={rowIndex}>
|
||||||
|
{headCells &&
|
||||||
|
//@ts-ignore
|
||||||
|
headCells.map((head, headIndex) => (
|
||||||
|
//@ts-ignore
|
||||||
|
<TableCell align={head.align} key={headIndex}>
|
||||||
|
{row[head.id]}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={6} align="center">
|
||||||
|
No Data Found
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
{/* End Table Body */}
|
||||||
|
</TableContent>
|
||||||
|
</TableContainer>
|
||||||
|
{/* End Table */}
|
||||||
|
|
||||||
|
{/* Pagination */}
|
||||||
|
<BaseTablePagination
|
||||||
|
count={paginations.paginationTable.total}
|
||||||
|
onPageChange={onPageChangeHandle}
|
||||||
|
page={paginations.page}
|
||||||
|
rowsPerPage={paginations.rowsPerPage}
|
||||||
|
onRowsPerPageChange={onRowsPerPageChangeHandle}
|
||||||
|
/>
|
||||||
|
{/* End Pagination */}
|
||||||
|
</Grid>
|
||||||
|
{/* End Field 2 */}
|
||||||
|
</Grid>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
// @mui
|
|
||||||
import { Typography, Container, Grid } from '@mui/material';
|
|
||||||
// hooks
|
|
||||||
import useSettings from '../../hooks/useSettings';
|
|
||||||
// components
|
|
||||||
import Page from '../../components/Page';
|
|
||||||
// theme
|
|
||||||
import CardNotification from '../../sections/dashboard/CardNotification';
|
|
||||||
import CardBalance from '../../sections/dashboard/CardBalance';
|
|
||||||
import TableList from '../../sections/dashboard/TableList';
|
|
||||||
import { useContext, useEffect, useState } from 'react';
|
|
||||||
import axios from '../../utils/axios';
|
|
||||||
import { Stack } from '@mui/system';
|
|
||||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
const itemList = [
|
|
||||||
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
|
||||||
];
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
/* ---------------------------------- types --------------------------------- */
|
|
||||||
|
|
||||||
type PolicyProps = {
|
|
||||||
myLimit: {
|
|
||||||
balance: number;
|
|
||||||
total: number;
|
|
||||||
percentage: number;
|
|
||||||
};
|
|
||||||
lockLimit: {
|
|
||||||
balance: number;
|
|
||||||
percentage: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* ------------------------------ default data ------------------------------ */
|
|
||||||
const defaultPolicyData = {
|
|
||||||
myLimit: {
|
|
||||||
balance: 0,
|
|
||||||
total: 0,
|
|
||||||
percentage: 0,
|
|
||||||
},
|
|
||||||
lockLimit: {
|
|
||||||
balance: 0,
|
|
||||||
percentage: 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
export default function Dashboard() {
|
|
||||||
const { themeStretch } = useSettings();
|
|
||||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
|
||||||
|
|
||||||
// const [tableData, setTableData] = useState([]);
|
|
||||||
const [policyData, setPolicyData] = useState<PolicyProps>(defaultPolicyData);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
setPolicyData(defaultPolicyData);
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
||||||
const dashboard = await axios.get(`${corporateValue}/policy`);
|
|
||||||
setPolicyData(dashboard.data.policy);
|
|
||||||
})();
|
|
||||||
}, [corporateValue]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Page title="Dashboard">
|
|
||||||
<Container maxWidth={themeStretch ? false : 'xl'}>
|
|
||||||
<Stack direction="row" justifyContent="space-between">
|
|
||||||
<Typography variant="h3" component="h1" paragraph>
|
|
||||||
Dashboard
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12} lg={6} md={12}>
|
|
||||||
<CardNotification data={itemList} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} lg={6} md={12}>
|
|
||||||
<CardBalance data={policyData} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} lg={12} md={12}>
|
|
||||||
<TableList />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Container>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
290
frontend/client-portal/src/pages/Dashboard/Index.tsx
Executable file
290
frontend/client-portal/src/pages/Dashboard/Index.tsx
Executable file
@@ -0,0 +1,290 @@
|
|||||||
|
// @mui
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import {
|
||||||
|
Typography,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
|
Button,
|
||||||
|
IconButton,
|
||||||
|
LinearProgress,
|
||||||
|
linearProgressClasses,
|
||||||
|
} from '@mui/material';
|
||||||
|
// hooks
|
||||||
|
import useSettings from '../../hooks/useSettings';
|
||||||
|
// components
|
||||||
|
import Page from '../../components/Page';
|
||||||
|
// theme
|
||||||
|
import CardNotification from '../../sections/dashboard/CardNotification';
|
||||||
|
import CardPolicy from '../../sections/dashboard/CardPolicy';
|
||||||
|
import { useContext, useEffect, useState } from 'react';
|
||||||
|
import axios from '../../utils/axios';
|
||||||
|
import { Stack } from '@mui/system';
|
||||||
|
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||||
|
import { PolicyProps } from '../../@types/policy';
|
||||||
|
import Table from '../../components/Table';
|
||||||
|
import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import palette from '../../theme/palette';
|
||||||
|
import { MoreVert as MoreVertIcon } from '@mui/icons-material';
|
||||||
|
import TableList from '../../sections/dashboard/TableList';
|
||||||
|
import { fSplit } from '../../utils/formatNumber';
|
||||||
|
|
||||||
|
const itemList = [
|
||||||
|
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
||||||
|
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
||||||
|
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
||||||
|
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
||||||
|
];
|
||||||
|
|
||||||
|
/* ------------------------------ default data ------------------------------ */
|
||||||
|
const defaultPolicyData = {
|
||||||
|
myLimit: {
|
||||||
|
balance: 0,
|
||||||
|
total: 0,
|
||||||
|
percentage: 0,
|
||||||
|
},
|
||||||
|
lockLimit: {
|
||||||
|
balance: 0,
|
||||||
|
percentage: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
export default function Index() {
|
||||||
|
const { themeStretch } = useSettings();
|
||||||
|
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||||
|
|
||||||
|
const [memberData, setMemberData] = useState([]);
|
||||||
|
const [policyData, setPolicyData] = useState<PolicyProps>(defaultPolicyData);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* setting up for the table */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
|
const loadings = {
|
||||||
|
isLoading: isLoading,
|
||||||
|
setIsLoading: setIsLoading,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------------------- limit progress ----------------------------- */
|
||||||
|
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 6,
|
||||||
|
[`&.${linearProgressClasses.colorPrimary}`]: {
|
||||||
|
backgroundColor: '#D1F1F1',
|
||||||
|
},
|
||||||
|
[`& .${linearProgressClasses.bar}`]: {
|
||||||
|
borderRadius: 6,
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------------ handle params ----------------------------- */
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const [appliedParams, setAppliedParams] = useState({});
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
searchParams: searchParams,
|
||||||
|
setSearchParams: setSearchParams,
|
||||||
|
appliedParams: appliedParams,
|
||||||
|
setAppliedParams: setAppliedParams,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------------ handle order ------------------------------ */
|
||||||
|
const [order, setOrder] = useState<Order>('asc');
|
||||||
|
const [orderBy, setOrderBy] = useState('fullName');
|
||||||
|
|
||||||
|
const orders = {
|
||||||
|
order: order,
|
||||||
|
setOrder: setOrder,
|
||||||
|
orderBy: orderBy,
|
||||||
|
setOrderBy: setOrderBy,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ---------------------------- handle pagination --------------------------- */
|
||||||
|
const [page, setPage] = useState(0);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||||
|
|
||||||
|
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
|
||||||
|
current_page: 0,
|
||||||
|
from: 0,
|
||||||
|
last_page: 0,
|
||||||
|
links: [],
|
||||||
|
path: '',
|
||||||
|
per_page: 0,
|
||||||
|
to: 0,
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const paginations = {
|
||||||
|
page: page,
|
||||||
|
setPage: setPage,
|
||||||
|
rowsPerPage: rowsPerPage,
|
||||||
|
setRowsPerPage: setRowsPerPage,
|
||||||
|
paginationTable: paginationTable,
|
||||||
|
setPaginationTable: setPaginationTable,
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------------- headCell -------------------------------- */
|
||||||
|
const headCells: HeadCell<never>[] = [
|
||||||
|
{
|
||||||
|
id: 'memberId',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Member ID',
|
||||||
|
isSort: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fullName',
|
||||||
|
align: 'center',
|
||||||
|
label: 'Name',
|
||||||
|
isSort: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'division',
|
||||||
|
align: 'center',
|
||||||
|
label: 'Divisi',
|
||||||
|
isSort: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'limit',
|
||||||
|
align: 'center',
|
||||||
|
label: 'Limit',
|
||||||
|
isSort: false,
|
||||||
|
// width: 170,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'status',
|
||||||
|
align: 'center',
|
||||||
|
label: 'Status',
|
||||||
|
isSort: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'action',
|
||||||
|
align: 'right',
|
||||||
|
label: '',
|
||||||
|
isSort: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------- handler action ----------------------------- */
|
||||||
|
const handleAction = () => {
|
||||||
|
alert('action');
|
||||||
|
};
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||||
|
|
||||||
|
const parameters =
|
||||||
|
Object.keys(appliedParams).length !== 0
|
||||||
|
? appliedParams
|
||||||
|
: Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]);
|
||||||
|
|
||||||
|
// get data policy, division, member using axios
|
||||||
|
const corporatePolicyLimit = await axios.get(`${corporateValue}/policy`);
|
||||||
|
const corporateDivision = await axios.get(`${corporateValue}/division`);
|
||||||
|
const corporateMembers = await axios.get(`${corporateValue}/members`, {
|
||||||
|
params: { ...parameters },
|
||||||
|
});
|
||||||
|
|
||||||
|
setPolicyData(corporatePolicyLimit.data.data);
|
||||||
|
|
||||||
|
setSearchParams(parameters);
|
||||||
|
setMemberData(corporateMembers.data.data);
|
||||||
|
setPaginationTable(corporateMembers.data);
|
||||||
|
setRowsPerPage(corporateMembers.data.per_page);
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
})();
|
||||||
|
}, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]);
|
||||||
|
|
||||||
|
const newMemberData: any = memberData.map((obj: any) => {
|
||||||
|
return {
|
||||||
|
...obj,
|
||||||
|
limit: (
|
||||||
|
<Stack>
|
||||||
|
<BorderLinearProgress variant="determinate" value={obj.limit.percentage} sx={{ mb: 1 }} />
|
||||||
|
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
||||||
|
{fSplit(obj.limit.current)} / {fSplit(obj.limit.total)}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
),
|
||||||
|
status:
|
||||||
|
obj.status === 1 ? (
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
backgroundColor: 'rgba(84, 214, 44, 0.16)',
|
||||||
|
color: palette.dark.success.dark,
|
||||||
|
paddingY: 0,
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(84, 214, 44, 0.32)',
|
||||||
|
color: palette.dark.success.darker,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Active
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
backgroundColor: 'rgba(255, 72, 66, 0.16)',
|
||||||
|
color: palette.dark.error.dark,
|
||||||
|
paddingY: 0,
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(255, 72, 66, 0.32)',
|
||||||
|
color: palette.dark.error.darker,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Inactive
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
action: (
|
||||||
|
<IconButton onClick={handleAction}>
|
||||||
|
<MoreVertIcon />
|
||||||
|
</IconButton>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page title="Dashboard">
|
||||||
|
<Container maxWidth={themeStretch ? false : 'xl'}>
|
||||||
|
<Stack direction="row" justifyContent="space-between">
|
||||||
|
<Typography variant="h3" component="h1" paragraph>
|
||||||
|
Dashboard
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} lg={6} md={12}>
|
||||||
|
<CardNotification data={itemList} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} lg={6} md={12}>
|
||||||
|
<CardPolicy data={policyData} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} lg={12} md={12}>
|
||||||
|
<Table
|
||||||
|
headCells={headCells}
|
||||||
|
rows={newMemberData}
|
||||||
|
orders={orders}
|
||||||
|
paginations={paginations}
|
||||||
|
loadings={loadings}
|
||||||
|
params={params}
|
||||||
|
/>
|
||||||
|
{/* <TableList /> */}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -144,7 +144,7 @@ export default function Router() {
|
|||||||
const Login = Loadable(lazy(() => import('../pages/auth/Login')));
|
const Login = Loadable(lazy(() => import('../pages/auth/Login')));
|
||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
const Dashboard = Loadable(lazy(() => import('../pages/Dashboard/Dashboard')));
|
const Dashboard = Loadable(lazy(() => import('../pages/Dashboard/Index')));
|
||||||
const NotFound = Loadable(lazy(() => import('../pages/Page404')));
|
const NotFound = Loadable(lazy(() => import('../pages/Page404')));
|
||||||
|
|
||||||
// Alarm Center
|
// Alarm Center
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
// @mui
|
|
||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Typography,
|
|
||||||
Stack,
|
|
||||||
LinearProgress,
|
|
||||||
linearProgressClasses,
|
|
||||||
} from '@mui/material';
|
|
||||||
// utils
|
|
||||||
import { fCurrency } from '../../utils/formatNumber';
|
|
||||||
// components
|
|
||||||
import Iconify from '../../components/Iconify';
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
const RootStyle = styled(Card)(({ theme }) => ({
|
|
||||||
boxShadow: 'none',
|
|
||||||
padding: theme.spacing(3),
|
|
||||||
color: 'black',
|
|
||||||
backgroundColor: theme.palette.grey[200],
|
|
||||||
maxHeight: '240px',
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
const INITIAL = '500.000.000';
|
|
||||||
const TOTAL = 375000000;
|
|
||||||
const PERCENT = 75;
|
|
||||||
|
|
||||||
export default function BalanceCard(props: any) {
|
|
||||||
const { setOpenPopup } = props;
|
|
||||||
|
|
||||||
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
|
||||||
height: 10,
|
|
||||||
borderRadius: 6,
|
|
||||||
[`&.${linearProgressClasses.colorPrimary}`]: {
|
|
||||||
backgroundColor: theme.palette.grey[theme.palette.mode === 'light' ? 300 : 800],
|
|
||||||
},
|
|
||||||
[`& .${linearProgressClasses.bar}`]: {
|
|
||||||
borderRadius: 6,
|
|
||||||
backgroundColor: theme.palette.primary.main,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RootStyle>
|
|
||||||
<Stack direction="row" justifyContent="space-between" sx={{ mb: 1 }}>
|
|
||||||
<div>
|
|
||||||
<Typography variant="body2" component="span" sx={{ opacity: 0.72 }}>
|
|
||||||
Total Limit
|
|
||||||
</Typography>
|
|
||||||
<Typography sx={{ typography: 'body2' }}>{fCurrency(TOTAL)}</Typography>
|
|
||||||
<Typography sx={{ typography: 'caption', color: '#919EAB' }}>/ {INITIAL}</Typography>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Stack direction="row" alignItems="center" justifyContent="center">
|
|
||||||
<Typography variant="h5" sx={{ ml: 0.5 }}>
|
|
||||||
{PERCENT}%
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<BorderLinearProgress variant="determinate" value={PERCENT} sx={{ mb: 1 }} />
|
|
||||||
|
|
||||||
<Stack sx={{ backgroundColor: '#B2E8E8', paddingY: 1, paddingX: 1.5, mb: 2 }}>
|
|
||||||
<Typography sx={{ typography: 'caption', display: 'flex', alignItems: 'center' }}>
|
|
||||||
<Iconify
|
|
||||||
icon="bxs:lock-alt"
|
|
||||||
width={12}
|
|
||||||
height={13}
|
|
||||||
sx={{ color: '#424242', marginRight: '6px' }}
|
|
||||||
/>
|
|
||||||
<Typography variant="caption" component="span">
|
|
||||||
Lock Fund ( 25% )
|
|
||||||
</Typography>
|
|
||||||
</Typography>
|
|
||||||
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
|
||||||
125.000.000 / 125.000.000
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Stack direction="row" spacing={2}>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
startIcon={<Iconify icon="bi:clipboard-check-fill" />}
|
|
||||||
fullWidth={true}
|
|
||||||
onClick={() => setOpenPopup(true)}
|
|
||||||
>
|
|
||||||
Submit Claim
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
startIcon={<Iconify icon="heroicons-solid:cash" />}
|
|
||||||
fullWidth={true}
|
|
||||||
>
|
|
||||||
Top Up
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</RootStyle>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -26,9 +26,10 @@ type NotificationProps = {
|
|||||||
|
|
||||||
const RootNotificationStyle = styled(Card)(({ theme }) => ({
|
const RootNotificationStyle = styled(Card)(({ theme }) => ({
|
||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
padding: '1rem 0.5rem',
|
padding: '1.5rem',
|
||||||
color: 'black',
|
color: 'black',
|
||||||
backgroundColor: theme.palette.grey[200],
|
backgroundColor: theme.palette.grey[200],
|
||||||
|
height: '100%',
|
||||||
maxHeight: '240px',
|
maxHeight: '240px',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -37,6 +38,10 @@ const ItemNotificationStyle = styled(Card)(({ theme }) => ({
|
|||||||
padding: theme.spacing(1),
|
padding: theme.spacing(1),
|
||||||
borderRadius: 0.5,
|
borderRadius: 0.5,
|
||||||
color: 'black',
|
color: 'black',
|
||||||
|
marginTop: 2,
|
||||||
|
overflowY: 'auto',
|
||||||
|
maxHeight: '154px',
|
||||||
|
gap: '0.5rem',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -95,11 +100,11 @@ export default function CardNotification({ data }: NotificationProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<ItemNotificationStyle sx={{ marginTop: 2, overflowY: 'auto', maxHeight: '154px' }}>
|
<ItemNotificationStyle>
|
||||||
{data
|
{data
|
||||||
? data.map(({ info, date, time }, key) => (
|
? data.map(({ info, date, time }, index) => (
|
||||||
<div key={key}>
|
<div key={index}>
|
||||||
{key >= 1 ? <Divider sx={{ marginY: 0.5 }} /> : ''}
|
{index >= 1 ? <Divider sx={{ marginY: 0.5 }} /> : ''}
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||||
<Stack direction="column" justifyContent="flex-start" alignItems="flex-start">
|
<Stack direction="column" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Typography sx={{ typography: 'caption' }}>{info}</Typography>
|
<Typography sx={{ typography: 'caption' }}>{info}</Typography>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import DialogClaimSubmitMember from './DialogClaimSubmitMember';
|
|||||||
|
|
||||||
/* ---------------------------------- types --------------------------------- */
|
/* ---------------------------------- types --------------------------------- */
|
||||||
|
|
||||||
type CardBalanceProps = {
|
type CardPolicyProps = {
|
||||||
data: {
|
data: {
|
||||||
myLimit: {
|
myLimit: {
|
||||||
balance: number;
|
balance: number;
|
||||||
@@ -60,7 +60,7 @@ const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
|||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
export default function CardBalance(props: CardBalanceProps) {
|
export default function CardPolicy(props: CardPolicyProps) {
|
||||||
const [openDialog, setOpenDialog] = useState(false);
|
const [openDialog, setOpenDialog] = useState(false);
|
||||||
const [dialogTitle, setDialogTitle] = useState('');
|
const [dialogTitle, setDialogTitle] = useState('');
|
||||||
const [isDialog, setIsDialog] = useState('');
|
const [isDialog, setIsDialog] = useState('');
|
||||||
@@ -1,315 +0,0 @@
|
|||||||
// @mui
|
|
||||||
import {
|
|
||||||
Autocomplete,
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Collapse,
|
|
||||||
IconButton,
|
|
||||||
InputLabel,
|
|
||||||
MenuItem,
|
|
||||||
OutlinedInput,
|
|
||||||
Paper,
|
|
||||||
Select,
|
|
||||||
SelectChangeEvent,
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableContainer,
|
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
Badge,
|
|
||||||
Tab,
|
|
||||||
Tabs,
|
|
||||||
CardHeader,
|
|
||||||
Stack,
|
|
||||||
Menu,
|
|
||||||
ButtonGroup,
|
|
||||||
Pagination,
|
|
||||||
TablePagination,
|
|
||||||
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';
|
|
||||||
// hooks
|
|
||||||
import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react';
|
|
||||||
import useSettings from '../../hooks/useSettings';
|
|
||||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
|
|
||||||
// components
|
|
||||||
import axios from '../../utils/axios';
|
|
||||||
import { LaravelPaginatedData } from '../../@types/paginated-data';
|
|
||||||
import { Member } from '../../@types/member';
|
|
||||||
import Iconify from '../../components/Iconify';
|
|
||||||
|
|
||||||
export default function DashboardTable() {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const { themeStretch } = useSettings();
|
|
||||||
const { corporate_id } = useParams();
|
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
|
||||||
const [importResult, setImportResult] = useState(null);
|
|
||||||
|
|
||||||
function SearchInput(props: any) {
|
|
||||||
// SEARCH
|
|
||||||
const searchInput = useRef<HTMLInputElement>(null);
|
|
||||||
const [searchText, setSearchText] = useState('');
|
|
||||||
|
|
||||||
const handleSearchChange = (event: any) => {
|
|
||||||
const newSearchText = event.target.value ?? '';
|
|
||||||
setSearchText(newSearchText);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchSubmit = (event: any) => {
|
|
||||||
event.preventDefault();
|
|
||||||
props.onSearch(searchText); // Trigger to Parent
|
|
||||||
};
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// // Trigger First Search
|
|
||||||
// setSearchText(searchParams.get('search') ?? '');
|
|
||||||
// }, [searchParams]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSearchSubmit} style={{ flex: '1' }}>
|
|
||||||
<TextField
|
|
||||||
id="search-input"
|
|
||||||
ref={searchInput}
|
|
||||||
label="Search"
|
|
||||||
variant="outlined"
|
|
||||||
fullWidth
|
|
||||||
onChange={handleSearchChange}
|
|
||||||
value={searchText}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ImportForm(props: any) {
|
|
||||||
// IMPORT
|
|
||||||
// Create Button Menu
|
|
||||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
|
||||||
const createMenu = Boolean(anchorEl);
|
|
||||||
const importForm = useRef<HTMLInputElement>(null);
|
|
||||||
const [currentImportFileName, setCurrentImportFileName] = useState(null);
|
|
||||||
|
|
||||||
const handleImportChange = (event: any) => {
|
|
||||||
if (event.target.files[0]) {
|
|
||||||
setCurrentImportFileName(event.target.files[0].name);
|
|
||||||
} else {
|
|
||||||
setCurrentImportFileName(null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = ['All', 'Option 2'];
|
|
||||||
const [value, setValue] = React.useState<string | null>(options[0]);
|
|
||||||
const [inputValue, setInputValue] = React.useState('');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Stack direction={'row'} justifyContent="space-between" spacing={2} sx={{ p: 2 }}>
|
|
||||||
{/* Filter Division */}
|
|
||||||
<Autocomplete
|
|
||||||
value={value}
|
|
||||||
onChange={(event: any, newValue: string | null) => {
|
|
||||||
setValue(newValue);
|
|
||||||
}}
|
|
||||||
inputValue={inputValue}
|
|
||||||
onInputChange={(event, newInputValue) => {
|
|
||||||
setInputValue(newInputValue);
|
|
||||||
}}
|
|
||||||
id="controllable-states-demo"
|
|
||||||
options={options}
|
|
||||||
sx={{ minWidth: 240 }}
|
|
||||||
renderInput={(params) => <TextField {...params} label="Division" />}
|
|
||||||
/>
|
|
||||||
{/* Search */}
|
|
||||||
<SearchInput onSearch={applyFilter} />
|
|
||||||
|
|
||||||
{/* Button Import */}
|
|
||||||
<Button
|
|
||||||
id="import-button"
|
|
||||||
variant="outlined"
|
|
||||||
startIcon={<Iconify icon="eva:download-fill" />}
|
|
||||||
sx={{ p: 1.8, minWidth: '104px' }}
|
|
||||||
// onClick={() => {}}
|
|
||||||
>
|
|
||||||
Import
|
|
||||||
</Button>
|
|
||||||
{/* <input
|
|
||||||
type="file"
|
|
||||||
id="file"
|
|
||||||
ref={importForm}
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
onChange={handleImportChange}
|
|
||||||
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain"
|
|
||||||
/> */}
|
|
||||||
{/* Button Add Task */}
|
|
||||||
<Button variant="contained" startIcon={<AddIcon />} sx={{ p: 1.8, minWidth: '142px' }}>
|
|
||||||
Add Data
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called on every row to map the data to the columns
|
|
||||||
function createData(member: Member): Member {
|
|
||||||
return {
|
|
||||||
...member,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the every row of the table
|
|
||||||
// function Row(props: { row: ReturnType<typeof createData> }) {
|
|
||||||
// const { row } = props;
|
|
||||||
// const [open, setOpen] = React.useState(true);
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <React.Fragment>
|
|
||||||
// <TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
|
|
||||||
// <TableCell>
|
|
||||||
// <IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
|
|
||||||
// {open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
|
|
||||||
// </IconButton>
|
|
||||||
// </TableCell>
|
|
||||||
// <TableCell align="left">{row.member_id}</TableCell>
|
|
||||||
// <TableCell align="left">{row.payor_id}</TableCell>
|
|
||||||
// <TableCell align="left">{row.name}</TableCell>
|
|
||||||
// <TableCell align="left">{row.nik}</TableCell>
|
|
||||||
// <TableCell align="left">{row.nric}</TableCell>
|
|
||||||
|
|
||||||
// <TableCell align="right">
|
|
||||||
// <Button variant="outlined" color="success" size="small">
|
|
||||||
// Active
|
|
||||||
// </Button>
|
|
||||||
// </TableCell>
|
|
||||||
// {/* <TableCell align="right"><Button variant="outlined" color="error" size="small">Disable</Button></TableCell> */}
|
|
||||||
// </TableRow>
|
|
||||||
// {/* COLLAPSIBLE ROW */}
|
|
||||||
// <TableRow>
|
|
||||||
// <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={99}>
|
|
||||||
// <Collapse in={open} timeout="auto" unmountOnExit>
|
|
||||||
// <Box sx={{ borderBottom: 1 }}>
|
|
||||||
// <Typography variant="body2" gutterBottom component="div">
|
|
||||||
// <Grid></Grid>
|
|
||||||
// </Typography>
|
|
||||||
// </Box>
|
|
||||||
// </Collapse>
|
|
||||||
// </TableCell>
|
|
||||||
// </TableRow>
|
|
||||||
// </React.Fragment>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Dummy Default Data
|
|
||||||
const [dataTableIsLoading, setDataTableLoading] = useState(true);
|
|
||||||
const [dataTableData, setDataTableData] = useState<LaravelPaginatedData>({
|
|
||||||
current_page: 1,
|
|
||||||
data: [],
|
|
||||||
path: '',
|
|
||||||
first_page_url: '',
|
|
||||||
last_page: 1,
|
|
||||||
last_page_url: '',
|
|
||||||
next_page_url: '',
|
|
||||||
prev_page_url: '',
|
|
||||||
per_page: 10,
|
|
||||||
from: 0,
|
|
||||||
to: 0,
|
|
||||||
total: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const loadDataTableData = async (appliedFilter: any | null = null) => {
|
|
||||||
setDataTableLoading(true);
|
|
||||||
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
|
|
||||||
const response = await axios.get('/members', { params: filter });
|
|
||||||
|
|
||||||
setDataTableData(response.data.members);
|
|
||||||
setDataTableLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const headStyle = {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
};
|
|
||||||
|
|
||||||
const applyFilter = async (searchFilter: string) => {
|
|
||||||
await loadDataTableData({ search: searchFilter });
|
|
||||||
setSearchParams({ search: searchFilter });
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
loadDataTableData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<ImportForm />
|
|
||||||
<Stack>
|
|
||||||
{/* The Main Table */}
|
|
||||||
<TableContainer component={Paper}>
|
|
||||||
<Table aria-label="collapsible table">
|
|
||||||
<TableBody>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell style={headStyle} align="left">
|
|
||||||
MemberID
|
|
||||||
</TableCell>
|
|
||||||
<TableCell style={headStyle} align="left">
|
|
||||||
Name
|
|
||||||
</TableCell>
|
|
||||||
<TableCell style={headStyle} align="left">
|
|
||||||
Divisi
|
|
||||||
</TableCell>
|
|
||||||
<TableCell style={headStyle} align="left">
|
|
||||||
Limit
|
|
||||||
</TableCell>
|
|
||||||
<TableCell style={headStyle} align="right" width={100}>
|
|
||||||
Status
|
|
||||||
</TableCell>
|
|
||||||
<TableCell style={headStyle} align="right" width={100}>
|
|
||||||
Action
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableBody>
|
|
||||||
{dataTableIsLoading ? (
|
|
||||||
<TableBody>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={8} align="center">
|
|
||||||
No Data Found
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableBody>
|
|
||||||
) : dataTableData.data.length === 0 ? (
|
|
||||||
<TableBody>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={8} align="center">
|
|
||||||
No Data
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableBody>
|
|
||||||
) : (
|
|
||||||
<TableBody>
|
|
||||||
{/* {dataTableData.data.map((row) => (
|
|
||||||
<Row key={row.id} row={row} />
|
|
||||||
))} */}
|
|
||||||
Testing
|
|
||||||
</TableBody>
|
|
||||||
)}
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
|
|
||||||
{/* <TablePagination
|
|
||||||
rowsPerPageOptions={[5, 10, 25]}
|
|
||||||
component="div"
|
|
||||||
count={rows.length}
|
|
||||||
rowsPerPage={rowsPerPage}
|
|
||||||
page={page}
|
|
||||||
onPageChange={handleChangePage}
|
|
||||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
|
||||||
/> */}
|
|
||||||
</Stack>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
// @mui
|
|
||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import { Button, Card, Divider, Link, Typography, Stack } from '@mui/material';
|
|
||||||
import { ChevronRight } from '@mui/icons-material';
|
|
||||||
// components
|
|
||||||
import Iconify from '../../components/Iconify';
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
const RootStyle = styled(Card)(({ theme }) => ({
|
|
||||||
boxShadow: 'none',
|
|
||||||
padding: '1rem 0.5rem',
|
|
||||||
color: 'black',
|
|
||||||
backgroundColor: theme.palette.grey[200],
|
|
||||||
maxHeight: '240px',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const ItemStyle = styled(Card)(({ theme }) => ({
|
|
||||||
boxShadow: 'none',
|
|
||||||
padding: theme.spacing(1),
|
|
||||||
borderRadius: 0.5,
|
|
||||||
color: 'black',
|
|
||||||
maxHeight: '170px',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const itemList = [
|
|
||||||
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
|
||||||
];
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
export default function NotificationCard() {
|
|
||||||
return (
|
|
||||||
<RootStyle>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Typography>
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
component="span"
|
|
||||||
sx={{ display: 'flex', alignItems: 'center' }}
|
|
||||||
>
|
|
||||||
<Iconify icon="eva:bell-fill" marginRight={0.75} />
|
|
||||||
Notification
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: '12px',
|
|
||||||
height: '12px',
|
|
||||||
backgroundColor: '#19BBBB',
|
|
||||||
marginLeft: '0.5rem',
|
|
||||||
borderRadius: '50%',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Typography>
|
|
||||||
</Typography>
|
|
||||||
<Button sx={{ typography: 'body2' }} endIcon={<ChevronRight />}>
|
|
||||||
View All
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Stack sx={{ marginTop: 2 }}>
|
|
||||||
<ItemStyle>
|
|
||||||
{itemList.map(({ info, date, time }, key) => (
|
|
||||||
<div key={key}>
|
|
||||||
{key >= 1 ? <Divider sx={{ marginY: 0.5 }} /> : ''}
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Stack direction="column" justifyContent="flex-start" alignItems="flex-start">
|
|
||||||
<Typography sx={{ typography: 'caption' }}>{info}</Typography>
|
|
||||||
<Link
|
|
||||||
component="button"
|
|
||||||
variant="caption"
|
|
||||||
underline="always"
|
|
||||||
onClick={() => {
|
|
||||||
alert('Info Detail');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Info Detail
|
|
||||||
</Link>
|
|
||||||
</Stack>
|
|
||||||
<Stack direction="column" justifyContent="flex-start" alignItems="flex-start">
|
|
||||||
<Typography sx={{ typography: 'caption', color: '#656565' }}>{date}</Typography>
|
|
||||||
<Typography sx={{ typography: 'caption', color: '#656565' }}>{time}</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</ItemStyle>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{/* <BorderLinearProgress variant="determinate" value={50} sx={{ mb: 1 }} />
|
|
||||||
|
|
||||||
<Stack sx={{ backgroundColor: '#B2E8E8', paddingY: 1, paddingX: 1.5, mb: 2 }}>
|
|
||||||
<Typography sx={{ typography: 'caption' }}>Lock Fund ( 25% )</Typography>
|
|
||||||
<Typography sx={{ typography: 'caption' }}>125.000.000 / 125.000.000</Typography>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Stack direction="row" spacing={2}>
|
|
||||||
<Button variant="outlined" fullWidth={true}>
|
|
||||||
Submit Claim
|
|
||||||
</Button>
|
|
||||||
<Button variant="contained" startIcon={<Payments />} fullWidth={true}>
|
|
||||||
Top Up
|
|
||||||
</Button>
|
|
||||||
</Stack> */}
|
|
||||||
</RootStyle>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,443 +0,0 @@
|
|||||||
/* ---------------------------------- @mui ---------------------------------- */
|
|
||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import {
|
|
||||||
Paper,
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableContainer,
|
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
TextField,
|
|
||||||
Button,
|
|
||||||
TableSortLabel,
|
|
||||||
Box,
|
|
||||||
IconButton,
|
|
||||||
Card,
|
|
||||||
Grid,
|
|
||||||
FormControl,
|
|
||||||
InputLabel,
|
|
||||||
Select,
|
|
||||||
MenuItem,
|
|
||||||
SelectChangeEvent,
|
|
||||||
Stack,
|
|
||||||
Typography,
|
|
||||||
LinearProgress,
|
|
||||||
linearProgressClasses,
|
|
||||||
} from '@mui/material';
|
|
||||||
import { visuallyHidden } from '@mui/utils';
|
|
||||||
/* ---------------------------------- axios --------------------------------- */
|
|
||||||
import axios from '../../utils/axios';
|
|
||||||
/* ---------------------------------- react --------------------------------- */
|
|
||||||
import { useContext, useEffect, useState } from 'react';
|
|
||||||
/* -------------------------------- component ------------------------------- */
|
|
||||||
import Iconify from '../../components/Iconify';
|
|
||||||
import BaseTablePagination from '../../components/BaseTablePagination';
|
|
||||||
/* ---------------------------------- theme --------------------------------- */
|
|
||||||
import palette from '../../theme/palette';
|
|
||||||
import { useSearchParams } from 'react-router-dom';
|
|
||||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
|
||||||
import { fSplit } from '../../utils/formatNumber';
|
|
||||||
|
|
||||||
/* ---------------------------------- types --------------------------------- */
|
|
||||||
type PaginationTableProps = {
|
|
||||||
current_page: number;
|
|
||||||
from: number;
|
|
||||||
last_page: number;
|
|
||||||
links: [];
|
|
||||||
path: string;
|
|
||||||
per_page: number;
|
|
||||||
to: number;
|
|
||||||
total: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type DataTableProps = {
|
|
||||||
fullName: string;
|
|
||||||
memberId: string;
|
|
||||||
division: string;
|
|
||||||
limit: {
|
|
||||||
current: number;
|
|
||||||
total: number;
|
|
||||||
percentage: number;
|
|
||||||
};
|
|
||||||
status: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Order = 'asc' | 'desc';
|
|
||||||
|
|
||||||
interface HeadCell {
|
|
||||||
id: string;
|
|
||||||
align: string;
|
|
||||||
label: string;
|
|
||||||
isSort: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EnhancedTableProps {
|
|
||||||
onRequestSort: (event: React.MouseEvent<unknown>, property: string) => void;
|
|
||||||
order: Order;
|
|
||||||
orderBy: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type DivisionDataProps = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* --------------------------------- 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 -------------------------- */
|
|
||||||
const headCells: readonly HeadCell[] = [
|
|
||||||
{
|
|
||||||
id: 'member_id',
|
|
||||||
align: 'left',
|
|
||||||
label: 'Member ID',
|
|
||||||
isSort: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'name',
|
|
||||||
align: 'center',
|
|
||||||
label: 'Name',
|
|
||||||
isSort: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'division',
|
|
||||||
align: 'center',
|
|
||||||
label: 'Divisi',
|
|
||||||
isSort: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'limit',
|
|
||||||
align: 'center',
|
|
||||||
label: 'Limit',
|
|
||||||
isSort: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'active',
|
|
||||||
align: 'center',
|
|
||||||
label: 'Status',
|
|
||||||
isSort: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function EnhancedTableHead({ order, orderBy, onRequestSort }: EnhancedTableProps) {
|
|
||||||
const createSortHandler = (property: string) => (event: React.MouseEvent<unknown>) => {
|
|
||||||
onRequestSort(event, property);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
{headCells.map((headCell) => (
|
|
||||||
<TableCell
|
|
||||||
key={headCell.id}
|
|
||||||
sortDirection={orderBy === headCell.id ? order : false}
|
|
||||||
// @ts-ignore
|
|
||||||
align={headCell.align}
|
|
||||||
sx={{ padding: 2 }}
|
|
||||||
>
|
|
||||||
{headCell.isSort ? (
|
|
||||||
<TableSortLabel
|
|
||||||
active={orderBy === headCell.id}
|
|
||||||
direction={orderBy === headCell.id ? order : 'asc'}
|
|
||||||
onClick={createSortHandler(headCell.id)}
|
|
||||||
>
|
|
||||||
{headCell.label}
|
|
||||||
{orderBy === headCell.id ? (
|
|
||||||
<Box component="span" sx={visuallyHidden}>
|
|
||||||
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
|
||||||
</Box>
|
|
||||||
) : null}
|
|
||||||
</TableSortLabel>
|
|
||||||
) : (
|
|
||||||
headCell.label
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
<TableCell align="center">{''}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
export default function TableList(props: any) {
|
|
||||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
|
||||||
|
|
||||||
const [dataTable, setDataTable] = useState([]);
|
|
||||||
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
|
|
||||||
current_page: 0,
|
|
||||||
from: 0,
|
|
||||||
last_page: 0,
|
|
||||||
links: [],
|
|
||||||
path: '',
|
|
||||||
per_page: 0,
|
|
||||||
to: 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 ------------------------------ */
|
|
||||||
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
|
||||||
const isAsc = orderBy === property && order === 'asc';
|
|
||||||
setOrder(isAsc ? 'desc' : 'asc');
|
|
||||||
setOrderBy(property);
|
|
||||||
const params = Object.fromEntries([
|
|
||||||
...searchParams.entries(),
|
|
||||||
['order', isAsc ? 'desc' : 'asc'],
|
|
||||||
['orderBy', property],
|
|
||||||
]);
|
|
||||||
setAppliedParams(params);
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* ----------------------------- division field ----------------------------- */
|
|
||||||
const [divisionValue, setDivisionValue] = useState('all');
|
|
||||||
const [divisionData, setDivisionData] = useState([]);
|
|
||||||
|
|
||||||
const handleDivisionChange = (event: SelectChangeEvent) => {
|
|
||||||
setDivisionValue(event.target.value as string);
|
|
||||||
|
|
||||||
if (event.target.value === 'all') {
|
|
||||||
searchParams.delete('division');
|
|
||||||
const params = Object.fromEntries([...searchParams.entries()]);
|
|
||||||
setAppliedParams(params);
|
|
||||||
} else {
|
|
||||||
const params = Object.fromEntries([
|
|
||||||
...searchParams.entries(),
|
|
||||||
['division', event.target.value as string],
|
|
||||||
]);
|
|
||||||
setAppliedParams(params);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* ------------------------------ Search field ------------------------------ */
|
|
||||||
const [searchText, setSearchText] = useState('');
|
|
||||||
|
|
||||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
event.preventDefault();
|
|
||||||
setIsLoading(true);
|
|
||||||
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));
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* ------------------------ button change pagination ------------------------ */
|
|
||||||
const onPageChangeHandle = async (
|
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
|
||||||
newPage: number
|
|
||||||
) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
const params = Object.fromEntries([...searchParams.entries(), ['page', newPage + 1]]);
|
|
||||||
setPage(newPage);
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
||||||
setAppliedParams(params);
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* --------------------------- row page per limit --------------------------- */
|
|
||||||
const onRowsPerPageChangeHandle = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
searchParams.delete('page');
|
|
||||||
const params = Object.fromEntries([
|
|
||||||
...searchParams.entries(),
|
|
||||||
['per_page', parseInt(event.target.value, 10)],
|
|
||||||
]);
|
|
||||||
setRowsPerPage(parseInt(event.target.value, 10));
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
||||||
setAppliedParams(params);
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
|
|
||||||
const division = await axios.get(`${corporateValue}/division`);
|
|
||||||
setDivisionData(division.data);
|
|
||||||
|
|
||||||
const params =
|
|
||||||
Object.keys(appliedParams).length !== 0
|
|
||||||
? appliedParams
|
|
||||||
: Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]);
|
|
||||||
|
|
||||||
const corporateMembers = await axios.get(`${corporateValue}/members`, {
|
|
||||||
params: { ...params, claimMember: false },
|
|
||||||
});
|
|
||||||
|
|
||||||
setSearchParams(params);
|
|
||||||
setDataTable(corporateMembers.data.data);
|
|
||||||
setPaginationTable(corporateMembers.data);
|
|
||||||
setRowsPerPage(corporateMembers.data.per_page);
|
|
||||||
setIsLoading(false);
|
|
||||||
})();
|
|
||||||
}, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<Grid container>
|
|
||||||
{/* Field 1 */}
|
|
||||||
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12} lg={3} xl={2}>
|
|
||||||
<FormControl fullWidth>
|
|
||||||
<InputLabel id="simple-division-select-lable">Division</InputLabel>
|
|
||||||
<Select
|
|
||||||
labelId="simple-division-select-lable"
|
|
||||||
id="division-select-lable"
|
|
||||||
value={divisionValue}
|
|
||||||
label="Division"
|
|
||||||
onChange={handleDivisionChange}
|
|
||||||
>
|
|
||||||
<MenuItem value="all">All</MenuItem>
|
|
||||||
{divisionData.map((row: DivisionDataProps, index) => (
|
|
||||||
<MenuItem key={index} value={row.id}>
|
|
||||||
{row.name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} lg={9} xl={10}>
|
|
||||||
<form onSubmit={handleSearchSubmit}>
|
|
||||||
<TextField
|
|
||||||
id="search-input"
|
|
||||||
label="Search"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={(event) => setSearchText(event.target.value)}
|
|
||||||
value={searchText}
|
|
||||||
fullWidth
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
{/* End Field 1 */}
|
|
||||||
{/* Field 2 */}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<TableContainer component={Paper}>
|
|
||||||
<Table aria-label="collapsible table" size="small">
|
|
||||||
<EnhancedTableHead
|
|
||||||
order={order}
|
|
||||||
orderBy={orderBy}
|
|
||||||
onRequestSort={handleRequestSort}
|
|
||||||
/>
|
|
||||||
<TableBody>
|
|
||||||
{isLoading ? (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={6} align="center">
|
|
||||||
Loading . . .
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
) : dataTable.length >= 1 ? (
|
|
||||||
dataTable.map((row: DataTableProps, index) => (
|
|
||||||
<TableRow key={index}>
|
|
||||||
<TableCell align="left">{row.memberId}</TableCell>
|
|
||||||
<TableCell align="center">{row.fullName}</TableCell>
|
|
||||||
<TableCell align="center">{row.division}</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">
|
|
||||||
{row.status === 1 ? (
|
|
||||||
<Button
|
|
||||||
sx={{
|
|
||||||
backgroundColor: 'rgba(84, 214, 44, 0.16)',
|
|
||||||
color: palette.dark.success.dark,
|
|
||||||
paddingY: 0,
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'rgba(84, 214, 44, 0.32)',
|
|
||||||
color: palette.dark.success.darker,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Active
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
sx={{
|
|
||||||
backgroundColor: 'rgba(255, 72, 66, 0.16)',
|
|
||||||
color: palette.dark.error.dark,
|
|
||||||
paddingY: 0,
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'rgba(255, 72, 66, 0.32)',
|
|
||||||
color: palette.dark.error.darker,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Inactive
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
{/* <TableCell align="right">
|
|
||||||
<IconButton>
|
|
||||||
<Iconify icon="ic:baseline-more-vert" />
|
|
||||||
</IconButton>
|
|
||||||
</TableCell> */}
|
|
||||||
</TableRow>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={6} align="center">
|
|
||||||
No Data Found
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
|
|
||||||
{/* Pagination */}
|
|
||||||
<BaseTablePagination
|
|
||||||
count={paginationTable.total}
|
|
||||||
onPageChange={onPageChangeHandle}
|
|
||||||
page={page}
|
|
||||||
rowsPerPage={rowsPerPage}
|
|
||||||
onRowsPerPageChange={onRowsPerPageChangeHandle}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
{/* End Field 2 */}
|
|
||||||
</Grid>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user