Merge remote-tracking branch 'origin/staging' into origin/production
This commit is contained in:
@@ -14,6 +14,9 @@ use Modules\Internal\Emails\SendVerifyEmail;
|
|||||||
use Modules\Internal\Events\ForgetPassword;
|
use Modules\Internal\Events\ForgetPassword;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Modules\HospitalPortal\Helpers\ApiResponse;
|
use Modules\HospitalPortal\Helpers\ApiResponse;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use Illuminate\Support\Facades\View;
|
||||||
|
|
||||||
class AuthController extends Controller
|
class AuthController extends Controller
|
||||||
{
|
{
|
||||||
@@ -27,9 +30,9 @@ class AuthController extends Controller
|
|||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'password' => 'required'
|
'password' => 'required'
|
||||||
], [
|
], [
|
||||||
'email.required' => trans('validation.required',['attribute' => 'Email']),
|
'email.required' => trans('Validation.required',['attribute' => 'Email']),
|
||||||
'email.email' => trans('validation.email'),
|
'email.email' => trans('Validation.email'),
|
||||||
'password.required' => trans('validation.required',['attribute' => 'Password']),
|
'password.required' => trans('Validation.required',['attribute' => 'Password']),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails())
|
if ($validator->fails())
|
||||||
@@ -40,11 +43,11 @@ class AuthController extends Controller
|
|||||||
{
|
{
|
||||||
$user = User::where('email', $request->email)->first();
|
$user = User::where('email', $request->email)->first();
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
return ApiResponse::apiResponse('Not Found', $data, trans('message.not_found'), 404);
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.not_found'), 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hash::check($request->password, $user->password)) {
|
if (!Hash::check($request->password, $user->password)) {
|
||||||
return ApiResponse::apiResponse('Bad Request', $data, trans('message.password'), 400);
|
return ApiResponse::apiResponse('Bad Request', $data, trans('Message.password'), 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$res_data = [
|
$res_data = [
|
||||||
@@ -52,16 +55,15 @@ class AuthController extends Controller
|
|||||||
'token' => $user->createToken('app')->plainTextToken
|
'token' => $user->createToken('app')->plainTextToken
|
||||||
];
|
];
|
||||||
|
|
||||||
return ApiResponse::apiResponse("Success", $res_data, trans('message.success'), 200);
|
return ApiResponse::apiResponse("Success", $res_data, trans('Message.success'), 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function logout(Request $request)
|
public function logout(Request $request)
|
||||||
{
|
{
|
||||||
$token = $request->bearerToken();
|
$request->user()->tokens()->delete();
|
||||||
Auth::user()->tokens()->where('id', $token)->delete();
|
|
||||||
|
|
||||||
return response(['message' => 'Berhasil Logout.']);
|
return ApiResponse::apiResponse('Success', [], trans('Message.logout'), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resetPassword(Request $request)
|
public function resetPassword(Request $request)
|
||||||
@@ -75,12 +77,12 @@ class AuthController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (!Hash::check($request['old_password'], $user->password)) {
|
if (!Hash::check($request['old_password'], $user->password)) {
|
||||||
return response(['message' => 'Password Salah'], 403);
|
return response(['Message' => 'Password Salah'], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request["new_password"] != $request["confirm_new_password"]) {
|
if ($request["new_password"] != $request["confirm_new_password"]) {
|
||||||
return response([
|
return response([
|
||||||
'message' => "Password Tidak Sama"
|
'Message' => "Password Tidak Sama"
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,52 +94,202 @@ class AuthController extends Controller
|
|||||||
|
|
||||||
public function verifyEmail(Request $request)
|
public function verifyEmail(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$data = [
|
||||||
|
'email' => $request->email,
|
||||||
|
];
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
|
], [
|
||||||
|
'email.required' => trans('Validation.required',['attribute' => 'Email']),
|
||||||
|
'email.email' => trans('Validation.email'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user = User::query()
|
if ($validator->fails())
|
||||||
->where('email', $request->email)
|
{
|
||||||
|
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$user = User::where('email', $request->email)->first();
|
||||||
|
if (!$user) {
|
||||||
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.not_found'), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
//send email
|
||||||
|
// Insert data notifications
|
||||||
|
$emailTo = $request->email;
|
||||||
|
$dataNotif = [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'email' => $emailTo,
|
||||||
|
'title' => 'Forgot Password',
|
||||||
|
'description' => 'Request forgot password from Hospital Portal',
|
||||||
|
'type' => 1,
|
||||||
|
'isUnRead' => true,
|
||||||
|
'created_by' => auth()->check() ? auth()->user()->id : null,
|
||||||
|
'created_at' => date('Y-m-d H:i:s'),
|
||||||
|
'updated_at' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
$sendNotif = Helper::insertNotification($dataNotif);
|
||||||
|
//Insert data password reset
|
||||||
|
$token = mt_rand(100000, 999999); // Menghasilkan angka acak antara 100000 dan 999999
|
||||||
|
$p_resets = DB::table('password_resets')
|
||||||
|
->insert([
|
||||||
|
'email' => $request->email,
|
||||||
|
'token' => $token,
|
||||||
|
'created_at' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
// Send Email after insert notifications
|
||||||
|
if($sendNotif && $p_resets)
|
||||||
|
{
|
||||||
|
//send to alarm
|
||||||
|
$nameTo = 'User';
|
||||||
|
$dataEmail = [
|
||||||
|
'email' => $emailTo,
|
||||||
|
'name' => $nameTo,
|
||||||
|
'subject' => 'Request Forgot Password from Hospital Portal Date '. date('Y-m-d H:i:s'),
|
||||||
|
'body' => View::make('email/forgot_password', ['token' => $token])->render(),
|
||||||
|
];
|
||||||
|
Helper::sendEmail($dataEmail);
|
||||||
|
|
||||||
|
$res = DB::table('password_resets')
|
||||||
|
->where('email', '=', $request->email)
|
||||||
|
->where('token', '=', $token)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
return ApiResponse::apiResponse("Success", $res, trans('Message.success'), 200);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ApiResponse::apiResponse("Internal Server Error", $data, trans('Message.server_error'), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verifCode(Request $request)
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'email' => $request->email,
|
||||||
|
'token' => $request->token,
|
||||||
|
];
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'email' => 'required|email',
|
||||||
|
'token' => 'required|numeric',
|
||||||
|
], [
|
||||||
|
'email.required' => trans('Validation.required',['attribute' => 'Email']),
|
||||||
|
'email.email' => trans('Validation.email'),
|
||||||
|
'token.required' => trans('Validation.required',['attribute' => 'Token']),
|
||||||
|
'token.numeric' => trans('Validation.required',['attribute' => 'Code Numeric']),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails())
|
||||||
|
{
|
||||||
|
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Check Time
|
||||||
|
$check = DB::table('password_resets')
|
||||||
|
->where('email', '=', $request->email)
|
||||||
|
->where('token', '=', $request->token)
|
||||||
|
->select('created_at')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$user) {
|
if($check)
|
||||||
return response(['message' => 'User Tidak Ditemukan'], 404);
|
{
|
||||||
|
$created_at = strtotime($check->created_at); // Konversi string waktu ke UNIX timestamp
|
||||||
|
$now = time(); // Waktu sekarang dalam UNIX timestamp
|
||||||
|
|
||||||
|
// Hitung selisih waktu dalam menit
|
||||||
|
$diffInMinutes = ($now - $created_at) / 60;
|
||||||
|
|
||||||
|
if ($diffInMinutes > 60) {
|
||||||
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.token_expired'), 404);
|
||||||
|
} else {
|
||||||
|
// Lanjutkan dengan proses pemulihan kata sandi
|
||||||
|
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.not_found'), 404);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Event(new ForgetPassword($user));
|
|
||||||
|
|
||||||
// Mail::to($user->email)->send(new SendVerifyEmail($user));
|
|
||||||
|
|
||||||
return response()->json($user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forgetPassword(Request $request)
|
public function forgetPassword(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$data = [
|
||||||
'new_password' => 'required',
|
'email' => $request->email,
|
||||||
'confirm_new_password' => 'required'
|
'token' => $request->token,
|
||||||
|
'new_password' => $request->new_password
|
||||||
|
];
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'email' => 'required|email',
|
||||||
|
'token' => 'required|numeric',
|
||||||
|
'new_password' => [
|
||||||
|
'required',
|
||||||
|
'min:8',
|
||||||
|
'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/'
|
||||||
|
]
|
||||||
|
], [
|
||||||
|
'email.required' => trans('Validation.required',['attribute' => 'Email']),
|
||||||
|
'email.email' => trans('Validation.email'),
|
||||||
|
'token.required' => trans('Validation.required',['attribute' => 'Token']),
|
||||||
|
'new_password.required' => trans('Validation.required',['attribute' => 'New Password']),
|
||||||
|
'new_password.min' => trans('Validation.min',['attribute' => 'New Password']),
|
||||||
|
'new_password.regex' => trans('Validation.regex',['attribute' => 'New Password']),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$token = Crypt::decryptString($request->token);
|
if($request->new_password != $request->confirm_new_password)
|
||||||
$email = explode('|', $token)[0];
|
{
|
||||||
|
return ApiResponse::apiResponse('Bad Request', $data, 'Confirm password is not the same', 400);
|
||||||
$user = User::query()
|
}
|
||||||
->where('email', $email)
|
else if ($validator->fails())
|
||||||
|
{
|
||||||
|
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Check Time
|
||||||
|
$check = DB::table('password_resets')
|
||||||
|
->where('email', '=', $request->email)
|
||||||
|
->where('token', '=', $request->token)
|
||||||
|
->select('created_at')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$user) {
|
if($check)
|
||||||
return response(['message' => 'User Tidak Ditemukan'], 404);
|
{
|
||||||
}
|
$created_at = strtotime($check->created_at); // Konversi string waktu ke UNIX timestamp
|
||||||
|
$now = time(); // Waktu sekarang dalam UNIX timestamp
|
||||||
|
|
||||||
if ($request["new_password"] != $request["confirm_new_password"]) {
|
// Hitung selisih waktu dalam menit
|
||||||
return response([
|
$diffInMinutes = ($now - $created_at) / 60;
|
||||||
'message' => "Password Tidak Sama"
|
|
||||||
], 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$user->update([
|
if ($diffInMinutes > 60) {
|
||||||
'password' => Hash::make($request->confirm_new_password),
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.token_expired'), 404);
|
||||||
]);
|
} else {
|
||||||
return response()->json($user);
|
// Lanjutkan dengan proses pemulihan kata sandi
|
||||||
|
$user = User::where('email', $request->email)->first();
|
||||||
|
if ($user)
|
||||||
|
{
|
||||||
|
$newPassword = Hash::make($request->new_password);
|
||||||
|
$user->password = $newPassword;
|
||||||
|
$user->save();
|
||||||
|
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.token_expired'), 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ApiResponse::apiResponse('Not Found', $data, trans('Message.not_found'), 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,10 @@ Route::prefix('v1')->group(function() {
|
|||||||
Route::post('login', 'login');
|
Route::post('login', 'login');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//Route::post('forget-password', [AuthController::class, 'forgetPassword'])->name('forget-password');
|
Route::post('forget-password', [AuthController::class, 'forgetPassword']);
|
||||||
//Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email');
|
Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email');
|
||||||
|
Route::post('verify-code', [AuthController::class, 'verifCode']);
|
||||||
|
|
||||||
|
|
||||||
Route::middleware('auth:sanctum')->group(function () {
|
Route::middleware('auth:sanctum')->group(function () {
|
||||||
|
|||||||
@@ -575,6 +575,12 @@ class CorporateController extends Controller
|
|||||||
"file_url" => url('files/Template Import Request LOG.xlsx')
|
"file_url" => url('files/Template Import Request LOG.xlsx')
|
||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
|
case 'final-log-invoice':
|
||||||
|
return Helper::responseJson([
|
||||||
|
'file_name' => "Template Import Invoice.xlsx",
|
||||||
|
"file_url" => url('files/Template Import Invoice.xlsx')
|
||||||
|
]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return Helper::responseJson([], 'error', 404);
|
return Helper::responseJson([], 'error', 404);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ use Carbon\Carbon;
|
|||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
|
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
|
||||||
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
|
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
|
||||||
|
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;
|
||||||
|
use Box\Spout\Common\Entity\Style\CellAlignment;
|
||||||
|
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
@@ -672,6 +674,181 @@ class RequestLogController extends Controller
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function importInvoice(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->hasFile('file')) {
|
||||||
|
$file = $request->file('file');
|
||||||
|
$data = Excel::toArray([], $file);
|
||||||
|
|
||||||
|
$processedData = $this->processCategoryNames($data);
|
||||||
|
|
||||||
|
$importedRows = 0;
|
||||||
|
$result_rows = [];
|
||||||
|
$failedRows = [];
|
||||||
|
|
||||||
|
foreach ($processedData as $row) {
|
||||||
|
if($row['code'])
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$affectedRows = DB::table('request_logs')
|
||||||
|
->where('code','=', $row['code'])
|
||||||
|
->update([
|
||||||
|
'invoice_no' => $row['invoice_no'],
|
||||||
|
'billing_no' => $row['billing_no'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($affectedRows === 0) {
|
||||||
|
$row['code_error'] = '500';
|
||||||
|
$row['error'] = 'Gagal update karena data sudah ada ';
|
||||||
|
$result_rows[] = $row;
|
||||||
|
$failedRows[] = $row;
|
||||||
|
} else {
|
||||||
|
$importedRows += $affectedRows;
|
||||||
|
$row['code_error'] = '200';
|
||||||
|
$row['error'] = 'Sukses';
|
||||||
|
$result_rows[] = $row;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$row['code_error'] = '500';
|
||||||
|
$row['error'] = $e->getMessage();
|
||||||
|
if(!$row['code'])
|
||||||
|
{
|
||||||
|
$row['error'] = 'Kolom Code wajib isi';
|
||||||
|
}
|
||||||
|
if(!$row['invoice_no'])
|
||||||
|
{
|
||||||
|
$row['error'] = 'No Invoice wajib isi';
|
||||||
|
}
|
||||||
|
if(!$row['billing_no'])
|
||||||
|
{
|
||||||
|
$row['error'] = 'No Billing wajib isi';
|
||||||
|
}
|
||||||
|
$result_rows[] = $row;
|
||||||
|
$failedRows[] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'message' => 'File uploaded and data saved to database',
|
||||||
|
'metaData' => 'invoice',
|
||||||
|
'data' => [
|
||||||
|
'total_success_row' => $importedRows,
|
||||||
|
'total_failed_row' => count($failedRows),
|
||||||
|
'result_rows' => $result_rows,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['error' => 'No file uploaded.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processCategoryNames($data)
|
||||||
|
{
|
||||||
|
$header = [];
|
||||||
|
$row = [];
|
||||||
|
for ($i = 1; $i < count($data[0]); $i++) {
|
||||||
|
$row[] = $data[0][$i];
|
||||||
|
$header[] = $data[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$filed = [];
|
||||||
|
foreach ($header[0] as $value)
|
||||||
|
{
|
||||||
|
$modelColumn = strtolower(preg_replace('/\s+/', '_', trim($value)));
|
||||||
|
$modelColumn = str_replace(['*', ' '], '', $modelColumn);
|
||||||
|
if($modelColumn)
|
||||||
|
{
|
||||||
|
$filed[] = $modelColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($row as $subarray) {
|
||||||
|
$trimmedSubarray = [];
|
||||||
|
for ($i = 0; $i < count($filed); $i++) {
|
||||||
|
$trimmedSubarray[$filed[$i]] = $subarray[$i] ? $subarray[$i] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result[] = $trimmedSubarray;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportFiledInvoice(Request $request)
|
||||||
|
{
|
||||||
|
$writer = WriterEntityFactory::createXLSXWriter();
|
||||||
|
$writer->openToFile(public_path('files/Report-Data-Result-Import.xlsx'));
|
||||||
|
$header = [
|
||||||
|
'Code*',
|
||||||
|
'Inovice No*',
|
||||||
|
'Billing NO*',
|
||||||
|
'Ingest Code',
|
||||||
|
'Ingest Note'
|
||||||
|
];
|
||||||
|
$style = (new StyleBuilder())
|
||||||
|
->setFontBold()
|
||||||
|
// ->setFontSize(15)
|
||||||
|
// ->setFontColor(Color::BLUE)
|
||||||
|
// ->setShouldWrapText()
|
||||||
|
->setCellAlignment(CellAlignment::LEFT)
|
||||||
|
// ->setBackgroundColor(Color::YELLOW)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$headerRow = WriterEntityFactory::createRowFromArray($header, $style);
|
||||||
|
$writer->addRow($headerRow);
|
||||||
|
// ============================
|
||||||
|
|
||||||
|
foreach($request->params as $item)
|
||||||
|
{
|
||||||
|
|
||||||
|
$rowData = [
|
||||||
|
$item['code'],
|
||||||
|
$item['invoice_no'],
|
||||||
|
$item['billing_no'],
|
||||||
|
$item['code_error'],
|
||||||
|
$item['error']
|
||||||
|
];
|
||||||
|
$style = (new StyleBuilder())
|
||||||
|
//->setFontBold()
|
||||||
|
// ->setFontSize(15)
|
||||||
|
// ->setFontColor(Color::BLUE)
|
||||||
|
// ->setShouldWrapText()
|
||||||
|
->setCellAlignment(CellAlignment::LEFT)
|
||||||
|
// ->setBackgroundColor(Color::YELLOW)
|
||||||
|
->build();
|
||||||
|
$row = WriterEntityFactory::createRowFromArray($rowData, $style);
|
||||||
|
$writer->addRow($row);
|
||||||
|
}
|
||||||
|
$footer = [
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
];
|
||||||
|
$style = (new StyleBuilder())
|
||||||
|
->setFontBold()
|
||||||
|
// ->setFontSize(15)
|
||||||
|
// ->setFontColor(Color::BLUE)
|
||||||
|
// ->setShouldWrapText()
|
||||||
|
->setCellAlignment(CellAlignment::LEFT)
|
||||||
|
// ->setBackgroundColor(Color::YELLOW)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$footerRow = WriterEntityFactory::createRowFromArray($footer, $style);
|
||||||
|
$writer->addRow($footerRow);
|
||||||
|
|
||||||
|
$writer->close();
|
||||||
|
|
||||||
|
return Helper::responseJson([
|
||||||
|
'file_name' => 'Report-Data-Result-Import',
|
||||||
|
"file_url" => url('files/Report-Data-Result-Import.xlsx')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function claimRequestDetail($claimRequestId)
|
public function claimRequestDetail($claimRequestId)
|
||||||
{
|
{
|
||||||
$status = DB::table('claim_requests')
|
$status = DB::table('claim_requests')
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ Route::prefix('internal')->group(function () {
|
|||||||
Route::put('customer-service/request/final_log/{id}', [RequestLogController::class, 'deleteFinalLog']);
|
Route::put('customer-service/request/final_log/{id}', [RequestLogController::class, 'deleteFinalLog']);
|
||||||
Route::get('customer-service/request/{id}/download', [RequestLogController::class, 'generateRequestLog']);
|
Route::get('customer-service/request/{id}/download', [RequestLogController::class, 'generateRequestLog']);
|
||||||
Route::post('customer-service/request/import', [RequestLogController::class, 'importRequestLog']);
|
Route::post('customer-service/request/import', [RequestLogController::class, 'importRequestLog']);
|
||||||
|
Route::post('customer-service/request/import-invoice', [RequestLogController::class, 'importInvoice']);
|
||||||
|
Route::post('customer-service/request/exportFiledInvoice', [RequestLogController::class, 'exportFiledInvoice']);
|
||||||
Route::get('customer-service/request/data', [RequestLogController::class, 'generateDataRequestLogExcel']);
|
Route::get('customer-service/request/data', [RequestLogController::class, 'generateDataRequestLogExcel']);
|
||||||
Route::post('customer-service/request/{id}/add_file', [RequestLogController::class, 'requestFiles']);
|
Route::post('customer-service/request/{id}/add_file', [RequestLogController::class, 'requestFiles']);
|
||||||
Route::post('customer-service/request/{id}/delete_file', [RequestLogController::class, 'deleteFiles']);
|
Route::post('customer-service/request/{id}/delete_file', [RequestLogController::class, 'deleteFiles']);
|
||||||
|
|||||||
@@ -19,33 +19,47 @@ class AuthController extends Controller
|
|||||||
{
|
{
|
||||||
private $url;
|
private $url;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct()
|
||||||
|
{
|
||||||
$this->url = $_ENV['LMS_APP_URL'];
|
$this->url = $_ENV['LMS_APP_URL'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function login(Request $request)
|
public function login(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
// 'email' => 'email',
|
// 'email' => 'email',
|
||||||
'phone_or_email' => 'required',
|
'phone_or_email' => 'required',
|
||||||
// 'phone' => '',
|
// 'phone' => '',
|
||||||
// 'otp' => 'required_with:phone',
|
// 'otp' => 'required_with:phone',
|
||||||
'password' => 'required',
|
'password' => 'required',
|
||||||
|
'fcm_token' => 'required'
|
||||||
// 'otp' => 'required'
|
// 'otp' => 'required'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Login hit ke API linksehat, karena encrypt nya pake CI
|
// Login hit ke API linksehat, karena encrypt nya pake CI
|
||||||
$response = Http::post($this->url.'login', [
|
$response = Http::post($this->url . 'login', [
|
||||||
'sEmail' => $request->phone_or_email,
|
'sEmail' => $request->phone_or_email,
|
||||||
'sPassword' => $request->password,
|
'sPassword' => $request->password,
|
||||||
'sRemember' => $request->remember
|
'sRemember' => $request->remember
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = $response->json();
|
$response = $response->json();
|
||||||
if ($response['success']){
|
if ($response['success']) {
|
||||||
$user = User::with('detail')
|
$user = User::with('detail')
|
||||||
->where('sEmail', $request->phone_or_email)
|
->where('sEmail', $request->phone_or_email)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
$user->notificationTokens()->updateOrCreate([
|
||||||
|
'device_id' => $request->device_id,
|
||||||
|
'token' => $request->fcm_token,
|
||||||
|
], [
|
||||||
|
'origin' => $request->origin,
|
||||||
|
'device_id' => $request->device_id,
|
||||||
|
'type' => $request->type,
|
||||||
|
'token' => $request->fcm_token,
|
||||||
|
'status' => $request->status,
|
||||||
|
]);
|
||||||
|
|
||||||
return Helper::responseJson(
|
return Helper::responseJson(
|
||||||
data: [
|
data: [
|
||||||
'token' => $user->createToken('app')->plainTextToken,
|
'token' => $user->createToken('app')->plainTextToken,
|
||||||
@@ -58,18 +72,19 @@ class AuthController extends Controller
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forgetPassword(Request $request){
|
public function forgetPassword(Request $request)
|
||||||
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Login hit ke API linksehat, karena encrypt nya pake CI
|
// Login hit ke API linksehat, karena encrypt nya pake CI
|
||||||
$response = Http::post($this->url.'forgot_password', [
|
$response = Http::post($this->url . 'forgot_password', [
|
||||||
'sEmail' => $request->email,
|
'sEmail' => $request->email,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = $response->json();
|
$response = $response->json();
|
||||||
if ($response['success']){
|
if ($response['success']) {
|
||||||
return Helper::responseJson(
|
return Helper::responseJson(
|
||||||
data: [],
|
data: [],
|
||||||
message: 'Message has been sent.'
|
message: 'Message has been sent.'
|
||||||
@@ -79,7 +94,8 @@ class AuthController extends Controller
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resetPassword(Request $request){
|
public function resetPassword(Request $request)
|
||||||
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'code' => 'required',
|
'code' => 'required',
|
||||||
@@ -87,14 +103,14 @@ class AuthController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Login hit ke API linksehat, karena encrypt nya pake CI
|
// Login hit ke API linksehat, karena encrypt nya pake CI
|
||||||
$response = Http::post($this->url.'reset_password', [
|
$response = Http::post($this->url . 'reset_password', [
|
||||||
'sCode' => $request->code,
|
'sCode' => $request->code,
|
||||||
'sEmail' => $request->email,
|
'sEmail' => $request->email,
|
||||||
'sPassword' => $request->password,
|
'sPassword' => $request->password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = $response->json();
|
$response = $response->json();
|
||||||
if ($response['success']){
|
if ($response['success']) {
|
||||||
return Helper::responseJson(
|
return Helper::responseJson(
|
||||||
data: [],
|
data: [],
|
||||||
message: 'Password telah di reset'
|
message: 'Password telah di reset'
|
||||||
@@ -105,7 +121,7 @@ class AuthController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function loginPhone(Request $request)
|
public function loginPhone(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'phone_or_email' => 'required',
|
'phone_or_email' => 'required',
|
||||||
'otp' => 'required',
|
'otp' => 'required',
|
||||||
@@ -116,10 +132,9 @@ class AuthController extends Controller
|
|||||||
'sPhone' => $request->phone_or_email,
|
'sPhone' => $request->phone_or_email,
|
||||||
'sVerificationCode' => $request->otp
|
'sVerificationCode' => $request->otp
|
||||||
])
|
])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($user){
|
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
$updateVericationCode = User::with('detail')
|
$updateVericationCode = User::with('detail')
|
||||||
->where([
|
->where([
|
||||||
'sPhone' => $request->phone_or_email,
|
'sPhone' => $request->phone_or_email,
|
||||||
@@ -127,6 +142,9 @@ class AuthController extends Controller
|
|||||||
])->update([
|
])->update([
|
||||||
'sVerificationCode' => null,
|
'sVerificationCode' => null,
|
||||||
]);
|
]);
|
||||||
|
$user->fcm_token = $request->fcm_token;
|
||||||
|
$user->save();
|
||||||
|
|
||||||
return Helper::responseJson(
|
return Helper::responseJson(
|
||||||
data: [
|
data: [
|
||||||
'token' => $user->createToken('app')->plainTextToken,
|
'token' => $user->createToken('app')->plainTextToken,
|
||||||
@@ -145,15 +163,15 @@ class AuthController extends Controller
|
|||||||
$user = User::with('detail')
|
$user = User::with('detail')
|
||||||
->where('sPhone', $request->phone_or_email)
|
->where('sPhone', $request->phone_or_email)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($user){
|
if ($user) {
|
||||||
// Request OTP ke API linksehat
|
// Request OTP ke API linksehat
|
||||||
$response = Http::post($this->url.'generate_code', [
|
$response = Http::post($this->url . 'generate_code', [
|
||||||
'sPhone' => $request->phone_or_email
|
'sPhone' => $request->phone_or_email
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = $response->json();
|
$response = $response->json();
|
||||||
|
|
||||||
return Helper::responseJson(
|
return Helper::responseJson(
|
||||||
data: [
|
data: [
|
||||||
'otp' => $response['message'],
|
'otp' => $response['message'],
|
||||||
@@ -168,9 +186,6 @@ class AuthController extends Controller
|
|||||||
message: 'Nomor tidak ditemukan'
|
message: 'Nomor tidak ditemukan'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function register(Request $request)
|
public function register(Request $request)
|
||||||
@@ -209,7 +224,7 @@ class AuthController extends Controller
|
|||||||
return Helper::responseJson(message: 'Behasil Logout.');
|
return Helper::responseJson(message: 'Behasil Logout.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function mockOtp(Request $request)
|
public function mockOtp(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
@@ -256,4 +271,32 @@ class AuthController extends Controller
|
|||||||
'token' => $user->createToken('app')->plainTextToken
|
'token' => $user->createToken('app')->plainTextToken
|
||||||
], message: 'Selamat Datang');
|
], message: 'Selamat Datang');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function notificationToken(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
$origin = $request->origin;
|
||||||
|
$device_id = $request->device_id;
|
||||||
|
$type = $request->type;
|
||||||
|
$token = $request->token;
|
||||||
|
$status = $request->status;
|
||||||
|
|
||||||
|
$user->fcm_token = $request->token;
|
||||||
|
$user->save();
|
||||||
|
// $userUpdate = User::where
|
||||||
|
|
||||||
|
$user->notificationTokens()->updateOrCreate([
|
||||||
|
'device_id' => $device_id,
|
||||||
|
], [
|
||||||
|
'origin' => $origin,
|
||||||
|
'device_id' => $device_id,
|
||||||
|
'type' => $type,
|
||||||
|
'token' => $token,
|
||||||
|
'status' => $status,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Token berhasil disimpan',
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class ChatController extends Controller
|
|||||||
public function listChannel(Request $request){
|
public function listChannel(Request $request){
|
||||||
// Validasi request jika diperlukan
|
// Validasi request jika diperlukan
|
||||||
$channel = Channel::where('member_id',$request->user_id)->get()->toArray();
|
$channel = Channel::where('member_id',$request->user_id)->get()->toArray();
|
||||||
|
|
||||||
if (!$channel) {
|
if (!$channel) {
|
||||||
$dataChannel = Channel::where('doctor_id',$request->user_id)->get()->toArray();
|
$dataChannel = Channel::where('doctor_id',$request->user_id)->get()->toArray();
|
||||||
$data = [];
|
$data = [];
|
||||||
@@ -86,11 +86,11 @@ class ChatController extends Controller
|
|||||||
->first();
|
->first();
|
||||||
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
$avatarMember = $user->detail->sImage ?? $urlAvatarDefault;
|
$avatarMember = $user->detail->sImage ?? $urlAvatarDefault;
|
||||||
|
|
||||||
$arr['id'] = $d['id'];
|
$arr['id'] = $d['id'];
|
||||||
$arr['avatar'] = $avatarMember;
|
$arr['avatar'] = $avatarMember;
|
||||||
$arr['name'] = $user->sFirstName .' '.$user->sLastName;
|
$arr['name'] = $user->sFirstName .' '.$user->sLastName;
|
||||||
$arr['last_message'] = $lastMessage;
|
$arr['last_message'] = $lastMessage;
|
||||||
|
|
||||||
array_push($data, $arr);
|
array_push($data, $arr);
|
||||||
}
|
}
|
||||||
@@ -101,14 +101,14 @@ class ChatController extends Controller
|
|||||||
|
|
||||||
return response()->json(['message' => 'Get List Channel successfully', 'channel' => $channel]);
|
return response()->json(['message' => 'Get List Channel successfully', 'channel' => $channel]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendMessage(Request $request)
|
public function sendMessage(Request $request)
|
||||||
{
|
{
|
||||||
// Validasi request jika diperlukan
|
// Validasi request jika diperlukan
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'user_id' => 'required'
|
'user_id' => 'required'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Ambil data dari request
|
// Ambil data dari request
|
||||||
$message = Message::create([
|
$message = Message::create([
|
||||||
'content' => $request->message,
|
'content' => $request->message,
|
||||||
@@ -142,7 +142,7 @@ class ChatController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
// Berikan respons yang sesuai ke klien
|
// Berikan respons yang sesuai ke klien
|
||||||
|
|
||||||
$channel = Channel::where('id',$request->channel_id)->first();
|
$channel = Channel::where('id',$request->channel_id)->first();
|
||||||
if($channel->member_id == $request->user_id){
|
if($channel->member_id == $request->user_id){
|
||||||
// Get nama dokter
|
// Get nama dokter
|
||||||
@@ -151,13 +151,13 @@ class ChatController extends Controller
|
|||||||
} else {
|
} else {
|
||||||
// Get nama pasien
|
// Get nama pasien
|
||||||
$person = User::where('nID', $channel->member_id)->first();
|
$person = User::where('nID', $channel->member_id)->first();
|
||||||
$name = $person->sFirstName . ' ' . $person->sLastName;
|
$name = $person->sFirstName . ' ' . $person->sLastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessageSent::dispatch($message);
|
ChatMessageSent::dispatch($message);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Message sent successfully',
|
'message' => 'Message sent successfully',
|
||||||
'data' => [
|
'data' => [
|
||||||
'header' => $name,
|
'header' => $name,
|
||||||
]
|
]
|
||||||
@@ -169,8 +169,8 @@ class ChatController extends Controller
|
|||||||
// Buat instance Pusher dengan konfigurasi yang sesuai
|
// Buat instance Pusher dengan konfigurasi yang sesuai
|
||||||
$channel = Channel::where('id',$request->channel_id)->first();
|
$channel = Channel::where('id',$request->channel_id)->first();
|
||||||
$livechat = Livechat::where([
|
$livechat = Livechat::where([
|
||||||
'doctor_id' => $channel->doctor_id,
|
'doctor_id' => $channel->doctor_id,
|
||||||
'patient_id' => $channel->member_id,
|
'patient_id' => $channel->member_id,
|
||||||
])->latest('created_at')->first();
|
])->latest('created_at')->first();
|
||||||
|
|
||||||
if($channel->member_id == $request->user_id){
|
if($channel->member_id == $request->user_id){
|
||||||
@@ -181,37 +181,61 @@ class ChatController extends Controller
|
|||||||
$age = '';
|
$age = '';
|
||||||
$gender = '';
|
$gender = '';
|
||||||
$question = '';
|
$question = '';
|
||||||
|
|
||||||
$consultationStart = $livechat->start_date;
|
$consultationStart = $livechat->start_date;
|
||||||
$consultationEnd = $livechat->end_date;
|
$consultationEnd = $livechat->end_date;
|
||||||
$work = '';
|
$work = '';
|
||||||
|
$weight = '-';
|
||||||
|
$height = '-';
|
||||||
$address = '';
|
$address = '';
|
||||||
|
$maritalStatus = '';
|
||||||
} else {
|
} else {
|
||||||
// Get nama pasien
|
// Get nama pasien
|
||||||
$user = User::where('nID', $channel->member_id)->with('detail')->first();
|
$user = User::where('nID', $channel->member_id)->with('detail')->first();
|
||||||
$name = $user->sFirstName . ' ' . $user->sLastName;
|
$name = $user->sFirstName . ' ' . $user->sLastName;
|
||||||
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
$gender = null;
|
||||||
$avatar = $user->detail->sImage ?? $urlAvatarDefault;
|
if ($user->detail) {
|
||||||
$gender = DB::connection('oldlms')->table('tm_jenis_kelamin')->where('nID', $user->detail->nIDJenisKelamin)->first('sJenisKelamin');
|
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
if ($gender){
|
$avatar = $user->detail->sImage ?? $urlAvatarDefault;
|
||||||
$gender = $gender->sJenisKelamin;
|
$gender = DB::connection('oldlms')->table('tm_jenis_kelamin')->where('nID', $user->detail->nIDJenisKelamin)->first('sJenisKelamin');
|
||||||
|
$age = Helper::calculateAge($user->detail->dTanggalLahir);
|
||||||
|
if ($gender){
|
||||||
|
$gender = $gender->sJenisKelamin;
|
||||||
|
}
|
||||||
|
$work = DB::connection('oldlms')->table('tm_pekerjaan')->where('nID', $user->detail->nIDPekerjaan)->first('sPekerjaan');
|
||||||
|
|
||||||
|
if($work){
|
||||||
|
$work = $work->sPekerjaan;
|
||||||
|
}
|
||||||
|
$maritalStatus = DB::connection('oldlms')->table('tm_status_pernikahan')->where('nID', $user->detail->sMartialStatus)->first('sStatusPernikahan');
|
||||||
|
if($maritalStatus){
|
||||||
|
$maritalStatus = $maritalStatus->sStatusPernikahan;
|
||||||
|
}
|
||||||
|
|
||||||
|
$weight = $user->detail->sWeight;
|
||||||
|
$height = $user->detail->sWeight;
|
||||||
|
} else {
|
||||||
|
$avatar = 'https://linksehat.dev/assets/img/users/male-avatar.png';
|
||||||
|
$age = '-';
|
||||||
|
$work = '-';
|
||||||
|
$maritalStatus = '-';
|
||||||
|
$weight = '-';
|
||||||
|
$height = '-';
|
||||||
|
|
||||||
}
|
}
|
||||||
$age = Helper::calculateAge($user->detail->dTanggalLahir);
|
|
||||||
$question = $livechat->descriptions;
|
$question = $livechat->descriptions;
|
||||||
$consultationStart = $livechat->start_date;
|
$consultationStart = $livechat->start_date;
|
||||||
$consultationEnd = $livechat->end_date;
|
$consultationEnd = $livechat->end_date;
|
||||||
$work = DB::connection('oldlms')->table('tm_pekerjaan')->where('nID', $user->detail->nIDPekerjaan)->first('sPekerjaan');
|
|
||||||
|
|
||||||
if($work){
|
|
||||||
$work = $work->sPekerjaan;
|
|
||||||
}
|
|
||||||
$address = DB::connection('oldlms')->table('tm_users_address')->where('nIDUser', $user->nID)->first('sAlamat');
|
$address = DB::connection('oldlms')->table('tm_users_address')->where('nIDUser', $user->nID)->first('sAlamat');
|
||||||
if($address){
|
if($address){
|
||||||
$address = $address->sAlamat;
|
$address = $address->sAlamat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ini Untul Chat
|
// Ini Untul Chat
|
||||||
$perPage = $request->input('per_page', 10); // Default 10 pesan per halaman
|
$perPage = $request->input('per_page', 10); // Default 10 pesan per halaman
|
||||||
$page = $request->input('page', 1); // Default halaman 1
|
$page = $request->input('page', 1); // Default halaman 1
|
||||||
@@ -220,7 +244,7 @@ class ChatController extends Controller
|
|||||||
->where('type', '!=', 'trigger')
|
->where('type', '!=', 'trigger')
|
||||||
->orderBy('created_at', 'desc') // Urutkan berdasarkan created_at secara descending
|
->orderBy('created_at', 'desc') // Urutkan berdasarkan created_at secara descending
|
||||||
->paginate($perPage, ['*'], 'page', $page);
|
->paginate($perPage, ['*'], 'page', $page);
|
||||||
|
|
||||||
// Data Consultation Summary
|
// Data Consultation Summary
|
||||||
$consultationSummary = [
|
$consultationSummary = [
|
||||||
'subject' => $livechat->subject,
|
'subject' => $livechat->subject,
|
||||||
@@ -240,12 +264,22 @@ class ChatController extends Controller
|
|||||||
'header' => $name,
|
'header' => $name,
|
||||||
'avatar' => $avatar,
|
'avatar' => $avatar,
|
||||||
'gender' => $gender,
|
'gender' => $gender,
|
||||||
|
'marital_status' => $maritalStatus,
|
||||||
'age' => $age,
|
'age' => $age,
|
||||||
|
'weight' => $weight,
|
||||||
|
'height' => $height,
|
||||||
'question' => $question,
|
'question' => $question,
|
||||||
|
'diseases' => [],
|
||||||
|
'medications' => [],
|
||||||
|
'allergy' => [],
|
||||||
|
'family_history' => [],
|
||||||
'start' => $consultationStart,
|
'start' => $consultationStart,
|
||||||
'end' => $consultationEnd,
|
'end' => $consultationEnd,
|
||||||
'work' => $work,
|
'work' => $work,
|
||||||
'address' => $address,
|
'address' => $address,
|
||||||
|
'consultation_id' => $livechat->id,
|
||||||
|
'consultation_status' => Helper::getStatusLivechat($livechat->status),
|
||||||
|
'health_sertificate' => $healthSertificate,
|
||||||
'chat' => $data->items(),
|
'chat' => $data->items(),
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'total' => $data->total(),
|
'total' => $data->total(),
|
||||||
@@ -256,8 +290,7 @@ class ChatController extends Controller
|
|||||||
'to' => $data->lastItem(),
|
'to' => $data->lastItem(),
|
||||||
],
|
],
|
||||||
'summary' => $consultationSummary,
|
'summary' => $consultationSummary,
|
||||||
'livechat_id' => $livechat->id,
|
|
||||||
'health_sertificate' => $healthSertificate,
|
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -278,7 +311,7 @@ class ChatController extends Controller
|
|||||||
])->latest('created_at')->first();
|
])->latest('created_at')->first();
|
||||||
|
|
||||||
$user = User::where('nID', $livechat->patient_id)->with('detail')->first();
|
$user = User::where('nID', $livechat->patient_id)->with('detail')->first();
|
||||||
$name = $user->sFirstName . ' ' . $user->sLastName;
|
$name = $user->sFirstName . ' ' . $user->sLastName;
|
||||||
$age = Helper::calculateAge($user->detail->dTanggalLahir);
|
$age = Helper::calculateAge($user->detail->dTanggalLahir);
|
||||||
|
|
||||||
$person = Person::where('id', $livechat->doctor_id)->first();
|
$person = Person::where('id', $livechat->doctor_id)->first();
|
||||||
@@ -294,7 +327,7 @@ class ChatController extends Controller
|
|||||||
}
|
}
|
||||||
// Memuat view pdf_view.php ke dalam variabel
|
// Memuat view pdf_view.php ke dalam variabel
|
||||||
$calculateDate = Helper::calculateDateDifference($livechat->health_certificate_start, $livechat->health_certificate_end);
|
$calculateDate = Helper::calculateDateDifference($livechat->health_certificate_start, $livechat->health_certificate_end);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'age' => $age,
|
'age' => $age,
|
||||||
|
|||||||
@@ -24,15 +24,18 @@ class AuthDoctorController extends Controller
|
|||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
'email' => $request->email,
|
'email' => $request->email,
|
||||||
'password' => $request->password
|
'password' => $request->password,
|
||||||
|
'fcm_token' => $request->fcm_token,
|
||||||
];
|
];
|
||||||
$validator = Validator::make($request->all(), [
|
$validator = Validator::make($request->all(), [
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'password' => 'required'
|
'password' => 'required',
|
||||||
|
'fcm_token' => 'required'
|
||||||
], [
|
], [
|
||||||
'email.required' => trans('Validation.required',['attribute' => 'Email']),
|
'email.required' => trans('Validation.required',['attribute' => 'Email']),
|
||||||
'email.email' => trans('Validation.email'),
|
'email.email' => trans('Validation.email'),
|
||||||
'password.required' => trans('Validation.required',['attribute' => 'Password']),
|
'password.required' => trans('Validation.required',['attribute' => 'Password']),
|
||||||
|
'fcm_token.required' => trans('Validation.required',['attribute' => 'FCM Token']),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails())
|
if ($validator->fails())
|
||||||
@@ -50,6 +53,18 @@ class AuthDoctorController extends Controller
|
|||||||
return ApiResponse::apiResponse('Bad Request', $data, trans('Message.password'), 400);
|
return ApiResponse::apiResponse('Bad Request', $data, trans('Message.password'), 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user->notificationTokens()->updateOrCreate([
|
||||||
|
'device_id' => $request->device_id,
|
||||||
|
'token' => $request->fcm_token,
|
||||||
|
], [
|
||||||
|
'origin' => $request->origin,
|
||||||
|
'device_id' => $request->device_id,
|
||||||
|
'type' => $request->type,
|
||||||
|
'token' => $request->fcm_token,
|
||||||
|
'status' => $request->status,
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
$res_data = [
|
$res_data = [
|
||||||
// 'user' => $user,
|
// 'user' => $user,
|
||||||
'token' => $user->createToken('app')->plainTextToken
|
'token' => $user->createToken('app')->plainTextToken
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace Modules\Linksehat\Http\Controllers\Api\Doctor;
|
namespace Modules\Linksehat\Http\Controllers\Api\Doctor;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Notifications\SendNotification;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\OLDLMS\User as UserLMS;
|
use App\Models\OLDLMS\User as UserLMS;
|
||||||
use App\Models\Livechat;
|
use App\Models\Livechat;
|
||||||
@@ -23,6 +24,8 @@ use Modules\HospitalPortal\Helpers\ApiResponse;
|
|||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Kreait\Firebase\Messaging\CloudMessage;
|
||||||
|
use Kreait\Laravel\Firebase\Facades\Firebase;
|
||||||
|
|
||||||
class ChatDoctorController extends Controller
|
class ChatDoctorController extends Controller
|
||||||
{
|
{
|
||||||
@@ -44,8 +47,12 @@ class ChatDoctorController extends Controller
|
|||||||
if($chat) {
|
if($chat) {
|
||||||
foreach($chat as $c){
|
foreach($chat as $c){
|
||||||
$patient = UserLMS::where('nID',$c->patient_id)->with('detail')->first();
|
$patient = UserLMS::where('nID',$c->patient_id)->with('detail')->first();
|
||||||
$urlAvatarDefault = $patient->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
if ( $patient->detail) {
|
||||||
$avatarMember = $patient->detail->sImage ?? $urlAvatarDefault;
|
$urlAvatarDefault = $patient->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
|
$avatarMember = $patient->detail->sImage ?? $urlAvatarDefault;
|
||||||
|
} else {
|
||||||
|
$avatarMember = 'https://linksehat.dev/assets/img/users/male-avatar.png';
|
||||||
|
}
|
||||||
$arr['id'] = $c->id;
|
$arr['id'] = $c->id;
|
||||||
$arr['patient_id'] = $patient->nID;
|
$arr['patient_id'] = $patient->nID;
|
||||||
$arr['avatar'] = $avatarMember;
|
$arr['avatar'] = $avatarMember;
|
||||||
@@ -68,11 +75,11 @@ class ChatDoctorController extends Controller
|
|||||||
} else {
|
} else {
|
||||||
$avatarMember = 'https://linksehat.dev/assets/img/users/male-avatar.png';
|
$avatarMember = 'https://linksehat.dev/assets/img/users/male-avatar.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
$arr['id'] = $d['id'];
|
$arr['id'] = $d['id'];
|
||||||
$arr['avatar'] = $avatarMember;
|
$arr['avatar'] = $avatarMember;
|
||||||
$arr['name'] = $user->sFirstName .' '.$user->sLastName;
|
$arr['name'] = $user->sFirstName .' '.$user->sLastName;
|
||||||
$arr['last_message'] = $lastMessage;
|
$arr['last_message'] = $lastMessage;
|
||||||
|
|
||||||
array_push($dataOnGoing, $arr);
|
array_push($dataOnGoing, $arr);
|
||||||
}
|
}
|
||||||
@@ -119,7 +126,7 @@ class ChatDoctorController extends Controller
|
|||||||
}
|
}
|
||||||
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
|
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function declineChat(Request $request)
|
public function declineChat(Request $request)
|
||||||
{
|
{
|
||||||
$livechat = Livechat::find($request->id);
|
$livechat = Livechat::find($request->id);
|
||||||
@@ -128,6 +135,34 @@ class ChatDoctorController extends Controller
|
|||||||
$livechat->status = 3; // Decline
|
$livechat->status = 3; // Decline
|
||||||
// Menyimpan perubahan ke database
|
// Menyimpan perubahan ke database
|
||||||
$livechat->save();
|
$livechat->save();
|
||||||
|
|
||||||
|
// Send Notification
|
||||||
|
$doctorId = $livechat->doctor_id;
|
||||||
|
$title = 'Decline Livechat';
|
||||||
|
$body = 'Decline Livechat';
|
||||||
|
$channel = Channel::where([
|
||||||
|
'member_id' => $livechat->patient_id,
|
||||||
|
'doctor_id' => $livechat->doctor_id
|
||||||
|
])->first();
|
||||||
|
$dataNotif = [
|
||||||
|
'channel_id' => $channel->id,
|
||||||
|
'livechat_id' => $livechat->id,
|
||||||
|
'type' => 'decline-chat'
|
||||||
|
];
|
||||||
|
|
||||||
|
$user = UserLMS::where('nID',$livechat->patient_id)->first();
|
||||||
|
if ($user) {
|
||||||
|
$user->notify(new SendNotification($title, $body, $dataNotif));
|
||||||
|
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
||||||
|
} else {
|
||||||
|
return Helper::responseJson(
|
||||||
|
status: 'Not Found',
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'Doctor not found.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
||||||
} else {
|
} else {
|
||||||
return response()->json(['message' => 'Livechat not found'], 404);
|
return response()->json(['message' => 'Livechat not found'], 404);
|
||||||
@@ -143,7 +178,33 @@ class ChatDoctorController extends Controller
|
|||||||
$livechat->accept_date = date('Y-m-d H:i:s'); // Accept
|
$livechat->accept_date = date('Y-m-d H:i:s'); // Accept
|
||||||
// Menyimpan perubahan ke database
|
// Menyimpan perubahan ke database
|
||||||
$livechat->save();
|
$livechat->save();
|
||||||
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
|
||||||
|
// Send Notification
|
||||||
|
$doctorId = $livechat->doctor_id;
|
||||||
|
$title = 'Approve Request Livechat';
|
||||||
|
$body = 'Approve Livechat';
|
||||||
|
$channel = Channel::where([
|
||||||
|
'member_id' => $livechat->patient_id,
|
||||||
|
'doctor_id' => $livechat->doctor_id
|
||||||
|
])->first();
|
||||||
|
$dataNotif = [
|
||||||
|
'channel_id' => $channel->id,
|
||||||
|
'livechat_id' => $livechat->id,
|
||||||
|
'type' => 'approve-chat'
|
||||||
|
];
|
||||||
|
|
||||||
|
$user = UserLMS::where('nID',$livechat->patient_id)->first();
|
||||||
|
if ($user) {
|
||||||
|
$user->notify(new SendNotification($title, $body, $dataNotif));
|
||||||
|
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
||||||
|
} else {
|
||||||
|
return Helper::responseJson(
|
||||||
|
status: 'Not Found',
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'Doctor not found.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return response()->json(['message' => 'Livechat not found'], 404);
|
return response()->json(['message' => 'Livechat not found'], 404);
|
||||||
}
|
}
|
||||||
@@ -155,10 +216,36 @@ class ChatDoctorController extends Controller
|
|||||||
if ($livechat) {
|
if ($livechat) {
|
||||||
// Memperbarui atribut model
|
// Memperbarui atribut model
|
||||||
$livechat->status = 6; // End Chat
|
$livechat->status = 6; // End Chat
|
||||||
$livechat->end_date = date('Y-m-d H:i:s'); // Accept
|
$livechat->end_date = date('Y-m-d H:i:s'); // Endchat
|
||||||
// Menyimpan perubahan ke database
|
// Menyimpan perubahan ke database
|
||||||
$livechat->save();
|
$livechat->save();
|
||||||
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
|
||||||
|
// Send Notification
|
||||||
|
$doctorId = $livechat->doctor_id;
|
||||||
|
$title = 'End Livechat';
|
||||||
|
$body = 'End Livechat';
|
||||||
|
$channel = Channel::where([
|
||||||
|
'member_id' => $livechat->patient_id,
|
||||||
|
'doctor_id' => $livechat->doctor_id
|
||||||
|
])->first();
|
||||||
|
$dataNotif = [
|
||||||
|
'channel_id' => $channel->id,
|
||||||
|
'livechat_id' => $livechat->id,
|
||||||
|
'type' => 'end-chat'
|
||||||
|
];
|
||||||
|
|
||||||
|
$user = UserLMS::where('nID',$livechat->patient_id)->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$user->notify(new SendNotification($title, $body, $dataNotif));
|
||||||
|
return ApiResponse::apiResponse("Success",['message' => 'Livechat updated successfully'], trans('Message.success'), 200);
|
||||||
|
} else {
|
||||||
|
return Helper::responseJson(
|
||||||
|
status: 'Not Found',
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'Doctor not found.'
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return response()->json(['message' => 'Livechat not found'], 404);
|
return response()->json(['message' => 'Livechat not found'], 404);
|
||||||
}
|
}
|
||||||
@@ -166,7 +253,6 @@ class ChatDoctorController extends Controller
|
|||||||
|
|
||||||
public function summaryChat(Request $request)
|
public function summaryChat(Request $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$livechat = Livechat::find($request->id);
|
$livechat = Livechat::find($request->id);
|
||||||
if ($livechat) {
|
if ($livechat) {
|
||||||
// Memperbarui atribut model
|
// Memperbarui atribut model
|
||||||
|
|||||||
@@ -3,11 +3,14 @@
|
|||||||
namespace Modules\Linksehat\Http\Controllers\Api;
|
namespace Modules\Linksehat\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
|
use App\Notifications\SendNotification;
|
||||||
use App\Models\Organization;
|
use App\Models\Organization;
|
||||||
use App\Models\Speciality;
|
use App\Models\Speciality;
|
||||||
use App\Models\Livechat;
|
use App\Models\Livechat;
|
||||||
use App\Models\Channel;
|
use App\Models\Channel;
|
||||||
use App\Models\UserChannel;
|
use App\Models\UserChannel;
|
||||||
|
use App\Models\User as UserAso;
|
||||||
|
use App\Models\OLDLMS\User;
|
||||||
use Illuminate\Contracts\Support\Renderable;
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -285,16 +288,15 @@ class DuitkuController extends Controller
|
|||||||
'created_at' => date('Y-m-d H:i:s')
|
'created_at' => date('Y-m-d H:i:s')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($notif->resultCode == "00") {
|
if ($notif->resultCode == "00") { // berhasil melakukan pembayaran
|
||||||
// Action Success
|
// Action Success
|
||||||
$livechat = Livechat::where('uuid', $notif->merchantOrderId)->first();
|
$livechat = Livechat::where('uuid', $notif->merchantOrderId)->first();
|
||||||
// Update status pembayaran
|
// Update status pembayaran
|
||||||
$livechat->payment_method = $notif->paymentCode;
|
$livechat->payment_method = $notif->paymentCode;
|
||||||
$livechat->status = 5; // success payment
|
$livechat->status = 5; // success payment
|
||||||
$livechat->save();
|
|
||||||
|
|
||||||
// Update start chat
|
// Update start chat
|
||||||
$livechat->start_date = date('Y-m-d H:i:s');
|
$livechat->start_date = date('Y-m-d H:i:s');
|
||||||
|
$livechat->save();
|
||||||
// Buat dan simpan data channel ke dalam tabel
|
// Buat dan simpan data channel ke dalam tabel
|
||||||
$channel = Channel::updateOrCreate([
|
$channel = Channel::updateOrCreate([
|
||||||
'name' => $livechat->patient_id .'_' . $request->doctor_id,
|
'name' => $livechat->patient_id .'_' . $request->doctor_id,
|
||||||
@@ -330,9 +332,26 @@ class DuitkuController extends Controller
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Send Notification
|
||||||
|
$doctorId = $livechat->doctor_id;
|
||||||
|
$userDokter = UserAso::find($doctorId);
|
||||||
|
$title = 'Payment Succes Livechat';
|
||||||
|
$patient = User::where('nID', $livechat->patient_id)->first();
|
||||||
|
$body = 'Payment Succes Livechat from ' . $patient->sFirstName . ' ' . $patient->sLastName;
|
||||||
|
$channel = Channel::where([
|
||||||
|
'member_id' => $livechat->patient_id,
|
||||||
|
'doctor_id' => $livechat->doctor_id
|
||||||
|
])->first();
|
||||||
|
$dataNotif = [
|
||||||
|
'channel_id' => $channel->id,
|
||||||
|
'livechat_id' => $livechat->id,
|
||||||
|
'type' => 'success-payment'
|
||||||
|
];
|
||||||
|
$userDokter->notify(new SendNotification($title, $body, $dataNotif));
|
||||||
|
|
||||||
// Berikan respons yang sesuai ke klien
|
// Berikan respons yang sesuai ke klien
|
||||||
return response()->json(['message' => 'Channel created successfully', 'channel' => $channel]);
|
return response()->json(['message' => 'Channel created successfully', 'channel' => $channel]);
|
||||||
|
|
||||||
} else if ($notif->resultCode == "01") {
|
} else if ($notif->resultCode == "01") {
|
||||||
// Action Failed
|
// Action Failed
|
||||||
$livechat = Livechat::where('uuid', $notif->merchantOrderId)->first();
|
$livechat = Livechat::where('uuid', $notif->merchantOrderId)->first();
|
||||||
@@ -341,6 +360,22 @@ class DuitkuController extends Controller
|
|||||||
$livechat->status = 7; // failed payment
|
$livechat->status = 7; // failed payment
|
||||||
$livechat->save();
|
$livechat->save();
|
||||||
|
|
||||||
|
// Send Notification
|
||||||
|
$doctorId = $livechat->doctor_id;
|
||||||
|
$userDokter = UserAso::find($doctorId);
|
||||||
|
$title = 'Payment Failed Livechat';
|
||||||
|
$patient = User::where('nID', $livechat->patient_id)->first();
|
||||||
|
$body = 'Payment Failed Livechat from ' . $patient->sFirstName . ' ' . $patient->sLastName;
|
||||||
|
$channel = Channel::where([
|
||||||
|
'member_id' => $livechat->patient_id,
|
||||||
|
'doctor_id' => $livechat->doctor_id
|
||||||
|
])->first();
|
||||||
|
$dataNotif = [
|
||||||
|
'channel_id' => $channel->id,
|
||||||
|
'livechat_id' => $livechat->id,
|
||||||
|
'type' => 'failed-payment'
|
||||||
|
];
|
||||||
|
$userDokter->notify(new SendNotification($title, $body, $dataNotif));
|
||||||
return response()->json(['message' => 'User Gagal melakukan pembayaran']);
|
return response()->json(['message' => 'User Gagal melakukan pembayaran']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Modules\Linksehat\Http\Controllers\Api;
|
namespace Modules\Linksehat\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Notifications\SendNotification;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Helpers\DuitkuHelper;
|
use App\Helpers\DuitkuHelper;
|
||||||
use App\Services\Duitku;
|
use App\Services\Duitku;
|
||||||
@@ -9,8 +10,10 @@ use App\Models\Organization;
|
|||||||
use App\Models\PractitionerRole;
|
use App\Models\PractitionerRole;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\PaymentsMethods;
|
use App\Models\PaymentsMethods;
|
||||||
|
use App\Models\Channel;
|
||||||
use App\Models\Livechat;
|
use App\Models\Livechat;
|
||||||
use App\Models\OLDLMS\User;
|
use App\Models\OLDLMS\User;
|
||||||
|
use App\Models\User as UserAso;
|
||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@@ -20,6 +23,9 @@ use Illuminate\Support\Facades\Validator;
|
|||||||
use App\Http\Controllers\DuitkuController;
|
use App\Http\Controllers\DuitkuController;
|
||||||
|
|
||||||
use DB;
|
use DB;
|
||||||
|
use Illuminate\Contracts\Filesystem\Cloud;
|
||||||
|
use Kreait\Firebase\Messaging\CloudMessage;
|
||||||
|
use Kreait\Laravel\Firebase\Facades\Firebase;
|
||||||
use Str;
|
use Str;
|
||||||
|
|
||||||
class LivechatController extends Controller
|
class LivechatController extends Controller
|
||||||
@@ -45,7 +51,7 @@ class LivechatController extends Controller
|
|||||||
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
$avatarMember = $user->detail->sImage ?? $urlAvatarDefault;
|
$avatarMember = $user->detail->sImage ?? $urlAvatarDefault;
|
||||||
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $user->nIDHubunganKeluarga)->first('sHubunganKeluarga');
|
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $user->nIDHubunganKeluarga)->first('sHubunganKeluarga');
|
||||||
|
|
||||||
$dataUser = [
|
$dataUser = [
|
||||||
'id' => $user->nID,
|
'id' => $user->nID,
|
||||||
'name' => $user->sFirstName . ' ' . $user->sLastName,
|
'name' => $user->sFirstName . ' ' . $user->sLastName,
|
||||||
@@ -59,7 +65,7 @@ class LivechatController extends Controller
|
|||||||
$urlAvatarDefault = $m['detail']['nIDJenisKelamin'] == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
$urlAvatarDefault = $m['detail']['nIDJenisKelamin'] == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
$avatarMember = $m['detail']['sImage'] ?? $urlAvatarDefault;
|
$avatarMember = $m['detail']['sImage'] ?? $urlAvatarDefault;
|
||||||
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $m['nIDHubunganKeluarga'])->first('sHubunganKeluarga');
|
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $m['nIDHubunganKeluarga'])->first('sHubunganKeluarga');
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'id' => $m['nID'],
|
'id' => $m['nID'],
|
||||||
'name' => $m['full_name'],
|
'name' => $m['full_name'],
|
||||||
@@ -75,17 +81,17 @@ class LivechatController extends Controller
|
|||||||
$memberProfile = User::with('detail')->where('nIDUser', $nID)->get()->toArray();
|
$memberProfile = User::with('detail')->where('nIDUser', $nID)->get()->toArray();
|
||||||
|
|
||||||
$dataMember = User::with('detail')->where('nID', $nID)->get()->first();
|
$dataMember = User::with('detail')->where('nID', $nID)->get()->first();
|
||||||
|
|
||||||
if ($user->detail){
|
if ($user->detail){
|
||||||
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
$urlAvatarDefault = $user->detail->nIDJenisKelamin == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
} else {
|
} else {
|
||||||
$urlAvatarDefault = 'https://linksehat.dev/assets/img/users/male-avatar.png';
|
$urlAvatarDefault = 'https://linksehat.dev/assets/img/users/male-avatar.png';
|
||||||
}
|
}
|
||||||
$avatar = $user->detail->sImage ?? $urlAvatarDefault;
|
$avatar = $user->detail->sImage ?? $urlAvatarDefault;
|
||||||
|
|
||||||
$avatarMember = $dataMember->detail->sImage ?? $urlAvatarDefault;
|
$avatarMember = $dataMember->detail->sImage ?? $urlAvatarDefault;
|
||||||
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $user->detail->nIDHubunganKeluarga)->first('sHubunganKeluarga');
|
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $user->detail->nIDHubunganKeluarga)->first('sHubunganKeluarga');
|
||||||
|
|
||||||
$dataUser = [
|
$dataUser = [
|
||||||
'id' => $dataMember->nID,
|
'id' => $dataMember->nID,
|
||||||
'name' => $dataMember->sFirstName . ' ' . $dataMember->sLastName,
|
'name' => $dataMember->sFirstName . ' ' . $dataMember->sLastName,
|
||||||
@@ -99,20 +105,20 @@ class LivechatController extends Controller
|
|||||||
$urlAvatarDefault = $m['detail']['nIDJenisKelamin'] == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
$urlAvatarDefault = $m['detail']['nIDJenisKelamin'] == 1 ? 'https://linksehat.dev/assets/img/users/male-avatar.png' : 'https://linksehat.dev/assets/img/users/female-avatar.png';
|
||||||
$avatarMember = $m['detail']['sImage'] ?? $urlAvatarDefault;
|
$avatarMember = $m['detail']['sImage'] ?? $urlAvatarDefault;
|
||||||
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $m['nIDHubunganKeluarga'])->first('sHubunganKeluarga');
|
$relationship = DB::connection('oldlms')->table('tm_hubungan_keluarga')->where('nID', $m['nIDHubunganKeluarga'])->first('sHubunganKeluarga');
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'id' => $m['nID'],
|
'id' => $m['nID'],
|
||||||
'name' => $m['full_name'],
|
'name' => $m['full_name'],
|
||||||
'relationship' => $relationship->sHubunganKeluarga,
|
'relationship' => $relationship->sHubunganKeluarga,
|
||||||
'avatar' => $avatarMember,
|
'avatar' => $avatarMember,
|
||||||
];
|
];
|
||||||
|
|
||||||
array_push( $dataMemberProfile, $data);
|
array_push( $dataMemberProfile, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Helper::responseJson([
|
return Helper::responseJson([
|
||||||
'member' => $dataMemberProfile
|
'member' => $dataMemberProfile
|
||||||
]);
|
]);
|
||||||
@@ -133,11 +139,11 @@ class LivechatController extends Controller
|
|||||||
'descriptions' => 'required',
|
'descriptions' => 'required',
|
||||||
], [
|
], [
|
||||||
'doctor_id.required' => 'ID Dokter harus diisi',
|
'doctor_id.required' => 'ID Dokter harus diisi',
|
||||||
'patient_id.required' => 'ID Dokter harus diisi',
|
'patient_id.required' => 'ID Pasien harus diisi',
|
||||||
'descriptions.required' => 'Description harus diisi',
|
'descriptions.required' => 'Deskripsi harus diisi',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails()){
|
if ($validator->fails()) {
|
||||||
return Helper::responseJson(
|
return Helper::responseJson(
|
||||||
status: 'Bad Request',
|
status: 'Bad Request',
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
@@ -148,27 +154,52 @@ class LivechatController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Status Livechat
|
* Status Livechat
|
||||||
* 1=Request, 2=Accept, 3=Decline, 4=Waiting Payment, 5=Success Payment, 6 = End Chat
|
* 1=Request, 2=Accept, 3=Decline, 4=Waiting Payment, 5=Success Payment, 6 = End Chat, 7=Payment Failed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$timezone = date_default_timezone_get();
|
$timezone = date_default_timezone_get();
|
||||||
$data['request_date'] = date('Y-m-d H:i:s');
|
$data['request_date'] = date('Y-m-d H:i:s');
|
||||||
$data['timezone'] = $timezone;
|
$data['timezone'] = $timezone;
|
||||||
$data['uuid'] = (string) Str::orderedUuid();
|
$data['uuid'] = (string) Str::orderedUuid();
|
||||||
$data['status'] = 1;
|
$data['status'] = 1; // Request
|
||||||
|
|
||||||
$livechat = Livechat::create($data);
|
$livechat = Livechat::create($data);
|
||||||
$doctor = $livechat->doctor;
|
$doctor = $livechat->doctor;
|
||||||
$data = [
|
$responseData = [
|
||||||
'id' => $livechat->id,
|
'id' => $livechat->id,
|
||||||
'request_date' => $livechat->request_date,
|
'request_date' => $livechat->request_date,
|
||||||
'image_path' =>'https'
|
'image_path' => 'https' // Ganti dengan path yang benar jika ada
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Send Notification
|
||||||
return Helper::responseJson(data: $data);
|
$doctorId = $livechat->doctor_id;
|
||||||
|
$user = UserAso::find($doctorId);
|
||||||
|
$title = 'New Request Livechat';
|
||||||
|
$patient = User::where('nID', $livechat->patient_id)->first();
|
||||||
|
$body = 'Request Livechat from ' . $patient->sFirstName . ' ' . $patient->sLastName;
|
||||||
|
$channel = Channel::where([
|
||||||
|
'member_id' => $livechat->patient_id,
|
||||||
|
'doctor_id' => $livechat->doctor_id
|
||||||
|
])->first();
|
||||||
|
$dataNotif = [
|
||||||
|
'channel_id' => $channel->id,
|
||||||
|
'livechat_id' => $livechat->id,
|
||||||
|
'type' => 'request-chat'
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$user->notify(new SendNotification($title, $body, $dataNotif));
|
||||||
|
return Helper::responseJson(data: $responseData);
|
||||||
|
} else {
|
||||||
|
return Helper::responseJson(
|
||||||
|
status: 'Not Found',
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'Doctor not found.'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function consultation_request_show($id){
|
public function consultation_request_show($id){
|
||||||
$livechat = Livechat::where('id', $id)->with(['doctor', 'practitioner'])->first();
|
$livechat = Livechat::where('id', $id)->with(['doctor', 'practitioner'])->first();
|
||||||
$practitionerRole = PractitionerRole::where('id',$livechat->practitioner->id)->first();
|
$practitionerRole = PractitionerRole::where('id',$livechat->practitioner->id)->first();
|
||||||
@@ -198,7 +229,7 @@ class LivechatController extends Controller
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
'total' => $totalPay
|
'total' => $totalPay
|
||||||
|
|
||||||
];
|
];
|
||||||
return Helper::responseJson(data: $data);
|
return Helper::responseJson(data: $data);
|
||||||
}
|
}
|
||||||
@@ -216,9 +247,9 @@ class LivechatController extends Controller
|
|||||||
'active' => 1,
|
'active' => 1,
|
||||||
'config_pmc_id' => 2,
|
'config_pmc_id' => 2,
|
||||||
])->get()->toArray();
|
])->get()->toArray();
|
||||||
|
|
||||||
$payment = DuitkuHelper::paymentMethod();
|
$payment = DuitkuHelper::paymentMethod();
|
||||||
|
|
||||||
$price = $practitionerRole->price ? $practitionerRole->price : 30000;
|
$price = $practitionerRole->price ? $practitionerRole->price : 30000;
|
||||||
$discount = 0;
|
$discount = 0;
|
||||||
$adminFee = 5000;
|
$adminFee = 5000;
|
||||||
@@ -234,7 +265,7 @@ class LivechatController extends Controller
|
|||||||
'va' => $va
|
'va' => $va
|
||||||
]
|
]
|
||||||
// 'payment_method' => json_decode($payment)
|
// 'payment_method' => json_decode($payment)
|
||||||
|
|
||||||
];
|
];
|
||||||
return Helper::responseJson(data: $data);
|
return Helper::responseJson(data: $data);
|
||||||
}
|
}
|
||||||
@@ -290,7 +321,6 @@ class LivechatController extends Controller
|
|||||||
// Membuat invoice menggunakan DuitkuHelper
|
// Membuat invoice menggunakan DuitkuHelper
|
||||||
$duitku = DuitkuHelper::createInvoice($data);
|
$duitku = DuitkuHelper::createInvoice($data);
|
||||||
|
|
||||||
|
|
||||||
return response()->json(['success' => true, 'data' => $duitku], 200);
|
return response()->json(['success' => true, 'data' => $duitku], 200);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// Menangkap error dan mengembalikan respon error
|
// Menangkap error dan mengembalikan respon error
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use Modules\Linksehat\Http\Controllers\Api\Doctor\ChatDoctorController;
|
|||||||
|
|
||||||
Broadcast::routes(['middleware' => ['auth:sanctum']]);
|
Broadcast::routes(['middleware' => ['auth:sanctum']]);
|
||||||
Route::prefix('linksehat')->group(function () {
|
Route::prefix('linksehat')->group(function () {
|
||||||
|
|
||||||
Route::get('dashboard/{query}/{limit?}', [DashboardController::class, 'index']);
|
Route::get('dashboard/{query}/{limit?}', [DashboardController::class, 'index']);
|
||||||
|
|
||||||
Route::controller(SearchController::class)->group(function () {
|
Route::controller(SearchController::class)->group(function () {
|
||||||
@@ -72,13 +72,14 @@ Route::prefix('linksehat')->group(function () {
|
|||||||
Route::get('doctors/{id}', 'show')->name('doctors.show');
|
Route::get('doctors/{id}', 'show')->name('doctors.show');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::middleware('auth:sanctum')->group(function () {
|
Route::middleware(['auth:sanctum', 'linksehat.old.auth'])->group(function () {
|
||||||
|
Route::post('notification-token', [AuthController::class,'notificationToken']);
|
||||||
Route::get('profile/{id}', [ProfileController::class, 'index'])->name('profile');
|
Route::get('profile/{id}', [ProfileController::class, 'index'])->name('profile');
|
||||||
Route::get('change-profile/{id}', [ProfileController::class, 'changeProfile'])->name('change-profile');
|
Route::get('change-profile/{id}', [ProfileController::class, 'changeProfile'])->name('change-profile');
|
||||||
Route::post('profile', [ProfileController::class, 'update'])->name('profile.update');
|
Route::post('profile', [ProfileController::class, 'update'])->name('profile.update');
|
||||||
Route::post('profile-add', [ProfileController::class, 'store'])->name('profile.store');
|
Route::post('profile-add', [ProfileController::class, 'store'])->name('profile.store');
|
||||||
Route::post('notification-tokens/delete/{id}', [NotificationTokenController::class, 'destroy'])->name('profile.delete.token');
|
// Route::post('notification-tokens/delete/{id}', [NotificationTokenController::class, 'destroy'])->name('profile.delete.token');
|
||||||
Route::post('notification-tokens', [NotificationTokenController::class, 'store'])->name('profile.store.token');
|
// Route::post('notification-tokens', [NotificationTokenController::class, 'store'])->name('profile.store.token');
|
||||||
Route::apiResource('appointment', AppointmentController::class);
|
Route::apiResource('appointment', AppointmentController::class);
|
||||||
Route::apiResource('families', PersonController::class)->except(['destroy']);
|
Route::apiResource('families', PersonController::class)->except(['destroy']);
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ Route::prefix('linksehat')->group(function () {
|
|||||||
Route::get('home', 'index')->name('homes.index');
|
Route::get('home', 'index')->name('homes.index');
|
||||||
Route::get('home/hospital', 'listHospital')->name('homes.listHospital');
|
Route::get('home/hospital', 'listHospital')->name('homes.listHospital');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::controller(LivechatController::class)->group(function () {
|
Route::controller(LivechatController::class)->group(function () {
|
||||||
Route::get('livechat', 'index')->name('livechats.index');
|
Route::get('livechat', 'index')->name('livechats.index');
|
||||||
Route::get('livechat/consultation', 'consultation')->name('livechats.consultation');
|
Route::get('livechat/consultation', 'consultation')->name('livechats.consultation');
|
||||||
@@ -114,15 +115,14 @@ Route::prefix('linksehat')->group(function () {
|
|||||||
Route::controller(ChatController::class)->group(function () {
|
Route::controller(ChatController::class)->group(function () {
|
||||||
Route::post('livechat/send-message', 'sendMessage');
|
Route::post('livechat/send-message', 'sendMessage');
|
||||||
Route::get('livechat/get-message', 'getMessage');
|
Route::get('livechat/get-message', 'getMessage');
|
||||||
Route::post('livechat/channel','createChannel');
|
Route::post('livechat/channel', 'createChannel');
|
||||||
Route::get('livechat/channel','listChannel');
|
Route::get('livechat/channel', 'listChannel');
|
||||||
Route::get('livechat/{id}/health-sertificate','downloadHealtcare');
|
Route::get('livechat/{id}/health-sertificate', 'downloadHealtcare');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Route::post('create-invoice-duitku', [DuitkuController::class, 'createInvoice']);
|
Route::post('create-invoice-duitku', [DuitkuController::class, 'createInvoice']);
|
||||||
Route::post('check-status-duitku', [DuitkuController::class, 'checkStatus']);
|
Route::post('check-status-duitku', [DuitkuController::class, 'checkStatus']);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::post('payment-method-duitku', [DuitkuController::class, 'paymentMethod']);
|
Route::post('payment-method-duitku', [DuitkuController::class, 'paymentMethod']);
|
||||||
@@ -130,9 +130,9 @@ Route::prefix('linksehat')->group(function () {
|
|||||||
Route::get('redirect-duitku', [DuitkuController::class, 'redirect']);
|
Route::get('redirect-duitku', [DuitkuController::class, 'redirect']);
|
||||||
|
|
||||||
//DOCTOR API
|
//DOCTOR API
|
||||||
Route::prefix('doctor')->group(function() {
|
Route::prefix('doctor')->group(function () {
|
||||||
//Version 1.0
|
//Version 1.0
|
||||||
Route::prefix('v1')->group(function() {
|
Route::prefix('v1')->group(function () {
|
||||||
Route::middleware(Authentication::class)->group(function () {
|
Route::middleware(Authentication::class)->group(function () {
|
||||||
Route::controller(AuthDoctorController::class)->group(function () {
|
Route::controller(AuthDoctorController::class)->group(function () {
|
||||||
Route::post('login', 'login');
|
Route::post('login', 'login');
|
||||||
@@ -163,7 +163,6 @@ Route::prefix('linksehat')->group(function () {
|
|||||||
Route::post('resend-code', 'forgotPassword');
|
Route::post('resend-code', 'forgotPassword');
|
||||||
Route::post('reset-password', 'resetPassword');
|
Route::post('reset-password', 'resetPassword');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});;
|
||||||
;});
|
});
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ class Helper
|
|||||||
public static function calculateAge($date_brith_day){
|
public static function calculateAge($date_brith_day){
|
||||||
// Konversi tanggal lahir ke dalam format UNIX timestamp
|
// Konversi tanggal lahir ke dalam format UNIX timestamp
|
||||||
$dob = strtotime($date_brith_day);
|
$dob = strtotime($date_brith_day);
|
||||||
|
|
||||||
// Hitung umur berdasarkan tanggal lahir
|
// Hitung umur berdasarkan tanggal lahir
|
||||||
$umur = date('Y') - date('Y', $dob);
|
$umur = date('Y') - date('Y', $dob);
|
||||||
|
|
||||||
@@ -498,5 +498,34 @@ class Helper
|
|||||||
return $start->diffInDays($end) + 1;
|
return $start->diffInDays($end) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getStatusLivechat($status) {
|
||||||
|
switch ($status) {
|
||||||
|
case 1:
|
||||||
|
return 'Requested'; // Clearer status name
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return 'Accepted';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
return 'Declined';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
return 'Waiting Payment';
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
return 'Payment Successful';
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
return 'Chat Ended';
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
return 'Payment Failed';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 'Unknown Status'; // Handle unknown statuses
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class Kernel extends HttpKernel
|
|||||||
protected $middleware = [
|
protected $middleware = [
|
||||||
// \App\Http\Middleware\TrustHosts::class,
|
// \App\Http\Middleware\TrustHosts::class,
|
||||||
\App\Http\Middleware\TrustProxies::class,
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
|
\App\Http\Middleware\LinksehatOldAuthMiddleware::class,
|
||||||
\Illuminate\Http\Middleware\HandleCors::class,
|
\Illuminate\Http\Middleware\HandleCors::class,
|
||||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ namespace App\Http\Middleware;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use App\Models\OLDLMS\PersonalAccessToken;
|
||||||
|
use Laravel\Sanctum\Sanctum;
|
||||||
|
|
||||||
class LinksehatOldAuthMiddleware
|
class LinksehatOldAuthMiddleware
|
||||||
{
|
{
|
||||||
@@ -17,12 +19,12 @@ class LinksehatOldAuthMiddleware
|
|||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if ($request->header('authorization') == 'Bearer LpMbGm0NQvFC3lUBiy1Ch3NzS0CIPSmanR12FcdP') {
|
// if ($request->header('authorization') == 'Bearer LpMbGm0NQvFC3lUBiy1Ch3NzS0CIPSmanR12FcdP') {
|
||||||
Auth::loginUsingId(1);
|
// Auth::loginUsingId(1);
|
||||||
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
return abort(401, "Unauthenticated");
|
// return $next($request);
|
||||||
|
// }
|
||||||
|
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
|
||||||
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
33
app/Models/OLDLMS/NotificationToken.php
Normal file
33
app/Models/OLDLMS/NotificationToken.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\OLDLMS;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class NotificationToken extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $connection = 'oldlms';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'origin',
|
||||||
|
'type',
|
||||||
|
'token',
|
||||||
|
'status',
|
||||||
|
'device_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $hidden = [
|
||||||
|
'notifiabletoken_type',
|
||||||
|
'notifiabletoken_id',
|
||||||
|
'created_at',
|
||||||
|
'updated_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function notifiabletoken()
|
||||||
|
{
|
||||||
|
return $this->morphTo();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models\OLDLMS;
|
namespace App\Models\OLDLMS;
|
||||||
|
|
||||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
@@ -15,7 +14,7 @@ use Illuminate\Notifications\Notifiable;
|
|||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
use HasFactory, SoftDeletes, HasApiTokens, HasRoles, Notifiable, Notifiable;
|
use HasFactory, SoftDeletes, HasApiTokens, HasRoles, Notifiable;
|
||||||
|
|
||||||
const CREATED_AT = 'dCreateOn';
|
const CREATED_AT = 'dCreateOn';
|
||||||
const UPDATED_AT = 'dUpdateOn';
|
const UPDATED_AT = 'dUpdateOn';
|
||||||
@@ -39,6 +38,7 @@ class User extends Authenticatable
|
|||||||
'nIDHubunganKeluarga',
|
'nIDHubunganKeluarga',
|
||||||
'dUpdateOn',
|
'dUpdateOn',
|
||||||
'sIPAddress',
|
'sIPAddress',
|
||||||
|
'fcm_token',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected function fullName(): Attribute
|
protected function fullName(): Attribute
|
||||||
@@ -62,7 +62,7 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
return $this->hasOne(UserDetail::class, 'nIDUser', 'nID');
|
return $this->hasOne(UserDetail::class, 'nIDUser', 'nID');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function insurances()
|
public function insurances()
|
||||||
{
|
{
|
||||||
return $this->hasMany(UserInsurance::class, 'nIDUser', 'nID');
|
return $this->hasMany(UserInsurance::class, 'nIDUser', 'nID');
|
||||||
@@ -72,4 +72,9 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
return $this->morphMany(NotificationToken::class, 'notifiabletoken');
|
return $this->morphMany(NotificationToken::class, 'notifiabletoken');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function routeNotificationForFcm()
|
||||||
|
{
|
||||||
|
return $this->notificationTokens()->pluck('token')->toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
return $this->belongsToMany(Corporate::class, 'corporate_manager', 'user_id', 'corporate_id');
|
return $this->belongsToMany(Corporate::class, 'corporate_manager', 'user_id', 'corporate_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function metas()
|
public function metas()
|
||||||
{
|
{
|
||||||
return $this->morphMany(Meta::class, 'metaable');
|
return $this->morphMany(Meta::class, 'metaable');
|
||||||
@@ -102,13 +102,18 @@ class User extends Authenticatable
|
|||||||
return $this->hasMany(Person::class, 'owner_user_id');
|
return $this->hasMany(Person::class, 'owner_user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOrganization()
|
||||||
|
{
|
||||||
|
return $this->hasOne(OrganizationUser::class, 'user_id');
|
||||||
|
}
|
||||||
|
|
||||||
public function notificationTokens()
|
public function notificationTokens()
|
||||||
{
|
{
|
||||||
return $this->morphMany(NotificationToken::class, 'notifiabletoken');
|
return $this->morphMany(NotificationToken::class, 'notifiabletoken');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOrganization()
|
public function routeNotificationForFcm()
|
||||||
{
|
{
|
||||||
return $this->hasOne(OrganizationUser::class, 'user_id');
|
return $this->notificationTokens()->pluck('token')->toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
app/Notifications/SendNotification.php
Normal file
90
app/Notifications/SendNotification.php
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
use Kreait\Firebase\Messaging\CloudMessage;
|
||||||
|
use Kreait\Laravel\Firebase\Facades\Firebase;
|
||||||
|
use NotificationChannels\Fcm\FcmChannel;
|
||||||
|
use NotificationChannels\Fcm\FcmMessage;;
|
||||||
|
use NotificationChannels\Fcm\Resources\AndroidConfig;
|
||||||
|
use NotificationChannels\Fcm\Resources\AndroidFcmOptions;
|
||||||
|
use NotificationChannels\Fcm\Resources\AndroidNotification;
|
||||||
|
use NotificationChannels\Fcm\Resources\ApnsConfig;
|
||||||
|
use NotificationChannels\Fcm\Resources\ApnsFcmOptions;
|
||||||
|
use NotificationChannels\Fcm\Resources\Notification as FcmNotification;
|
||||||
|
|
||||||
|
|
||||||
|
class SendNotification extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
private $title;
|
||||||
|
private $body;
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
public function __construct($title, $body, $data)
|
||||||
|
{
|
||||||
|
$this->title = $title;
|
||||||
|
$this->body = $body;
|
||||||
|
$this->data = is_array($data) ? $data : (array) $data; // Pastikan data adalah array
|
||||||
|
}
|
||||||
|
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return [FcmChannel::class];
|
||||||
|
}
|
||||||
|
|
||||||
|
// public function toFcm($notifiable)
|
||||||
|
// {
|
||||||
|
// return FcmMessage::create()
|
||||||
|
// ->setData($this->data)
|
||||||
|
// ->setNotification([
|
||||||
|
// 'title' => $this->title,
|
||||||
|
// 'body' => $this->body,
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function toFcm($notifiable)
|
||||||
|
{
|
||||||
|
$deviceTokens = $notifiable->routeNotificationFor('fcm');
|
||||||
|
$notification = [
|
||||||
|
'title' => $this->title,
|
||||||
|
'body' => $this->body,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (count($deviceTokens)){
|
||||||
|
foreach($deviceTokens as $token) {
|
||||||
|
$message = CloudMessage::withTarget('token', $token)
|
||||||
|
->withNotification($notification) // optional
|
||||||
|
->withData($this->data);
|
||||||
|
Firebase::messaging()->send($message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataFcm = FcmMessage::create()
|
||||||
|
->setToken($deviceTokens[0])
|
||||||
|
->setData([])
|
||||||
|
->setNotification(
|
||||||
|
FcmNotification::create()
|
||||||
|
->setTitle('ini title')
|
||||||
|
->setBody('ini body')
|
||||||
|
)
|
||||||
|
->setAndroid(
|
||||||
|
AndroidConfig::create()
|
||||||
|
->setFcmOptions(AndroidFcmOptions::create()->setAnalyticsLabel('analytics'))
|
||||||
|
->setNotification(AndroidNotification::create()->setColor('#0A0A0A'))
|
||||||
|
|
||||||
|
)->setApns(
|
||||||
|
ApnsConfig::create()
|
||||||
|
->setFcmOptions(ApnsFcmOptions::create()->setAnalyticsLabel('analytics_ios'))
|
||||||
|
);
|
||||||
|
return $dataFcm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fcmProject($notifiable, $message){
|
||||||
|
return 'app';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -206,7 +206,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
$this->logAuditTrail($model, 'deleted');
|
$this->logAuditTrail($model, 'deleted');
|
||||||
});
|
});
|
||||||
|
|
||||||
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
|
// Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function logAuditTrail($model, $action)
|
private function logAuditTrail($model, $action)
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
"guzzlehttp/guzzle": "^7.2",
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
"h4cc/wkhtmltoimage-amd64": "^0.12.4",
|
"h4cc/wkhtmltoimage-amd64": "^0.12.4",
|
||||||
"h4cc/wkhtmltopdf-amd64": "0.12.x",
|
"h4cc/wkhtmltopdf-amd64": "0.12.x",
|
||||||
|
"kreait/firebase-php": "^6.9",
|
||||||
|
"laravel-notification-channels/fcm": "^2.1",
|
||||||
"laravel/framework": "^9.11",
|
"laravel/framework": "^9.11",
|
||||||
"laravel/sanctum": "^2.15",
|
"laravel/sanctum": "^2.15",
|
||||||
"laravel/socialite": "^5.5",
|
"laravel/socialite": "^5.5",
|
||||||
|
|||||||
1902
composer.lock
generated
1902
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -202,6 +202,11 @@ return [
|
|||||||
App\Providers\EventServiceProvider::class,
|
App\Providers\EventServiceProvider::class,
|
||||||
App\Providers\RouteServiceProvider::class,
|
App\Providers\RouteServiceProvider::class,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package Firebase Cloud Message
|
||||||
|
*/
|
||||||
|
NotificationChannels\Fcm\FcmServiceProvider::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
5
config/fcm.php
Normal file
5
config/fcm.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'server_key' => env('FCM_SERVER_KEY'),
|
||||||
|
];
|
||||||
192
config/firebase.php
Normal file
192
config/firebase.php
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Default Firebase project
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
'default' => env('FIREBASE_PROJECT', 'app'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Firebase project configurations
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
'projects' => [
|
||||||
|
'app' => [
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Credentials / Service Account
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* In order to access a Firebase project and its related services using a
|
||||||
|
* server SDK, requests must be authenticated. For server-to-server
|
||||||
|
* communication this is done with a Service Account.
|
||||||
|
*
|
||||||
|
* If you don't already have generated a Service Account, you can do so by
|
||||||
|
* following the instructions from the official documentation pages at
|
||||||
|
*
|
||||||
|
* https://firebase.google.com/docs/admin/setup#initialize_the_sdk
|
||||||
|
*
|
||||||
|
* Once you have downloaded the Service Account JSON file, you can use it
|
||||||
|
* to configure the package.
|
||||||
|
*
|
||||||
|
* If you don't provide credentials, the Firebase Admin SDK will try to
|
||||||
|
* auto-discover them
|
||||||
|
*
|
||||||
|
* - by checking the environment variable FIREBASE_CREDENTIALS
|
||||||
|
* - by checking the environment variable GOOGLE_APPLICATION_CREDENTIALS
|
||||||
|
* - by trying to find Google's well known file
|
||||||
|
* - by checking if the application is running on GCE/GCP
|
||||||
|
*
|
||||||
|
* If no credentials file can be found, an exception will be thrown the
|
||||||
|
* first time you try to access a component of the Firebase Admin SDK.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
'credentials' => [
|
||||||
|
'file' => env('FIREBASE_CREDENTIALS', env('GOOGLE_APPLICATION_CREDENTIALS')),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you want to prevent the auto discovery of credentials, set the
|
||||||
|
* following parameter to false. If you disable it, you must
|
||||||
|
* provide a credentials file.
|
||||||
|
*/
|
||||||
|
'auto_discovery' => true,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Firebase Auth Component
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
'auth' => [
|
||||||
|
'tenant_id' => env('FIREBASE_AUTH_TENANT_ID'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Firebase Realtime Database
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
'database' => [
|
||||||
|
/*
|
||||||
|
* In most of the cases the project ID defined in the credentials file
|
||||||
|
* determines the URL of your project's Realtime Database. If the
|
||||||
|
* connection to the Realtime Database fails, you can override
|
||||||
|
* its URL with the value you see at
|
||||||
|
*
|
||||||
|
* https://console.firebase.google.com/u/1/project/_/database
|
||||||
|
*
|
||||||
|
* Please make sure that you use a full URL like, for example,
|
||||||
|
* https://my-project-id.firebaseio.com
|
||||||
|
*/
|
||||||
|
'url' => env('FIREBASE_DATABASE_URL'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As a best practice, a service should have access to only the resources it needs.
|
||||||
|
* To get more fine-grained control over the resources a Firebase app instance can access,
|
||||||
|
* use a unique identifier in your Security Rules to represent your service.
|
||||||
|
*
|
||||||
|
* https://firebase.google.com/docs/database/admin/start#authenticate-with-limited-privileges
|
||||||
|
*/
|
||||||
|
// 'auth_variable_override' => [
|
||||||
|
// 'uid' => 'my-service-worker'
|
||||||
|
// ],
|
||||||
|
],
|
||||||
|
|
||||||
|
'dynamic_links' => [
|
||||||
|
/*
|
||||||
|
* Dynamic links can be built with any URL prefix registered on
|
||||||
|
*
|
||||||
|
* https://console.firebase.google.com/u/1/project/_/durablelinks/links/
|
||||||
|
*
|
||||||
|
* You can define one of those domains as the default for new Dynamic
|
||||||
|
* Links created within your project.
|
||||||
|
*
|
||||||
|
* The value must be a valid domain, for example,
|
||||||
|
* https://example.page.link
|
||||||
|
*/
|
||||||
|
'default_domain' => env('FIREBASE_DYNAMIC_LINKS_DEFAULT_DOMAIN'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Firebase Cloud Storage
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
'storage' => [
|
||||||
|
/*
|
||||||
|
* Your project's default storage bucket usually uses the project ID
|
||||||
|
* as its name. If you have multiple storage buckets and want to
|
||||||
|
* use another one as the default for your application, you can
|
||||||
|
* override it here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default_bucket' => env('FIREBASE_STORAGE_DEFAULT_BUCKET'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Caching
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* The Firebase Admin SDK can cache some data returned from the Firebase
|
||||||
|
* API, for example Google's public keys used to verify ID tokens.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
'cache_store' => env('FIREBASE_CACHE_STORE', 'file'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Logging
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Enable logging of HTTP interaction for insights and/or debugging.
|
||||||
|
*
|
||||||
|
* Log channels are defined in config/logging.php
|
||||||
|
*
|
||||||
|
* Successful HTTP messages are logged with the log level 'info'.
|
||||||
|
* Failed HTTP messages are logged with the the log level 'notice'.
|
||||||
|
*
|
||||||
|
* Note: Using the same channel for simple and debug logs will result in
|
||||||
|
* two entries per request and response.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'logging' => [
|
||||||
|
'http_log_channel' => env('FIREBASE_HTTP_LOG_CHANNEL'),
|
||||||
|
'http_debug_log_channel' => env('FIREBASE_HTTP_DEBUG_LOG_CHANNEL'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* HTTP Client Options
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Behavior of the HTTP Client performing the API requests
|
||||||
|
*/
|
||||||
|
'http_client_options' => [
|
||||||
|
/*
|
||||||
|
* Use a proxy that all API requests should be passed through.
|
||||||
|
* (default: none)
|
||||||
|
*/
|
||||||
|
'proxy' => env('FIREBASE_HTTP_CLIENT_PROXY'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the maximum amount of seconds (float) that can pass before
|
||||||
|
* a request is considered timed out
|
||||||
|
*
|
||||||
|
* The default time out can be reviewed at
|
||||||
|
* https://github.com/kreait/firebase-php/blob/6.x/src/Firebase/Http/HttpClientOptions.php
|
||||||
|
*/
|
||||||
|
'timeout' => env('FIREBASE_HTTP_CLIENT_TIMEOUT'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -37,4 +37,9 @@ return [
|
|||||||
'redirect' => env('GOOGLE_REDIRECT_URI'),
|
'redirect' => env('GOOGLE_REDIRECT_URI'),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'fcm' => [
|
||||||
|
'key' => env('FCM_SERVER_KEY'),
|
||||||
|
'sender_id' => env('FCM_SENDER_ID'),
|
||||||
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ return new class extends Migration
|
|||||||
$table->id();
|
$table->id();
|
||||||
$table->morphs('notifiabletoken', 'notifiabletoken');
|
$table->morphs('notifiabletoken', 'notifiabletoken');
|
||||||
$table->string('origin');
|
$table->string('origin');
|
||||||
|
$table->string('device_id')->nullable();
|
||||||
$table->string('type');
|
$table->string('type');
|
||||||
$table->string('token');
|
$table->string('token');
|
||||||
$table->string('status');
|
$table->string('status');
|
||||||
@@ -26,7 +27,7 @@ return new class extends Migration
|
|||||||
$table->unsignedBigInteger('created_by')->nullable()->index();
|
$table->unsignedBigInteger('created_by')->nullable()->index();
|
||||||
$table->unsignedBigInteger('updated_by')->nullable()->index();
|
$table->unsignedBigInteger('updated_by')->nullable()->index();
|
||||||
$table->unsignedBigInteger('deleted_by')->nullable()->index();
|
$table->unsignedBigInteger('deleted_by')->nullable()->index();
|
||||||
|
|
||||||
$table->index('token');
|
$table->index('token');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('notifications', function (Blueprint $table) {
|
||||||
|
$table->text('data')->after('notifiable_id')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('notifications', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('data');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->string('fcm_token')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('fcm_token');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -115,13 +115,12 @@ export default function List() {
|
|||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
};
|
};
|
||||||
|
const [paramImport, setParamImport] = useState('');
|
||||||
const handleImportButton = () => {
|
const handleImportButton = (param:any) => {
|
||||||
|
setParamImport(param);
|
||||||
if (importForm?.current) {
|
if (importForm?.current) {
|
||||||
handleClose();
|
handleClose();
|
||||||
importForm.current ? importForm.current.click() : console.log('No File selected');
|
importForm.current ? importForm.current.click() : console.log('No File selected');
|
||||||
} else {
|
|
||||||
alert('No file selected');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,12 +143,18 @@ export default function List() {
|
|||||||
formData.append('file', importForm.current?.files[0]);
|
formData.append('file', importForm.current?.files[0]);
|
||||||
|
|
||||||
setImportLoading(true);
|
setImportLoading(true);
|
||||||
|
let url = 'claim-requests/import';
|
||||||
|
if(paramImport == 'invoice')
|
||||||
|
{
|
||||||
|
url = 'customer-service/request/import-invoice'
|
||||||
|
}
|
||||||
axios
|
axios
|
||||||
.post(`claim-requests/import`, formData)
|
.post(`${url}`, formData)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
handleCancelImportButton();
|
handleCancelImportButton();
|
||||||
loadDataTableData();
|
// loadDataTableData();
|
||||||
setImportResult(response.data);
|
setImportResult(response.data);
|
||||||
|
setParamImport(response.data.metaData);
|
||||||
// alert('Succesfully read '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows');
|
// alert('Succesfully read '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows');
|
||||||
setImportLoading(false);
|
setImportLoading(false);
|
||||||
})
|
})
|
||||||
@@ -166,6 +171,28 @@ export default function List() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleExportReportFiled = async () => {
|
||||||
|
|
||||||
|
await axios
|
||||||
|
.post('customer-service/request/exportFiledInvoice', { params: importResult?.data.result_rows })
|
||||||
|
.then((res) => {
|
||||||
|
enqueueSnackbar('Data berhasil di Export', {
|
||||||
|
variant: 'success',
|
||||||
|
anchorOrigin: { horizontal: 'right', vertical: 'top' },
|
||||||
|
});
|
||||||
|
setImportLoading(false);
|
||||||
|
|
||||||
|
document.location.href = res.data.data.file_url;
|
||||||
|
})
|
||||||
|
.catch((err) =>
|
||||||
|
enqueueSnackbar('Data Gagal di Export', {
|
||||||
|
variant: 'error',
|
||||||
|
anchorOrigin: { horizontal: 'right', vertical: 'top' },
|
||||||
|
})
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const handleGetTemplate = (type :string) => {
|
const handleGetTemplate = (type :string) => {
|
||||||
axios.get('corporates/import-document-example/' + type)
|
axios.get('corporates/import-document-example/' + type)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -220,9 +247,11 @@ export default function List() {
|
|||||||
'aria-labelledby': 'basic-button',
|
'aria-labelledby': 'basic-button',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem onClick={handleImportButton}>Import</MenuItem>
|
<MenuItem onClick={() => {handleImportButton('claim')}}>Import</MenuItem>
|
||||||
<MenuItem onClick={() => {handleGetTemplate('claim-request')}}>Download Template</MenuItem>
|
<MenuItem onClick={() => {handleGetTemplate('claim-request')}}>Download Template</MenuItem>
|
||||||
<MenuItem onClick={() => {handleGetData('data-plan-benefit')}}>Download Claim Request</MenuItem>
|
<MenuItem onClick={() => {handleGetData('data-plan-benefit')}}>Download Claim Request</MenuItem>
|
||||||
|
<MenuItem onClick={() => {handleImportButton('invoice')}}>Import Invoice</MenuItem>
|
||||||
|
<MenuItem onClick={() => {handleGetTemplate('final-log-invoice')}}>Download Template Invoice</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
{/* <Button
|
{/* <Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
@@ -265,16 +294,35 @@ export default function List() {
|
|||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
{importResult && (
|
{importResult && importResult?.metaData == 'invoice' ? (
|
||||||
|
<Stack direction={'row'} sx={{ px: 2, pb: 2 }}>
|
||||||
|
<Box sx={{ color: 'text.secondary' }}>
|
||||||
|
Last Import Result :{' '}
|
||||||
|
<Box sx={{ color: 'success.main', display: 'inline' }}>
|
||||||
|
{importResult.data.total_success_row ?? 0}
|
||||||
|
</Box>{' '}
|
||||||
|
Row Processed,{' '}
|
||||||
|
<Box sx={{ color: 'error.main', display: 'inline' }}>
|
||||||
|
{importResult.data.total_failed_row}
|
||||||
|
</Box>{' '}
|
||||||
|
Failed,
|
||||||
|
{/* {importResult.data.failed_rows.map((row, index) => (
|
||||||
|
<Typography variant='body' key={index} color="error"> [Code={row.code ? row.code : 'Required'}]</Typography>
|
||||||
|
))} */}
|
||||||
|
Report:
|
||||||
|
<u onClick={handleExportReportFiled} style={{cursor:'pointer'}}>Download Data Result Import</u>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
) : importResult ? (
|
||||||
<Stack direction={'row'} sx={{ px: 2, pb: 2 }}>
|
<Stack direction={'row'} sx={{ px: 2, pb: 2 }}>
|
||||||
<Box sx={{ color: 'text.secondary' }}>
|
<Box sx={{ color: 'text.secondary' }}>
|
||||||
Last Import Result Report :{' '}
|
Last Import Result Report {paramImport} :{' '}
|
||||||
<a href={importResult.result_file?.url ?? '#'}>
|
<a href={importResult?.result_file?.url ?? '#'}>
|
||||||
{importResult.result_file?.name ?? '-'}
|
{importResult?.result_file?.name ?? '-'}
|
||||||
</a>
|
</a>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
):''}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"txtDialogMember3" : "Detail",
|
"txtDialogMember3" : "Detail",
|
||||||
"txtDialogMember4" : "Please select services",
|
"txtDialogMember4" : "Please select services",
|
||||||
"txtDialogMember5" : "Admission Date",
|
"txtDialogMember5" : "Admission Date",
|
||||||
"txtDialogMember6" : "Please select admission date",
|
"txtDialogMember6" : "Please select admission date",
|
||||||
"txtWarningDischargeDate" : "Please select discharge date",
|
"txtWarningDischargeDate" : "Please select discharge date",
|
||||||
"txtCreateAt" : "Create at",
|
"txtCreateAt" : "Create at",
|
||||||
"txtDateBirth" : "Date of Birth",
|
"txtDateBirth" : "Date of Birth",
|
||||||
@@ -59,5 +59,24 @@
|
|||||||
"txtApprove": "Approve",
|
"txtApprove": "Approve",
|
||||||
"txtDialogConfirmation": "Are you sure you want to proceed with this action?",
|
"txtDialogConfirmation": "Are you sure you want to proceed with this action?",
|
||||||
"txtStartDate": "Start Date",
|
"txtStartDate": "Start Date",
|
||||||
"txtEndDate": "End Date"
|
"txtEndDate": "End Date",
|
||||||
|
"txtHelp1" : "Has problem with your account?",
|
||||||
|
"txtLupaSandi": "Forgot password?",
|
||||||
|
"txtIngatkanSaya": "Remember me",
|
||||||
|
"txtLogin": "Login",
|
||||||
|
"txtForgotYourPassword": "Forgot your password?",
|
||||||
|
"txtPleaseEnterPassword": "Please enter the email address associated with your account and We will email you a code to reset your password.",
|
||||||
|
"txtBack": "Back",
|
||||||
|
"txtSuccessSend": "Request sent successfully",
|
||||||
|
"txtCodeConfirm": "We have sent a confirmation email to",
|
||||||
|
"txtPleasCheck": "Please check your email.",
|
||||||
|
"txtCheckEmail": "Please check your email!",
|
||||||
|
"txtEmail": "We have emailed a 6-digit confirmation code and check spam folder, please enter the code in below box to verify your email.",
|
||||||
|
"txtDont": "Don’t have a code?",
|
||||||
|
"txtResendCode": "Resend code",
|
||||||
|
"txtSecond": "Second",
|
||||||
|
"txtPleaseInput": "Please enter your new password.",
|
||||||
|
"txtNewPassword": "New Password",
|
||||||
|
"txtConfPassword": "Confirm Kata Sandi"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,5 +59,23 @@
|
|||||||
"txtApprove": "Terima",
|
"txtApprove": "Terima",
|
||||||
"txtDialogConfirmation": "Apakah Anda yakin ingin melanjutkan tindakan ini?",
|
"txtDialogConfirmation": "Apakah Anda yakin ingin melanjutkan tindakan ini?",
|
||||||
"txtStartDate": "Tanggal Mulai",
|
"txtStartDate": "Tanggal Mulai",
|
||||||
"txtEndDate": "Tanggal Akhir"
|
"txtEndDate": "Tanggal Akhir",
|
||||||
|
"txtHelp1" : "Punya masalah dengan akun Anda?",
|
||||||
|
"txtLupaSandi": "Lupa sandi?",
|
||||||
|
"txtIngatkanSaya": "Ingatkan saya",
|
||||||
|
"txtLogin": "Masuk",
|
||||||
|
"txtForgotYourPassword": "Lupa password anda?",
|
||||||
|
"txtPleaseEnterPassword": "Silakan masukkan alamat email yang terkait dengan akun Anda dan Kami akan mengirimkan email berisi kode untuk mengatur ulang kata sandi Anda.",
|
||||||
|
"txtBack": "Kembali",
|
||||||
|
"txtSuccessSend": "Permintaan berhasil dikirim",
|
||||||
|
"txtCodeConfirm": "Kami telah mengirimkan email konfirmasi ke",
|
||||||
|
"txtPleasCheck": "Mohon cek email Anda.",
|
||||||
|
"txtCheckEmail": "Mohon periksa email Anda!",
|
||||||
|
"txtEmail": "Kami telah mengirimkan kode konfirmasi 6 digit melalui email cek juga difolder spam, silakan masukkan kode di kotak bawah ini untuk memverifikasi email Anda.",
|
||||||
|
"txtDont": "Tidak mendapatkan kode?",
|
||||||
|
"txtResendCode": "Kirim ulang kode",
|
||||||
|
"txtSecond": "Detik",
|
||||||
|
"txtPleaseInput": "Mohon masukan kata sandi baru Anda.",
|
||||||
|
"txtNewPassword": "Kata Sandi Baru",
|
||||||
|
"txtConfPassword": "Konfirmasi Kata Sandi"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export type JWTContextType = {
|
|||||||
isInitialized: boolean;
|
isInitialized: boolean;
|
||||||
user: AuthUser;
|
user: AuthUser;
|
||||||
method: 'jwt';
|
method: 'jwt';
|
||||||
login: (email: string, password: string) => Promise<void>;
|
login: (email: string, password: string, rememberMe: boolean) => Promise<void>;
|
||||||
register: (email: string, password: string, firstName: string, lastName: string) => Promise<void>;
|
register: (email: string, password: string, firstName: string, lastName: string) => Promise<void>;
|
||||||
logout: () => Promise<void>;
|
logout: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
const getLocalizedData = async (locale) => {
|
// const getLocalizedData = async (locale) => {
|
||||||
const response = await fetch(`/lang/${locale}.json`); // Mengambil file lokal berdasarkan bahasa yang dipilih
|
// const response = await fetch(`/lang/${locale}.json`); // Mengambil file lokal berdasarkan bahasa yang dipilih
|
||||||
const data = await response.json();
|
// const data = await response.json();
|
||||||
return data;
|
// return data;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default getLocalizedData;
|
||||||
|
|
||||||
|
// LocalizationUtil.js
|
||||||
|
import idID from './lang/id-ID.json';
|
||||||
|
import enUS from './lang/en-US.json';
|
||||||
|
|
||||||
|
const localizedData = {
|
||||||
|
'id-ID': idID,
|
||||||
|
'en-US': enUS,
|
||||||
|
// Tambahkan bahasa lain sesuai kebutuhan
|
||||||
};
|
};
|
||||||
|
|
||||||
export default getLocalizedData;
|
const getLocalizedData = async (locale) => {
|
||||||
|
return localizedData[locale] || localizedData['id-ID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getLocalizedData;
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export default function Table<T>({
|
|||||||
]);
|
]);
|
||||||
params.setAppliedParams(parameters);
|
params.setAppliedParams(parameters);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { localeData }: any = useContext(LanguageContext);
|
const { localeData }: any = useContext(LanguageContext);
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ export default function Table<T>({
|
|||||||
return (
|
return (
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
{selected.useSelected && selected.selectedRows.length > 0 ? (
|
{selected.useSelected && selected.selectedRows.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<TableCell style={{ backgroundColor: '#D1F1F1', }} align="left" colSpan={selected.totRows} sx={{ padding: 2 }}>
|
<TableCell style={{ backgroundColor: '#D1F1F1', }} align="left" colSpan={selected.totRows} sx={{ padding: 2 }}>
|
||||||
<Grid container alignItems="center" justifyContent="space-between">
|
<Grid container alignItems="center" justifyContent="space-between">
|
||||||
@@ -169,10 +169,10 @@ export default function Table<T>({
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
);
|
);
|
||||||
@@ -294,7 +294,7 @@ export default function Table<T>({
|
|||||||
</form>
|
</form>
|
||||||
</Grid>
|
</Grid>
|
||||||
}
|
}
|
||||||
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : null }
|
) : null }
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ export default function Table<T>({
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
) : null }
|
) : null }
|
||||||
|
|
||||||
{/* Export Report */}
|
{/* Export Report */}
|
||||||
|
|
||||||
@@ -389,11 +389,11 @@ export default function Table<T>({
|
|||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
<Button variant='contained' sx={{p:2}}>
|
<Button variant='contained' sx={{p:2}}>
|
||||||
<Download />
|
<Download />
|
||||||
<Typography variant='inherit' sx={{marginLeft: 1}}>Export</Typography>
|
<Typography variant='inherit' sx={{marginLeft: 1}}>Export</Typography>
|
||||||
</Button>
|
</Button>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
) : null }
|
) : null }
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -428,7 +428,7 @@ export default function Table<T>({
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
):(
|
):(
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
{headCells &&
|
{headCells &&
|
||||||
@@ -443,7 +443,7 @@ export default function Table<T>({
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={6} align="center">
|
<TableCell colSpan={headCells?.length} align="center">
|
||||||
{localeData.txtDataNotFound}
|
{localeData.txtDataNotFound}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export const LanguageContext = createContext();
|
|||||||
export const LanguageProvider = ({ children }) => {
|
export const LanguageProvider = ({ children }) => {
|
||||||
const [currentLocale, setCurrentLocale] = useState(localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID');
|
const [currentLocale, setCurrentLocale] = useState(localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID');
|
||||||
const [localeData, setLocaleData] = useState('id');
|
const [localeData, setLocaleData] = useState('id');
|
||||||
const cancelToken = useRef(null);
|
const cancelToken = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createContext, ReactNode, useEffect, useReducer } from 'react';
|
|||||||
// utils
|
// utils
|
||||||
import axios from '@/utils/axios';
|
import axios from '@/utils/axios';
|
||||||
// import { isValidToken, setSession } from '@/utils/jwt';
|
// import { isValidToken, setSession } from '@/utils/jwt';
|
||||||
import { setSession, getSession, setUser, getUser } from '@/utils/token';
|
import { setSession, getSession, setUser, getUser, getCookie } from '@/utils/token';
|
||||||
// @types
|
// @types
|
||||||
import { ActionMap, AuthState, AuthUser, JWTContextType } from '@/@types/auth';
|
import { ActionMap, AuthState, AuthUser, JWTContextType } from '@/@types/auth';
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -86,12 +86,16 @@ function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
const initialize = async () => {
|
const initialize = async () => {
|
||||||
try {
|
try {
|
||||||
const accessToken = getSession();
|
const accessToken = getSession();
|
||||||
if (accessToken) {
|
const rememberMe = getCookie('rememberMe') == 'OK' ? false : true;
|
||||||
setSession(accessToken);
|
|
||||||
|
if (accessToken) {
|
||||||
|
const userString = getUser();
|
||||||
|
const storedUser = userString ? JSON.parse(userString) : null;
|
||||||
|
setUser(storedUser, rememberMe);
|
||||||
|
setSession(accessToken, rememberMe);
|
||||||
|
const response = await axios.get('/user');
|
||||||
|
const user = response.data;
|
||||||
|
|
||||||
const response = await axios.get('/user');
|
|
||||||
const user = response.data;
|
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: Types.Initial,
|
type: Types.Initial,
|
||||||
payload: {
|
payload: {
|
||||||
@@ -126,16 +130,16 @@ function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type' : 'application/json',
|
'Content-Type' : 'application/json',
|
||||||
'Accept-Language': (localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID'),
|
'Accept-Language': localStorage.getItem('currentLocale') ?? 'id-ID',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const login = async (email: string, password: string) => axios
|
const login = async (email: string, password: string, rememberMe: boolean) => axios
|
||||||
.post('/login', { email, password }, headers)
|
.post('/login', { email, password }, headers)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const { user, token } = response.data.data;
|
const { user, token } = response.data.data;
|
||||||
setSession(token);
|
setSession(token, rememberMe);
|
||||||
setUser(user);
|
setUser(user, rememberMe);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: Types.Login,
|
type: Types.Login,
|
||||||
@@ -168,8 +172,9 @@ function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
setSession(null);
|
await axios.post('logout');
|
||||||
setUser(null);
|
setSession(null, false);
|
||||||
|
setUser(null, false);
|
||||||
dispatch({ type: Types.Logout });
|
dispatch({ type: Types.Logout });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,9 +192,9 @@ function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// if (state.isInitialized) {
|
// if (state.isInitialized) {
|
||||||
// return (!state.isAuthenticated && location.pathname !== '/auth/login') ?
|
// return (!state.isAuthenticated && location.pathname !== '/auth/login') ?
|
||||||
// (<Navigate to="/auth/login" replace={true} />)
|
// (<Navigate to="/auth/login" replace={true} />)
|
||||||
// : false && location.pathname == '/auth/login' ?
|
// : false && location.pathname == '/auth/login' ?
|
||||||
// (<Navigate to="/dashboard" replace={true} />)
|
// (<Navigate to="/dashboard" replace={true} />)
|
||||||
// : (
|
// : (
|
||||||
// <AuthContext.Provider
|
// <AuthContext.Provider
|
||||||
|
|||||||
82
frontend/hospital-portal/src/lang/en-US.json
Normal file
82
frontend/hospital-portal/src/lang/en-US.json
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"greeting": "Hello",
|
||||||
|
"buttonText": "Click Me",
|
||||||
|
"infoLogin": "Enter the registered account",
|
||||||
|
"txtLogin1" : "Sign in to Hospital Portal",
|
||||||
|
"txtLogin2" : "Enter your details below",
|
||||||
|
"txtCardSearchMember1" : "Membership Query",
|
||||||
|
"txtCardSearchMember2" : "Search Member",
|
||||||
|
"txtCardSearchMember3" : "Date of Birth",
|
||||||
|
"txtCardSearchMember4" : "Member ID",
|
||||||
|
"txtCardSearchMember5" : "Member",
|
||||||
|
"txtDialogMember1" : "Services",
|
||||||
|
"txtDialogMember2" : "Request LOG",
|
||||||
|
"txtDialogMember3" : "Detail",
|
||||||
|
"txtDialogMember4" : "Please select services",
|
||||||
|
"txtDialogMember5" : "Admission Date",
|
||||||
|
"txtDialogMember6" : "Please select admission date",
|
||||||
|
"txtWarningDischargeDate" : "Please select discharge date",
|
||||||
|
"txtCreateAt" : "Create at",
|
||||||
|
"txtDateBirth" : "Date of Birth",
|
||||||
|
"txtGender" : "Gender",
|
||||||
|
"txtMaritalStatus" : "Marital Status",
|
||||||
|
"txtLanguage" : "Language",
|
||||||
|
"txtRelationship" : "Relationship",
|
||||||
|
"txtRequestDate" : "Request Date",
|
||||||
|
"txtMemberID" : "Member ID",
|
||||||
|
"txtClaimCode" : "Claim Code",
|
||||||
|
"txtRequestCode" : "Request Code",
|
||||||
|
"txtName" : "Name",
|
||||||
|
"txtStatus" : "Status",
|
||||||
|
"txtSearch" : "Search Name or Member ID...",
|
||||||
|
"txtAll" : "All",
|
||||||
|
"txtSubmissionDate" : "Admission Date",
|
||||||
|
"txtDataNotFound" : "Data Not Found",
|
||||||
|
"txtConditionDocument" : "Condition Document",
|
||||||
|
"txtDiagnosisDokument" : "Diagnosis Dokument",
|
||||||
|
"txtSupportingResultDocument" : "Supporting Result Document",
|
||||||
|
"txtAddResult" : "Add Result",
|
||||||
|
"txtServiceType" : "Service Type",
|
||||||
|
"txtAdditionalDocuments" : "Additional Documents",
|
||||||
|
"txtAddNew" : "Add New",
|
||||||
|
"txtAddress" : "Address",
|
||||||
|
"txtProvider": "Provider",
|
||||||
|
"txtAlertProvider" : "Please enter provider",
|
||||||
|
"txtHelp" : "Need help?",
|
||||||
|
"txtContactUs" : "Contact Us",
|
||||||
|
"txtNotifications" : "Notifications",
|
||||||
|
"txtYouHave" : "You have",
|
||||||
|
"txtUnm" : "unread messages",
|
||||||
|
"txtNew" : "New",
|
||||||
|
"txtBeforeThat" : "Before that",
|
||||||
|
"txtDischargeDate" : "Discharge Date",
|
||||||
|
"txtPatner" : "Patner",
|
||||||
|
"txtSelected": "Selected",
|
||||||
|
"txtConfirmation": "Confirmation",
|
||||||
|
"txtReason": "Reason Decline",
|
||||||
|
"txtCancel": "Cancel",
|
||||||
|
"txtDecline": "Decline",
|
||||||
|
"txtApprove": "Approve",
|
||||||
|
"txtDialogConfirmation": "Are you sure you want to proceed with this action?",
|
||||||
|
"txtStartDate": "Start Date",
|
||||||
|
"txtEndDate": "End Date",
|
||||||
|
"txtHelp1" : "Has problem with your account?",
|
||||||
|
"txtLupaSandi": "Forgot password?",
|
||||||
|
"txtIngatkanSaya": "Remember me",
|
||||||
|
"txtLogin": "Login",
|
||||||
|
"txtForgotYourPassword": "Forgot your password?",
|
||||||
|
"txtPleaseEnterPassword": "Please enter the email address associated with your account and We will email you a code to reset your password.",
|
||||||
|
"txtBack": "Back",
|
||||||
|
"txtSuccessSend": "Request sent successfully",
|
||||||
|
"txtCodeConfirm": "We have sent a confirmation email to",
|
||||||
|
"txtPleasCheck": "Please check your email.",
|
||||||
|
"txtCheckEmail": "Please check your email!",
|
||||||
|
"txtEmail": "We have emailed a 6-digit confirmation code and check spam folder, please enter the code in below box to verify your email.",
|
||||||
|
"txtDont": "Don’t have a code?",
|
||||||
|
"txtResendCode": "Resend code",
|
||||||
|
"txtSecond": "Second",
|
||||||
|
"txtPleaseInput": "Please enter your new password.",
|
||||||
|
"txtNewPassword": "New Password",
|
||||||
|
"txtConfPassword": "Confirm Kata Sandi"
|
||||||
|
|
||||||
|
}
|
||||||
81
frontend/hospital-portal/src/lang/id-ID.json
Normal file
81
frontend/hospital-portal/src/lang/id-ID.json
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"greeting": "Halo",
|
||||||
|
"buttonText": "Klik Saya",
|
||||||
|
"infoLogin": "Masukan akun yang telah terdaftar",
|
||||||
|
"txtLogin1" : "Masuk ke Hospital Portal",
|
||||||
|
"txtLogin2" : "Masukkan detail Anda di bawah ini",
|
||||||
|
"txtCardSearchMember1" : "Pengajuan Jaminan",
|
||||||
|
"txtCardSearchMember2" : "Cari Anggota",
|
||||||
|
"txtCardSearchMember3" : "Tanggal Lahir",
|
||||||
|
"txtCardSearchMember4" : "Member ID",
|
||||||
|
"txtCardSearchMember5" : "Member",
|
||||||
|
"txtDialogMember1" : "Layanan",
|
||||||
|
"txtDialogMember2" : "Request LOG",
|
||||||
|
"txtDialogMember3" : "Detail",
|
||||||
|
"txtDialogMember4" : "Mohon pilih layanan",
|
||||||
|
"txtDialogMember5" : "Tanggal Masuk",
|
||||||
|
"txtDialogMember6" : "Mohon pilih tanggal masuk",
|
||||||
|
"txtWarningDischargeDate" : "Mohon pilih tanggal keluar",
|
||||||
|
"txtCreateAt" : "Tanggal Buat",
|
||||||
|
"txtDateBirth" : "Tanggal Lahir",
|
||||||
|
"txtGender" : "Jenis Kelamin",
|
||||||
|
"txtMaritalStatus" : "Status Perkawinan",
|
||||||
|
"txtLanguage" : "Bahasa",
|
||||||
|
"txtRelationship" : "Hubungan",
|
||||||
|
"txtRequestDate" : "Tanggal Permintaan",
|
||||||
|
"txtMemberID" : "ID Anggota",
|
||||||
|
"txtClaimCode" : "Kode Klaim",
|
||||||
|
"txtRequestCode" : "Kode Pengajuan",
|
||||||
|
"txtName" : "Nama",
|
||||||
|
"txtStatus" : "Status",
|
||||||
|
"txtSearch" : "Cari Nama atau ID Anggota...",
|
||||||
|
"txtAll" : "Semua",
|
||||||
|
"txtSubmissionDate" : "Tanggal Masuk",
|
||||||
|
"txtDataNotFound" : "Data Tidak Ditemukan",
|
||||||
|
"txtConditionDocument" : "Dokumen Kondisi",
|
||||||
|
"txtDiagnosisDokument" : "Dokumen Diagnosis",
|
||||||
|
"txtSupportingResultDocument" : "Dokumen Pendukung",
|
||||||
|
"txtAddResult" : "Tambah Hasil",
|
||||||
|
"txtServiceType" : "Tipe Layanan",
|
||||||
|
"txtAdditionalDocuments" : "Dokumen Tambahan",
|
||||||
|
"txtAddNew" : "Tambah Baru",
|
||||||
|
"txtAddress" : "Alamat",
|
||||||
|
"txtProvider": "Provider",
|
||||||
|
"txtAlertProvider" : "Mohon masukan provider",
|
||||||
|
"txtHelp" : "Butuh Bantuan?",
|
||||||
|
"txtContactUs" : "Kontak Kami",
|
||||||
|
"txtNotifications" : "Notifikasi",
|
||||||
|
"txtYouHave" : "Anda memiliki",
|
||||||
|
"txtUnm" : "pesan yang belum dibaca",
|
||||||
|
"txtNew" : "Baru",
|
||||||
|
"txtBeforeThat" : "Sebelum",
|
||||||
|
"txtDischargeDate" : "Tanggal Keluar",
|
||||||
|
"txtPatner" : "Rekanan",
|
||||||
|
"txtSelected": "Terpilih",
|
||||||
|
"txtConfirmation": "Konfirmasi",
|
||||||
|
"txtReason": "Alasan Penolakan",
|
||||||
|
"txtCancel": "Batal",
|
||||||
|
"txtDecline": "Tolak",
|
||||||
|
"txtApprove": "Terima",
|
||||||
|
"txtDialogConfirmation": "Apakah Anda yakin ingin melanjutkan tindakan ini?",
|
||||||
|
"txtStartDate": "Tanggal Mulai",
|
||||||
|
"txtEndDate": "Tanggal Akhir",
|
||||||
|
"txtHelp1" : "Punya masalah dengan akun Anda?",
|
||||||
|
"txtLupaSandi": "Lupa sandi?",
|
||||||
|
"txtIngatkanSaya": "Ingatkan saya",
|
||||||
|
"txtLogin": "Masuk",
|
||||||
|
"txtForgotYourPassword": "Lupa password anda?",
|
||||||
|
"txtPleaseEnterPassword": "Silakan masukkan alamat email yang terkait dengan akun Anda dan Kami akan mengirimkan email berisi kode untuk mengatur ulang kata sandi Anda.",
|
||||||
|
"txtBack": "Kembali",
|
||||||
|
"txtSuccessSend": "Permintaan berhasil dikirim",
|
||||||
|
"txtCodeConfirm": "Kami telah mengirimkan email konfirmasi ke",
|
||||||
|
"txtPleasCheck": "Mohon cek email Anda.",
|
||||||
|
"txtCheckEmail": "Mohon periksa email Anda!",
|
||||||
|
"txtEmail": "Kami telah mengirimkan kode konfirmasi 6 digit melalui email cek juga difolder spam, silakan masukkan kode di kotak bawah ini untuk memverifikasi email Anda.",
|
||||||
|
"txtDont": "Tidak mendapatkan kode?",
|
||||||
|
"txtResendCode": "Kirim ulang kode",
|
||||||
|
"txtSecond": "Detik",
|
||||||
|
"txtPleaseInput": "Mohon masukan kata sandi baru Anda.",
|
||||||
|
"txtNewPassword": "Kata Sandi Baru",
|
||||||
|
"txtConfPassword": "Konfirmasi Kata Sandi"
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import { IconButtonAnimate } from '@/components/animate';
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import useAuth from '@/hooks/useAuth';
|
import useAuth from '@/hooks/useAuth';
|
||||||
|
|
||||||
|
import { getUser } from '@/utils/token';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
const MENU_OPTIONS = [
|
const MENU_OPTIONS = [
|
||||||
@@ -45,6 +47,8 @@ export default function AccountPopover() {
|
|||||||
navigate('/auth/login');
|
navigate('/auth/login');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const userString = getUser();
|
||||||
|
const storedUser = userString ? JSON.parse(userString) : null;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IconButtonAnimate
|
<IconButtonAnimate
|
||||||
@@ -89,7 +93,7 @@ export default function AccountPopover() {
|
|||||||
Hospital Admin
|
Hospital Admin
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
|
<Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
|
||||||
hospitaladmin@gmail.com
|
{storedUser?.email}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import Iconify from '@/components/Iconify';
|
|||||||
// sections
|
// sections
|
||||||
import { ForgetPasswordForm } from '@/sections/auth/forget-password';
|
import { ForgetPasswordForm } from '@/sections/auth/forget-password';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import { useState, useContext, useEffect } from 'react';
|
||||||
|
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -25,6 +27,8 @@ const RootStyle = styled('div')(({ theme }) => ({
|
|||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
export default function ForgetPassword() {
|
export default function ForgetPassword() {
|
||||||
|
|
||||||
|
const { localeData } = useContext(LanguageContext);
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const token = searchParams.get('token');
|
const token = searchParams.get('token');
|
||||||
|
|
||||||
@@ -42,12 +46,12 @@ export default function ForgetPassword() {
|
|||||||
startIcon={<Iconify icon={'eva:arrow-ios-back-fill'} width={20} height={20} />}
|
startIcon={<Iconify icon={'eva:arrow-ios-back-fill'} width={20} height={20} />}
|
||||||
sx={{ mb: 3 }}
|
sx={{ mb: 3 }}
|
||||||
>
|
>
|
||||||
Back
|
{localeData.txtBack}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Typography variant="h3" paragraph></Typography>
|
<Typography variant="h3" paragraph></Typography>
|
||||||
<Typography sx={{ color: 'text.secondary' }}>
|
<Typography sx={{ color: 'text.secondary' }}>
|
||||||
Please enter your new password.
|
{localeData.txtPleaseInput}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Box sx={{ mt: 5, mb: 3 }}>
|
<Box sx={{ mt: 5, mb: 3 }}>
|
||||||
|
|||||||
@@ -78,29 +78,28 @@ export default function Login() {
|
|||||||
const smUp = useResponsive("up", "sm");
|
const smUp = useResponsive("up", "sm");
|
||||||
|
|
||||||
const mdUp = useResponsive("up", "md");
|
const mdUp = useResponsive("up", "md");
|
||||||
|
const handleClick = () => {
|
||||||
|
window.location.href = 'https://wa.me/6285890008500';
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title="Login">
|
<Page title="Login">
|
||||||
<RootStyle>
|
<RootStyle>
|
||||||
<HeaderStyle>
|
<HeaderStyle>
|
||||||
{/*<Logo sx={{ width: 150, height: 150 }} />
|
<Logo sx={{ width: 150, height: 150, display: 'none' }} />
|
||||||
{smUp && (
|
{smUp && (
|
||||||
<Typography variant="body2" sx={{ mt: { md: -2 } }}>
|
<Typography variant="body2" sx={{ mt: { md: -2 } }}>
|
||||||
Has problem with your account? {""}
|
{localeData.txtHelp1} {""}
|
||||||
<Link
|
<Link
|
||||||
variant="subtitle2"
|
variant="subtitle2"
|
||||||
component={RouterLink}
|
component={RouterLink}
|
||||||
to="#"
|
to="#"
|
||||||
onClick={(e) => {
|
onClick={handleClick}
|
||||||
window.location.href =
|
|
||||||
"mailto:admin@linksehat.com";
|
|
||||||
e.preventDefault();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Contact Us
|
{localeData.txtContactUs}
|
||||||
</Link>
|
</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
)}*/}
|
)}
|
||||||
</HeaderStyle>
|
</HeaderStyle>
|
||||||
|
|
||||||
{/* {mdUp && (
|
{/* {mdUp && (
|
||||||
@@ -116,7 +115,7 @@ export default function Login() {
|
|||||||
/>
|
/>
|
||||||
</SectionStyle>
|
</SectionStyle>
|
||||||
)} */}
|
)} */}
|
||||||
|
|
||||||
<Container maxWidth="sm">
|
<Container maxWidth="sm">
|
||||||
<ContentStyle>
|
<ContentStyle>
|
||||||
<Card sx={{padding:2}}>
|
<Card sx={{padding:2}}>
|
||||||
@@ -125,7 +124,7 @@ export default function Login() {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
sx={{ mb: 5 }}
|
sx={{ mb: 5 }}
|
||||||
>
|
>
|
||||||
|
|
||||||
<Logo sx={{ width: 90, height: 90 }} />
|
<Logo sx={{ width: 90, height: 90 }} />
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
<Typography variant="h4" gutterBottom>
|
<Typography variant="h4" gutterBottom>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useContext } from 'react';
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
// @mui
|
// @mui
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
@@ -13,6 +13,9 @@ import Page from '@/components/Page';
|
|||||||
import { ResetPasswordForm } from '@/sections/auth/reset-password';
|
import { ResetPasswordForm } from '@/sections/auth/reset-password';
|
||||||
// assets
|
// assets
|
||||||
import { SentIcon } from '@/assets';
|
import { SentIcon } from '@/assets';
|
||||||
|
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||||
|
|
||||||
|
import { useNavigate } from 'react-router-dom'; // Import useNavigate
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -27,10 +30,17 @@ const RootStyle = styled('div')(({ theme }) => ({
|
|||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
export default function ResetPassword() {
|
export default function ResetPassword() {
|
||||||
|
const { localeData } = useContext(LanguageContext);
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
|
|
||||||
const [sent, setSent] = useState(false);
|
const [sent, setSent] = useState(false);
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleSent = () => {
|
||||||
|
setSent(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title="Reset Password" sx={{ height: 1 }}>
|
<Page title="Reset Password" sx={{ height: 1 }}>
|
||||||
<RootStyle>
|
<RootStyle>
|
||||||
@@ -41,16 +51,15 @@ export default function ResetPassword() {
|
|||||||
{!sent ? (
|
{!sent ? (
|
||||||
<>
|
<>
|
||||||
<Typography variant="h3" paragraph>
|
<Typography variant="h3" paragraph>
|
||||||
Forgot your password?
|
{localeData.txtForgotYourPassword}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography sx={{ color: 'text.secondary', mb: 5 }}>
|
<Typography sx={{ color: 'text.secondary', mb: 5 }}>
|
||||||
Please enter the email address associated with your account and We will email you
|
{localeData.txtPleaseEnterPassword}
|
||||||
a link to reset your password.
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<ResetPasswordForm
|
<ResetPasswordForm
|
||||||
onSent={() => setSent(true)}
|
onSent={handleSent}
|
||||||
onGetEmail={(value) => setEmail(value)}
|
onGetEmail={(value) => setEmail(value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -61,7 +70,7 @@ export default function ResetPassword() {
|
|||||||
to={PATH_AUTH.login}
|
to={PATH_AUTH.login}
|
||||||
sx={{ mt: 3 }}
|
sx={{ mt: 3 }}
|
||||||
>
|
>
|
||||||
Back
|
{localeData.txtBack}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@@ -69,24 +78,24 @@ export default function ResetPassword() {
|
|||||||
<SentIcon sx={{ mb: 5, mx: 'auto', height: 160 }} />
|
<SentIcon sx={{ mb: 5, mx: 'auto', height: 160 }} />
|
||||||
|
|
||||||
<Typography variant="h3" gutterBottom>
|
<Typography variant="h3" gutterBottom>
|
||||||
Request sent successfully
|
{localeData.txtSuccessSend}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography>
|
<Typography>
|
||||||
We have sent a confirmation email to
|
{localeData.txtCodeConfirm}
|
||||||
<strong>{email}</strong>
|
<strong>{email}</strong>
|
||||||
<br />
|
<br />
|
||||||
Please check your email.
|
{localeData.txtPleasCheck}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
size="large"
|
size="large"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
component={RouterLink}
|
component={RouterLink}
|
||||||
to={PATH_AUTH.login}
|
to={PATH_AUTH.verify}
|
||||||
sx={{ mt: 5 }}
|
sx={{ mt: 5 }}
|
||||||
>
|
>
|
||||||
Back
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink, useLocation } from 'react-router-dom';
|
||||||
// @mui
|
// @mui
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import { Box, Button, Link, Container, Typography } from '@mui/material';
|
import { Box, Button, Link, Container, Typography } from '@mui/material';
|
||||||
@@ -11,6 +11,9 @@ import Page from '@/components/Page';
|
|||||||
import Iconify from '@/components/Iconify';
|
import Iconify from '@/components/Iconify';
|
||||||
// sections
|
// sections
|
||||||
import { VerifyCodeForm } from '@/sections/auth/verify-code';
|
import { VerifyCodeForm } from '@/sections/auth/verify-code';
|
||||||
|
import { useState, useContext, useEffect } from 'react';
|
||||||
|
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||||
|
import axios from '@/utils/axios';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -21,9 +24,41 @@ const RootStyle = styled('div')(({ theme }) => ({
|
|||||||
padding: theme.spacing(12, 0),
|
padding: theme.spacing(12, 0),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function useQuery() {
|
||||||
|
return new URLSearchParams(useLocation().search);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
export default function VerifyCode() {
|
export default function VerifyCode() {
|
||||||
|
const { localeData } = useContext(LanguageContext);
|
||||||
|
const query = useQuery();
|
||||||
|
const email = query.get('email');
|
||||||
|
const [timer, setTimer] = useState(60); // Initialize timer with 60 seconds
|
||||||
|
const [canResend, setCanResend] = useState(false); // State to control resend button visibility
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setTimer((prev) => {
|
||||||
|
if (prev > 0) {
|
||||||
|
return prev - 1;
|
||||||
|
} else {
|
||||||
|
clearInterval(interval);
|
||||||
|
setCanResend(true); // Enable resend button when timer reaches 0
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval); // Cleanup interval on component unmount
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleResend = () => {
|
||||||
|
setCanResend(false);
|
||||||
|
setTimer(60); // Reset timer to 60 seconds
|
||||||
|
// Add logic to resend the code here
|
||||||
|
axios.post('/verify-email', {email: email});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title="Verify" sx={{ height: 1 }}>
|
<Page title="Verify" sx={{ height: 1 }}>
|
||||||
<RootStyle>
|
<RootStyle>
|
||||||
@@ -34,30 +69,42 @@ export default function VerifyCode() {
|
|||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
component={RouterLink}
|
component={RouterLink}
|
||||||
to={PATH_AUTH.login}
|
to={PATH_AUTH.resetPassword}
|
||||||
startIcon={<Iconify icon={'eva:arrow-ios-back-fill'} width={20} height={20} />}
|
startIcon={<Iconify icon={'eva:arrow-ios-back-fill'} width={20} height={20} />}
|
||||||
sx={{ mb: 3 }}
|
sx={{ mb: 3 }}
|
||||||
>
|
>
|
||||||
Back
|
{localeData.txtBack}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Typography variant="h3" paragraph>
|
<Typography variant="h3" paragraph>
|
||||||
Please check your email!
|
{localeData.txtCheckEmail}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography variant='subtitle1'>{email}</Typography>
|
||||||
<Typography sx={{ color: 'text.secondary' }}>
|
<Typography sx={{ color: 'text.secondary' }}>
|
||||||
We have emailed a 6-digit confirmation code to acb@domain, please enter the code in
|
{localeData.txtEmail}
|
||||||
below box to verify your email.
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Box sx={{ mt: 5, mb: 3 }}>
|
<Box sx={{ mt: 5, mb: 3 }}>
|
||||||
<VerifyCodeForm />
|
<VerifyCodeForm
|
||||||
|
onGetEmail={email}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography variant="body2" align="center">
|
{/* <Typography variant="body2" align="center">
|
||||||
Don’t have a code?
|
Don’t have a code?
|
||||||
<Link variant="subtitle2" underline="none" onClick={() => {}}>
|
<Link variant="subtitle2" underline="none" onClick={() => {}}>
|
||||||
Resend code
|
Resend code
|
||||||
</Link>
|
</Link>
|
||||||
|
</Typography> */}
|
||||||
|
<Typography variant="body2" align="center">
|
||||||
|
{localeData.txtDont}
|
||||||
|
{canResend ? (
|
||||||
|
<Link sx={{cursor: 'pointer'}} variant="subtitle2" underline="none" onClick={handleResend}>
|
||||||
|
{localeData.txtResendCode}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span>{`${localeData.txtResendCode} ${timer} ${localeData.txtSecond}`}</span>
|
||||||
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export default function Router() {
|
|||||||
// { path: 'register-unprotected', element: <Register /> },
|
// { path: 'register-unprotected', element: <Register /> },
|
||||||
{ path: 'reset-password', element: <ResetPassword /> },
|
{ path: 'reset-password', element: <ResetPassword /> },
|
||||||
{ path: 'forget-password', element: <ForgetPassword /> },
|
{ path: 'forget-password', element: <ForgetPassword /> },
|
||||||
// { path: 'verify', element: <VerifyCode /> },
|
{ path: 'verify', element: <VerifyCode /> },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import * as Yup from 'yup';
|
|||||||
// form
|
// form
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useContext, useMemo, useRef, useState } from 'react';
|
||||||
import { Link as RouterLink, useNavigate } from 'react-router-dom';
|
import { Link as RouterLink, useNavigate, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
// @mui
|
// @mui
|
||||||
import { Alert, IconButton, InputAdornment, Stack, Typography } from '@mui/material';
|
import { Alert, IconButton, InputAdornment, Stack, Typography } from '@mui/material';
|
||||||
@@ -14,6 +14,9 @@ import useIsMountedRef from '@/hooks/useIsMountedRef';
|
|||||||
import { FormProvider, RHFTextField } from '@/components/hook-form';
|
import { FormProvider, RHFTextField } from '@/components/hook-form';
|
||||||
import axios from '@/utils/axios';
|
import axios from '@/utils/axios';
|
||||||
import Iconify from '@/components/Iconify';
|
import Iconify from '@/components/Iconify';
|
||||||
|
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||||
|
|
||||||
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -26,9 +29,19 @@ type Props = {
|
|||||||
token: string;
|
token: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function useQuery() {
|
||||||
|
return new URLSearchParams(useLocation().search);
|
||||||
|
}
|
||||||
|
|
||||||
export default function ForgetPasswordForm({ token }: Props) {
|
export default function ForgetPasswordForm({ token }: Props) {
|
||||||
|
const { localeData } = useContext(LanguageContext);
|
||||||
const isMountedRef = useIsMountedRef();
|
const isMountedRef = useIsMountedRef();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const query = useQuery();
|
||||||
|
const email = query.get('email');
|
||||||
|
|
||||||
|
const token_ = query.get('token');
|
||||||
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const [showPasswordNew, setShowPasswordNew] = useState(false);
|
const [showPasswordNew, setShowPasswordNew] = useState(false);
|
||||||
const [showPasswordConfirmNew, setShowPasswordConfirmNew] = useState(false);
|
const [showPasswordConfirmNew, setShowPasswordConfirmNew] = useState(false);
|
||||||
@@ -47,19 +60,19 @@ export default function ForgetPasswordForm({ token }: Props) {
|
|||||||
|
|
||||||
const onSubmit = async (data: FormValuesProps) => {
|
const onSubmit = async (data: FormValuesProps) => {
|
||||||
try {
|
try {
|
||||||
await axios.post('/forget-password', { ...data, token });
|
await axios.post('/forget-password', { ...data, email:email, token:token_ });
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
// await new Promise((resolve) => setTimeout(resolve, 500));
|
// await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
|
enqueueSnackbar('Password reset was successful', { variant: 'success' });
|
||||||
navigate('/auth/login', { replace: true });
|
navigate('/auth/login', { replace: true });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.response.data);
|
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
setError('afterSubmit', { ...error, message: error.response.data.message });
|
setError('afterSubmit', { ...error, message: error.response.data.meta.message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -68,10 +81,10 @@ export default function ForgetPasswordForm({ token }: Props) {
|
|||||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
||||||
<Typography>Kata Sandi Baru</Typography>
|
<Typography>{localeData.txtNewPassword}</Typography>
|
||||||
<RHFTextField
|
<RHFTextField
|
||||||
name="new_password"
|
name="new_password"
|
||||||
label="Kata Sandi Baru"
|
label={localeData.txtNewPassword}
|
||||||
type={showPasswordNew ? 'text' : 'password'}
|
type={showPasswordNew ? 'text' : 'password'}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
@@ -83,10 +96,10 @@ export default function ForgetPasswordForm({ token }: Props) {
|
|||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography>Konfirmasi Kata Sandi </Typography>
|
<Typography>{localeData.txtConfPassword}</Typography>
|
||||||
<RHFTextField
|
<RHFTextField
|
||||||
name="confirm_new_password"
|
name="confirm_new_password"
|
||||||
label="Konfirmasi Kata Sandi"
|
label={localeData.txtConfPassword}
|
||||||
type={showPasswordConfirmNew ? 'text' : 'password'}
|
type={showPasswordConfirmNew ? 'text' : 'password'}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export default function LoginForm() {
|
|||||||
|
|
||||||
const onSubmit = async (data: FormValuesProps) => {
|
const onSubmit = async (data: FormValuesProps) => {
|
||||||
try {
|
try {
|
||||||
const loginResult = await login(data.email, data.password);
|
const loginResult = await login(data.email, data.password, data.remember);
|
||||||
|
|
||||||
navigate('/dashboard');
|
navigate('/dashboard');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -100,10 +100,10 @@ export default function LoginForm() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ my: 2 }}>
|
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ my: 2 }}>
|
||||||
{/*<RHFCheckbox name="remember" label="Remember me" />
|
<RHFCheckbox name="remember" label={localeData.txtIngatkanSaya}/>
|
||||||
<Link component={RouterLink} variant="subtitle2" to={PATH_AUTH.resetPassword}>
|
<Link component={RouterLink} variant="subtitle2" to={PATH_AUTH.resetPassword}>
|
||||||
Forgot password?
|
{localeData.txtLupaSandi}
|
||||||
</Link>*/}
|
</Link>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
@@ -114,7 +114,7 @@ export default function LoginForm() {
|
|||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
sx={{ marginTop: 2 }}
|
sx={{ marginTop: 2 }}
|
||||||
>
|
>
|
||||||
Login
|
{localeData.txtLogin}
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import useIsMountedRef from '@/hooks/useIsMountedRef';
|
|||||||
// components
|
// components
|
||||||
import { FormProvider, RHFTextField } from '@/components/hook-form';
|
import { FormProvider, RHFTextField } from '@/components/hook-form';
|
||||||
import axios from '@/utils/axios';
|
import axios from '@/utils/axios';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -26,6 +27,8 @@ type Props = {
|
|||||||
export default function ResetPasswordForm({ onSent, onGetEmail }: Props) {
|
export default function ResetPasswordForm({ onSent, onGetEmail }: Props) {
|
||||||
const isMountedRef = useIsMountedRef();
|
const isMountedRef = useIsMountedRef();
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const ResetPasswordSchema = Yup.object().shape({
|
const ResetPasswordSchema = Yup.object().shape({
|
||||||
email: Yup.string().email('Email must be a valid email address').required('Email is required'),
|
email: Yup.string().email('Email must be a valid email address').required('Email is required'),
|
||||||
});
|
});
|
||||||
@@ -43,19 +46,22 @@ export default function ResetPasswordForm({ onSent, onGetEmail }: Props) {
|
|||||||
|
|
||||||
const onSubmit = async (data: FormValuesProps) => {
|
const onSubmit = async (data: FormValuesProps) => {
|
||||||
try {
|
try {
|
||||||
await axios.post('/verify-email', data);
|
const response = await axios.post('/verify-email', data);
|
||||||
console.log(data);
|
if(response.data.data.email)
|
||||||
|
{
|
||||||
|
|
||||||
|
onGetEmail(response.data.data.email);
|
||||||
|
navigate(`/auth/verify?email=${response.data.data.email}`);
|
||||||
|
}
|
||||||
// await new Promise((resolve) => setTimeout(resolve, 500));
|
// await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
onSent();
|
onSent();
|
||||||
onGetEmail(data.email);
|
onGetEmail(response.data.data.email);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.response.data);
|
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
setError('afterSubmit', { ...error, message: error.response.data.message });
|
setError('afterSubmit', { ...error, message: error.response.data.meta.message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import { useEffect } from 'react';
|
|||||||
import { useForm, Controller } from 'react-hook-form';
|
import { useForm, Controller } from 'react-hook-form';
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
// @mui
|
// @mui
|
||||||
import { OutlinedInput, Stack } from '@mui/material';
|
import { OutlinedInput, Alert, Stack } from '@mui/material';
|
||||||
|
import useIsMountedRef from '@/hooks/useIsMountedRef';
|
||||||
import { LoadingButton } from '@mui/lab';
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { FormProvider, RHFTextField } from '@/components/hook-form';
|
||||||
// routes
|
// routes
|
||||||
|
import axios from '@/utils/axios';
|
||||||
// import { PATH_DASHBOARD } from '@/routes/paths';
|
// import { PATH_DASHBOARD } from '@/routes/paths';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -23,8 +26,11 @@ type FormValuesProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type ValueNames = 'code1' | 'code2' | 'code3' | 'code4' | 'code5' | 'code6';
|
type ValueNames = 'code1' | 'code2' | 'code3' | 'code4' | 'code5' | 'code6';
|
||||||
|
type Props = {
|
||||||
export default function VerifyCodeForm() {
|
onGetEmail: (value: string) => void;
|
||||||
|
};
|
||||||
|
export default function VerifyCodeForm({ onGetEmail }: Props) {
|
||||||
|
const isMountedRef = useIsMountedRef();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
@@ -51,8 +57,9 @@ export default function VerifyCodeForm() {
|
|||||||
watch,
|
watch,
|
||||||
control,
|
control,
|
||||||
setValue,
|
setValue,
|
||||||
|
setError,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { isSubmitting, isValid },
|
formState: { isSubmitting, isValid , errors},
|
||||||
} = useForm({
|
} = useForm({
|
||||||
mode: 'onBlur',
|
mode: 'onBlur',
|
||||||
resolver: yupResolver(VerifyCodeSchema),
|
resolver: yupResolver(VerifyCodeSchema),
|
||||||
@@ -67,16 +74,36 @@ export default function VerifyCodeForm() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onSubmit = async (data: FormValuesProps) => {
|
const onSubmit = async (data: FormValuesProps) => {
|
||||||
|
// try {
|
||||||
|
// await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
// console.log('code:', Object.values(data).join(''));
|
||||||
|
|
||||||
|
// enqueueSnackbar('Verify success!', { variant: 'success' });
|
||||||
|
|
||||||
|
// navigate('/dashboard', { replace: true });
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error(error);
|
||||||
|
// }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
const response = await axios.post('/verify-code', {email: onGetEmail, token: Object.values(data).join('')});
|
||||||
console.log('code:', Object.values(data).join(''));
|
// await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
enqueueSnackbar('Verify success!', { variant: 'success' });
|
if(response.data.meta.code === 200)
|
||||||
|
{
|
||||||
navigate('/dashboard', { replace: true });
|
navigate(`/auth/forget-password?email=${response.data.data.email}&token=${response.data.data.token}`);
|
||||||
} catch (error) {
|
}
|
||||||
console.error(error);
|
if (isMountedRef.current) {
|
||||||
}
|
if(response.data.meta.code === 404)
|
||||||
|
{
|
||||||
|
setError('afterSubmit', { ...response, message: response.data.meta.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (isMountedRef.current) {
|
||||||
|
setError('afterSubmit', { ...error, message: error.response.data.meta.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePasteClipboard = (event: ClipboardEvent) => {
|
const handlePasteClipboard = (event: ClipboardEvent) => {
|
||||||
@@ -115,35 +142,38 @@ export default function VerifyCodeForm() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<Stack direction="row" spacing={2} justifyContent="center">
|
<Stack spacing={3}>
|
||||||
{Object.keys(values).map((name, index) => (
|
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
||||||
<Controller
|
<Stack direction="row" spacing={2} justifyContent="center">
|
||||||
key={name}
|
{Object.keys(values).map((name, index) => (
|
||||||
name={`code${index + 1}` as ValueNames}
|
<Controller
|
||||||
control={control}
|
key={name}
|
||||||
render={({ field }) => (
|
name={`code${index + 1}` as ValueNames}
|
||||||
<OutlinedInput
|
control={control}
|
||||||
{...field}
|
render={({ field }) => (
|
||||||
id="field-code"
|
<OutlinedInput
|
||||||
autoFocus={index === 0}
|
{...field}
|
||||||
placeholder="-"
|
id="field-code"
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
autoFocus={index === 0}
|
||||||
handleChangeWithNextField(event, field.onChange)
|
placeholder="-"
|
||||||
}
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
inputProps={{
|
handleChangeWithNextField(event, field.onChange)
|
||||||
maxLength: 1,
|
}
|
||||||
sx: {
|
inputProps={{
|
||||||
p: 0,
|
maxLength: 1,
|
||||||
textAlign: 'center',
|
sx: {
|
||||||
width: { xs: 36, sm: 56 },
|
p: 0,
|
||||||
height: { xs: 36, sm: 56 },
|
textAlign: 'center',
|
||||||
},
|
width: { xs: 36, sm: 56 },
|
||||||
}}
|
height: { xs: 36, sm: 56 },
|
||||||
/>
|
},
|
||||||
)}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
)}
|
||||||
</Stack>
|
/>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|||||||
@@ -25,34 +25,98 @@ import axios from './axios';
|
|||||||
// }, timeLeft);
|
// }, timeLeft);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const setSession = (accessToken: string | null) => {
|
// let expiredCookie = 1/24/60; 1 menit
|
||||||
|
let expiredCookie = 12/24; //12 jam
|
||||||
|
|
||||||
|
const setCookie = (name:any, value:any, days:any) => {
|
||||||
|
let expires = "";
|
||||||
|
if (days) {
|
||||||
|
const date = new Date();
|
||||||
|
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||||
|
expires = "; expires=" + date.toUTCString();
|
||||||
|
}
|
||||||
|
document.cookie = name + "=" + decodeURIComponent(value || "") + expires + "; path=/; SameSite=Strict";
|
||||||
|
};
|
||||||
|
|
||||||
|
const setSession = (accessToken: string | null, rememberMe: boolean) => {
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
localStorage.setItem('accessToken', accessToken);
|
const userString = getUser();
|
||||||
|
const storedUser = userString ? JSON.parse(userString) : null;
|
||||||
|
if(rememberMe)
|
||||||
|
{
|
||||||
|
localStorage.setItem('accessToken', accessToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setCookie('accessToken', accessToken, expiredCookie);
|
||||||
|
setCookie('rememberMe', 'OK', expiredCookie);
|
||||||
|
}
|
||||||
|
|
||||||
axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
|
axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
|
||||||
axios.defaults.headers.common['Accept-Language'] = (localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID');
|
axios.defaults.headers.common['Accept-Language'] = localStorage.getItem('currentLocale') ?? 'id-ID';
|
||||||
axios.defaults.headers.common['Accept'] = 'application/json';
|
axios.defaults.headers.common['Accept'] = 'application/json';
|
||||||
axios.defaults.headers.common['Content-Type'] = 'application/json';
|
axios.defaults.headers.common['Content-Type'] = 'application/json';
|
||||||
|
axios.defaults.headers.common['Organization-id'] = storedUser?.organization_id;
|
||||||
// This function below will handle when token is expired
|
// This function below will handle when token is expired
|
||||||
// const { exp } = jwtDecode(accessToken);
|
// const { exp } = jwtDecode(accessToken);
|
||||||
// handleTokenExpired(exp);
|
// handleTokenExpired(exp);
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem('accessToken');
|
localStorage.removeItem('accessToken');
|
||||||
|
removeCookie('accessToken');
|
||||||
|
removeCookie('rememberMe');
|
||||||
delete axios.defaults.headers.common.Authorization;
|
delete axios.defaults.headers.common.Authorization;
|
||||||
delete axios.defaults.headers.common['Accept-Language'];
|
delete axios.defaults.headers.common['Accept-Language'];
|
||||||
delete axios.defaults.headers.common['Accept'];
|
delete axios.defaults.headers.common['Accept'];
|
||||||
delete axios.defaults.headers.common['Content-Type'];
|
delete axios.defaults.headers.common['Content-Type'];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setUser = (user: any) => {
|
const setUser = (user: any, rememberMe: boolean) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
localStorage.setItem('user', user);
|
if(rememberMe)
|
||||||
|
{
|
||||||
|
localStorage.setItem('user', JSON.stringify(user));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setCookie('user', JSON.stringify(user), expiredCookie);
|
||||||
|
setCookie('rememberMe', 'OK', expiredCookie);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
|
removeCookie('user');
|
||||||
|
removeCookie('rememberMe');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSession = () => window.localStorage.getItem('accessToken')
|
const getCookie = (name:any) => {
|
||||||
const getUser = () => window.localStorage.getItem('user')
|
const cookies = document.cookie.split('; ');
|
||||||
|
for (let i = 0; i < cookies.length; i++) {
|
||||||
|
const cookiePair = cookies[i].split('=');
|
||||||
|
if (cookiePair[0] === name) {
|
||||||
|
return decodeURIComponent(cookiePair[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
export { setSession, getSession, setUser, getUser };
|
const getSession = () => {
|
||||||
|
const localToken = window.localStorage.getItem('accessToken');
|
||||||
|
const cookieToken = getCookie('accessToken');
|
||||||
|
// Prioritaskan token dari localStorage
|
||||||
|
return localToken || cookieToken;
|
||||||
|
};
|
||||||
|
// const getUser = () => window.localStorage.getItem('user') || window.sessionStorage.getItem('user')
|
||||||
|
const getUser = () => {
|
||||||
|
const localUser = window.localStorage.getItem('user');
|
||||||
|
const cookieUser = getCookie('user');
|
||||||
|
|
||||||
|
// Prioritaskan token dari localStorage
|
||||||
|
return localUser || cookieUser;
|
||||||
|
};
|
||||||
|
const removeCookie = (name:any) => {
|
||||||
|
document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
|
||||||
|
};
|
||||||
|
|
||||||
|
export { setSession, getSession, setUser, getUser, getCookie };
|
||||||
|
|||||||
BIN
public/files/Template Import Invoice.xlsx
Normal file
BIN
public/files/Template Import Invoice.xlsx
Normal file
Binary file not shown.
Reference in New Issue
Block a user