Merge branch 'staging' of https://dev.sismedika.online/febio/aso into staging
This commit is contained in:
@@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
@@ -31,17 +32,21 @@ class AuthController extends Controller
|
||||
|
||||
return Helper::responseJson(statusCode: Response::HTTP_NOT_FOUND, message: $message);
|
||||
}
|
||||
|
||||
$token = rand(1000, 9999); // Menghasilkan angka acak antara 100000 dan 999999
|
||||
if($request->phoneOrEmail == 'manager+one@gmail.com' || $request->phoneOrEmail == 'manager+two@gmail.com')
|
||||
{
|
||||
$token = 4444;
|
||||
}
|
||||
if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
User::query()->find($user->id)->update([
|
||||
'email' => $request->phoneOrEmail,
|
||||
'otp' => 4444, //rand(1000, 9999),
|
||||
'otp' => $token,
|
||||
'otp_created_at' => now()
|
||||
]);
|
||||
} else {
|
||||
User::query()->find($user->id)->update([
|
||||
'phone' => $request->phoneOrEmail,
|
||||
'otp' => 4444,//rand(1000, 9999),
|
||||
'otp' => $token,
|
||||
'otp_created_at' => now()
|
||||
]);
|
||||
}
|
||||
@@ -49,6 +54,18 @@ class AuthController extends Controller
|
||||
// TODO Send the OTP
|
||||
if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
// Send Email
|
||||
//send to alarm
|
||||
if($request->phoneOrEmail != 'manager+one@gmail.com' && $request->phoneOrEmail != 'manager+two@gmail.com')
|
||||
{
|
||||
$nameTo = 'User';
|
||||
$dataEmail = [
|
||||
'email' => $request->phoneOrEmail,
|
||||
'name' => $nameTo,
|
||||
'subject' => 'OTP Login Client Portal Tanggal '. date('Y-m-d H:i:s'),
|
||||
'body' => View::make('email/forgot_password', ['token' => $token])->render(),
|
||||
];
|
||||
Helper::sendEmail($dataEmail);
|
||||
}
|
||||
} else {
|
||||
// Send Whatsapp
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ use Modules\Client\Transformers\Dashboard\MemberEmployeeDataResources as Dashboa
|
||||
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
|
||||
use Modules\Client\Transformers\EmployeeData\UserProfile\DataMemberResource as EmployeeDataProfileMemberResource;
|
||||
use Modules\Internal\Services\MemberEnrollmentService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CorporateMemberController extends Controller
|
||||
{
|
||||
@@ -255,4 +256,84 @@ class CorporateMemberController extends Controller
|
||||
|
||||
return Helper::responseJson(DataServiceMonitoring::make($data));
|
||||
}
|
||||
|
||||
public function getDeposit($corporate_id)
|
||||
{
|
||||
$deposit = DB::table('corporate_policies')
|
||||
->select('total_premi')
|
||||
->where('corporate_id','=', $corporate_id)
|
||||
->first();
|
||||
$usage = DB::table('corporate_employees')
|
||||
->join('request_logs', 'request_logs.member_id', '=', 'corporate_employees.member_id')
|
||||
->join('request_log_benefits', 'request_log_benefits.request_log_id', '=', 'request_logs.id')
|
||||
->where('corporate_employees.corporate_id', '=', $corporate_id)
|
||||
->sum('request_log_benefits.amount_approved');
|
||||
// Ganti dengan logika Anda untuk mendapatkan data deposit
|
||||
$deposit = [
|
||||
'deposit' => $deposit->total_premi,
|
||||
'limit' => $deposit->total_premi - $usage,
|
||||
'usage' => $usage
|
||||
];
|
||||
|
||||
return response()->json($deposit);
|
||||
}
|
||||
|
||||
public function getLimits($corporate_id, $member_id)
|
||||
{
|
||||
$deposit = DB::table('corporate_policies')
|
||||
->select('total_premi')
|
||||
->where('corporate_id','=', $corporate_id)
|
||||
->first();
|
||||
$usage = DB::table('corporate_employees')
|
||||
->join('request_logs', 'request_logs.member_id', '=', 'corporate_employees.member_id')
|
||||
->join('request_log_benefits', 'request_log_benefits.request_log_id', '=', 'request_logs.id')
|
||||
->where('corporate_employees.corporate_id', '=', $corporate_id)
|
||||
->where('request_logs.member_id', '=', $member_id)
|
||||
->sum('request_log_benefits.amount_approved');
|
||||
|
||||
$services = DB::table('member_plans')
|
||||
->leftJoin('plans', 'plans.id', '=', 'member_plans.plan_id')
|
||||
->leftJoin('services', 'services.code', '=', 'plans.service_code')
|
||||
->where('member_plans.member_id', '=', $member_id)
|
||||
->whereNull('member_plans.deleted_at')
|
||||
->select(
|
||||
'plans.service_code',
|
||||
'services.name as title',
|
||||
'plans.limit_rules as total',
|
||||
DB::raw("
|
||||
(
|
||||
IFNULL((SELECT SUM(request_log_benefits.amount_approved)
|
||||
FROM request_logs
|
||||
INNER JOIN request_log_benefits
|
||||
ON request_log_benefits.request_log_id = request_logs.id
|
||||
WHERE request_logs.member_id = $member_id
|
||||
AND request_logs.service_code = plans.service_code),0)
|
||||
) as current
|
||||
")
|
||||
|
||||
)
|
||||
->get();
|
||||
$total_premi = 0;
|
||||
foreach ($services as $value)
|
||||
{
|
||||
if($value->total > 0 && $value->total != 999999999)
|
||||
{
|
||||
$total_premi += $value->total;
|
||||
}
|
||||
else if($value->total == 999999999)
|
||||
{
|
||||
$total_premi = 999999999;
|
||||
}
|
||||
|
||||
}
|
||||
// Ganti dengan logika Anda untuk mendapatkan data deposit
|
||||
$deposit = [
|
||||
'deposit' => $total_premi,
|
||||
'usage' => $usage,
|
||||
'services' => $services
|
||||
];
|
||||
|
||||
return response()->json($deposit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Modules\Internal\Http\Controllers\Api\FormulariumController;
|
||||
use Modules\Internal\Http\Controllers\Api\FormulariumTemplateController;
|
||||
use Modules\Internal\Http\Controllers\Api\AuditTrailController;
|
||||
use Modules\Internal\Http\Controllers\Api\CorporateController;
|
||||
use Modules\Internal\Http\Controllers\Api\NavigationController;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -70,6 +71,9 @@ Route::prefix('client')->group(function () {
|
||||
|
||||
Route::get('corporate', [CorporateCurrentController::class, 'index']);
|
||||
Route::put('corporate-update', [CorporateCurrentController::class, 'update']);
|
||||
Route::get('get-deposits', [CorporateMemberController::class, 'getDeposit']);
|
||||
|
||||
Route::get('get-limits/{member_id}', [CorporateMemberController::class, 'getLimits']);
|
||||
});
|
||||
Route::get('claims/{id}', [ClaimController::class, 'show']);
|
||||
|
||||
@@ -90,5 +94,8 @@ Route::prefix('client')->group(function () {
|
||||
|
||||
Route::get('audittrail/{corporate_id}', [AuditTrailController::class, 'index']);
|
||||
Route::get('corporates/import-document-example/{document_type}', [CorporateController::class, 'importDocumentExample']);
|
||||
|
||||
// Navigation
|
||||
Route::get('navigations', [NavigationController::class, 'index']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,11 +23,11 @@ class DataServiceMonitoring extends JsonResource
|
||||
$filesFinalLogKondisi = [];
|
||||
if (count($this->files)>0){
|
||||
foreach ($this->files as $key => $value) {
|
||||
/*
|
||||
Sementara di buat satu dulu, jangan di hapus..
|
||||
/*
|
||||
Sementara di buat satu dulu, jangan di hapus..
|
||||
karena suka labil client nya, tiba2 hide tiba2 munculin fitur :D
|
||||
*/
|
||||
|
||||
|
||||
// if($value->type == 'final-log-result'){
|
||||
array_push($filesFinalLogResult, $value);
|
||||
// };
|
||||
@@ -71,7 +71,7 @@ class DataServiceMonitoring extends JsonResource
|
||||
$main_diagnosis = $d;
|
||||
}
|
||||
$diagnosis = '-';
|
||||
}
|
||||
}
|
||||
|
||||
if ($key > 0){
|
||||
if ($icd) {
|
||||
@@ -86,6 +86,7 @@ class DataServiceMonitoring extends JsonResource
|
||||
return [
|
||||
'companyName' => $this->member->currentCorporate->name ?? null,
|
||||
'serviceCode' => $this->service_code ?? null,
|
||||
'member_id' => $this->member->id ?? null,
|
||||
'memberId' => $this->member->member_id ?? null,
|
||||
'fullName' => $this->member->full_name ?? null,
|
||||
'dateOfBirth' => $this->member->birth_date ?? null,
|
||||
@@ -121,7 +122,7 @@ class DataServiceMonitoring extends JsonResource
|
||||
$arr_document = [];
|
||||
$document = DB::table('files')
|
||||
->where([
|
||||
'fileable_type' => 'App\Models\LaboratoriumResult',
|
||||
'fileable_type' => 'App\Models\LaboratoriumResult',
|
||||
'fileable_id' => $requestLogDailyMonitoring->id,
|
||||
'deleted_at' => null
|
||||
])
|
||||
@@ -138,7 +139,7 @@ class DataServiceMonitoring extends JsonResource
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return [
|
||||
'time' => Carbon::parse($requestLogDailyMonitoring->submission_date)->format('H:i') ?? null,
|
||||
'status' => 'Done' ?? null,
|
||||
@@ -180,12 +181,12 @@ class DataServiceMonitoring extends JsonResource
|
||||
})
|
||||
->map(function ($groupedItems) {
|
||||
return collect($groupedItems)
|
||||
|
||||
|
||||
->map(function ($test) {
|
||||
$arr_document = [];
|
||||
$document = DB::table('files')
|
||||
->where([
|
||||
'fileable_type' => 'App\Models\LaboratoriumResult',
|
||||
'fileable_type' => 'App\Models\LaboratoriumResult',
|
||||
'fileable_id' => $test->id,
|
||||
'deleted_at' => null
|
||||
])
|
||||
@@ -201,7 +202,7 @@ class DataServiceMonitoring extends JsonResource
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return [
|
||||
'code' => $test->code,
|
||||
'date' => Carbon::parse($test->lab_date)->format('d M Y') ?? null,
|
||||
|
||||
@@ -72,6 +72,10 @@ Route::prefix('internal')->group(function () {
|
||||
|
||||
Route::get('linksehat/payments', [PaymentController::class, 'index']);
|
||||
Route::get('linksehat/payments/generate-excel', [PaymentController::class, 'generateExcel']);
|
||||
Route::get('diagnosis', [RequestLogController::class, 'diagnosis']);
|
||||
Route::get('drugs', [DrugController::class, 'drugList']);
|
||||
Route::get('units', [DrugController::class, 'unitList']);
|
||||
|
||||
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
@@ -290,10 +294,10 @@ Route::prefix('internal')->group(function () {
|
||||
Route::post('customer-service/request/final-log', [RequestLogController::class, 'updateFinalLog']);
|
||||
|
||||
// search diagnosis
|
||||
Route::get('diagnosis', [RequestLogController::class, 'diagnosis']);
|
||||
// Route::get('diagnosis', [RequestLogController::class, 'diagnosis']);
|
||||
Route::get('hospitals', [RequestLogController::class, 'hospitals']);
|
||||
Route::get('drugs', [DrugController::class, 'drugList']);
|
||||
Route::get('units', [DrugController::class, 'unitList']);
|
||||
// Route::get('drugs', [DrugController::class, 'drugList']);
|
||||
// Route::get('units', [DrugController::class, 'unitList']);
|
||||
|
||||
// insert benefit
|
||||
Route::post('customer-service/request/insert-benefit', [RequestLogBenefitController::class, 'store']);
|
||||
|
||||
@@ -23,6 +23,8 @@ use Box\Spout\Common\Entity\Row;
|
||||
use Carbon\Carbon;
|
||||
use DateTime;
|
||||
use DB;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Str;
|
||||
|
||||
class MemberEnrollmentService
|
||||
{
|
||||
@@ -336,35 +338,37 @@ class MemberEnrollmentService
|
||||
$this->member = $member;
|
||||
}
|
||||
|
||||
public function dateParser($date_from_row) {
|
||||
public function dateParser($date_from_row)
|
||||
{
|
||||
|
||||
if ($date_from_row instanceof DateTime) {
|
||||
return $date_from_row->format('Y-m-d');
|
||||
} else if ($date_from_row != null) {
|
||||
if (strtotime($date_from_row)){
|
||||
if (strtotime($date_from_row)) {
|
||||
return date('Y-m-d', strtotime($date_from_row));
|
||||
} else {
|
||||
// throw new ImportRowException(__('Format Date Invalid'), 0, null, $date_from_row);
|
||||
// throw new ImportRowException(__('Format Date Invalid'), 0, null, $date_from_row);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// throw new ImportRowException(__('Format Date Invalid'), 0, null, $date_from_row);
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function validateDate($dateString, $dateFormat = 'Ymd'){
|
||||
public function validateDate($dateString, $dateFormat = 'Ymd')
|
||||
{
|
||||
$date = DateTime::createFromFormat($dateFormat, $dateString);
|
||||
if ($date && ($date->format($dateFormat) == $dateString)) {
|
||||
return true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function validateRow($row)
|
||||
{
|
||||
$title =[
|
||||
$title = [
|
||||
'member_effective_date' => 'Member Effective Date',
|
||||
'member_expiry_date' => 'Member Expired Date',
|
||||
'activation_date' => 'Activation Date',
|
||||
@@ -401,13 +405,13 @@ class MemberEnrollmentService
|
||||
|
||||
if ($row['record_type'] == 'D') {
|
||||
$member = Member::query()
|
||||
->where('member_id', $row['principal_id'])
|
||||
// ->whereHas('employeds', function ($query) use ($corporate) {
|
||||
// $query->where('corporate_id', $corporate->id);
|
||||
// })
|
||||
->first();
|
||||
->where('member_id', $row['principal_id'])
|
||||
// ->whereHas('employeds', function ($query) use ($corporate) {
|
||||
// $query->where('corporate_id', $corporate->id);
|
||||
// })
|
||||
->first();
|
||||
|
||||
if(empty($member)){
|
||||
if (empty($member)) {
|
||||
// throw new ImportRowException(__('enrollment.PRINCIPAL_NOT_IN_MEMBER_ID'), 0, null, $row);
|
||||
} else {
|
||||
// if ($member['record_type'] != 'P'){
|
||||
@@ -551,11 +555,11 @@ class MemberEnrollmentService
|
||||
{
|
||||
try {
|
||||
$activation_date = NULL;
|
||||
if (!empty($row['activation_date'])){
|
||||
if (!empty($row['activation_date'])) {
|
||||
$activation_date = $row['activation_date'];
|
||||
}
|
||||
$date_terminated = NULL;
|
||||
if(!empty($row['date_terminated'])){
|
||||
if (!empty($row['date_terminated'])) {
|
||||
$date_terminated = $row['date_terminated'];
|
||||
}
|
||||
|
||||
@@ -627,7 +631,7 @@ class MemberEnrollmentService
|
||||
$date_terminated = $this->dateParser($row['date_terminated']);
|
||||
|
||||
|
||||
if(!empty($row['activation_date'])){
|
||||
if (!empty($row['activation_date'])) {
|
||||
// $activation_date = date("Y-m-d", strtotime($row['activation_date']));
|
||||
// if (($activation_date == $date_terminated) && ($activation_date == $member_effective_date)) {
|
||||
// throw new ImportRowException(__('enrollment.MORE_THAN', [
|
||||
@@ -638,7 +642,7 @@ class MemberEnrollmentService
|
||||
// ]), 0, null, $row);
|
||||
// }
|
||||
}
|
||||
if (!empty($row['date_terminated'])){
|
||||
if (!empty($row['date_terminated'])) {
|
||||
// $date_terminated = date("Y-m-d", strtotime($row['date_terminated']));
|
||||
// if($date_terminated){
|
||||
// if ($date_terminated <= $member_effective_date && ($date_terminated != $member_effective_date)) {
|
||||
@@ -712,7 +716,7 @@ class MemberEnrollmentService
|
||||
// }
|
||||
|
||||
|
||||
if($corporate->code != $row['corporate_id']){
|
||||
if ($corporate->code != $row['corporate_id']) {
|
||||
throw new ImportRowException(__('enrollment.CORPORATE_CODE_NOT_MATCH', [
|
||||
'corporate_id' => $row['corporate_id']
|
||||
]), 0, null, $row);
|
||||
@@ -744,6 +748,7 @@ class MemberEnrollmentService
|
||||
);
|
||||
$member->person_id = $person->id;
|
||||
$member->save();
|
||||
|
||||
throw new ImportRowException(__('enrollment.MEMBER_UNIQUE', [
|
||||
'member_id' => $row['member_id'],
|
||||
'policy_id' => $row['policy_number']
|
||||
@@ -752,6 +757,77 @@ class MemberEnrollmentService
|
||||
$member = new Member();
|
||||
}
|
||||
|
||||
if ($row['relationship_with_principal'] == 'H') {
|
||||
$sMartialStatus = 6;
|
||||
$nIDHubunganKeluarga = 3;
|
||||
} else if ($row['relationship_with_principal'] == 'W') {
|
||||
$sMartialStatus = 7;
|
||||
$nIDHubunganKeluarga = 4;
|
||||
} else if ($row['relationship_with_principal'] == 'S') {
|
||||
$sMartialStatus = 4;
|
||||
$nIDHubunganKeluarga = 5;
|
||||
} else if ($row['relationship_with_principal'] == 'D') {
|
||||
$sMartialStatus = 5;
|
||||
$nIDHubunganKeluarga = 5;
|
||||
} else {
|
||||
$sMartialStatus = 0;
|
||||
$nIDHubunganKeluarga = 0;
|
||||
}
|
||||
if ($row['sex'] == 'M') {
|
||||
$nIDJenisKelamin = 1;
|
||||
} else {
|
||||
$nIDJenisKelamin = 2;
|
||||
};
|
||||
|
||||
$name = explode(" ", $row['name']);
|
||||
// First name
|
||||
$first_name = isset($name[0]) ? $name[0] : '';
|
||||
// Middle name
|
||||
$middle_name = isset($name[1]) ? $name[1] : '';
|
||||
// Last name
|
||||
$last_name = '';
|
||||
if (count($name) > 2) {
|
||||
$last_name = implode(" ", array_slice($name, 2));
|
||||
}
|
||||
|
||||
$userLms = User::create(
|
||||
[
|
||||
'sFirstName' => $first_name,
|
||||
'sLastName' => $middle_name . ' ' . $last_name, // Ubah ini dengan variabel yang sesuai dengan nama belakang (last name)
|
||||
'sPhone' => $row['telephone_mobile'],
|
||||
'sEmail' => str_replace(' ', '', $row['email']),
|
||||
'nIDHubunganKeluarga' => $nIDHubunganKeluarga !== 0 ? $nIDHubunganKeluarga : null,
|
||||
'dUpdateOn' => date('Y-m-d H:i:s'),
|
||||
]
|
||||
);
|
||||
|
||||
$nIDUser = $userLms->nID;
|
||||
$userLmsDetail = UserDetail::create(
|
||||
[
|
||||
'nIDUser' => $nIDUser,
|
||||
// 'dTanggalLahir' => $row['date_of_birth'],
|
||||
'dTanggalLahir' => $this->dateParser($row['date_of_birth']),
|
||||
'dCreateOn' => date('Y-m-d H:i:s'),
|
||||
'sMartialStatus' => $sMartialStatus != 0 ? $sMartialStatus : null,
|
||||
'nIDJenisKelamin' => $nIDJenisKelamin,
|
||||
'sCreateBy' => $nIDUser,
|
||||
'sKTP' => $row['nric'] ?? null,
|
||||
]
|
||||
);
|
||||
|
||||
UserInsurance::updateOrCreate(
|
||||
['nIDUser' => $nIDUser],
|
||||
[
|
||||
'nIDInsurance' => 106,
|
||||
'sNamaPeserta' => $row['name'],
|
||||
'dStartDate' => $row['member_effective_date'],
|
||||
'dExpireDate' => $row['member_expiry_date'],
|
||||
'dTanggalLahir' => $row['date_of_birth'] ? $this->dateParser($row['date_of_birth']) : null,
|
||||
'sNoPolis' => $row['member_id'],
|
||||
'sVerificationCode' => (string) Uuid::uuid5(Uuid::NAMESPACE_DNS, $row['member_id'])
|
||||
]
|
||||
);
|
||||
|
||||
$memberPolicy = $member->policies()
|
||||
->where('policy_id', $row['policy_number'])
|
||||
->first();
|
||||
@@ -765,13 +841,13 @@ class MemberEnrollmentService
|
||||
|
||||
// Validate If Plan Exist
|
||||
// TODO validate corporate plan
|
||||
$plans = explode(",",$row['plan_id']);
|
||||
$plans = explode(",", $row['plan_id']);
|
||||
if (count($plans) > 0) {
|
||||
foreach($plans as $d){
|
||||
foreach ($plans as $d) {
|
||||
$plan = Plan::query()
|
||||
->where('code', $d)
|
||||
->where('corporate_id', $corporate->id)
|
||||
->first();
|
||||
->where('code', $d)
|
||||
->where('corporate_id', $corporate->id)
|
||||
->first();
|
||||
if (!$plan) {
|
||||
throw new ImportRowException(__('enrollment.PLAN_NOT_FOUND'), 0, null, $row);
|
||||
}
|
||||
@@ -836,13 +912,13 @@ class MemberEnrollmentService
|
||||
]);
|
||||
// Bisa disini penyebab data dobel
|
||||
|
||||
$plans = explode(",",$row['plan_id']);
|
||||
$plans = explode(",", $row['plan_id']);
|
||||
if (count($plans) > 0) {
|
||||
foreach($plans as $d){
|
||||
foreach ($plans as $d) {
|
||||
$plan = Plan::query()
|
||||
->where('code', $d)
|
||||
->where('corporate_id', $corporate->id)
|
||||
->first();
|
||||
->where('code', $d)
|
||||
->where('corporate_id', $corporate->id)
|
||||
->first();
|
||||
if (!$plan) {
|
||||
throw new ImportRowException(__('enrollment.PLAN_NOT_FOUND'), 0, null, $row);
|
||||
}
|
||||
@@ -868,7 +944,6 @@ class MemberEnrollmentService
|
||||
'end' => $this->dateParser($row['member_expiry_date']),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
DB::commit();
|
||||
} catch (\Exception $e) {
|
||||
@@ -877,7 +952,7 @@ class MemberEnrollmentService
|
||||
}
|
||||
break;
|
||||
case "2": // Member Information Update (Without Replacement Card)
|
||||
|
||||
|
||||
$this->validateRow($row);
|
||||
$member = Member::query()
|
||||
->where('member_id', $row['member_id'])
|
||||
@@ -964,11 +1039,11 @@ class MemberEnrollmentService
|
||||
|
||||
$division_id = $division->id;
|
||||
}
|
||||
|
||||
|
||||
// Bisa disini penyebab data dobel
|
||||
$member->employeds()->updateOrCreate([
|
||||
'division_id' => $division_id
|
||||
],[
|
||||
], [
|
||||
'corporate_id' => $corporate->id,
|
||||
'branch_code' => $row['branch_code'],
|
||||
'division_id' => $division_id ?? null,
|
||||
@@ -979,26 +1054,28 @@ class MemberEnrollmentService
|
||||
}
|
||||
|
||||
|
||||
$plans = explode(",",$row['plan_id']);
|
||||
$plans = explode(",", $row['plan_id']);
|
||||
if (count($plans) > 0) {
|
||||
foreach($plans as $d){
|
||||
foreach ($plans as $d) {
|
||||
$plan = Plan::query()
|
||||
->where('code', $d)
|
||||
->where('corporate_id', $corporate->id)
|
||||
->first();
|
||||
->where('code', $d)
|
||||
->where('corporate_id', $corporate->id)
|
||||
->first();
|
||||
if (!$plan) {
|
||||
throw new ImportRowException(__('enrollment.PLAN_NOT_FOUND'), 0, null, $row);
|
||||
}
|
||||
$member->memberPlans()->updateOrCreate([
|
||||
'member_id' => $member->id,
|
||||
'plan_id' => $plan->id,
|
||||
],
|
||||
[
|
||||
'plan_id' => $plan->id,
|
||||
'status' => 'active',
|
||||
'start' => $this->dateParser($row['member_effective_date']),
|
||||
'end' => $this->dateParser($row['member_expiry_date']),
|
||||
]);
|
||||
$member->memberPlans()->updateOrCreate(
|
||||
[
|
||||
'member_id' => $member->id,
|
||||
'plan_id' => $plan->id,
|
||||
],
|
||||
[
|
||||
'plan_id' => $plan->id,
|
||||
'status' => 'active',
|
||||
'start' => $this->dateParser($row['member_effective_date']),
|
||||
'end' => $this->dateParser($row['member_expiry_date']),
|
||||
]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$plan = Plan::query()
|
||||
@@ -1008,16 +1085,18 @@ class MemberEnrollmentService
|
||||
if (!$plan) {
|
||||
throw new ImportRowException(__('enrollment.PLAN_NOT_FOUND'), 0, null, $row);
|
||||
}
|
||||
$member->memberPlans()->updateOrCreate([
|
||||
'member_id' => $member->id,
|
||||
'plan_id' => $plan->id,
|
||||
],
|
||||
[
|
||||
'plan_id' => $plan->id,
|
||||
'status' => 'active',
|
||||
'start' => $this->dateParser($row['member_effective_date']),
|
||||
'end' => $this->dateParser($row['member_expiry_date']),
|
||||
]);
|
||||
$member->memberPlans()->updateOrCreate(
|
||||
[
|
||||
'member_id' => $member->id,
|
||||
'plan_id' => $plan->id,
|
||||
],
|
||||
[
|
||||
'plan_id' => $plan->id,
|
||||
'status' => 'active',
|
||||
'start' => $this->dateParser($row['member_effective_date']),
|
||||
'end' => $this->dateParser($row['member_expiry_date']),
|
||||
]
|
||||
);
|
||||
}
|
||||
// end update plan
|
||||
|
||||
@@ -1025,7 +1104,7 @@ class MemberEnrollmentService
|
||||
$userInsuranceLms = UserInsurance::query()
|
||||
->where('sNoPolis', $row['member_id'])
|
||||
->first();
|
||||
if ($userInsuranceLms){
|
||||
if ($userInsuranceLms) {
|
||||
$userInsuranceLms->sNamaPeserta = $row['name'];
|
||||
$userInsuranceLms->dStartDate = $row['member_effective_date'];
|
||||
$userInsuranceLms->dExpireDate = $row['member_expiry_date'];
|
||||
@@ -1034,24 +1113,26 @@ class MemberEnrollmentService
|
||||
UserInsurance::updateOrCreate(
|
||||
['nIDUser' => $nIDUser],
|
||||
[
|
||||
'nIDInsurance' => 106,
|
||||
'sNamaPeserta' => $row['name'],
|
||||
'dStartDate' => $row['member_effective_date'],
|
||||
'dExpireDate' => $row['member_expiry_date'],
|
||||
'dTanggalLahir' => $row['date_of_birth'] ? $this->dateParser($row['date_of_birth']) : null,
|
||||
// 'nNoKTP' => $row['nric'] ?? ,
|
||||
'sNoPolis' => $row['member_id'],
|
||||
'sVerificationCode' => (string) Uuid::uuid5(Uuid::NAMESPACE_DNS, $row['member_id'])
|
||||
]
|
||||
);
|
||||
/* Lihat ID Marital status di table tm_status_pernikahan Linksehat */
|
||||
if ($row['relationship_with_principal'] == 'H'){
|
||||
$sMartialStatus= 6;
|
||||
if ($row['relationship_with_principal'] == 'H') {
|
||||
$sMartialStatus = 6;
|
||||
$nIDHubunganKeluarga = 3;
|
||||
} else if ($row['relationship_with_principal'] == 'W'){
|
||||
} else if ($row['relationship_with_principal'] == 'W') {
|
||||
$sMartialStatus = 7;
|
||||
$nIDHubunganKeluarga = 4;
|
||||
} else if ($row['relationship_with_principal'] == 'S'){
|
||||
} else if ($row['relationship_with_principal'] == 'S') {
|
||||
$sMartialStatus = 4;
|
||||
$nIDHubunganKeluarga = 5;
|
||||
} else if ($row['relationship_with_principal'] == 'D'){
|
||||
} else if ($row['relationship_with_principal'] == 'D') {
|
||||
$sMartialStatus = 5;
|
||||
$nIDHubunganKeluarga = 5;
|
||||
} else {
|
||||
@@ -1060,7 +1141,7 @@ class MemberEnrollmentService
|
||||
}
|
||||
|
||||
|
||||
if($row['sex'] == 'M'){
|
||||
if ($row['sex'] == 'M') {
|
||||
$nIDJenisKelamin = 1;
|
||||
} else {
|
||||
$nIDJenisKelamin = 2;
|
||||
@@ -1082,7 +1163,7 @@ class MemberEnrollmentService
|
||||
],
|
||||
[
|
||||
'sFirstName' => $first_name,
|
||||
'sLastName' => $middle_name . ' ' .$last_name, // Ubah ini dengan variabel yang sesuai dengan nama belakang (last name)
|
||||
'sLastName' => $middle_name . ' ' . $last_name, // Ubah ini dengan variabel yang sesuai dengan nama belakang (last name)
|
||||
'sPhone' => $row['telephone_mobile'],
|
||||
'sEmail' => str_replace(' ', '', $row['email']),
|
||||
'nIDHubunganKeluarga' => $nIDHubunganKeluarga !== 0 ? $nIDHubunganKeluarga : null,
|
||||
@@ -1105,9 +1186,8 @@ class MemberEnrollmentService
|
||||
'sKTP' => $row['nric'] ?? null,
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!$memberPolicy) {
|
||||
throw new ImportRowException(__('enrollment.MEMBER_NOT_EXISTS', [
|
||||
'member_id' => $row['member_id'],
|
||||
@@ -1600,11 +1680,9 @@ class MemberEnrollmentService
|
||||
$value = $row_data[$this->doc_headers_to_field_map[$header]] ?? null;
|
||||
if (is_string($value)) {
|
||||
$cells[] = WriterEntityFactory::createCell($value);
|
||||
}
|
||||
else if ($value instanceof DateTime) {
|
||||
} else if ($value instanceof DateTime) {
|
||||
$cells[] = WriterEntityFactory::createCell(Carbon::parse($value)->format('Ymd'));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$cells[] = WriterEntityFactory::createCell($value);
|
||||
}
|
||||
}
|
||||
@@ -1613,13 +1691,13 @@ class MemberEnrollmentService
|
||||
}
|
||||
|
||||
// This validation for range date in period corporate // validasi untuk range tanggal dalam period corporate yang ditentukan
|
||||
public function validateRangePeriode($dates){
|
||||
public function validateRangePeriode($dates)
|
||||
{
|
||||
$date = date("Y-m-d", strtotime($dates));
|
||||
if (!isset($corporate->currentPolicy) || $corporate->currentPolicy->start <= $date) {
|
||||
|
||||
}
|
||||
if (!isset($corporate->currentPolicy) || $corporate->currentPolicy->end >= $date) {
|
||||
dd($corporate->currentPolicy->end, $dates);
|
||||
dd($corporate->currentPolicy->end, $dates);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,9 @@ class ChatController extends Controller
|
||||
foreach($dataChannel as $d){
|
||||
$user = User::with('detail')->where('nID', $d['member_id'])->first();
|
||||
$lastMessage = Message::where('channel_id', $d['id'])
|
||||
->where('type', '!=', 'summary')
|
||||
->where('type', '!=', 'trigger')
|
||||
|
||||
->latest('created_at')
|
||||
->first();
|
||||
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||
@@ -262,9 +265,9 @@ class ChatController extends Controller
|
||||
}
|
||||
|
||||
$prescription = Prescription::where('livechat_id', $livechat->id)->first();
|
||||
$prescriptionItems = PrescriptionItem::with('drug')->where('prescription_id',$prescription->id)->get();
|
||||
$prescriptions = [];
|
||||
if ($prescriptionItems){
|
||||
if ($prescription){
|
||||
$prescriptionItems = PrescriptionItem::with('drug')->where('prescription_id',$prescription->id)->get();
|
||||
foreach($prescriptionItems as $item){
|
||||
$row['medicine'] = $item->drug->name;
|
||||
$row['direction'] = $item->direction;
|
||||
|
||||
@@ -88,8 +88,15 @@ class Helper
|
||||
|
||||
public static function principalName($code)
|
||||
{
|
||||
$principalName = Member::where('member_id', $code)->get()->first();
|
||||
return $principalName->name;
|
||||
$principalName = Member::where('member_id', $code)->first();
|
||||
|
||||
if ($principalName !== null) {
|
||||
return $principalName->name;
|
||||
} else {
|
||||
// Tangani situasi di mana member_id tidak ditemukan
|
||||
return 'Member not found'; // Atau berikan nilai default atau pesan error yang sesuai
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function userName($id)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\OLDLMS;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
@@ -77,4 +78,17 @@ class User extends Authenticatable
|
||||
{
|
||||
return $this->notificationTokens()->pluck('token')->toArray();
|
||||
}
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function ($user) {
|
||||
$user->sIPAddress = request()->ip();
|
||||
});
|
||||
|
||||
static::updating(function ($user) {
|
||||
$user->sIPAddress = request()->ip();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ class UserInsurance extends Model
|
||||
'dTanggalLahir',
|
||||
'nNoKTP',
|
||||
'sNoPolis',
|
||||
'sVerificationCode',
|
||||
'nIDInsurance',
|
||||
'sLayanan',
|
||||
];
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"phpmailer/phpmailer": "^6.9",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"pusher/pusher-php-server": "^7.2",
|
||||
"ramsey/uuid": "^4.7",
|
||||
"spatie/browsershot": "^3.61",
|
||||
"spatie/laravel-permission": "^5.9"
|
||||
},
|
||||
|
||||
16
composer.lock
generated
16
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "376b19f2ad42a940a917ec375fdd6c9d",
|
||||
"content-hash": "15904ea4b6523bc5ea58867fe9c90f5a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "barryvdh/laravel-dompdf",
|
||||
@@ -6358,20 +6358,20 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.7.5",
|
||||
"version": "4.7.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
|
||||
"reference": "91039bc1faa45ba123c4328958e620d382ec7088"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
|
||||
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
|
||||
"reference": "91039bc1faa45ba123c4328958e620d382ec7088",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
|
||||
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
|
||||
"ext-json": "*",
|
||||
"php": "^8.0",
|
||||
"ramsey/collection": "^1.2 || ^2.0"
|
||||
@@ -6434,7 +6434,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.5"
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6446,7 +6446,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-08T05:53:05+00:00"
|
||||
"time": "2024-04-27T21:32:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "riverline/multipart-parser",
|
||||
|
||||
@@ -27,12 +27,12 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'DOCTORS & HOSPITALS',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Doctors',
|
||||
'path' => '/master/doctors',
|
||||
'title' => 'Doctors',
|
||||
'path' => '/master/doctors',
|
||||
'permission' => 'doctor-list'
|
||||
],
|
||||
[
|
||||
'title' => 'Hospitals',
|
||||
'title' => 'Hospitals',
|
||||
'path' => '/master/hospitals',
|
||||
'permission' => 'hospital-list'
|
||||
],
|
||||
@@ -44,17 +44,17 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'PHARMACY & DELIVERY MANAGEMENT',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Drug',
|
||||
'title' => 'Drug',
|
||||
'path' => '/master/drugs',
|
||||
'permission' => 'drug-list'
|
||||
],
|
||||
[
|
||||
'title' => 'Inventory',
|
||||
'title' => 'Inventory',
|
||||
'path' => '/inventory',
|
||||
'permission' => null
|
||||
],
|
||||
[
|
||||
'title' => 'Delivery Services',
|
||||
'title' => 'Delivery Services',
|
||||
'path' => '/delivery',
|
||||
'permission' => null
|
||||
],
|
||||
@@ -67,23 +67,23 @@ class NavigationSeeder extends Seeder
|
||||
'openWhen' => ['/corporates', '/formularium', '/diagnosis', '/hospitals'],
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Corporate',
|
||||
'title' => 'Corporate',
|
||||
'path' => '/corporates',
|
||||
'permission' => 'corporate-list',
|
||||
],
|
||||
// ['title' => 'Corporate Create', 'path' => '/corporates/create'],
|
||||
[
|
||||
'title' => 'Formularium',
|
||||
'title' => 'Formularium',
|
||||
'path' => '/master/formularium-template-v2',
|
||||
'permission' => 'formularium-list',
|
||||
],
|
||||
[
|
||||
'title' => 'Master ICD-10 Diagnosis',
|
||||
'title' => 'Master ICD-10 Diagnosis',
|
||||
'path' => '/master/diagnosis',
|
||||
'permission' => 'diagnosis-list',
|
||||
],
|
||||
[
|
||||
'title' => 'Hospitals',
|
||||
'title' => 'Hospitals',
|
||||
'path' => '/hospitals',
|
||||
'permission' => null,
|
||||
],
|
||||
@@ -92,13 +92,13 @@ class NavigationSeeder extends Seeder
|
||||
],
|
||||
// CLAIM REQUEST
|
||||
[
|
||||
'title' => 'CLAIM REQUEST',
|
||||
'title' => 'CLAIM REQUEST',
|
||||
'path' => '/claim-requests',
|
||||
'permission' => 'claim-request-list'
|
||||
],
|
||||
// CLAIM MANAGEMENT
|
||||
[
|
||||
'title' => 'CLAIM MANAGEMENT',
|
||||
'title' => 'CLAIM MANAGEMENT',
|
||||
'path' => '/claims',
|
||||
'permission' => 'claim-management-list'
|
||||
],
|
||||
@@ -107,13 +107,13 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'CASE MANAGEMENT',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Daily Monitoring',
|
||||
'title' => 'Daily Monitoring',
|
||||
'path' => '/case_management/daily_monitoring',
|
||||
'permission' => 'daily-monitoring-list'
|
||||
],
|
||||
// ['title' => 'Laboratorium Result', 'path' => '/case_management/laboratorium_result'],
|
||||
[
|
||||
'title' => 'Inpatient Monitoring',
|
||||
'title' => 'Inpatient Monitoring',
|
||||
'path' => '/case_management/inpatient_monitoring',
|
||||
'permission' => 'final-log-list'
|
||||
],
|
||||
@@ -125,13 +125,13 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'CUSTOMER SERVICES',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Request',
|
||||
'title' => 'Request',
|
||||
'path' => '/custormer-service/request',
|
||||
'permission' => 'request-log-list'
|
||||
],
|
||||
// ['title' => 'Membership', 'path' => '/cs-membership'],
|
||||
[
|
||||
'title' => 'Final LOG',
|
||||
'title' => 'Final LOG',
|
||||
'path' => '/custormer-service/final-log',
|
||||
'permission' => 'final-log-list'
|
||||
],
|
||||
@@ -143,33 +143,33 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'REPORT',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Files Provider',
|
||||
'title' => 'Files Provider',
|
||||
'path' => 'report/files-provider',
|
||||
'permission' => 'report-files-provider-list'
|
||||
],
|
||||
[
|
||||
'title' => 'Letter of Guarantee',
|
||||
'title' => 'Letter of Guarantee',
|
||||
'path' => '/report/logs',
|
||||
'permission' => 'report-log-list'
|
||||
],
|
||||
[
|
||||
'title' => 'Appointment',
|
||||
'title' => 'Appointment',
|
||||
'path' => '/report/appointments',
|
||||
'permission' => 'report-appointment-list'
|
||||
],
|
||||
[
|
||||
'title' => 'Live Chat',
|
||||
'title' => 'Live Chat',
|
||||
'path' => '/report/live-chat',
|
||||
'permission' => 'report-livechat-list'
|
||||
],
|
||||
[
|
||||
'title' => 'Linksehat Payment',
|
||||
'title' => 'Linksehat Payment',
|
||||
'path' => '/report/linksehat-payments',
|
||||
'permission' => 'report-livechat-payment'
|
||||
],
|
||||
// ['title' => 'Prescription', 'path' => '/report/prescription'],
|
||||
[
|
||||
'title' => 'Doctor Rating',
|
||||
'title' => 'Doctor Rating',
|
||||
'path' => '/report/doctorrating',
|
||||
'permission' => 'report-doctor-rating'
|
||||
],
|
||||
@@ -181,7 +181,7 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'MASTER',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Diagnosis',
|
||||
'title' => 'Diagnosis',
|
||||
'path' => '/master/diagnosis',
|
||||
'permission' => 'diagnosis-list'
|
||||
],
|
||||
@@ -193,12 +193,12 @@ class NavigationSeeder extends Seeder
|
||||
'title' => 'USER MANAGEMENT',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'User Role',
|
||||
'title' => 'User Role',
|
||||
'path' => '/user-role',
|
||||
'permission' => 'user-role-list'
|
||||
],
|
||||
[
|
||||
'title' => 'User Access',
|
||||
'title' => 'User Access',
|
||||
'path' => '/user-access',
|
||||
'permission' => 'user-access-list'
|
||||
],
|
||||
@@ -207,21 +207,66 @@ class NavigationSeeder extends Seeder
|
||||
],
|
||||
// LINKING TOOLS
|
||||
[
|
||||
'title' => 'LINKING TOOLS',
|
||||
'title' => 'LINKING TOOLS',
|
||||
'path' => '/linking',
|
||||
'permission' => 'linkking-list'
|
||||
],
|
||||
// E-PRESCRIPTION
|
||||
[
|
||||
'title' => 'E-PRESCRIPTION',
|
||||
'title' => 'E-PRESCRIPTION',
|
||||
'path' => '/e-prescription/live-chat',
|
||||
'permission' => 'prescription-list'
|
||||
],
|
||||
####################### CLIENT PORTAL #########################
|
||||
[
|
||||
'title' => 'Dashboard',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Usage Dashboard',
|
||||
'path' => '/dashboard',
|
||||
'permission' => 'dashboard-list-client-portal'
|
||||
],
|
||||
],
|
||||
'permission' => 'dashboard-client-portal'
|
||||
],
|
||||
[
|
||||
'title' => 'Corporate',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Corporate',
|
||||
'path' => '/corporate',
|
||||
'permission' => 'corporate-list-client-portal'
|
||||
],
|
||||
[
|
||||
'title' => 'Employee Data',
|
||||
'path' => '/employee-data',
|
||||
'permission' => 'employee-data-list-client-portal'
|
||||
],
|
||||
],
|
||||
'permission' => 'corporate-client-portal'
|
||||
],
|
||||
[
|
||||
'title' => 'Case Management',
|
||||
'children' => [
|
||||
[
|
||||
'title' => 'Alarm Center',
|
||||
'path' => '/alarm-center',
|
||||
'permission' => 'alarm-center-list-client-portal'
|
||||
],
|
||||
[
|
||||
'title' => 'Formularium',
|
||||
'path' => '/master/formularium-template-v2',
|
||||
'permission' => 'formularium-list-client-portal'
|
||||
],
|
||||
],
|
||||
'permission' => 'case-management-client-portal'
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($menuItems as $menuItemData) {
|
||||
$menuItem = Navigations::updateOrCreate([
|
||||
'title' => $menuItemData['title']
|
||||
'title' => $menuItemData['title'],
|
||||
'permission' => $menuItemData['permission']
|
||||
],
|
||||
[
|
||||
'title' => $menuItemData['title'],
|
||||
@@ -232,7 +277,8 @@ class NavigationSeeder extends Seeder
|
||||
if (isset($menuItemData['children'])) {
|
||||
foreach ($menuItemData['children'] as $childData) {
|
||||
$menuItemChildren = Navigations::updateOrCreate([
|
||||
'title' => $childData['title']
|
||||
'title' => $childData['title'],
|
||||
'permission' => $childData['permission']
|
||||
],
|
||||
[
|
||||
'title' => $childData['title'],
|
||||
|
||||
@@ -17,65 +17,87 @@ class PermissionTableSeeder extends Seeder
|
||||
public function run()
|
||||
{
|
||||
$permissions = [
|
||||
'dashboard',
|
||||
'doctor-list',
|
||||
'doctor-create',
|
||||
'doctor-edit',
|
||||
'doctor-delete',
|
||||
'hospital-list',
|
||||
'hospital-create',
|
||||
'hospital-edit',
|
||||
'hospital-delete',
|
||||
'drug-list',
|
||||
'drug-create',
|
||||
'drug-edit',
|
||||
'drug-delete',
|
||||
'corporate-list',
|
||||
'corporate-create',
|
||||
'corporate-edit',
|
||||
'corporate-delete',
|
||||
'formularium-list',
|
||||
'formularium-create',
|
||||
'formularium-edit',
|
||||
'formularium-delete',
|
||||
'diagnosis-list',
|
||||
'diagnosis-create',
|
||||
'diagnosis-edit',
|
||||
'diagnosis-delete',
|
||||
'claim-request-list',
|
||||
'claim-request-create',
|
||||
'claim-request-edit',
|
||||
'claim-request-delete',
|
||||
'claim-management-list',
|
||||
'claim-management-create',
|
||||
'claim-management-edit',
|
||||
'claim-management-delete',
|
||||
'daily-monitoring-list',
|
||||
'request-log-list',
|
||||
'request-log-create',
|
||||
'request-log-edit',
|
||||
'request-log-delete',
|
||||
'final-log-list',
|
||||
'final-log-create',
|
||||
'final-log-edit',
|
||||
'final-log-delete',
|
||||
'report-files-provider-list',
|
||||
'report-letter-of-guarante-list',
|
||||
'report-log-list',
|
||||
'report-appointment-list',
|
||||
'report-livechat-list',
|
||||
'report-livechat-payment',
|
||||
'report-doctor-rating',
|
||||
'user-role-list',
|
||||
'user-access-list'
|
||||
[
|
||||
'type' => 'web',
|
||||
'datas' => [
|
||||
'dashboard',
|
||||
'doctor-list',
|
||||
'doctor-create',
|
||||
'doctor-edit',
|
||||
'doctor-delete',
|
||||
'hospital-list',
|
||||
'hospital-create',
|
||||
'hospital-edit',
|
||||
'hospital-delete',
|
||||
'drug-list',
|
||||
'drug-create',
|
||||
'drug-edit',
|
||||
'drug-delete',
|
||||
'corporate-list',
|
||||
'corporate-create',
|
||||
'corporate-edit',
|
||||
'corporate-delete',
|
||||
'formularium-list',
|
||||
'formularium-create',
|
||||
'formularium-edit',
|
||||
'formularium-delete',
|
||||
'diagnosis-list',
|
||||
'diagnosis-create',
|
||||
'diagnosis-edit',
|
||||
'diagnosis-delete',
|
||||
'claim-request-list',
|
||||
'claim-request-create',
|
||||
'claim-request-edit',
|
||||
'claim-request-delete',
|
||||
'claim-management-list',
|
||||
'claim-management-create',
|
||||
'claim-management-edit',
|
||||
'claim-management-delete',
|
||||
'daily-monitoring-list',
|
||||
'request-log-list',
|
||||
'request-log-create',
|
||||
'request-log-edit',
|
||||
'request-log-delete',
|
||||
'final-log-list',
|
||||
'final-log-create',
|
||||
'final-log-edit',
|
||||
'final-log-delete',
|
||||
'report-files-provider-list',
|
||||
'report-letter-of-guarante-list',
|
||||
'report-log-list',
|
||||
'report-appointment-list',
|
||||
'report-livechat-list',
|
||||
'report-livechat-payment',
|
||||
'report-doctor-rating',
|
||||
'user-role-list',
|
||||
'user-access-list'
|
||||
]
|
||||
],
|
||||
####################### CLIENT PORTAL #########################
|
||||
[
|
||||
'type' => 'client-portal',
|
||||
'datas' => [
|
||||
'dashboard-client-portal',
|
||||
'dashboard-list-client-portal',
|
||||
'corporate-list-client-portal',
|
||||
'employee-data-list-client-portal',
|
||||
'corporate-client-portal',
|
||||
'alarm-center-list-client-portal',
|
||||
'formularium-list-client-portal',
|
||||
'case-management-client-portal',
|
||||
'service-monitoring-limit-client-portal',
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
Permission::updateOrCreate(['name' => $permission],
|
||||
[
|
||||
'name' => $permission,
|
||||
'guard_name' => 'web'
|
||||
]);
|
||||
foreach ($permissions as $values) {
|
||||
foreach ($values['datas'] as $value) {
|
||||
Permission::updateOrCreate(['name' => $value],
|
||||
[
|
||||
'name' => $value,
|
||||
'guard_name' => $values['type']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,18 +32,16 @@ export default function NavSectionVertical({
|
||||
<Box {...other}>
|
||||
{navConfig.map((group, index) => (
|
||||
<List key={index} disablePadding sx={{ px: 2 }}>
|
||||
{group.subheader && (
|
||||
<ListSubheaderStyle
|
||||
key={index}
|
||||
sx={{
|
||||
...(isCollapse && {
|
||||
opacity: 0,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{group.subheader}
|
||||
</ListSubheaderStyle>
|
||||
)}
|
||||
<ListSubheaderStyle
|
||||
key={index}
|
||||
sx={{
|
||||
...(isCollapse && {
|
||||
opacity: 0,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{group.subheader}
|
||||
</ListSubheaderStyle>
|
||||
|
||||
{group.items.map((list) => (
|
||||
<NavListRoot key={list.title} list={list} isCollapse={isCollapse} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
// @mui
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
@@ -15,9 +15,11 @@ import Logo from '../../../components/Logo';
|
||||
import Scrollbar from '../../../components/Scrollbar';
|
||||
import { NavSectionVertical } from '../../../components/nav-section';
|
||||
//
|
||||
import navConfig from './NavConfig';
|
||||
// import navConfig from './NavConfig';
|
||||
import NavbarAccount from './NavbarAccount';
|
||||
import CollapseButton from './CollapseButton';
|
||||
import useAuth from '@/hooks/useAuth';
|
||||
import axios from '@/utils/axios';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -42,10 +44,54 @@ export default function NavbarVertical({ isOpenSidebar, onCloseSidebar }: Props)
|
||||
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const {user} = useAuth()
|
||||
|
||||
const isDesktop = useResponsive('up', 'lg');
|
||||
|
||||
const { isCollapse, collapseClick, collapseHover, onToggleCollapse, onHoverEnter, onHoverLeave } =
|
||||
useCollapseDrawer();
|
||||
const [navConfig, setNavConfig] = useState([]);
|
||||
useEffect(() => {
|
||||
const fetchNavConfig = async () => {
|
||||
try {
|
||||
const response = await axios.get('/navigations');
|
||||
const data = response.data.items;
|
||||
|
||||
// Pastikan user dan user.permissions terdefinisi dan merupakan array
|
||||
const userPermissions = user.user?.permissions?.map(permission => permission.name) || [];
|
||||
|
||||
// Fungsi untuk memeriksa apakah pengguna memiliki izin untuk item tertentu
|
||||
const hasPermission = (permission) => {
|
||||
return userPermissions.includes(permission);
|
||||
};
|
||||
|
||||
// Filter data berdasarkan izin pengguna
|
||||
const filteredNavConfig = data.map(section => {
|
||||
if (section.children && section.children.length > 0) {
|
||||
// Cek apakah ada satu atau lebih children yang memiliki izin
|
||||
const filteredChildren = section.children.filter(child => hasPermission(child.permission));
|
||||
|
||||
if (filteredChildren.length > 0) {
|
||||
return {
|
||||
...section,
|
||||
children: filteredChildren
|
||||
};
|
||||
} else {
|
||||
return null; // Lewati bagian yang tidak memiliki children dengan izin
|
||||
}
|
||||
}
|
||||
// Jika tidak ada children, cek izin untuk section itu sendiri
|
||||
return hasPermission(section.permission) ? section : null;
|
||||
}).filter(section => section !== null);
|
||||
|
||||
setNavConfig([{ items: filteredNavConfig }]);
|
||||
} catch (error) {
|
||||
console.error('Gagal mengambil konfigurasi navigasi:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchNavConfig();
|
||||
}, [user]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpenSidebar) {
|
||||
|
||||
@@ -20,11 +20,14 @@ import {
|
||||
ListItemText,
|
||||
ListItemButton,
|
||||
Divider,
|
||||
CardContent,
|
||||
LinearProgress
|
||||
} from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Download as DownloadIcon, Circle as CircleIcon, TableView } from '@mui/icons-material';
|
||||
// components
|
||||
import Page from '../../components/Page';
|
||||
import { fCurrency } from '../../utils/formatNumber';
|
||||
// utils
|
||||
import { useState, SyntheticEvent, useContext, useEffect } from 'react';
|
||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||
@@ -45,6 +48,8 @@ import TableMoreMenu from '../../components/table/TableMoreMenu';
|
||||
import Label from '../../components/Label';
|
||||
import { fSplit } from '../../utils/formatNumber';
|
||||
|
||||
import useAuth from '../../hooks/useAuth';
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
index: number;
|
||||
@@ -208,6 +213,13 @@ type ServiceMonitoringProps = {
|
||||
};
|
||||
|
||||
export default function ServiceMonitoring() {
|
||||
const {user} = useAuth();
|
||||
const checkIfNameExists = (name) => {
|
||||
return user.user.permissions.some(item => item.name === name);
|
||||
};
|
||||
|
||||
const nameToCheck = 'service-monitoring-limit-client-portal';
|
||||
const doesNameExist = checkIfNameExists(nameToCheck);
|
||||
const navigate = useNavigate();
|
||||
const controller = new AbortController();
|
||||
|
||||
@@ -221,7 +233,7 @@ export default function ServiceMonitoring() {
|
||||
|
||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||
const { memberId, requestLogId } = useParams();
|
||||
|
||||
const [depositData, setDepositData] = useState({ deposit: 0, limit: 0, usage: 0 });
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
@@ -236,6 +248,18 @@ export default function ServiceMonitoring() {
|
||||
if (response.data.data.serviceCode !== 'IP') {
|
||||
setValue(1);
|
||||
}
|
||||
|
||||
var member_id = response.data.data.member_id;
|
||||
const fetchDepositData = async () => {
|
||||
try {
|
||||
const response = await axios.get(`${corporateValue}/get-limits/${member_id}`);
|
||||
setDepositData(response.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch deposit data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchDepositData();
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching data:', error.message);
|
||||
} finally {
|
||||
@@ -248,7 +272,7 @@ export default function ServiceMonitoring() {
|
||||
};
|
||||
}, [corporateValue]);
|
||||
|
||||
|
||||
|
||||
const renderHTML = (data:string) => {
|
||||
return (
|
||||
<div style={{marginLeft: 20}}
|
||||
@@ -256,7 +280,32 @@ export default function ServiceMonitoring() {
|
||||
/>
|
||||
);
|
||||
}
|
||||
const formatNumber = (number) => {
|
||||
return new Intl.NumberFormat('id-ID').format(number);
|
||||
};
|
||||
const LimitPlanCard = ({ title, current, total }) => (
|
||||
<Card variant="outlined" sx={{ minWidth: 200, m: 1 }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6" component="div">
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="subtitle2" color="text.secondary">
|
||||
Yearly Limits
|
||||
</Typography>
|
||||
<Typography variant="subtitle1">
|
||||
{formatNumber(current)} / {formatNumber(total)}
|
||||
</Typography>
|
||||
<LinearProgress variant="determinate" value={(current / total) * 100} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
const plans = [
|
||||
{ title: 'Outpatient', current: 200000, total: 1000000 },
|
||||
{ title: 'Inpatient', current: 1000000, total: 5000000 },
|
||||
{ title: 'Dental', current: 250000, total: 1000000 },
|
||||
{ title: 'Maternity', current: 0, total: 3000000 },
|
||||
];
|
||||
|
||||
return (
|
||||
<Page title="Service Monitoring">
|
||||
@@ -277,14 +326,14 @@ export default function ServiceMonitoring() {
|
||||
<Grid item xs={12}>
|
||||
<Card sx={{ borderRadius: 2, padding: 3 }}>
|
||||
<Grid container spacing={5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography component={'h6'} fontWeight={700} fontSize={18}>
|
||||
{loading ? <Skeleton animation="wave" width={175} /> : 'Employee Profile'}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} container spacing={3}>
|
||||
<Grid item container spacing={3}>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Grid item xs={12}>
|
||||
<Typography component={'h6'} fontWeight={700} fontSize={18}>
|
||||
{loading ? <Skeleton animation="wave" width={175} /> : 'Employee Profile'}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Company Name'}
|
||||
</Typography>
|
||||
@@ -300,8 +349,6 @@ export default function ServiceMonitoring() {
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Member ID'}
|
||||
@@ -318,8 +365,6 @@ export default function ServiceMonitoring() {
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Full Name'}
|
||||
@@ -336,8 +381,6 @@ export default function ServiceMonitoring() {
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Date of Birth'}
|
||||
@@ -354,8 +397,6 @@ export default function ServiceMonitoring() {
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Phone Number'}
|
||||
@@ -372,8 +413,6 @@ export default function ServiceMonitoring() {
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Email'}
|
||||
@@ -391,6 +430,43 @@ export default function ServiceMonitoring() {
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} md={6} spacing={1.5}>
|
||||
{doesNameExist ? (
|
||||
<Stack direction="column" style={{width:'100%'}}>
|
||||
<Box flexWrap="wrap" justifyContent="left">
|
||||
<Card variant="outlined" sx={{ minWidth: 200, marginBottom: 1, borderRadius: 2, padding: 0 }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6" component="div">
|
||||
Total Limit
|
||||
</Typography>
|
||||
<Typography variant="subtitle2" color="text.secondary">
|
||||
Yearly Limits
|
||||
</Typography>
|
||||
<Typography variant="subtitle1">
|
||||
{formatNumber(depositData.usage)} / {formatNumber(depositData.deposit)}
|
||||
</Typography>
|
||||
<LinearProgress variant="determinate" value={(depositData.usage / depositData.deposit) * 100} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Box>
|
||||
<Card sx={{ borderRadius: 2, padding: 3 }}>
|
||||
<Typography component={'h6'} fontWeight={700} fontSize={18}>
|
||||
Limit Plan
|
||||
</Typography>
|
||||
<Box display="flex" flexWrap="wrap" justifyContent="left">
|
||||
{depositData.services?.map((plan) => (
|
||||
<LimitPlanCard
|
||||
key={plan.title}
|
||||
title={plan.title}
|
||||
current={plan.current}
|
||||
total={plan.total}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
</Card>
|
||||
</Stack>
|
||||
) : ''}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingY={2}>
|
||||
<Typography component={'h6'} fontWeight={700} fontSize={18}>
|
||||
@@ -400,7 +476,7 @@ export default function ServiceMonitoring() {
|
||||
|
||||
</Grid>
|
||||
</Card>
|
||||
|
||||
|
||||
</Grid>
|
||||
<Grid item container xs={12} spacing={5}>
|
||||
<Grid item container xs={12} md={6}>
|
||||
@@ -501,9 +577,9 @@ export default function ServiceMonitoring() {
|
||||
<Grid item>
|
||||
{loading ? (
|
||||
<Skeleton animation="wave" width={300} />
|
||||
) : data && data.files && data.files.result.length > 0 ?
|
||||
) : data && data.files && data.files.result.length > 0 ?
|
||||
(
|
||||
data.files.result.map((file, index) =>
|
||||
data.files.result.map((file, index) =>
|
||||
(
|
||||
(
|
||||
<Stack direction="column" spacing={2} key={index}>
|
||||
@@ -539,9 +615,9 @@ export default function ServiceMonitoring() {
|
||||
<Grid item>
|
||||
{loading ? (
|
||||
<Skeleton animation="wave" width={300} />
|
||||
) : data && data.files && data.files.diagnosis.length > 0 ?
|
||||
) : data && data.files && data.files.diagnosis.length > 0 ?
|
||||
(
|
||||
data.files.diagnosis.map((file, index) =>
|
||||
data.files.diagnosis.map((file, index) =>
|
||||
(
|
||||
(
|
||||
<Stack direction="column" spacing={2} key={index}>
|
||||
@@ -577,9 +653,9 @@ export default function ServiceMonitoring() {
|
||||
{/* <Grid item>
|
||||
{loading ? (
|
||||
<Skeleton animation="wave" width={300} />
|
||||
) : data && data.files && data.files.kondisi.length > 0 ?
|
||||
) : data && data.files && data.files.kondisi.length > 0 ?
|
||||
(
|
||||
data.files.kondisi.map((file, index) =>
|
||||
data.files.kondisi.map((file, index) =>
|
||||
(
|
||||
(
|
||||
<Stack direction="column" spacing={2} key={index}>
|
||||
@@ -1180,7 +1256,7 @@ export default function ServiceMonitoring() {
|
||||
{file.original_name}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<li>-</li>
|
||||
@@ -1259,7 +1335,7 @@ export default function ServiceMonitoring() {
|
||||
{file.original_name}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<li>-</li>
|
||||
|
||||
@@ -1,278 +1,174 @@
|
||||
// @mui
|
||||
import { Typography, Container, Grid, Button, SelectChangeEvent } from '@mui/material';
|
||||
import { Box,CardContent,Button, Container, Grid, styled, Typography, Card, Stack } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
// components
|
||||
import Page from '../../components/Page';
|
||||
// theme
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import axios from '../../utils/axios';
|
||||
import { Stack } from '@mui/system';
|
||||
import useAuth from '../../hooks/useAuth';
|
||||
import SomethingUsage from '../../sections/dashboard/SomethingUsage';
|
||||
import { fCurrency } from '../../utils/formatNumber';
|
||||
import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
|
||||
import TrendingUpIcon from '@mui/icons-material/TrendingUp';
|
||||
import MonetizationOnIcon from '@mui/icons-material/MonetizationOn';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
|
||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||
import Table from '../../components/Table';
|
||||
import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import palette from '../../theme/palette';
|
||||
|
||||
export default function Index() {
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function Dashboard() {
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { themeStretch } = useSettings();
|
||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||
const controller = new AbortController();
|
||||
|
||||
const [memberData, setMemberData] = useState([]);
|
||||
const { user } = useAuth();
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* setting up for the table */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const loadings = {
|
||||
isLoading: isLoading,
|
||||
setIsLoading: setIsLoading,
|
||||
};
|
||||
|
||||
/* ------------------------------ 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,
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ handle search ----------------------------- */
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (searchText === '') {
|
||||
searchParams.delete('search');
|
||||
const params = Object.fromEntries([...searchParams.entries()]);
|
||||
setAppliedParams(params);
|
||||
} else {
|
||||
const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]);
|
||||
setAppliedParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
const searchs = {
|
||||
useSearchs: false,
|
||||
searchText: searchText,
|
||||
setSearchText: setSearchText,
|
||||
handleSearchSubmit: handleSearchSubmit,
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ handle filter ----------------------------- */
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
const filters = {
|
||||
useFilter: true,
|
||||
config: {
|
||||
label: 'Division',
|
||||
divisionValue: divisionValue,
|
||||
divisionData: divisionData,
|
||||
handleDivisionChange: handleDivisionChange,
|
||||
},
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------- 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: 'status',
|
||||
align: 'center',
|
||||
label: 'Status',
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'action',
|
||||
align: 'right',
|
||||
label: '',
|
||||
isSort: false,
|
||||
},
|
||||
];
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const parameters =
|
||||
Object.keys(appliedParams).length !== 0
|
||||
? appliedParams
|
||||
: Object.fromEntries([
|
||||
...searchParams.entries(),
|
||||
['order', order],
|
||||
['orderBy', orderBy],
|
||||
]);
|
||||
|
||||
const [divisionResponse, membersResponse] = await Promise.all([
|
||||
axios.get(`${corporateValue}/division`, { signal: controller.signal }),
|
||||
axios.get(`${corporateValue}/members`, {
|
||||
params: { ...parameters },
|
||||
signal: controller.signal,
|
||||
}),
|
||||
]);
|
||||
|
||||
setSearchParams(parameters);
|
||||
setDivisionData(divisionResponse.data);
|
||||
setMemberData(
|
||||
membersResponse.data.data.map((obj: any) => ({
|
||||
...obj,
|
||||
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>
|
||||
),
|
||||
}))
|
||||
);
|
||||
setPaginationTable(membersResponse.data);
|
||||
setRowsPerPage(membersResponse.data.per_page);
|
||||
|
||||
if (searchParams.get('page')) {
|
||||
// @ts-ignore
|
||||
const currentPage = parseInt(searchParams.get('page')) - 1;
|
||||
paginationTable.current_page = currentPage;
|
||||
setPage(currentPage);
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching data:', error.message);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
controller.abort();
|
||||
const checkIfNameExists = (name) => {
|
||||
return user.user.permissions.some(item => item.name === name);
|
||||
};
|
||||
}, [appliedParams, searchParams, order, orderBy, setSearchParams, corporateValue]);
|
||||
|
||||
const nameToCheck = 'dashboard-list-client-portal';
|
||||
const doesNameExist = checkIfNameExists(nameToCheck);
|
||||
useEffect(() => {
|
||||
const doesNameExist = checkIfNameExists(nameToCheck);
|
||||
if (!doesNameExist) {
|
||||
navigate('/corporate');
|
||||
}
|
||||
}, [nameToCheck, user, navigate]);
|
||||
// const loadSomething = () => {
|
||||
// axios.get('/user')
|
||||
// };
|
||||
|
||||
const Wallet = styled(AccountBalanceWalletIcon)(({ theme }) => ({
|
||||
color: 'orange',
|
||||
marginRight: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const TrendUp = styled(TrendingUpIcon)(({ theme }) => ({
|
||||
color: 'blue',
|
||||
marginRight: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const Monet = styled(MonetizationOnIcon)(({ theme }) => ({
|
||||
color: 'orange',
|
||||
marginRight: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const DangerCard = styled(Card)(({ theme }) => ({
|
||||
boxShadow: 'none',
|
||||
padding: theme.spacing(3),
|
||||
color: theme.palette.error.main,
|
||||
backgroundColor: theme.palette.error.lighter,
|
||||
}));
|
||||
|
||||
const SuccessCard = styled(Card)(({ theme }) => ({
|
||||
boxShadow: 'none',
|
||||
padding: theme.spacing(3),
|
||||
color: theme.palette.success.darker,
|
||||
backgroundColor: theme.palette.success.lighter,
|
||||
}));
|
||||
|
||||
const DefaultCard = styled(Card)(({ theme }) => ({
|
||||
boxShadow: theme.shadows[3], // Menggunakan bayangan standar dari tema
|
||||
padding: theme.spacing(3),
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.paper, // Latar belakang putih
|
||||
}));
|
||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||
|
||||
const [depositData, setDepositData] = useState({ deposit: 0, limit: 0, usage: 0 });
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDepositData = async () => {
|
||||
try {
|
||||
const response = await axios.get(`${corporateValue}/get-deposits`);
|
||||
setDepositData(response.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch deposit data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchDepositData();
|
||||
}, [corporateValue]);
|
||||
|
||||
const handleGoBack = () => {
|
||||
// Logic untuk kembali ke halaman sebelumnya atau halaman utama
|
||||
navigate('/corporate')
|
||||
};
|
||||
|
||||
return (
|
||||
<Page title="Dashboard">
|
||||
<Container maxWidth={themeStretch ? false : 'xl'}>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Typography variant="h3" component="h1" paragraph>
|
||||
Dashboard
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography variant="h3" component="h1" paragraph>
|
||||
Dashboard
|
||||
</Typography>
|
||||
{doesNameExist ? (
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={4}>
|
||||
{/* <SomethingUsage /> */}
|
||||
<DefaultCard>
|
||||
<CardContent>
|
||||
<Stack direction="column" alignItems="flex-start" justifyContent="space-between" sx={{ mb: 0.6 }}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
|
||||
<Typography variant='h4'>{fCurrency(depositData.deposit)}</Typography>
|
||||
<Wallet />
|
||||
</Stack>
|
||||
<Typography variant='h6'>Deposit</Typography>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</DefaultCard>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<DefaultCard>
|
||||
<CardContent>
|
||||
<Stack direction="column" alignItems="flex-start" justifyContent="space-between" sx={{ mb: 0.6 }}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
|
||||
<Typography variant='h4'>{fCurrency(depositData.limit)}</Typography>
|
||||
<TrendUp />
|
||||
</Stack>
|
||||
<Typography variant='h6'>Limit</Typography>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</DefaultCard>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<DefaultCard>
|
||||
<CardContent>
|
||||
<Stack direction="column" alignItems="flex-start" justifyContent="space-between" sx={{ mb: 0.6 }}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
|
||||
<Typography variant='h4'>{fCurrency(depositData.usage)}</Typography>
|
||||
<Monet />
|
||||
</Stack>
|
||||
<Typography variant='h6'>This Year Usage</Typography>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</DefaultCard>
|
||||
</Grid>
|
||||
</Grid>
|
||||
):(
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
minHeight="55vh"
|
||||
textAlign="center"
|
||||
padding={2}
|
||||
>
|
||||
<Typography variant="body1" color="textSecondary" paragraph>
|
||||
Maaf, halaman ini tidak bisa diakses atau tidak ada.
|
||||
</Typography>
|
||||
<Button variant="contained" color="primary" onClick={handleGoBack}>
|
||||
Kembali
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} lg={12} md={12}>
|
||||
<Table
|
||||
headCells={headCells}
|
||||
rows={memberData}
|
||||
orders={orders}
|
||||
paginations={paginations}
|
||||
loadings={loadings}
|
||||
params={params}
|
||||
searchs={searchs}
|
||||
filters={filters}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</Page>
|
||||
);
|
||||
|
||||
279
frontend/client-portal/src/pages/Dashboard/Index_.tsx
Normal file
279
frontend/client-portal/src/pages/Dashboard/Index_.tsx
Normal file
@@ -0,0 +1,279 @@
|
||||
// @mui
|
||||
import { Typography, Container, Grid, Button, SelectChangeEvent } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
// components
|
||||
import Page from '../../components/Page';
|
||||
// theme
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import axios from '../../utils/axios';
|
||||
import { Stack } from '@mui/system';
|
||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||
import Table from '../../components/Table';
|
||||
import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import palette from '../../theme/palette';
|
||||
|
||||
export default function Index_() {
|
||||
const { themeStretch } = useSettings();
|
||||
const { corporateValue } = useContext(UserCurrentCorporateContext);
|
||||
const controller = new AbortController();
|
||||
|
||||
const [memberData, setMemberData] = useState([]);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* setting up for the table */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const loadings = {
|
||||
isLoading: isLoading,
|
||||
setIsLoading: setIsLoading,
|
||||
};
|
||||
|
||||
/* ------------------------------ 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,
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ handle search ----------------------------- */
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (searchText === '') {
|
||||
searchParams.delete('search');
|
||||
const params = Object.fromEntries([...searchParams.entries()]);
|
||||
setAppliedParams(params);
|
||||
} else {
|
||||
const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]);
|
||||
setAppliedParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
const searchs = {
|
||||
useSearchs: false,
|
||||
searchText: searchText,
|
||||
setSearchText: setSearchText,
|
||||
handleSearchSubmit: handleSearchSubmit,
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ handle filter ----------------------------- */
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
const filters = {
|
||||
useFilter: true,
|
||||
config: {
|
||||
label: 'Division',
|
||||
divisionValue: divisionValue,
|
||||
divisionData: divisionData,
|
||||
handleDivisionChange: handleDivisionChange,
|
||||
},
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------- 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: 'status',
|
||||
align: 'center',
|
||||
label: 'Status',
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'action',
|
||||
align: 'right',
|
||||
label: '',
|
||||
isSort: false,
|
||||
},
|
||||
];
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const parameters =
|
||||
Object.keys(appliedParams).length !== 0
|
||||
? appliedParams
|
||||
: Object.fromEntries([
|
||||
...searchParams.entries(),
|
||||
['order', order],
|
||||
['orderBy', orderBy],
|
||||
]);
|
||||
|
||||
const [divisionResponse, membersResponse] = await Promise.all([
|
||||
axios.get(`${corporateValue}/division`, { signal: controller.signal }),
|
||||
axios.get(`${corporateValue}/members`, {
|
||||
params: { ...parameters },
|
||||
signal: controller.signal,
|
||||
}),
|
||||
]);
|
||||
|
||||
setSearchParams(parameters);
|
||||
setDivisionData(divisionResponse.data);
|
||||
setMemberData(
|
||||
membersResponse.data.data.map((obj: any) => ({
|
||||
...obj,
|
||||
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>
|
||||
),
|
||||
}))
|
||||
);
|
||||
setPaginationTable(membersResponse.data);
|
||||
setRowsPerPage(membersResponse.data.per_page);
|
||||
|
||||
if (searchParams.get('page')) {
|
||||
// @ts-ignore
|
||||
const currentPage = parseInt(searchParams.get('page')) - 1;
|
||||
paginationTable.current_page = currentPage;
|
||||
setPage(currentPage);
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching data:', error.message);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
controller.abort();
|
||||
};
|
||||
}, [appliedParams, searchParams, order, orderBy, setSearchParams, 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={12} md={12}>
|
||||
<Table
|
||||
headCells={headCells}
|
||||
rows={memberData}
|
||||
orders={orders}
|
||||
paginations={paginations}
|
||||
loadings={loadings}
|
||||
params={params}
|
||||
searchs={searchs}
|
||||
filters={filters}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
@@ -9,7 +9,10 @@ import Iconify from '../../components/Iconify';
|
||||
import useLocalStorage from '../../hooks/useLocalStorage';
|
||||
/* -------------------------------- sections -------------------------------- */
|
||||
import { LoginEmailForm, LoginPhoneForm, VerifyCodeForm } from '../../sections/auth/login';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import axios from '../../utils/axios';
|
||||
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
/* --------------------------------- styled --------------------------------- */
|
||||
|
||||
const RootStyle = styled('div')(({ theme }) => ({
|
||||
@@ -36,6 +39,46 @@ export default function Login() {
|
||||
const [emailOrPhoneForm, setEmailOrPhoneForm] = useLocalStorage('emailOrPhoneForm', false);
|
||||
const [loginOrVerifyCode, setLoginOrVerifyCode] = useLocalStorage('loginOrVerifyCode', false);
|
||||
|
||||
const [lastSentTime, setLastSentTime] = useState(null);
|
||||
const [canSendOTP, setCanSendOTP] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
let timer;
|
||||
if (lastSentTime) {
|
||||
timer = setInterval(() => {
|
||||
const timeDiff = Math.floor((new Date() - lastSentTime) / 1000);
|
||||
if (timeDiff >= 60) {
|
||||
setCanSendOTP(true);
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, [lastSentTime]);
|
||||
|
||||
const sendOTP = (phoneOrEmail: string) => {
|
||||
if (canSendOTP) {
|
||||
// Logic untuk mengirim OTP
|
||||
axios
|
||||
.post('/login', { phoneOrEmail })
|
||||
.then(() => {
|
||||
enqueueSnackbar('Kode OTP telah dikirim, silahkan cek email dan spam folder', {
|
||||
variant: 'success',
|
||||
autoHideDuration: 5000,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response.status !== 404) throw error.response;
|
||||
if (error.response.status !== 422) throw error.response;
|
||||
});
|
||||
|
||||
setLastSentTime(new Date());
|
||||
setCanSendOTP(false);
|
||||
} else {
|
||||
alert('You can only send OTP once every minute.');
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Page title="Login">
|
||||
<RootStyle>
|
||||
@@ -87,7 +130,12 @@ export default function Login() {
|
||||
|
||||
<Stack sx={{ marginTop: 5 }} spacing={1} alignItems="center">
|
||||
<Typography>Tidak mendapatkan kode?</Typography>
|
||||
<Link sx={{ cursor: 'pointer' }}>Kirim Ulang Kode OTP</Link>
|
||||
<Link
|
||||
sx={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
sendOTP(emailOrPhone);
|
||||
}}
|
||||
>Kirim Ulang Kode OTP</Link>
|
||||
</Stack>
|
||||
</>
|
||||
) : (
|
||||
@@ -118,7 +166,7 @@ export default function Login() {
|
||||
</>
|
||||
)}
|
||||
|
||||
<Divider sx={{ marginTop: 5 }}>Atau</Divider>
|
||||
{/* <Divider sx={{ marginTop: 5 }}>Atau</Divider>
|
||||
|
||||
<Stack sx={{ marginTop: 5 }}>
|
||||
{emailOrPhoneForm ? (
|
||||
@@ -148,7 +196,7 @@ export default function Login() {
|
||||
Masuk menggunakan nomor handphone
|
||||
</Link>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack> */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ContentStyle>
|
||||
|
||||
@@ -57,9 +57,9 @@ export default function LoginForm({ setEmailOrPhone, setLoginOrVerifyCode }: Log
|
||||
setEmailOrPhone(data.email);
|
||||
setLoginOrVerifyCode(true);
|
||||
reset();
|
||||
enqueueSnackbar('Kode OTP telah dikirim, silahkan cek email yang login', {
|
||||
enqueueSnackbar('Kode OTP telah dikirim, silahkan cek email dan spam folder', {
|
||||
variant: 'success',
|
||||
autoHideDuration: 2000,
|
||||
autoHideDuration: 5000,
|
||||
});
|
||||
} catch (error: any) {
|
||||
reset();
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import merge from 'lodash/merge';
|
||||
import ReactApexChart from 'react-apexcharts';
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Card, Typography, Stack } from '@mui/material';
|
||||
// utils
|
||||
import { fCurrency, fPercent } from '../../utils/formatNumber';
|
||||
// components
|
||||
import Iconify from '../../components/Iconify';
|
||||
import BaseOptionChart from '../../components/chart/BaseOptionChart';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const RootStyle = styled(Card)(({ theme }) => ({
|
||||
boxShadow: 'none',
|
||||
padding: theme.spacing(3),
|
||||
color: theme.palette.primary.darker,
|
||||
backgroundColor: theme.palette.primary.lighter,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const INITIAL = 500000000
|
||||
const TOTAL = 257907000;
|
||||
const PERCENT = -3;
|
||||
const CHART_DATA = [{ data: [100, 99, 99, 85, 74, 57, 54, 51] }];
|
||||
|
||||
export default function SomethingUsage() {
|
||||
const chartOptions = merge(BaseOptionChart(), {
|
||||
chart: { sparkline: { enabled: true } },
|
||||
xaxis: { labels: { show: true } },
|
||||
yaxis: { labels: { show: false } },
|
||||
stroke: { width: 4 },
|
||||
legend: { show: false },
|
||||
grid: { show: false },
|
||||
tooltip: {
|
||||
marker: { show: false },
|
||||
y: {
|
||||
formatter: (seriesName: string) => (seriesName) + "%",
|
||||
title: {
|
||||
formatter: () => '',
|
||||
},
|
||||
},
|
||||
},
|
||||
fill: { gradient: { opacityFrom: 0, opacityTo: 0 } },
|
||||
});
|
||||
|
||||
return (
|
||||
<RootStyle>
|
||||
<Stack direction="row" justifyContent="space-between" sx={{ mb: 3 }}>
|
||||
<div>
|
||||
<Typography variant="body2" component="span" sx={{ opacity: 0.72 }}>
|
||||
{fCurrency(INITIAL)}
|
||||
</Typography>
|
||||
<Typography sx={{ typography: 'subtitle2' }}>Remaining Balance</Typography>
|
||||
<Typography sx={{ typography: 'h3' }}>{fCurrency(TOTAL)}</Typography>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Stack direction="row" alignItems="center" justifyContent="flex-end" sx={{ mb: 0.6 }}>
|
||||
<Iconify
|
||||
width={20}
|
||||
height={20}
|
||||
icon={PERCENT >= 0 ? 'eva:trending-up-fill' : 'eva:trending-down-fill'}
|
||||
/>
|
||||
<Typography variant="subtitle2" component="span" sx={{ ml: 0.5 }}>
|
||||
{PERCENT > 0 && '+'}
|
||||
{fPercent(PERCENT)}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography variant="body2" component="span" sx={{ opacity: 0.72 }}>
|
||||
than last month
|
||||
</Typography>
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
<ReactApexChart type="area" series={CHART_DATA} options={chartOptions} height={100} />
|
||||
</RootStyle>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user