Merge remote-tracking branch 'origin/staging' into origin/production
This commit is contained in:
0
.editorconfig
Normal file → Executable file
0
.editorconfig
Normal file → Executable file
2
.gitignore
vendored
2
.gitignore
vendored
@@ -23,4 +23,4 @@ yarn-error.log
|
||||
/public/hospital-portal
|
||||
/public/hospital-portal-staging
|
||||
|
||||
/public/files
|
||||
/public/files
|
||||
|
||||
0
.styleci.yml
Normal file → Executable file
0
.styleci.yml
Normal file → Executable file
@@ -34,24 +34,51 @@ class AuthController extends Controller
|
||||
|
||||
return Helper::responseJson(statusCode: Response::HTTP_NOT_FOUND, message: $message);
|
||||
}
|
||||
|
||||
|
||||
// $token = rand(1000, 9999); // Menghasilkan angka acak antara 100000 dan 999999
|
||||
$token = 4444; // Menghasilkan angka acak antara 100000 dan 999999
|
||||
if($request->phoneOrEmail == 'manager+one@gmail.com' || $request->phoneOrEmail == 'manager+two@gmail.com')
|
||||
{
|
||||
$token = 4444;
|
||||
}
|
||||
if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
User::query()->find($user->id)->update([
|
||||
'email' => $request->phoneOrEmail,
|
||||
'otp' => $token,
|
||||
'otp_created_at' => now()
|
||||
]);
|
||||
} else {
|
||||
User::query()->find($user->id)->update([
|
||||
'phone' => $request->phoneOrEmail,
|
||||
'otp' => $token,
|
||||
'otp_created_at' => now()
|
||||
]);
|
||||
// if($request->phoneOrEmail == 'manager+one@gmail.com' || $request->phoneOrEmail == 'manager+two@gmail.com')
|
||||
// {
|
||||
// $token = 4444;
|
||||
// }
|
||||
// if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
// User::query()->find($user->id)->update([
|
||||
// 'email' => $request->phoneOrEmail,
|
||||
// 'otp' => $token,
|
||||
// 'otp_created_at' => now()
|
||||
// ]);
|
||||
// } else {
|
||||
// User::query()->find($user->id)->update([
|
||||
// 'phone' => $request->phoneOrEmail,
|
||||
// 'otp' => $token,
|
||||
// 'otp_created_at' => now()
|
||||
// ]);
|
||||
// }
|
||||
|
||||
// // TODO Send the OTP
|
||||
// if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
// // Send Email
|
||||
// //send to alarm
|
||||
// if($request->phoneOrEmail != 'manager+one@gmail.com' && $request->phoneOrEmail != 'manager+two@gmail.com')
|
||||
// {
|
||||
// $nameTo = 'User';
|
||||
// $dataEmail = [
|
||||
// 'email' => $request->phoneOrEmail,
|
||||
// 'name' => $nameTo,
|
||||
// 'subject' => 'OTP Login Client Portal Tanggal '. date('Y-m-d H:i:s'),
|
||||
// 'body' => View::make('email/forgot_password', ['token' => $token])->render(),
|
||||
// ];
|
||||
// Helper::sendEmail($dataEmail);
|
||||
// }
|
||||
// } else {
|
||||
// // Send Whatsapp
|
||||
// }
|
||||
|
||||
// return Helper::responseJson(message: 'OTP Terkirim');
|
||||
|
||||
|
||||
if (!Hash::check($request->password, $user->password)) {
|
||||
return response(['message' => 'Password Salah'], 403);
|
||||
}
|
||||
|
||||
return Helper::responseJson(
|
||||
|
||||
93
Modules/HospitalPortal/Helpers/GrabHelper.php
Normal file
93
Modules/HospitalPortal/Helpers/GrabHelper.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\HospitalPortal\Helpers;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
|
||||
class GrabHelper
|
||||
{
|
||||
protected $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new Client();
|
||||
}
|
||||
|
||||
public function getToken()
|
||||
{
|
||||
$url = env('TOKEN_URL_GRAB');
|
||||
$headers = [
|
||||
'Content-Type' => 'application/json',
|
||||
];
|
||||
$body = json_encode([
|
||||
'client_id' => env('CLIENT_ID_GRAB'),
|
||||
'client_secret' => env('CLIENT_SECRET_GRAB'),
|
||||
'grant_type' => 'client_credentials',
|
||||
'scope' => 'grab_express.partner_deliveries',
|
||||
]);
|
||||
|
||||
$request = new Request('POST', $url, $headers, $body);
|
||||
$response = $this->client->send($request);
|
||||
$data = json_decode($response->getBody()->getContents(), true);
|
||||
|
||||
return $data['access_token'] ?? null;
|
||||
}
|
||||
|
||||
public function createDelivery($token,$body)
|
||||
{
|
||||
$url = env('BASE_URL_GRAB').'/v1/deliveries';
|
||||
$headers = [
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $token,
|
||||
];
|
||||
$request = new Request('POST', $url, $headers, $body);
|
||||
$response = $this->client->send($request);
|
||||
|
||||
return $response->getBody()->getContents();
|
||||
}
|
||||
|
||||
public function normalizePhoneNumber($phoneNumber) {
|
||||
// Remove any non-digit characters (e.g., '+', '-', spaces)
|
||||
$phoneNumber = preg_replace('/\D/', '', $phoneNumber);
|
||||
|
||||
// Check if the cleaned phone number is numeric
|
||||
if (!is_numeric($phoneNumber)) {
|
||||
return null; // Return false or handle the error as needed
|
||||
}
|
||||
|
||||
// Handle phone numbers starting with '62' or '+62'
|
||||
if (substr($phoneNumber, 0, 2) === '62') {
|
||||
$phoneNumber = '0' . substr($phoneNumber, 2);
|
||||
}
|
||||
|
||||
// Handle phone numbers that already start with '8'
|
||||
if (substr($phoneNumber, 0, 1) === '8') {
|
||||
$phoneNumber = '0' . $phoneNumber;
|
||||
}
|
||||
|
||||
return $phoneNumber;
|
||||
}
|
||||
|
||||
public function getScheduleTimes()
|
||||
{
|
||||
// Create a DateTime object for the current time in Jakarta timezone
|
||||
$pickupTimeFrom = new DateTime('now', new DateTimeZone('Asia/Jakarta'));
|
||||
|
||||
// Add 30 minutes to the current time for pickupTimeFrom
|
||||
$pickupTimeFrom->modify('+30 minutes');
|
||||
|
||||
// Clone the pickupTimeFrom to calculate pickupTimeTo
|
||||
$pickupTimeTo = clone $pickupTimeFrom;
|
||||
// Add 1 hour to pickupTimeFrom for pickupTimeTo
|
||||
$pickupTimeTo->modify('+1 hour');
|
||||
|
||||
// Format the times to ISO 8601 format (e.g., 2024-10-02T12:37:28+07:00)
|
||||
return [
|
||||
"pickupTimeFrom" => $pickupTimeFrom->format(DateTime::ATOM),
|
||||
"pickupTimeTo" => $pickupTimeTo->format(DateTime::ATOM),
|
||||
];
|
||||
}
|
||||
}
|
||||
695
Modules/HospitalPortal/Http/Controllers/ApotekController.php
Normal file
695
Modules/HospitalPortal/Http/Controllers/ApotekController.php
Normal file
@@ -0,0 +1,695 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\HospitalPortal\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Support\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Modules\HospitalPortal\Helpers\ApiResponse;
|
||||
use Modules\HospitalPortal\Helpers\GrabHelper;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
|
||||
|
||||
class ApotekController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @return Renderable
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$limit = $request->has('per_page') ? $request->input('per_page') : 10;
|
||||
|
||||
$results = DB::connection('oldlms')->table('tx_prescriptions')
|
||||
->join('tx_prescription_orders', 'tx_prescription_orders.nIDPrescription', '=', 'tx_prescriptions.nID')
|
||||
->join('tm_users', 'tm_users.nID', '=', 'tx_prescriptions.nIDUser')
|
||||
->when(auth()->user()->organization_id, function ($query, $organizationId) {
|
||||
$query->where('tx_prescription_orders.nIDApotek', '=', $organizationId);
|
||||
})
|
||||
->when($request->input('search'), function ($query, $search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->orWhere('tx_prescriptions.sKodeResep', 'like', "%" . $search . "%")
|
||||
->orWhere('tm_users.sFirstName', 'like', "%" . $search . "%");
|
||||
});
|
||||
})
|
||||
->when($request->has('orderBy'), function ($query) use ($request) {
|
||||
$orderBy = $request->orderBy;
|
||||
$direction = $request->order ?? 'asc';
|
||||
|
||||
if($orderBy == 'apotek')
|
||||
{
|
||||
$orderBy = 'nIDApotek';
|
||||
}
|
||||
|
||||
$query->orderBy($orderBy, $direction);
|
||||
})
|
||||
->when($request->input('start_date') && !$request->input('end_date'), function ($query, $start_date) {
|
||||
$query->where(function ($query) use ($start_date) {
|
||||
$query->where('tx_prescriptions.dTanggalresep', '<', $start_date);
|
||||
});
|
||||
})
|
||||
->when($request->input('status'), function ($query, $status) {
|
||||
$query->where(function ($query) use ($status) {
|
||||
$query->where('tx_prescription_orders.sStatus', '=', $status);
|
||||
});
|
||||
})
|
||||
->select(
|
||||
'tx_prescriptions.nID as id',
|
||||
'tx_prescription_orders.nID as nID_orders',
|
||||
'tx_prescriptions.nIDUser',
|
||||
'tx_prescriptions.sKodeResep as no_resep',
|
||||
'tx_prescriptions.dTanggalResep as tanggal',
|
||||
'tx_prescription_orders.nIDApotek',
|
||||
'tx_prescription_orders.sStatus as status',
|
||||
'tx_prescription_orders.sStatus',
|
||||
DB::raw('
|
||||
CASE
|
||||
WHEN tx_prescription_orders.sStatus = "waiting_pharmacy" THEN "Diterima"
|
||||
WHEN tx_prescription_orders.sStatus = "order_prepared" THEN "Siap Diambil"
|
||||
WHEN tx_prescription_orders.sStatus = "ready" THEN "Cari Kurir"
|
||||
WHEN tx_prescription_orders.sStatus = "failed" THEN "Cari Kurir"
|
||||
WHEN tx_prescription_orders.sStatus = "waiting_for_courir" THEN "Kurir Sudah Ambil Pesanan"
|
||||
WHEN tx_prescription_orders.sStatus = "package_picked_up" THEN "Sedang diantar ke Alamat Tujuan"
|
||||
WHEN tx_prescription_orders.sStatus = "package_on_delivery" THEN "Selesai"
|
||||
ELSE ""
|
||||
END AS button_accept'),
|
||||
DB::raw('CONCAT(
|
||||
COALESCE(tm_users.sFirstName, ""),
|
||||
" ",
|
||||
COALESCE(tm_users.sMiddleName, ""),
|
||||
" ",
|
||||
COALESCE(tm_users.sLastName, "")
|
||||
) as pasien'),
|
||||
DB::raw('
|
||||
(SELECT CONCAT(
|
||||
COALESCE(u.sFirstName, ""),
|
||||
" ",
|
||||
COALESCE(u.sMiddleName, ""),
|
||||
" ",
|
||||
COALESCE(u.sLastName, "")
|
||||
)
|
||||
FROM tm_dokter d
|
||||
LEFT JOIN tm_users u ON u.nID = d.nIDUser
|
||||
WHERE d.nID = tx_prescriptions.nIDDokter LIMIT 1) AS nama_dokter
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT s.sSpesialis
|
||||
FROM tm_dokter d
|
||||
LEFT JOIN tm_spesialis s ON s.nID = d.nIDSpesialis
|
||||
WHERE d.nID = tx_prescriptions.nIDDokter LIMIT 1) AS spesialis
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT t.sSIP
|
||||
FROM tm_dokter d
|
||||
LEFT JOIN tx_jadwal_dokter t ON t.nIDDokter = d.nID
|
||||
WHERE d.nID = tx_prescriptions.nIDDokter LIMIT 1) AS sip
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT u.sPhone
|
||||
FROM tm_dokter d
|
||||
LEFT JOIN tm_users u ON u.nID = d.nIDUser
|
||||
WHERE d.nID = tx_prescriptions.nIDDokter LIMIT 1) AS no_ponsel_dokter
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT tm_users_detail.dTanggalLahir
|
||||
FROM tm_users_detail
|
||||
WHERE tm_users_detail.nIDUser = tm_users.nID LIMIT 1) AS tgl_lahir_pasien
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT CASE
|
||||
WHEN tm_users_detail.nIDJenisKelamin = 1 THEN "Male"
|
||||
ELSE "Female"
|
||||
END
|
||||
FROM tm_users_detail
|
||||
WHERE tm_users_detail.nIDUser = tm_users.nID LIMIT 1) AS jenis_kelamin_pasien
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT CONCAT(tm_users_detail.sHeight, "/", tm_users_detail.sWeight)
|
||||
FROM tm_users_detail
|
||||
WHERE tm_users_detail.nIDUser = tm_users.nID LIMIT 1) AS tinggi_berat
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT tm_users_insurance.sNoPolis
|
||||
FROM tm_users_insurance
|
||||
LEFT JOIN tm_insurance ON tm_users_insurance.nIDInsurance = tm_insurance.nID
|
||||
WHERE tm_users_insurance.nIDUser = tx_prescriptions.nIDUser LIMIT 1) AS no_polis
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT tm_insurance.sInsurance
|
||||
FROM tm_users_insurance
|
||||
LEFT JOIN tm_insurance ON tm_users_insurance.nIDInsurance = tm_insurance.nID
|
||||
WHERE tm_users_insurance.nIDUser = tx_prescriptions.nIDUser LIMIT 1) AS perusahaan_asuransi
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT tm_users_insurance.sCorporateName
|
||||
FROM tm_users_insurance
|
||||
LEFT JOIN tm_insurance ON tm_users_insurance.nIDInsurance = tm_insurance.nID
|
||||
WHERE tm_users_insurance.nIDUser = tx_prescriptions.nIDUser LIMIT 1) AS nama_perusahaan
|
||||
'),
|
||||
DB::raw('
|
||||
(SELECT tm_users_insurance.sProductCode
|
||||
FROM tm_users_insurance
|
||||
LEFT JOIN tm_insurance ON tm_users_insurance.nIDInsurance = tm_insurance.nID
|
||||
WHERE tm_users_insurance.nIDUser = tx_prescriptions.nIDUser LIMIT 1) AS kode_produk
|
||||
'),
|
||||
DB::raw('
|
||||
(
|
||||
SELECT
|
||||
CASE
|
||||
WHEN tm_users_insurance.sPlanCode = "A" THEN "Alba"
|
||||
WHEN tm_users_insurance.sPlanCode = "B" THEN "Blue"
|
||||
WHEN tm_users_insurance.sPlanCode = "S" THEN "Silver"
|
||||
WHEN tm_users_insurance.sPlanCode = "G" THEN "Gold"
|
||||
WHEN tm_users_insurance.sPlanCode = "P" THEN "Platinum"
|
||||
WHEN tm_users_insurance.sPlanCode = "D" THEN "Diamond"
|
||||
ELSE ""
|
||||
END AS kelas_asuransi
|
||||
FROM tm_users_insurance
|
||||
LEFT JOIN tm_insurance ON tm_users_insurance.nIDInsurance = tm_insurance.nID
|
||||
WHERE tm_users_insurance.nIDUser = tx_prescriptions.nIDUser
|
||||
LIMIT 1
|
||||
) AS kelas_asuransi
|
||||
'),
|
||||
DB::raw('
|
||||
(
|
||||
SELECT
|
||||
CASE
|
||||
WHEN tm_hubungan_keluarga.sHubunganKeluarga = "Husband" THEN "S"
|
||||
WHEN tm_hubungan_keluarga.sHubunganKeluarga = "Wife" THEN "I"
|
||||
WHEN tm_hubungan_keluarga.sHubunganKeluarga = "Child" THEN "A"
|
||||
ELSE "P"
|
||||
END AS tipe_member
|
||||
FROM tm_hubungan_keluarga
|
||||
WHERE tm_hubungan_keluarga.nID = tm_users.nIDHubunganKeluarga
|
||||
LIMIT 1
|
||||
) AS tipe_member
|
||||
'),
|
||||
'tx_prescription_orders.sAddress AS alamat_penerima',
|
||||
'tx_prescription_orders.sDeliveryMethod AS pengiriman',
|
||||
'tx_prescription_orders.sDeliveryPrice AS total_kirim',
|
||||
'tx_prescriptions.sNoRefProvider AS noref_dokter',
|
||||
DB::raw('DATE_ADD(tx_prescriptions.dTanggalResep, INTERVAL 1 DAY) as valid_tanggal'),
|
||||
'tx_prescriptions.sNomorPenjamin AS nomor_penjamin',
|
||||
DB::raw('
|
||||
(SELECT tx_livechat.dCreateOn
|
||||
FROM tx_livechat
|
||||
WHERE tx_livechat.nID = tx_prescriptions.nIDLivechat LIMIT 1) AS tgl_livechat
|
||||
'),
|
||||
'tx_prescriptions.sDiagnose as diagnosa',
|
||||
'tx_prescription_orders.nDeliveryID',
|
||||
'tx_prescription_orders.sDeliveryStatus'
|
||||
)
|
||||
->paginate($limit);
|
||||
|
||||
// Secret key for generating the token
|
||||
$secret_key = env('SECRET_KEY_LMS');
|
||||
|
||||
// Transform the results to include the download link
|
||||
$results->getCollection()->transform(function ($item) use ($secret_key) {
|
||||
// Generate the token with the timestamp
|
||||
$expiry_time = time() + 86400; // Token expiry time (1 day)
|
||||
$token = hash_hmac('sha256', $item->id . $expiry_time, $secret_key);
|
||||
|
||||
// Construct the download link
|
||||
$path = 'prescription/barcode-print-pdf/' . $item->id . '?token=' . urlencode($token) . '&expiry=' . $expiry_time;
|
||||
$host = $_SERVER['HTTP_HOST']; // This will give you the host like 'linksehat.dev' or 'linksehat.com'
|
||||
$base_url = "https://m.linksehat.dev/";
|
||||
// Check if the host contains '.dev'
|
||||
if (strpos($host, '.com') !== false) {
|
||||
$base_url = "https://m.linksehat.com/";
|
||||
}
|
||||
$item->link_download = $base_url.$path;
|
||||
|
||||
return $item;
|
||||
});
|
||||
|
||||
$apotekIds = $results->pluck(value: 'nIDApotek')->unique()->filter();
|
||||
$organizations = DB::connection('mysql')->table('organizations')
|
||||
->whereIn('id', $apotekIds)
|
||||
->pluck('name', 'id');
|
||||
$results->getCollection()->transform(function ($item) use ($organizations) {
|
||||
$item->apotek = $organizations->get($item->nIDApotek, '-'); // Default to 'Unknown' if not found
|
||||
return $item;
|
||||
});
|
||||
// Transform results to include allergies
|
||||
$results->getCollection()->transform(function ($item) use ($organizations) {
|
||||
// Get the allergies for each user
|
||||
$allergies = $this->getAllergies($item->nIDUser);
|
||||
|
||||
// Concatenate the allergy description
|
||||
$alergi_desc = '';
|
||||
foreach ($allergies as $row) {
|
||||
$alergi_desc .= $row->sAlergi . ' - ' . $row->sKeterangan . ', ';
|
||||
}
|
||||
|
||||
// Set apotek and allergies data
|
||||
$item->apotek = $organizations->get($item->nIDApotek, '-'); // Default to 'Unknown' if not found
|
||||
$item->alergi_desc = rtrim($alergi_desc, ', '); // Remove the trailing comma
|
||||
|
||||
return $item;
|
||||
});
|
||||
// Extract unique Prescription IDs from the results
|
||||
$prescriptionIDs = $results->pluck('id')->unique()->filter();
|
||||
|
||||
// Fetch prescription items based on Prescription IDs
|
||||
$items = DB::connection('oldlms')->table('tx_prescription_items')
|
||||
->whereIn('nIDPrescription', $prescriptionIDs)
|
||||
->select('nIDPrescription', 'sItemName', 'sSigna', 'sTiming', 'sDuration', 'nQty', 'sNote')
|
||||
->get()
|
||||
->groupBy('nIDPrescription'); // Group items by their Prescription ID
|
||||
// Final transformation: Attach prescription items to each prescription
|
||||
$results->getCollection()->transform(function ($item) use ($items) {
|
||||
$item->prescription_items = $items->get($item->id, collect())->map(function ($prescriptionItem) {
|
||||
return [
|
||||
'sItemName' => $prescriptionItem->sItemName,
|
||||
'sSigna' => $prescriptionItem->sSigna,
|
||||
'sTiming' => $prescriptionItem->sTiming,
|
||||
'sDuration' => $prescriptionItem->sDuration,
|
||||
'nQty' => $prescriptionItem->nQty,
|
||||
'sNote' => $prescriptionItem->sNote,
|
||||
];
|
||||
});
|
||||
return $item;
|
||||
});
|
||||
return response()->json(Helper::paginateResources($results));
|
||||
}
|
||||
|
||||
public function getAllergies($nIDUser) {
|
||||
return DB::connection('oldlms')
|
||||
->table('tx_alergi_users as txa')
|
||||
->join('tm_alergi as ta', 'ta.nID', '=', 'txa.nIDAlergi')
|
||||
->select('ta.sAlergi', 'ta.sKeterangan')
|
||||
->where('txa.nIDUser', $nIDUser)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
* @return Renderable
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('hospitalportal::create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @param Request $request
|
||||
* @return Renderable
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
return view('hospitalportal::show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
return view('hospitalportal::edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$data = ['sStatus' => $request->sStatus];
|
||||
$validator = Validator::make($request->all(), [
|
||||
'sStatus' => 'required|string|max:255',
|
||||
], [
|
||||
'sStatus.required' => trans('Validation.required',['attribute' => 'Status']),
|
||||
]);
|
||||
|
||||
if ($validator->fails())
|
||||
{
|
||||
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
|
||||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
// Define the valid transitions
|
||||
$valid_transitions = [
|
||||
'waiting_for_payment' => 'waiting_pharmacy',
|
||||
'waiting_pharmacy' => 'order_prepared',
|
||||
'order_prepared' => 'ready',
|
||||
'ready' => 'waiting_for_courir',
|
||||
'waiting_for_courir' => 'package_picked_up',
|
||||
'package_picked_up' => 'package_on_delivery',
|
||||
'package_on_delivery' => 'package_delivered'
|
||||
];
|
||||
|
||||
// Get the current status from the request
|
||||
$inputStatus = $request->sStatus;
|
||||
|
||||
// Check if the input status has a valid next status in the map
|
||||
if (isset($valid_transitions[$inputStatus])) {
|
||||
// Get the next status
|
||||
$status = $valid_transitions[$inputStatus];
|
||||
|
||||
// Start the transaction
|
||||
DB::connection('oldlms')->beginTransaction();
|
||||
|
||||
// Update the status in the database
|
||||
DB::connection('oldlms')->table('tx_prescription_orders')
|
||||
->where('tx_prescription_orders.nID', '=', $id)
|
||||
->update([
|
||||
'sStatus' => $status,
|
||||
'sUpdateBy' => auth()->user()->id,
|
||||
'dUpdateOn' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
// Insert the log
|
||||
$prescriptionOrder = DB::connection('oldlms')
|
||||
->table('tx_prescription_orders')
|
||||
->where('tx_prescription_orders.nID', '=', $id)
|
||||
->join('tx_delivery_orders', 'tx_delivery_orders.nIDPrescriptionOrder', '=', 'tx_prescription_orders.nID')
|
||||
->select('tx_prescription_orders.*', 'tx_delivery_orders.*', 'tx_delivery_orders.nID as nIDDelivery') // Add specific columns you want to select
|
||||
->first();
|
||||
|
||||
if ($prescriptionOrder) {
|
||||
$createdBy = $prescriptionOrder->sCreateBy;
|
||||
$nIDPrescription = $prescriptionOrder->nIDPrescription;
|
||||
$nIDDeliveryOrder = $prescriptionOrder->nIDDelivery;
|
||||
|
||||
// Insert data into the tx_delivery_log table
|
||||
DB::connection('oldlms')->table('tx_delivery_log')->insert([
|
||||
'sStatus' => $prescriptionOrder->sDeliveryStatus,
|
||||
'sStatusPrescription' => $status,
|
||||
'nIDDeliveryOrder' => $nIDDeliveryOrder,
|
||||
'nIDPrescription' => $nIDPrescription,
|
||||
'dCreatedOn' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
DB::connection('oldlms')->commit();
|
||||
|
||||
// Return success response
|
||||
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
|
||||
} else {
|
||||
// If the input status is not valid, return an error
|
||||
return ApiResponse::apiResponse('Invalid Status', $data, 'The input status is not valid.', 400);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Rollback the transaction if an error occurs
|
||||
DB::connection('oldlms')->rollBack();
|
||||
|
||||
// Handle error, could log or return as response
|
||||
return ApiResponse::apiResponse('Server Error', $data, $e->getMessage(), 500);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function getDriver(Request $request, $id)
|
||||
{
|
||||
$data = ['sStatus' => $request->sStatus];
|
||||
|
||||
// Validation
|
||||
$validator = Validator::make($request->all(), [
|
||||
'sStatus' => 'required|string|max:255',
|
||||
], [
|
||||
'sStatus.required' => trans('Validation.required', ['attribute' => 'Status']),
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
|
||||
}
|
||||
|
||||
try {
|
||||
// Fetch prescription data
|
||||
$prescriptions = DB::connection('oldlms')->table('tx_prescription_orders')
|
||||
->leftJoin('tx_prescriptions', 'tx_prescriptions.nID', '=', 'tx_prescription_orders.nIDPrescription')
|
||||
->where('tx_prescription_orders.nID', '=', $id)
|
||||
->select(
|
||||
'tx_prescriptions.nIDUser',
|
||||
'tx_prescriptions.nID as id_prescription',
|
||||
'tx_prescriptions.sKodeResep as merchantOrderID',
|
||||
'tx_prescription_orders.nIDApotek'
|
||||
)
|
||||
->first();
|
||||
|
||||
if (!$prescriptions) {
|
||||
return ApiResponse::apiResponse('Not Found', [], 'Prescription not found', 404);
|
||||
}
|
||||
|
||||
// Fetch prescription items (medicine data)
|
||||
$items = DB::connection('oldlms')->table('tx_prescription_items')
|
||||
->where('nIDPrescription', $prescriptions->id_prescription)
|
||||
->select('nIDPrescription', 'sItemName', 'nQty', 'nHarga')
|
||||
->get();
|
||||
|
||||
$packages = [];
|
||||
foreach ($items as $item) {
|
||||
$packages[] = [
|
||||
'name' => $item->sItemName,
|
||||
'description' => $item->sItemName,
|
||||
'quantity' => (float)$item->nQty,
|
||||
'price' => (float)$item->nHarga,
|
||||
'dimensions' => [
|
||||
'height' => 0,
|
||||
'width' => 0,
|
||||
'depth' => 0,
|
||||
'weight' => 0,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Fetch pharmacy (apotek) data
|
||||
$apotek = DB::connection('mysql')->table('organizations')
|
||||
->leftJoin('addresses', 'addresses.id', '=', 'organizations.main_address_id')
|
||||
->where('organizations.id', '=', $prescriptions->nIDApotek)
|
||||
->select('organizations.name as nama_apotek', 'addresses.text as alamat_apotek', 'addresses.lat', 'addresses.lng')
|
||||
->first();
|
||||
|
||||
// Fetch patient (pasien) data
|
||||
$pasien = DB::connection('oldlms')->table('tm_users')
|
||||
->leftJoin('tm_users_detail', 'tm_users_detail.nIDuser', '=', 'tm_users.nID')
|
||||
->where('tm_users.nID', '=', $prescriptions->nIDUser)
|
||||
->select(
|
||||
DB::raw('CONCAT(
|
||||
COALESCE(tm_users.sFirstName, ""),
|
||||
" ",
|
||||
COALESCE(tm_users.sMiddleName, ""),
|
||||
" ",
|
||||
COALESCE(tm_users.sLastName, "")
|
||||
) as nama_pasien'),
|
||||
'tm_users.sFirstName as firstname',
|
||||
'tm_users.sLastName as lastname',
|
||||
'tm_users.sEmail as email',
|
||||
'tm_users.sPhone as phone',
|
||||
'tm_users_detail.sLatitude as latitude',
|
||||
'tm_users_detail.sLongitude as longitude',
|
||||
DB::raw('(SELECT tm_provinsi.sProvinsi FROM tm_provinsi WHERE tm_provinsi.nID = tm_users_detail.nIDProvinsi LIMIT 1) AS provinsi'),
|
||||
DB::raw('(SELECT tm_kota.sKota FROM tm_kota WHERE tm_kota.nID = tm_users_detail.nIDKota LIMIT 1) AS kota'),
|
||||
DB::raw('(SELECT tm_kecamatan.sKecamatan FROM tm_kecamatan WHERE tm_kecamatan.nID = tm_users_detail.nIDKecamatan LIMIT 1) AS kecamatan'),
|
||||
DB::raw('(SELECT tm_kelurahan.sKelurahan FROM tm_kelurahan WHERE tm_kelurahan.nID = tm_users_detail.nIDKelurahan LIMIT 1) AS kelurahan'),
|
||||
DB::raw('(SELECT tm_kelurahan.nKodePos FROM tm_kelurahan WHERE tm_kelurahan.nID = tm_users_detail.nIDKelurahan LIMIT 1) AS kode_pos')
|
||||
)
|
||||
->first();
|
||||
|
||||
if (!$pasien) {
|
||||
return ApiResponse::apiResponse('Not Found', [], 'Patient not found', 404);
|
||||
}
|
||||
|
||||
if(!$pasien->email)
|
||||
{
|
||||
return ApiResponse::apiResponse('Not Found', [], 'Email Patient not found', 404);
|
||||
}
|
||||
|
||||
if(!$pasien->phone)
|
||||
{
|
||||
return ApiResponse::apiResponse('Not Found', [], 'Phone Patient not found', 404);
|
||||
}
|
||||
|
||||
// Use GrabHelper to handle the API calls
|
||||
$grabHelper = new GrabHelper();
|
||||
$token = $grabHelper->getToken();
|
||||
$serviceType = 'INSTANT';
|
||||
$body = json_encode([
|
||||
"merchantOrderID" => $prescriptions->merchantOrderID,
|
||||
"serviceType" => $serviceType,
|
||||
"vehicleType" => "BIKE",
|
||||
"codType" => "REGULAR",
|
||||
"paymentMethod" => "CASHLESS",
|
||||
"highValue" => false,
|
||||
"packages" => $packages,
|
||||
"origin" => [
|
||||
"address" => $apotek->alamat_apotek,
|
||||
"coordinates" => [
|
||||
"latitude" => (float)$apotek->lat,
|
||||
"longitude" => (float)$apotek->lng
|
||||
]
|
||||
],
|
||||
"destination" => [
|
||||
"address" => "{$pasien->provinsi}, {$pasien->kota}, {$pasien->kecamatan}, {$pasien->kelurahan}, {$pasien->kode_pos}",
|
||||
"coordinates" => [
|
||||
"latitude" => (float)$pasien->latitude,
|
||||
"longitude" => (float)$pasien->longitude
|
||||
]
|
||||
],
|
||||
"recipient" => [
|
||||
"firstName" => $pasien->firstname,
|
||||
"lastName" => $pasien->lastname,
|
||||
"email" => $pasien->email,
|
||||
"phone" => $grabHelper->normalizePhoneNumber($pasien->phone),
|
||||
"smsEnabled" => true
|
||||
],
|
||||
"sender" => [
|
||||
"firstName" => env('SENDER_NAME_GRAB'),
|
||||
"companyName" => env('SENDER_COMPANY_NAME_GRAB'),
|
||||
"email" => env('SENDER_EMAIL_GRAB'),
|
||||
"phone" => env('SENDER_PHONE_GRAB'),
|
||||
"smsEnabled" => true
|
||||
],
|
||||
"schedule" => $grabHelper->getScheduleTimes()
|
||||
]);
|
||||
|
||||
// Create the delivery request
|
||||
$response = $grabHelper->createDelivery($token, $body);
|
||||
$data_grab = json_decode($response, true);
|
||||
|
||||
// Transaction to update status
|
||||
DB::connection('oldlms')->beginTransaction();
|
||||
|
||||
//insert to api logs
|
||||
$data_logs = [
|
||||
'sType' => 'out',
|
||||
'sContext' => 'grab',
|
||||
'sTarget' => 'deliveries/create-grab',
|
||||
'sRequest' => $body,
|
||||
'sResponse' => $response,
|
||||
'sCreateBy' => auth()->user()->id,
|
||||
'dCreateOn' => now(),
|
||||
];
|
||||
|
||||
DB::connection('oldlms')->table('api_logs')
|
||||
->insert($data_logs);
|
||||
|
||||
|
||||
DB::connection('oldlms')->table('tx_prescription_orders')
|
||||
->where('tx_prescription_orders.nID', '=', $id)
|
||||
->update([
|
||||
'nDeliveryID' => $data_grab['deliveryID'],
|
||||
'sDeliveryStatus' => $data_grab['status'],
|
||||
'sStatus' => 'waiting_for_courir',
|
||||
'sUpdateBy' => auth()->user()->id,
|
||||
'dUpdateOn' => now(),
|
||||
]);
|
||||
//insert to delivery order
|
||||
$tm_delivery_statuses = DB::connection('oldlms')->table('tm_delivery_statuses')
|
||||
->where('tm_delivery_statuses.sStatus', 'LIKE', '%' . $data_grab['status'] . '%')
|
||||
->where('tm_delivery_statuses.nIDDelivery', '=', 3)
|
||||
->select('tm_delivery_statuses.sStatusDescription')
|
||||
->first();
|
||||
$data_delivery_orders = [
|
||||
'nIDPrescriptionOrder' => $id,
|
||||
'sUUID' => $this->generateUuid($id),
|
||||
'nIDDelivery' => 3, //grab
|
||||
'sType' => $serviceType,
|
||||
'nOrderID' => $data_grab['deliveryID'],
|
||||
'nVehicleTypeID' => null,
|
||||
'sCreatedDateTime' => $data_grab['schedule']['pickupTimeFrom'],
|
||||
'sFinishDateTime' => $data_grab['schedule']['pickupTimeTo'],
|
||||
'sStatus' => $data_grab['status'],
|
||||
'sStatusDescription' => $tm_delivery_statuses->sStatusDescription,
|
||||
'sMatter' => 'medicine',
|
||||
'nTotalWeightKg' => 0,
|
||||
'nPaymentAmount' => $data_grab['quote']['amount'],
|
||||
'nDeliveryFeeAmount' => $data_grab['quote']['amount'],
|
||||
'sPaymentMethod' => 'cash',
|
||||
'sCreateBy' => auth()->user()->id,
|
||||
'dCreateOn' => now(),
|
||||
];
|
||||
// Use insertGetId to insert the data and get the last inserted ID
|
||||
$lastInsertId = DB::connection('oldlms')->table('tx_delivery_orders')->insertGetId($data_delivery_orders);
|
||||
$data_points = [
|
||||
'origin' => [
|
||||
'nIDDeliveryOrder' => $lastInsertId,
|
||||
'sUUID' => $this->generateUuid($lastInsertId),
|
||||
'nDeliveryID' => $data_grab['deliveryID'],
|
||||
'nPointID' => 1,
|
||||
'nType' => 1,
|
||||
'sAddress' => $data_grab['quote']['origin']['address'],
|
||||
'nLatitude' => $data_grab['quote']['origin']['coordinates']['latitude'] ?? null,
|
||||
'nLongitude' => $data_grab['quote']['origin']['coordinates']['longitude'] ?? null,
|
||||
'sName' => $data_grab['sender']['companyName'],
|
||||
'sPhone' => $data_grab['sender']['phone'],
|
||||
'sTrackingUrl' => null,
|
||||
'sCreateBy' => auth()->user()->id,
|
||||
'dCreateOn' => now(),
|
||||
],
|
||||
'destination' => [
|
||||
'nIDDeliveryOrder' => $lastInsertId,
|
||||
'sUUID' => $this->generateUuid($lastInsertId),
|
||||
'nDeliveryID' => $data_grab['deliveryID'],
|
||||
'nPointID' => 2,
|
||||
'nType' => 2,
|
||||
'sAddress' => $data_grab['quote']['destination']['address'],
|
||||
'nLatitude' => $data_grab['quote']['destination']['coordinates']['latitude'] ?? null,
|
||||
'nLongitude' => $data_grab['quote']['destination']['coordinates']['longitude'] ?? null,
|
||||
'sName' => $data_grab['recipient']['firstName'] . " " . $data_grab['recipient']['lastName'],
|
||||
'sPhone' => $data_grab['recipient']['phone'],
|
||||
'sTrackingUrl' => null,
|
||||
'sCreateBy' => auth()->user()->id,
|
||||
'dCreateOn' => now(),
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($data_points as $value_point) {
|
||||
DB::connection('oldlms')->table('tx_delivery_order_points')->insert($value_point);
|
||||
}
|
||||
|
||||
DB::connection('oldlms')->commit();
|
||||
|
||||
// Return success response
|
||||
return ApiResponse::apiResponse("Success", $data_grab, trans('Message.success'), 200);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Rollback transaction on error
|
||||
DB::connection('oldlms')->rollBack();
|
||||
|
||||
return ApiResponse::apiResponse('Server Error', [], $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function generateUuid($id_prescription_order)
|
||||
{
|
||||
// Define the namespace (using DNS in this example)
|
||||
$namespace = Uuid::NAMESPACE_DNS;
|
||||
|
||||
$uuidV5 = Uuid::uuid5($namespace, $id_prescription_order);
|
||||
return $uuidV5->toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,8 +7,10 @@ use Modules\HospitalPortal\Http\Controllers\Api\MemberController;
|
||||
use Modules\HospitalPortal\Http\Controllers\ClaimController;
|
||||
use Modules\HospitalPortal\Http\Controllers\Api\NotificationController;
|
||||
use Modules\HospitalPortal\Http\Controllers\Api\RequestLogController;
|
||||
use Modules\HospitalPortal\Http\Controllers\ApotekController;
|
||||
use Modules\HospitalPortal\Http\Middleware\Authentication;
|
||||
use Modules\HospitalPortal\Http\Middleware\Authorization;
|
||||
use Modules\Internal\Http\Controllers\Api\NavigationController;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -36,6 +38,10 @@ Route::prefix('v1')->group(function() {
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
|
||||
// Navigation
|
||||
Route::get('navigations', [NavigationController::class, 'index']);
|
||||
|
||||
|
||||
Route::post('logout', [AuthController::class, 'logout'])->name('logout');
|
||||
Route::get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
@@ -66,6 +72,9 @@ Route::prefix('v1')->group(function() {
|
||||
//Set read notification
|
||||
Route::post('set-read-notification', 'setReadNotification');
|
||||
});
|
||||
Route::get('get-prescription-orders',[ApotekController::class, 'index']);
|
||||
Route::put('put-prescription-orders/{id}',[ApotekController::class, 'update']);
|
||||
Route::put('put-driver-prescription-orders/{id}',[ApotekController::class, 'getDriver']);
|
||||
});
|
||||
// Request Final LOG
|
||||
Route::controller(RequestLogController::class)->group(function () {
|
||||
|
||||
@@ -26,7 +26,14 @@ class PrescriptionController extends Controller
|
||||
{
|
||||
// return $request->toArray();
|
||||
$prescription = Prescription::query()
|
||||
->with(['livechat', 'user', 'items']);
|
||||
->with(['livechat', 'user', 'items'])
|
||||
->join('tx_prescription_orders', 'tx_prescriptions.nID', '=', 'tx_prescription_orders.nIDPrescription')
|
||||
->select(
|
||||
'tx_prescriptions.*',
|
||||
'tx_prescription_orders.sStatus as status_prescription',
|
||||
'tx_prescription_orders.sAddress as kirim_ke',
|
||||
'tx_prescription_orders.sDeliveryMethod as delivery',
|
||||
);
|
||||
if ($request->has('search')) {
|
||||
$search = $request->search;
|
||||
$prescription->where(function ($query) use ($search) {
|
||||
@@ -34,13 +41,12 @@ class PrescriptionController extends Controller
|
||||
->orWhere('sKodeResep', 'LIKE', '%' . $search . "%");
|
||||
});
|
||||
}
|
||||
|
||||
if (($request->has('prescription_start') || $request->has('prescription_end'))
|
||||
&& !empty($request->prescription_start)
|
||||
&& !empty($request->prescription_end)
|
||||
) {
|
||||
|
||||
|
||||
|
||||
|
||||
$prescription = $prescription->where(function($q) use ($request) {
|
||||
$q->where('dTanggalResep', '>=', $request->prescription_start)
|
||||
->where('dTanggalResep', '<=', $request->prescription_end);
|
||||
@@ -156,6 +162,7 @@ class PrescriptionController extends Controller
|
||||
'Date Consultation',
|
||||
'Patient',
|
||||
'Doctor',
|
||||
'Status',
|
||||
'Jenis Obat (Drugs)',
|
||||
'Jumlah Obat (QTY)',
|
||||
'Cara Minum Obat',
|
||||
@@ -178,7 +185,7 @@ class PrescriptionController extends Controller
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->has('prescription_start') && $request->has('prescription_end') &&
|
||||
if ($request->has('prescription_start') && $request->has('prescription_end') &&
|
||||
!empty($request->prescription_start) && !empty($request->prescription_end)) {
|
||||
$prescriptionQuery->whereBetween('dTanggalResep', [$request->prescription_start, $request->prescription_end]);
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ class LivechatController extends Controller
|
||||
}
|
||||
})
|
||||
->orderBy('nID', 'desc')
|
||||
->get(['nID', 'nIDUser', 'dRequestTime', 'dAcceptTime', 'dStartTime', 'dEndTime', 'nIDDokter', 'nIDHealthCare', 'nIDAppointment', 'sStatus', 'sMediaDokter', 'sMedia', 'dCreateOn']);
|
||||
|
||||
->get(['nID', 'nIDUser', 'nIDDokter', 'nIDHealthCare', 'nIDAppointment', 'sStatus', 'sMediaDokter', 'sMedia', 'dCreateOn']);
|
||||
|
||||
$headers = [
|
||||
['value' => 'No', 'cell' => 'A1', 'mergeCell' => true, 'mergeToCell' => 'A2'],
|
||||
['value' => 'Kode TC', 'cell' => 'B1', 'mergeCell' => true, 'mergeToCell' => 'B2'],
|
||||
@@ -150,18 +150,18 @@ class LivechatController extends Controller
|
||||
$nIDUser = $liveChat->user->nIDUser ?? 0; // Principal or Dependent
|
||||
$paymentMethod = $liveChat->appointment ? Helper::sPaymentMethod($liveChat->appointment->sPaymentMethod) : 'N/A';
|
||||
$fullNameDoctor = '-';
|
||||
if ($liveChat->doctor->user !== null) {
|
||||
if (!empty($liveChat->doctor->user)) {
|
||||
$fullNameDoctor = '';
|
||||
|
||||
|
||||
if ($liveChat->doctor->user->detail !== null) {
|
||||
if ($liveChat->doctor->user->detail->sTitlePrefix !== null) {
|
||||
$fullNameDoctor .= $liveChat->doctor->user->detail->sTitlePrefix . '. ';
|
||||
}
|
||||
|
||||
|
||||
if ($liveChat->doctor->user->full_name !== null) {
|
||||
$fullNameDoctor .= $liveChat->doctor->user->full_name . ' ';
|
||||
}
|
||||
|
||||
|
||||
if ($liveChat->doctor->user->detail->sTitleSuffix !== null) {
|
||||
$fullNameDoctor .= $liveChat->doctor->user->detail->sTitleSuffix;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ class LivechatController extends Controller
|
||||
$recordType = 'P';
|
||||
if ($nIDUser){
|
||||
$recordType = 'D';
|
||||
}
|
||||
}
|
||||
switch ($status) {
|
||||
case 0:
|
||||
$statusLivechat = "Request TC";
|
||||
|
||||
@@ -54,6 +54,7 @@ class NavigationController extends Controller
|
||||
'permission' => $child['permission'],
|
||||
];
|
||||
}, $navItem['children']),
|
||||
'icon' => $navItem['icon'],
|
||||
'permission' => $navItem['permission'],
|
||||
];
|
||||
}, $navigationMaster)
|
||||
|
||||
@@ -48,6 +48,8 @@ class OrganizationController extends Controller
|
||||
public function store(Request $request)
|
||||
{
|
||||
$organization = [
|
||||
'phone' => $request->no_hp,
|
||||
'email' => $request->email,
|
||||
'code' => $request->code,
|
||||
'name' => $request->name,
|
||||
'type' => 'hospital',
|
||||
@@ -119,6 +121,8 @@ class OrganizationController extends Controller
|
||||
$update_organization = Organization::find($id);
|
||||
|
||||
$update_organization->update([
|
||||
'phone' => $request->no_hp,
|
||||
'email' => $request->email,
|
||||
'code' => $request->code,
|
||||
'name' => $request->name,
|
||||
'type' => 'hospital',
|
||||
@@ -152,7 +156,7 @@ class OrganizationController extends Controller
|
||||
'lat' => $request->lat,
|
||||
'lng' => $request->lng,
|
||||
]);
|
||||
|
||||
|
||||
$update_organization->main_address_id = $newAddres->id;
|
||||
$update_organization->save();
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace Modules\Internal\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Organization;
|
||||
use App\Models\CorporateManager;
|
||||
use Illuminate\Contracts\Support\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
@@ -110,14 +112,30 @@ class UserManagementController extends Controller
|
||||
return response()->json($data);
|
||||
}
|
||||
|
||||
public function list_organization(Request $request)
|
||||
{
|
||||
$query = Organization::where('type', 'hospital')->get();
|
||||
$data = [
|
||||
'data' => $query
|
||||
];
|
||||
return response()->json($data);
|
||||
}
|
||||
|
||||
public function store_access(Request $request){
|
||||
$user = User::create([
|
||||
'email' => $request->email,
|
||||
'username' => $request->username,
|
||||
'role_id' => $request->roles,
|
||||
'organization_id' => !empty($request->organizations) ? $request->organizations : null ,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
if ($request->corporates){
|
||||
CorporateManager::create([
|
||||
'user_id' => $user->id,
|
||||
'corporate_id' => $request->corporates
|
||||
]);
|
||||
}
|
||||
$person = Person::updateOrCreate(
|
||||
[
|
||||
'id' => $user->person_id
|
||||
@@ -164,6 +182,7 @@ class UserManagementController extends Controller
|
||||
$userAccess->email = $request->email;
|
||||
$userAccess->username = $request->username;
|
||||
$userAccess->role_id = $request->roles;
|
||||
$userAccess->organization_id = $request->organizations;
|
||||
|
||||
if ($request->password){
|
||||
$userAccess->password = Hash::make($request->password);
|
||||
|
||||
@@ -50,6 +50,7 @@ use Modules\Internal\Http\Controllers\Api\LaboratoriumResultController;
|
||||
use Modules\Internal\Http\Controllers\Api\CorporateManageController;
|
||||
use Modules\Internal\Http\Controllers\Api\UserManagementController;
|
||||
use Modules\Internal\Http\Controllers\ClaimEncounterController;
|
||||
use Modules\Linksehat\Http\Controllers\Api\AutocompleteController;
|
||||
|
||||
// Report
|
||||
use Modules\Internal\Http\Controllers\Api\ReportLogController;
|
||||
@@ -80,9 +81,12 @@ Route::prefix('internal')->group(function () {
|
||||
|
||||
|
||||
Route::get('diagnosis', [RequestLogController::class, 'diagnosis']);
|
||||
Route::get('drugs', [DrugController::class, 'drugList']);
|
||||
Route::get('units', [DrugController::class, 'unitList']);
|
||||
Route::get('cekphp', [RequestLogController::class, 'cekphp']);
|
||||
Route::get('drugs', [AutocompleteController::class, 'drugList']);
|
||||
Route::get('units', [AutocompleteController::class, 'unitList']);
|
||||
|
||||
|
||||
Route::get('signa', [AutocompleteController::class, 'signaList']);
|
||||
Route::post('signa-add', [AutocompleteController::class, 'signaAdd']);
|
||||
|
||||
|
||||
|
||||
@@ -395,6 +399,7 @@ Route::prefix('internal')->group(function () {
|
||||
Route::get('user/access/{id}', [UserManagementController::class, 'edit_access']);
|
||||
Route::put('user/access/{id}', [UserManagementController::class, 'update_access']);
|
||||
Route::get('role-list', [UserManagementController::class, 'list_role']);
|
||||
Route::get('organization-list', [UserManagementController::class, 'list_organization']);
|
||||
|
||||
// Navigation
|
||||
Route::get('navigations', [NavigationController::class, 'index']);
|
||||
|
||||
@@ -27,12 +27,14 @@ class OrganizationResource extends JsonResource
|
||||
}
|
||||
$corporatePartner = implode(', ', $corporateName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
$organization = [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'type' => $this->type,
|
||||
'no_hp' => $this->phone,
|
||||
'email' => $this->email,
|
||||
'code' => $this->code,
|
||||
'description' => $this->description,
|
||||
'kodeRs' => $this->meta->KodeRS ?? null,
|
||||
|
||||
@@ -16,7 +16,6 @@ class ReportPrescriptionResource extends JsonResource
|
||||
public function toArray($request)
|
||||
{
|
||||
$patientName = $this->user ? $this->user->sFirstName .' '. $this->user->sLastName : '-';
|
||||
|
||||
$data = [
|
||||
'id' => $this->nID,
|
||||
'patient_name' => $patientName,
|
||||
@@ -25,6 +24,7 @@ class ReportPrescriptionResource extends JsonResource
|
||||
'date_consultation' => $this->dTanggalResep ? Carbon::parse($this->dTanggalResep)->format('Y-m-d H:i:s') : null,
|
||||
'doctor_name' => $this->sDokterName ? $this->sDokterName : '-',
|
||||
'items' => $this->items ? $this->items : [],
|
||||
'status_prescription' => $this->status_prescription
|
||||
];
|
||||
|
||||
return $data;
|
||||
|
||||
@@ -111,18 +111,23 @@ class AutocompleteController extends Controller {
|
||||
return Helper::responseJson(data: $manipulatedIcds);
|
||||
}
|
||||
|
||||
|
||||
public function drugList(Request $request){
|
||||
|
||||
$drugs = Drug::query()
|
||||
->where([
|
||||
'atc_code' => 'lms', // ini untuk menggunakan list obat yang baru
|
||||
'atc_code' => $request->provider, // ini untuk menggunakan list obat yang baru
|
||||
])
|
||||
->get();
|
||||
|
||||
$manipulatedDrugs = $drugs->map(function ($drug) {
|
||||
// Contoh manipulasi, tambahkan atau ubah properti sesuai kebutuhan
|
||||
return [
|
||||
'value' => $drug->id, // Ganti dengan properti yang sesuai dari model Icd
|
||||
'label' => $drug->name, // Ganti dengan properti yang sesuai dari model Icd
|
||||
'value' => $drug->id,
|
||||
'label' => $drug->name,
|
||||
'code' => $drug->code,
|
||||
'price' => $drug->price,
|
||||
'unit' => $drug->unit,
|
||||
];
|
||||
});
|
||||
return Helper::responseJson(data: $manipulatedDrugs);
|
||||
@@ -142,5 +147,38 @@ class AutocompleteController extends Controller {
|
||||
return Helper::responseJson(data: $manipulatedUnits);
|
||||
}
|
||||
|
||||
public function signaList(Request $request){
|
||||
$signa = DB::connection('oldlms')->table('tm_signa')->get()->toArray();
|
||||
$data = [];
|
||||
|
||||
if ($signa){
|
||||
$temp = [];
|
||||
foreach($signa as $d){
|
||||
$temp['id'] = $d->nID;
|
||||
$temp['value'] = $d->signa;
|
||||
$temp['label'] = $d->signa;
|
||||
|
||||
array_push($data, $temp);
|
||||
}
|
||||
|
||||
}
|
||||
return Helper::responseJson($data);
|
||||
}
|
||||
|
||||
public function signaAdd(Request $request){
|
||||
$validatedData = $request->validate([
|
||||
'signa' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
// Insert the new signa into the tm_signa table
|
||||
DB::connection('oldlms')->table('tm_signa')->insert([
|
||||
'sStatusPernikahan' => $validatedData['signa']
|
||||
]);
|
||||
|
||||
// Return a success response
|
||||
return Helper::responseJson(['message' => 'Signa added successfully']);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ class Organization extends Model
|
||||
'corporate_id_partner',
|
||||
'phone',
|
||||
'email',
|
||||
'operational_day',
|
||||
'operational_hour',
|
||||
'operational_day_other',
|
||||
'operational_hour_other',
|
||||
];
|
||||
|
||||
// public $with = [
|
||||
|
||||
@@ -25,6 +25,7 @@ class User extends Authenticatable
|
||||
|
||||
protected $connection = 'mysql';
|
||||
protected $fillable = [
|
||||
'organization_id',
|
||||
'person_id',
|
||||
'name',
|
||||
'email',
|
||||
|
||||
11983
composer.lock
generated
11983
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'server_key' => env('FCM_SERVER_KEY'),
|
||||
];
|
||||
@@ -281,7 +281,27 @@ class NavigationSeeder extends Seeder
|
||||
]
|
||||
],
|
||||
'permission' => 'user-management-client-portal'
|
||||
]
|
||||
],
|
||||
####################### HOSPITAL PORTAL #########################
|
||||
[
|
||||
'title' => 'Dashboard',
|
||||
'path' => '/dashboard',
|
||||
'icon' => 'dashboard',
|
||||
'permission' => 'dashboard-hospital-portal'
|
||||
],
|
||||
[
|
||||
'title' => 'Claim',
|
||||
'path' => '/claim',
|
||||
'icon' => 'ic_booking',
|
||||
'permission' => 'dashboard-claim-hospital-portal'
|
||||
],
|
||||
####################### CS LMS & APOTEK PORTAL #########################
|
||||
[
|
||||
'title' => 'Dashboard',
|
||||
'path' => '/prescription-orders',
|
||||
'icon' => 'dashboard',
|
||||
'permission' => 'dashboard-apotek-portal'
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($menuItems as $menuItemData) {
|
||||
@@ -292,6 +312,7 @@ class NavigationSeeder extends Seeder
|
||||
[
|
||||
'title' => $menuItemData['title'],
|
||||
'path' => $menuItemData['path'] ?? null,
|
||||
'icon' => $menuItemData['icon'] ?? null,
|
||||
'permission' => $menuItemData['permission'] ?? null
|
||||
]);
|
||||
|
||||
@@ -304,6 +325,7 @@ class NavigationSeeder extends Seeder
|
||||
[
|
||||
'title' => $childData['title'],
|
||||
'path' => $childData['path'] ?? null,
|
||||
'icon' => $childData['icon'] ?? null,
|
||||
'parent_id' => $menuItem->id,
|
||||
'permission' => $childData['permission'] ?? null
|
||||
]);
|
||||
|
||||
@@ -89,14 +89,27 @@ class PermissionTableSeeder extends Seeder
|
||||
'service-monitoring-limit-client-portal',
|
||||
'user-management-client-portal',
|
||||
'user-role-list-client-portal',
|
||||
'user-access-list-client-portal'
|
||||
'user-access-list-client-portal',
|
||||
'file-billing-client-portal',
|
||||
'file-diagnosis-client-portal',
|
||||
'file-pendukung-medis-client-portal',
|
||||
'benefit-client-portal',
|
||||
]
|
||||
]
|
||||
],
|
||||
####################### HOSPITAL PORTAL #########################
|
||||
[
|
||||
'type' => 'hospital-portal',
|
||||
'datas' => [
|
||||
'dashboard-hospital-portal',
|
||||
'dashboard-claim-hospital-portal',
|
||||
'dashboard-apotek-portal',
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($permissions as $values) {
|
||||
foreach ($values['datas'] as $value) {
|
||||
Permission::updateOrCreate(['name' => $value],
|
||||
Permission::updateOrCreate(['name' => $value, 'guard_name' => $values['type']],
|
||||
[
|
||||
'name' => $value,
|
||||
'guard_name' => $values['type']
|
||||
|
||||
@@ -5,5 +5,5 @@ PORT=8083
|
||||
REACT_APP_HOST_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||
|
||||
# VITE_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||
VITE_API_URL="http://localhost:8000/api/client"
|
||||
VITE_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
GENERATE_SOURCEMAP=false
|
||||
|
||||
VITE_API_URL="https://primecenter-api.linksehat.com/api/client"
|
||||
VITE_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||
|
||||
@@ -219,7 +219,16 @@ export default function ServiceMonitoring() {
|
||||
};
|
||||
|
||||
const nameToCheck = 'service-monitoring-limit-client-portal';
|
||||
const fileBillingCheck = 'file-billing-client-portal';
|
||||
const fileDiagnosisCheck = 'file-diagnosis-client-portal';
|
||||
const filePendukungCheck = 'file-pendukung-medis-client-portal';
|
||||
const benefitCheck = 'benefit-client-portal';
|
||||
|
||||
const doesNameExist = checkIfNameExists(nameToCheck);
|
||||
const viewfileBilling = checkIfNameExists(fileBillingCheck);
|
||||
const viewfileDiagnosis = checkIfNameExists(fileDiagnosisCheck);
|
||||
const viewfilePendukungCheck = checkIfNameExists(filePendukungCheck);
|
||||
const viewBenefitCheck = checkIfNameExists(benefitCheck);
|
||||
const navigate = useNavigate();
|
||||
const controller = new AbortController();
|
||||
|
||||
@@ -283,6 +292,8 @@ export default function ServiceMonitoring() {
|
||||
const formatNumber = (number) => {
|
||||
return new Intl.NumberFormat('id-ID').format(number);
|
||||
};
|
||||
|
||||
console.log(viewfileBilling, 'test')
|
||||
const LimitPlanCard = ({ title, current, total }) => (
|
||||
<Card variant="outlined" sx={{ minWidth: 200, m: 1 }}>
|
||||
<CardContent>
|
||||
@@ -581,6 +592,37 @@ export default function ServiceMonitoring() {
|
||||
(
|
||||
data.files.result.map((file, index) =>
|
||||
(
|
||||
file.type == 'final-log-result' && viewfilePendukungCheck ?
|
||||
(
|
||||
<Stack direction="column" spacing={2} key={index}>
|
||||
<Stack direction="row" spacing={1} sx={{color: '#19BBBB'}}>
|
||||
<a
|
||||
href={file.url}
|
||||
download={file.original_name ? file.original_name : 'test'}
|
||||
style={{ cursor: 'pointer', textDecoration: 'none', color: '#19BBBB' }}
|
||||
target="_blank"
|
||||
>
|
||||
<Typography variant="body2" gutterBottom>{file.original_name ? file.original_name : '-'}</Typography>
|
||||
</a>
|
||||
</Stack>
|
||||
</Stack>
|
||||
) :
|
||||
file.type == 'final-log-diagnosis' && viewfileDiagnosis ?
|
||||
(
|
||||
<Stack direction="column" spacing={2} key={index}>
|
||||
<Stack direction="row" spacing={1} sx={{color: '#19BBBB'}}>
|
||||
<a
|
||||
href={file.url}
|
||||
download={file.original_name ? file.original_name : 'test'}
|
||||
style={{ cursor: 'pointer', textDecoration: 'none', color: '#19BBBB' }}
|
||||
target="_blank"
|
||||
>
|
||||
<Typography variant="body2" gutterBottom>{file.original_name ? file.original_name : '-'}</Typography>
|
||||
</a>
|
||||
</Stack>
|
||||
</Stack>
|
||||
) :
|
||||
file.type == 'final-log-kondisi' && viewfileBilling ?
|
||||
(
|
||||
<Stack direction="column" spacing={2} key={index}>
|
||||
<Stack direction="row" spacing={1} sx={{color: '#19BBBB'}}>
|
||||
@@ -595,6 +637,7 @@ export default function ServiceMonitoring() {
|
||||
</Stack>
|
||||
</Stack>
|
||||
)
|
||||
: ''
|
||||
)
|
||||
)
|
||||
) : (
|
||||
@@ -749,163 +792,171 @@ export default function ServiceMonitoring() {
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container spacing={1.5}>
|
||||
<Grid item>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Benefits'}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item container>
|
||||
{viewBenefitCheck ? (
|
||||
<Grid item container spacing={1.5}>
|
||||
<Grid item>
|
||||
{loading ? (
|
||||
<Skeleton animation="wave" width={300} />
|
||||
) : data && data.benefits && data.benefits.length > 0 ? (
|
||||
data.benefits.map((benefitValue, benefitIndex) => (
|
||||
<List
|
||||
subheader={
|
||||
<ListSubheader>
|
||||
<Typography variant="subtitle2" color={'grey.700'}>
|
||||
{benefitIndex + 1 + `. ` + benefitValue.name}
|
||||
</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
key={benefitIndex}
|
||||
>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Amount Incurred : Rp. {fSplit(benefitValue.amountIncurred)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Amount Approved : Rp {fSplit(benefitValue.amountApproved)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Amount Not Approved : Rp {fSplit(benefitValue.amountNotAprroved)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Excess Paid : Rp {fSplit(benefitValue.excessPaid)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Description : {benefitValue.description}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
</List>
|
||||
))
|
||||
) : (
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
-
|
||||
</Typography>
|
||||
)}
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Benefits'}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item container>
|
||||
<Grid item>
|
||||
{loading ? (
|
||||
<Skeleton animation="wave" width={300} />
|
||||
) : data && data.benefits && data.benefits.length > 0 ? (
|
||||
data.benefits.map((benefitValue, benefitIndex) => (
|
||||
<List
|
||||
subheader={
|
||||
<ListSubheader>
|
||||
<Typography variant="subtitle2" color={'grey.700'}>
|
||||
{benefitIndex + 1 + `. ` + benefitValue.name}
|
||||
</Typography>
|
||||
</ListSubheader>
|
||||
}
|
||||
key={benefitIndex}
|
||||
>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Amount Incurred : Rp {fSplit(benefitValue.amountApproved)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Amount Approved : Rp {fSplit(benefitValue.amountApproved)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Amount Not Approved : Rp {fSplit(benefitValue.amountNotAprroved)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Excess Paid : Rp {fSplit(benefitValue.excessPaid)}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem sx={{ paddingLeft: 4 }}>
|
||||
<ListItemText>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
color={'grey.900'}
|
||||
component={'div'}
|
||||
display="flex"
|
||||
alignItems={'center'}
|
||||
gap={1}
|
||||
>
|
||||
<CircleIcon sx={{ width: 8 }} />
|
||||
Description : {benefitValue.description}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
</List>
|
||||
))
|
||||
) : (
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
-
|
||||
</Typography>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container spacing={1.5}>
|
||||
<Grid item>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Benefits Total'}
|
||||
</Typography>
|
||||
|
||||
) : ('')
|
||||
}
|
||||
|
||||
{viewBenefitCheck ? (
|
||||
<Grid item container spacing={1.5}>
|
||||
<Grid item>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Benefits Total'}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Incurred : Rp. '}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalIncurred)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Approve : Rp. '}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalApprove)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Not Approve : Rp.'}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalNotApprove)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Excess : Rp.'}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalExcess)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Incurred : Rp. '}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalIncurred)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Approve : Rp. '}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalApprove)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Not Approve : Rp.'}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalNotApprove)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color={'grey.800'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Total Excess : Rp.'}
|
||||
{loading ? (
|
||||
<Skeleton animation={'wave'} width={300} />
|
||||
) : data && data.benefitTotal ? (
|
||||
fSplit(data.benefitTotal.totalExcess)
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item container xs={12} spacing={1.5}>
|
||||
) : ('')}
|
||||
|
||||
<Grid item container xs={12} spacing={1.5}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color={'grey.600'}>
|
||||
{loading ? <Skeleton animation={'wave'} width={200} /> : 'Hospital'}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export type Organizations = {
|
||||
id: number;
|
||||
code: string;
|
||||
no_hp: number;
|
||||
email: string;
|
||||
name: string;
|
||||
address: string;
|
||||
type: string;
|
||||
|
||||
@@ -134,6 +134,16 @@ export type Role = {
|
||||
permissions: number[]
|
||||
};
|
||||
|
||||
export type Organization = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type Corporate = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type Permisions = {
|
||||
name: string;
|
||||
guard_name: string;
|
||||
@@ -146,6 +156,8 @@ export type UserAccess = {
|
||||
email: string;
|
||||
person: Person;
|
||||
role: Role;
|
||||
organization_id: Organization;
|
||||
corporate_id: Corporate;
|
||||
}
|
||||
|
||||
export type Person = {
|
||||
|
||||
@@ -116,6 +116,8 @@ export default function OrganizationsForm({ isEdit, currentOrganizations }: Prop
|
||||
name: currentOrganizations?.name || '',
|
||||
code: currentOrganizations?.code || '',
|
||||
phone: currentOrganizations?.phone || '',
|
||||
no_hp: currentOrganizations?.no_hp || '',
|
||||
email: currentOrganizations?.email || '',
|
||||
lat: currentOrganizations?.lat || '',
|
||||
lng: currentOrganizations?.lng || '',
|
||||
address: currentOrganizations?.address || '',
|
||||
@@ -185,6 +187,8 @@ export default function OrganizationsForm({ isEdit, currentOrganizations }: Prop
|
||||
formData.append('name', data.name);
|
||||
formData.append('code', data.code);
|
||||
formData.append('phone', data.phone);
|
||||
formData.append('no_hp', data.no_hp);
|
||||
formData.append('email', data.email);
|
||||
formData.append('lat', data.lat);
|
||||
formData.append('lng', data.lng);
|
||||
formData.append('address', data.address);
|
||||
@@ -361,7 +365,7 @@ export default function OrganizationsForm({ isEdit, currentOrganizations }: Prop
|
||||
const findValueCorporate = selectedCorporatID.find(
|
||||
(item: any) => item.value === currentOrganizations?.corporate_id_partner
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Stack spacing={3}>
|
||||
@@ -391,6 +395,14 @@ export default function OrganizationsForm({ isEdit, currentOrganizations }: Prop
|
||||
<LabelStyle>Nomor IGD</LabelStyle>
|
||||
<RHFTextField name="phone" placeholder="Tuliskan No IGD" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<LabelStyle>No. HP</LabelStyle>
|
||||
<RHFTextField name="no_hp" placeholder="Tuliskan No. HP" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<LabelStyle>Email</LabelStyle>
|
||||
<RHFTextField name="email" placeholder="Tuliskan Email" />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<LabelStyle>Alamat</LabelStyle>
|
||||
<RHFTextField name="address" placeholder="Tuliskan Alamat" />
|
||||
|
||||
@@ -301,9 +301,21 @@ export default function List() {
|
||||
<Grid item xs={10}>
|
||||
: {row.code ? row.code : '-'}
|
||||
</Grid>
|
||||
<Grid item xs={2}>
|
||||
No. HP
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
: {row.no_hp ? row.no_hp : '-'}
|
||||
</Grid>
|
||||
<Grid item xs={2}>
|
||||
Email
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
: {row.email ? row.email : '-'}
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={2}>
|
||||
Rekanan
|
||||
Rekanan
|
||||
</Grid>
|
||||
<Grid item xs={10}>
|
||||
: {row.corporate_name ? row.corporate_name : '-'}
|
||||
|
||||
@@ -158,7 +158,6 @@ export default function List() {
|
||||
setSearchText(searchParams.get('search') ?? '');
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<form style={{ width: '100%' }}>
|
||||
@@ -337,6 +336,7 @@ export default function List() {
|
||||
<TableCell align="left">{row.date_consultation ? fDateTime(row.date_consultation) : '-'}</TableCell>
|
||||
<TableCell align="left">{row.patient_name ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.doctor_name ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.status_prescription ?? '-'}</TableCell>
|
||||
{/* <TableCell align="center">
|
||||
<ButtonGroup variant="text" aria-label="text button group">
|
||||
<Link to={'/report/appointments/' + row.id + '/show'}>
|
||||
@@ -390,7 +390,7 @@ export default function List() {
|
||||
</Collapse>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
|
||||
{/* END COLLAPSIBLE ROW */}
|
||||
|
||||
<Dialog
|
||||
@@ -542,6 +542,9 @@ export default function List() {
|
||||
<TableCell style={headStyle} align="left">
|
||||
Doctor
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Status
|
||||
</TableCell>
|
||||
{/* <TableCell style={headStyle} align="center">
|
||||
Aksi
|
||||
</TableCell> */}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {useContext, useEffect, useMemo, useState } from 'react';
|
||||
import axios from '../../../utils/axios';
|
||||
import UserAccessForm from './Form';
|
||||
import { Role, UserAccess } from '../../../@types/user';
|
||||
import Organizations from "@/pages/Master/Hospitals/Index";
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +14,8 @@ export default function UserAccessCreate() {
|
||||
const { id } = useParams();
|
||||
const [ currentUserAccess, setCurrentUserAccess ] = useState<UserAccess>();
|
||||
const [ roles, setRole ] = useState<any>();
|
||||
const [ corporate, setCorporate ] = useState<any>();
|
||||
const [ organizations, setOrganization ] = useState<any>();
|
||||
|
||||
|
||||
const navigate = useNavigate();
|
||||
@@ -40,9 +43,30 @@ export default function UserAccessCreate() {
|
||||
navigate('/404');
|
||||
}
|
||||
})
|
||||
axios.get('/organization-list')
|
||||
.then((res)=> {
|
||||
setOrganization(res.data)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response.status === 404) {
|
||||
navigate('/404');
|
||||
}
|
||||
})
|
||||
|
||||
axios.get('/corporates')
|
||||
.then((res)=> {
|
||||
setCorporate(res.data)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response.status === 404) {
|
||||
navigate('/404');
|
||||
}
|
||||
})
|
||||
|
||||
}, [id]);
|
||||
|
||||
console.log(corporate, 'test')
|
||||
|
||||
|
||||
return (
|
||||
<Page title= "User Access">
|
||||
@@ -57,7 +81,7 @@ export default function UserAccessCreate() {
|
||||
]}
|
||||
/>
|
||||
|
||||
<UserAccessForm isEdit={isEdit} currentUserAccess={currentUserAccess} roles={roles}/>
|
||||
<UserAccessForm isEdit={isEdit} currentUserAccess={currentUserAccess} roles={roles} organizations={organizations} corporate={corporate} />
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
import * as Yup from 'yup';
|
||||
import { LoadingButton } from "@mui/lab";
|
||||
import { Box, Card, Grid, Stack, Typography } from "@mui/material";
|
||||
import { Role, UserAccess } from "../../../@types/user";
|
||||
import { FormProvider, RHFSelect, RHFSwitch, RHFTextField } from "../../../components/hook-form";
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { Role, UserAccess, Organization } from "../../../@types/user";
|
||||
import { FormProvider, RHFSelect, RHFTextField } from "../../../components/hook-form";
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import axios from '../../../utils/axios';
|
||||
import palette from '@/theme/palette';
|
||||
import { Corporate } from '@/@types/corporates';
|
||||
|
||||
type Props = {
|
||||
isEdit: boolean;
|
||||
currentUserAccess?: UserAccess;
|
||||
roles: Role
|
||||
roles: Role;
|
||||
organizations: Organization;
|
||||
corporate: Corporate;
|
||||
};
|
||||
|
||||
export default function AccsessForm({ isEdit, currentUserAccess, roles }: Props) {
|
||||
export default function AccessForm({ isEdit, currentUserAccess, roles, organizations, corporate }: Props) {
|
||||
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const navigate = useNavigate();
|
||||
@@ -27,13 +30,14 @@ export default function AccsessForm({ isEdit, currentUserAccess, roles }: Props)
|
||||
name: Yup.string().required('Name is required'),
|
||||
});
|
||||
|
||||
console.log(currentUserAccess, 'test')
|
||||
const defaultValues = useMemo(
|
||||
() => ({
|
||||
name: currentUserAccess?.person?.name || '',
|
||||
username: currentUserAccess?.username || '',
|
||||
username: currentUserAccess?.username || '',
|
||||
email: currentUserAccess?.email || '',
|
||||
roles: currentUserAccess?.role?.id || [],
|
||||
roles: currentUserAccess?.role?.id || '',
|
||||
organizations: currentUserAccess?.organization_id || '',
|
||||
corporates: currentUserAccess?.corporate_id || '',
|
||||
password: '',
|
||||
}),
|
||||
[currentUserAccess]
|
||||
@@ -56,92 +60,119 @@ export default function AccsessForm({ isEdit, currentUserAccess, roles }: Props)
|
||||
const {
|
||||
reset,
|
||||
watch,
|
||||
control,
|
||||
setValue,
|
||||
getValues,
|
||||
setError,
|
||||
handleSubmit,
|
||||
setError,
|
||||
formState: { isSubmitting },
|
||||
} = methods;
|
||||
|
||||
// Watch 'roles' field to conditionally render other fields
|
||||
const selectedRole = watch('roles');
|
||||
|
||||
const onSubmit = async (data: any) => {
|
||||
|
||||
console.log(data);
|
||||
console.log(data, 'test123');
|
||||
if (!isEdit) {
|
||||
await axios
|
||||
.post('/user/access', data)
|
||||
.then((res) => {
|
||||
enqueueSnackbar('User created successfully', { variant: 'success' });
|
||||
})
|
||||
.then((res) => {
|
||||
navigate('/user-access', { replace: true });
|
||||
})
|
||||
.catch(({ response }) => {
|
||||
if (response.status === 422) {
|
||||
for (const [key, value] of Object.entries(response.data.errors)) {
|
||||
setError(key, { message: value[0] });
|
||||
enqueueSnackbar(value[0] ?? 'Failed Processing Request', { variant: 'error' });
|
||||
.post('/user/access', data)
|
||||
.then((res) => {
|
||||
enqueueSnackbar('User created successfully', { variant: 'success' });
|
||||
navigate('/user-access', { replace: true });
|
||||
})
|
||||
.catch(({ response }) => {
|
||||
if (response.status === 422) {
|
||||
for (const [key, value] of Object.entries(response.data.errors)) {
|
||||
setError(key, { message: value[0] });
|
||||
enqueueSnackbar(value[0] ?? 'Failed Processing Request', { variant: 'error' });
|
||||
}
|
||||
} else {
|
||||
enqueueSnackbar('Create Failed : ' + response.data.message, { variant: 'error' });
|
||||
}
|
||||
}
|
||||
else {
|
||||
enqueueSnackbar('Create Failed : '+ response.data.message, { variant: 'error' });
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
await axios
|
||||
.put('/user/access/' + currentUserAccess?.id, data)
|
||||
.then((res) => {
|
||||
enqueueSnackbar('User updated successfully', { variant: 'success' });
|
||||
})
|
||||
.then((res) => {
|
||||
navigate('/user-access' , { replace: true });
|
||||
navigate('/user-access', { replace: true });
|
||||
})
|
||||
.catch(({ response }) => {
|
||||
enqueueSnackbar('Update Failed : '+ response.data.message, { variant: 'error' });
|
||||
enqueueSnackbar('Update Failed : ' + response.data.message, { variant: 'error' });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const optionsRoles = roles?.data?.map(item => ({
|
||||
// Map role, organization, and corporate options
|
||||
const optionsRoles = roles?.data?.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
label: item.name,
|
||||
})) ?? [];
|
||||
|
||||
const optionsOrganization = organizations?.data?.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
})) ?? [];
|
||||
|
||||
const optionsCorporate = corporate?.data?.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
})) ?? [];
|
||||
|
||||
if (optionsRoles.length > 0) {
|
||||
optionsRoles.unshift({ value: '', label: '' });
|
||||
}
|
||||
|
||||
return (
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Box sx={{ px: 2 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={12}>
|
||||
<Card sx={{ px: 3, py: 4 }}>
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="h6" color={palette.light.primary.main}>User Access</Typography>
|
||||
<RHFTextField name="name" label="Name" />
|
||||
<RHFTextField name="username" label="Username" />
|
||||
<RHFTextField type="email" name="email" label="Email" />
|
||||
<RHFTextField type="password" name="password" label="Password" />
|
||||
<RHFSelect name="roles" label="Roles">
|
||||
{optionsRoles.map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</RHFSelect>
|
||||
<Box sx={{ px: 2 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={12}>
|
||||
<Card sx={{ px: 3, py: 4 }}>
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="h6" color={palette.light.primary.main}>
|
||||
User Access
|
||||
</Typography>
|
||||
<RHFTextField name="name" label="Name" />
|
||||
<RHFTextField name="username" label="Username" />
|
||||
<RHFTextField type="email" name="email" label="Email" />
|
||||
<RHFTextField type="password" name="password" label="Password" />
|
||||
|
||||
{/* Select for roles */}
|
||||
<RHFSelect name="roles" label="Roles">
|
||||
{optionsRoles.map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</RHFSelect>
|
||||
|
||||
<LoadingButton type="submit" variant="contained" size="large" fullWidth={true} loading={isSubmitting}>
|
||||
{ isEdit? 'Update' : 'Create' }
|
||||
</LoadingButton>
|
||||
{/* Conditional rendering based on selectedRole */}
|
||||
{selectedRole && (['8'].includes(selectedRole) ? (
|
||||
<RHFSelect name="organizations" label="Organizations">
|
||||
{optionsOrganization.map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</RHFSelect>
|
||||
) : ['2'].includes(selectedRole) ? (
|
||||
<RHFSelect name="corporates" label="Corporates">
|
||||
{optionsCorporate.map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</RHFSelect>
|
||||
) : null)}
|
||||
|
||||
</Stack>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</FormProvider>
|
||||
<LoadingButton
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
fullWidth={true}
|
||||
loading={isSubmitting}
|
||||
>
|
||||
{isEdit ? 'Update' : 'Create'}
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</FormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"txtSubmissionDate" : "Admission Date",
|
||||
"txtDataNotFound" : "Data Not Found",
|
||||
"txtConditionDocument" : "Condition Document",
|
||||
"txtBillingDocument" : "Billing Document",
|
||||
"txtDiagnosisDokument" : "Diagnosis Dokument",
|
||||
"txtSupportingResultDocument" : "Supporting Result Document",
|
||||
"txtAddResult" : "Add Result",
|
||||
|
||||
@@ -33,8 +33,9 @@
|
||||
"txtSubmissionDate" : "Tanggal Masuk",
|
||||
"txtDataNotFound" : "Data Tidak Ditemukan",
|
||||
"txtConditionDocument" : "Dokumen Kondisi",
|
||||
"txtBillingDocument" : "Dokumen Billing",
|
||||
"txtDiagnosisDokument" : "Dokumen Diagnosis",
|
||||
"txtSupportingResultDocument" : "Dokumen Pendukung",
|
||||
"txtSupportingResultDocument" : "Dokumen Pendukung Medis",
|
||||
"txtAddResult" : "Tambah Hasil",
|
||||
"txtServiceType" : "Tipe Layanan",
|
||||
"txtAdditionalDocuments" : "Dokumen Tambahan",
|
||||
|
||||
@@ -25,5 +25,5 @@ export default function Logo({ disabledLink = false, sx }: Props) {
|
||||
return <>{logo}</>;
|
||||
}
|
||||
|
||||
return <RouterLink to="/">{logo}</RouterLink>;
|
||||
return <RouterLink to="#">{logo}</RouterLink>;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,21 @@ import {
|
||||
Typography,
|
||||
LinearProgress,
|
||||
linearProgressClasses,
|
||||
Collapse,
|
||||
Divider,
|
||||
IconButton,
|
||||
Modal,
|
||||
CircularProgress
|
||||
} from '@mui/material';
|
||||
|
||||
import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
|
||||
import { visuallyHidden } from '@mui/utils';
|
||||
|
||||
import { DatePicker, LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers';
|
||||
|
||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
||||
|
||||
import { fDate, fDateSuffix, fDateTime, fDateTimeWithAge } from '../utils/formatTime';
|
||||
/* ---------------------------------- axios --------------------------------- */
|
||||
import axios from '../utils/axios';
|
||||
/* ---------------------------------- react --------------------------------- */
|
||||
@@ -50,6 +59,10 @@ import GetAppIcon from '@mui/icons-material/GetApp';
|
||||
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import useAuth from '@/hooks/useAuth';
|
||||
|
||||
/* --------------------------------- styled --------------------------------- */
|
||||
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
||||
@@ -79,6 +92,9 @@ export default function Table<T>({
|
||||
searchs,
|
||||
exportReport,
|
||||
selected,
|
||||
openRowId, // Receive the currently opened row ID
|
||||
setOpenRowId, // Receive the function to set the opened row ID
|
||||
reloadData,
|
||||
}: TableListProps<T>) {
|
||||
/* ------------------------------- handle sort ------------------------------ */
|
||||
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
||||
@@ -209,6 +225,114 @@ export default function Table<T>({
|
||||
params.setAppliedParams(parameters);
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
//============================== APOTEK =======================================//
|
||||
const {user} = useAuth();
|
||||
const formattedRoleName = user?.role.name;
|
||||
// List of statuses for 'apotek'
|
||||
const allowedStatusesForApotek = ['waiting_pharmacy', 'order_prepared'];
|
||||
const allowedStatusesForCSLMS = ['waiting_pharmacy', 'order_prepared', 'ready', 'waiting_for_courir', 'package_picked_up', 'package_on_delivery', 'failed'];
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const handleClick = () => {
|
||||
// handleClickKonfirmasi(row); // Call the function passed from parent
|
||||
setOpen(true); // Show modal
|
||||
setLoading(true); // Show loading animation
|
||||
|
||||
// Simulate finding driver (3 seconds delay)
|
||||
setTimeout(() => {
|
||||
setLoading(false); // Hide loading after 3 seconds
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const [openDialogStatus, setOpenDialogStatus] = useState(false);
|
||||
const [dialogIDRow, setDialogIDRow] = useState<number | null>(null);
|
||||
const [dialogIDRowDriver, setDialogIDRowDriver] = useState<number | null>(null);
|
||||
const [txtStatusDriver, setTxtStatusDriver] = useState('');
|
||||
const [txtIDDriver, setTxtIDDriver] = useState('');
|
||||
const handleClose = (row:any) => {
|
||||
setDialogIDRowDriver(row.id === dialogIDRowDriver ? null : row.id);
|
||||
if (reloadData) {
|
||||
reloadData();
|
||||
}
|
||||
};
|
||||
const handleCloseDialogUpdate = () => {
|
||||
setOpenDialogStatus(false);
|
||||
}
|
||||
const handleEditDataStatus = (data: any) => {
|
||||
setOpenDialogStatus(true);
|
||||
}
|
||||
const [isDisabled, setIsDisabled] = useState(false);
|
||||
const handleClickKonfirmasi = (row: any) => {
|
||||
setTxtStatusDriver('');
|
||||
setTxtIDDriver('');
|
||||
if(row.sStatus === 'ready' || row.sStatus === 'failed')
|
||||
{
|
||||
//close
|
||||
setDialogIDRow(row.id === dialogIDRow ? null : row.id);
|
||||
//get driver
|
||||
setDialogIDRowDriver(row.id === dialogIDRowDriver ? null : row.id);
|
||||
// setOpen(true); // Show modal
|
||||
setLoading(true); // Show loading animation
|
||||
|
||||
// Simulate finding driver (3 seconds delay)
|
||||
// setTimeout(() => {
|
||||
// setLoading(false); // Hide loading after 3 seconds
|
||||
// }, 3000);
|
||||
|
||||
const updateData = {
|
||||
sStatus: row.sStatus
|
||||
};
|
||||
|
||||
axios
|
||||
.put(`/put-driver-prescription-orders/${row.nID_orders}`, updateData)
|
||||
.then((response) => {
|
||||
setTxtStatusDriver(response?.data?.data?.status);
|
||||
setTxtIDDriver(response?.data?.data?.deliveryID);
|
||||
setLoading(false);
|
||||
// enqueueSnackbar(response?.data?.meta?.message, { variant: 'success' });
|
||||
|
||||
// Call reloadData to refresh the table
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorMessage = error.response?.data?.meta?.message || 'Failed to update status';
|
||||
enqueueSnackbar(errorMessage, { variant: 'error' });
|
||||
setLoading(false);
|
||||
setIsDisabled(false); // Re-enable the button after success
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
putPrescriptionOrders(row);
|
||||
}
|
||||
}
|
||||
const putPrescriptionOrders = (row: any) => {
|
||||
setIsDisabled(true); // Disable button after clicking
|
||||
const updateData = {
|
||||
sStatus: row.sStatus
|
||||
};
|
||||
axios
|
||||
.put(`/put-prescription-orders/${row.nID_orders}`, updateData)
|
||||
.then((response) => {
|
||||
enqueueSnackbar(response?.data?.meta?.message, { variant: 'success' });
|
||||
setDialogIDRow(row.id === dialogIDRow ? null : row.id);
|
||||
setIsDisabled(false); // Re-enable the button after success
|
||||
|
||||
// Call reloadData to refresh the table
|
||||
if (reloadData) {
|
||||
reloadData();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorMessage = error.response?.data?.meta?.message || 'Failed to update status';
|
||||
enqueueSnackbar(errorMessage, { variant: 'error' });
|
||||
setIsDisabled(false); // Re-enable the button after success
|
||||
});
|
||||
}
|
||||
return (
|
||||
// <Card>
|
||||
<Grid container>
|
||||
@@ -416,6 +540,7 @@ export default function Table<T>({
|
||||
</TableRow>
|
||||
) : rows && rows.length >= 1 ? (
|
||||
rows.map((row, rowIndex) => (
|
||||
<>
|
||||
<TableRow key={rowIndex}>
|
||||
{!selected.useSelected ? (
|
||||
''
|
||||
@@ -440,6 +565,378 @@ export default function Table<T>({
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
{/* COLLAPSIBLE ROW */}
|
||||
<TableRow
|
||||
sx={{ cursor: 'pointer' }} // Use pointer cursor always, or conditionally based on your preference
|
||||
>
|
||||
<TableCell colSpan={6}>
|
||||
<Collapse in={openRowId === row.id} timeout="auto" unmountOnExit>
|
||||
<Card sx={{padding:2}}>
|
||||
{/* Icon inside a Box for spacing and alignment */}
|
||||
<Stack direction="row" padding={2} justifyContent="space-between" alignItems="center">
|
||||
<Stack direction="row">
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', marginRight: 1 }}>
|
||||
<InfoIcon sx={{ color: row.sStatus == 'waiting_pharmacy' ? '#D3D3D3' : '#00E676', fontSize: 24 }} /> {/* Adjust size and color */}
|
||||
</Box>
|
||||
<Typography variant='subtitle2' sx={{ color: '#00E676' }}>
|
||||
{row.status}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{row.nDeliveryID && (
|
||||
<Box sx={{ ml: 'auto' }}>
|
||||
<Typography variant='subtitle2'>
|
||||
Grab Delivery ID: {row.nDeliveryID}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<Box onClick={() => {setOpenRowId(openRowId === row.id ? null : row.id);}} sx={{ padding: '20px', maxWidth: '1200px', margin: '0 auto', backgroundColor: '#ffffff', borderRadius: '8px' }}>
|
||||
<Grid container spacing={2}>
|
||||
|
||||
{/* Row 1 */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="h6" fontWeight="bold">{localeData.txtProviderDoctorInformation}</Typography>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNamaDokter} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.nama_dokter}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtSpesialisasiDokter} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.spesialis}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">SIP :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.sip}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNoPonsel} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.no_ponsel_dokter}</strong></Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiPasien}</Typography>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNamaPasien} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.pasien}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTanggalLahirUmur} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.tgl_lahir_pasien && row.tgl_lahir_pasien !=='0000-00-00' ? fDateTimeWithAge(row.tgl_lahir_pasien) : ''}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtJenisKelamin} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.jenis_kelamin_pasien}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTinggi} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.tinggi_berat}</strong></Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Divider */}
|
||||
<Grid item xs={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiAsuransi}</Typography>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNomorKartu} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.no_polis}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtAsuransi} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.perusahaan_asuransi}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtPerusahaan} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.nama_perusahaan}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTipeAsuransi} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.kode_produk}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtKelasAsuransi} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.kelas_asuransi}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTipeMember} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.tipe_member}</strong></Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiOrder}</Typography>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNamaPenerima} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.pasien}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtAlamatPenerima} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.alamat_penerima}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtPengiriman} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.pengiriman}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTotal} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.total_kirim}</strong></Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Divider */}
|
||||
<Grid item xs={12}>
|
||||
<Divider />
|
||||
</Grid>
|
||||
|
||||
{/* Row 2 */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiResep}</Typography>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNomorResep} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.no_resep}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNomorRefDokter} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.noref_dokter}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTanggalTerbitResep} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.tanggal}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTanggalKedaluwarsa} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.valid_tanggal}</strong></Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiKonsultasi}</Typography>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtNomorPenjamin} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.nomor_penjamin}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtTanggalKonsultasi} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.tgl_livechat}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtAlergi} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.alergi_desc}</strong></Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2">{localeData.txtDiagnosis} :</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body2"><strong>{row.diagnosa}</strong></Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
<Box onClick={() => {setOpenRowId(openRowId === row.id ? null : row.id);}} sx={{ padding: '20px', maxWidth: '1200px', margin: '20px auto', backgroundColor: '#ffffff', borderRadius: '8px' }}>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>{localeData.txtObat}</TableCell>
|
||||
<TableCell align="left">{localeData.txtSigna}</TableCell>
|
||||
<TableCell align="left">{localeData.txtWaktu}</TableCell>
|
||||
<TableCell align="left">{localeData.txtDurasi}</TableCell>
|
||||
<TableCell align="left">{localeData.txtJumlah}</TableCell>
|
||||
<TableCell align="left">{localeData.txtCatatanObat}</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{row.prescription_items ?
|
||||
(
|
||||
row.prescription_items.map((row : any, rowIndex: any) => (
|
||||
<TableRow key={rowIndex}>
|
||||
<TableCell>{row.sItemName}</TableCell>
|
||||
<TableCell align="left">{row.sSigna}</TableCell>
|
||||
<TableCell align="left">{row.sTiming}</TableCell>
|
||||
<TableCell align="left">{row.sDuration}</TableCell>
|
||||
<TableCell align="left">{row.nQty}</TableCell>
|
||||
<TableCell align="left">{row.sNote}</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={headCells?.length} align="center">
|
||||
{localeData.txtDataNotFound}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
|
||||
{/* Close Button on the Left */}
|
||||
<Button variant="outlined" color="inherit" onClick={() => setOpenRowId(null)}>
|
||||
{localeData.txtButtonClose}
|
||||
</Button>
|
||||
{/* Accept Button on the Right */}
|
||||
{row.button_accept && formattedRoleName === 'admin-apotek' && allowedStatusesForApotek.includes(row.sStatus) ? (
|
||||
<Button variant="contained" color="primary" onClick={() => setDialogIDRow(row.id === dialogIDRow ? null : row.id)}>
|
||||
{row.button_accept}
|
||||
</Button>
|
||||
) : ''}
|
||||
{row.button_accept && formattedRoleName === 'cs-lms' && allowedStatusesForCSLMS.includes(row.sStatus) ? (
|
||||
<Button variant="contained" color="primary" onClick={() => setDialogIDRow(row.id === dialogIDRow ? null : row.id)}>
|
||||
{row.button_accept}
|
||||
</Button>
|
||||
) : ''}
|
||||
</Box>
|
||||
|
||||
|
||||
|
||||
{/* Dialog Update Status */}
|
||||
<Dialog open={dialogIDRow === row.id} fullWidth={true}>
|
||||
<DialogTitle sx={{ backgroundColor: '#19BBBB', color: '#FFF', padding: 2 }}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
||||
<Stack direction="row" alignItems='center' spacing={1}>
|
||||
<Typography variant="h6">{localeData.txtConfirmation}</Typography>
|
||||
</Stack>
|
||||
<IconButton sx={{ color: '#FFF' }} onClick={() => setDialogIDRow(row.id === dialogIDRow ? null : row.id)}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stack spacing={2} padding={2}>
|
||||
<Typography variant='body1'>{localeData.txtDialogConfirmation}</Typography>
|
||||
<Card sx={{padding:2}} >
|
||||
<Stack direction='row' spacing={2}>
|
||||
<Typography variant='subtitle2' sx={{color: '#919EAB', width: '50%'}}>{localeData.txtNomorResep}</Typography>
|
||||
<Typography variant='subtitle2' sx={{width: '50%'}}>{row.no_resep}</Typography>
|
||||
</Stack>
|
||||
<Stack direction='row' spacing={2}>
|
||||
<Typography variant='subtitle2' sx={{color: '#919EAB', width: '50%'}}>{localeData.txtTanggalTerbitResep}</Typography>
|
||||
<Typography variant='subtitle2' sx={{width: '50%'}}>{row.tanggal}</Typography>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button sx={{backgroundColor: '#19BBBB'}} variant="contained" onClick={() => handleClickKonfirmasi(row)} disabled={isDisabled}>{localeData.txtOK}</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
{/* Modal for fullscreen display */}
|
||||
<Modal open={dialogIDRowDriver === row.id} onClose={() => handleClose(row)}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100vh',
|
||||
// backgroundColor: 'rgba(0, 0, 0, 0.8)', // semi-transparent background
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<>
|
||||
<CircularProgress color="inherit" />
|
||||
<Typography variant="h6" sx={{ mt: 2 }}>
|
||||
{localeData.txtFindingDriver}
|
||||
</Typography>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Typography variant="h4">Info!</Typography>
|
||||
<Typography variant="h6" sx={{ mt: 2 }}>
|
||||
{txtIDDriver ? (
|
||||
`${localeData.txtDriverFound} ${txtIDDriver} status ${txtStatusDriver}.`
|
||||
) : (
|
||||
// You can add an alternative UI or message here, or leave it empty
|
||||
`Failed to get driver, please check the message info.`
|
||||
)}
|
||||
|
||||
|
||||
</Typography>
|
||||
<Button
|
||||
sx={{ mt: 4, backgroundColor: '#19BBBB' }}
|
||||
variant="contained"
|
||||
onClick={() => handleClose(row)}
|
||||
>
|
||||
{localeData.txtOK}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Modal>
|
||||
</Card>
|
||||
</Collapse>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
|
||||
@@ -28,26 +28,42 @@ export default function NavSectionVertical({
|
||||
isCollapse = false,
|
||||
...other
|
||||
}: NavSectionProps) {
|
||||
return (
|
||||
<Box {...other}>
|
||||
{navConfig.map((group, index) => (
|
||||
<List key={index} disablePadding sx={{ px: 2 }}>
|
||||
<ListSubheaderStyle
|
||||
key={index}
|
||||
sx={{
|
||||
...(isCollapse && {
|
||||
opacity: 0,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{group.subheader}
|
||||
</ListSubheaderStyle>
|
||||
return (
|
||||
<Box {...other}>
|
||||
{navConfig.length === 0 ? ( // Check if navConfig is empty
|
||||
<List disablePadding sx={{ px: 2, display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
|
||||
<ListSubheaderStyle
|
||||
sx={{
|
||||
...(isCollapse && {
|
||||
opacity: 0,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{/* Optional: You can put a title or leave it empty */}
|
||||
</ListSubheaderStyle>
|
||||
|
||||
<div style={{ textAlign: 'center', marginTop: '50px' }}>Loading...</div> {/* Adjust marginTop as needed */}
|
||||
</List>
|
||||
) : (
|
||||
navConfig.map((group, index) => (
|
||||
<List key={index} disablePadding sx={{ px: 2 }}>
|
||||
<ListSubheaderStyle
|
||||
sx={{
|
||||
...(isCollapse && {
|
||||
opacity: 0,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{group.subheader}
|
||||
</ListSubheaderStyle>
|
||||
|
||||
{group.items.map((list) => (
|
||||
<NavListRoot key={list.title} list={list} isCollapse={isCollapse} />
|
||||
))}
|
||||
</List>
|
||||
))
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
|
||||
{group.items.map((list) => (
|
||||
<NavListRoot key={list.title} list={list} isCollapse={isCollapse} />
|
||||
))}
|
||||
</List>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,14 @@ type GuestGuardProps = {
|
||||
|
||||
export default function GuestGuard({ children }: GuestGuardProps) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
|
||||
if (isAuthenticated) {
|
||||
const {user} = useAuth();
|
||||
const formattedRoleName = user?.role.name;
|
||||
if((formattedRoleName === 'admin-apotek' || formattedRoleName === 'cs-lms') && isAuthenticated)
|
||||
{
|
||||
return <Navigate to={'/prescription-orders'} replace={true}/>;
|
||||
}
|
||||
if(formattedRoleName === 'hospital-admin')
|
||||
{
|
||||
return <Navigate to={'/dashboard'} replace={true}/>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { Container, Alert, AlertTitle } from '@mui/material';
|
||||
import useAuth from '@/hooks/useAuth';
|
||||
import Page404 from '@/pages/Page404';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -9,9 +11,10 @@ type RoleBasedGuardProp = {
|
||||
};
|
||||
|
||||
const useCurrentRole = () => {
|
||||
// Logic here to get current user role
|
||||
const role = 'admin';
|
||||
return role;
|
||||
// Fetch the role from useAuth
|
||||
const { user } = useAuth();
|
||||
const formattedRoleName = user?.role.name || ''; // Default to empty string if role is undefined
|
||||
return formattedRoleName;
|
||||
};
|
||||
|
||||
export default function RoleBasedGuard({ accessibleRoles, children }: RoleBasedGuardProp) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"greeting": "Hello",
|
||||
"buttonText": "Click Me",
|
||||
"infoLogin": "Enter the registered account",
|
||||
"txtLogin1" : "Sign in to Hospital Portal",
|
||||
"txtLogin1" : "Sign in",
|
||||
"txtLogin2" : "Enter your details below",
|
||||
"txtCardSearchMember1" : "Membership Query",
|
||||
"txtCardSearchMember2" : "Search Member",
|
||||
@@ -28,11 +28,12 @@
|
||||
"txtRequestCode" : "Request Code",
|
||||
"txtName" : "Name",
|
||||
"txtStatus" : "Status",
|
||||
"txtSearch" : "Search Name or Member ID...",
|
||||
"txtSearch" : "Search...",
|
||||
"txtAll" : "All",
|
||||
"txtSubmissionDate" : "Admission Date",
|
||||
"txtDataNotFound" : "Data Not Found",
|
||||
"txtConditionDocument" : "Condition Document",
|
||||
"txtBillingDocument" : "Billing Document",
|
||||
"txtDiagnosisDokument" : "Diagnosis Dokument",
|
||||
"txtSupportingResultDocument" : "Supporting Result Document",
|
||||
"txtAddResult" : "Add Result",
|
||||
@@ -77,6 +78,63 @@
|
||||
"txtSecond": "Second",
|
||||
"txtPleaseInput": "Please enter your new password.",
|
||||
"txtNewPassword": "New Password",
|
||||
"txtConfPassword": "Confirm Kata Sandi"
|
||||
"txtConfPassword": "Confirm Kata Sandi",
|
||||
"txtPrescriptionNumber" : "Prescription Number",
|
||||
"txtPrescriptionDate" : "Date",
|
||||
"txtPrescriptionPatient" : "Patient",
|
||||
"txtPrescriptionPharmacy" : "Pharmacy",
|
||||
"txtPrescriptionDetail" : "Detail",
|
||||
"txtPrescriptionDownload" : "Download Prescription",
|
||||
"txtProviderDoctorInformation" : "Provider & Doctor Information",
|
||||
"txtInformasiPasien" : "Patient Information",
|
||||
"txtNamaDokter" : "Doctor's Name",
|
||||
"txtSpesialisasiDokter" : "Doctor's Specialization",
|
||||
"txtNoPonsel" : "Mobile No.",
|
||||
"txtInformasiAsuransi": "Insurance Information",
|
||||
"txtNomorKartu": "Card Number",
|
||||
"txtAsuransi": "Insurance",
|
||||
"txtPerusahaan": "Company",
|
||||
"txtTipeAsuransi": "Insurance Type",
|
||||
"txtKelasAsuransi": "Insurance Class",
|
||||
"txtTipeMember": "Member Type",
|
||||
"txtInformasiOrder": "Order Information",
|
||||
"txtNamaPenerima": "Recipient Name",
|
||||
"txtAlamatPenerima": "Recipient Address",
|
||||
"txtPengiriman": "Delivery",
|
||||
"txtTotal": "Total",
|
||||
"txtInformasiResep": "Prescription Information",
|
||||
"txtNomorResep": "Prescription Number",
|
||||
"txtNomorRefDokter": "Doctor's Reference Number",
|
||||
"txtTanggalTerbitResep": "Prescription Issue Date",
|
||||
"txtTanggalKedaluwarsa": "Expiration Date",
|
||||
"txtInformasiKonsultasi": "Consultation Information",
|
||||
"txtNomorPenjamin": "Guarantor Number",
|
||||
"txtTanggalKonsultasi": "Consultation Date",
|
||||
"txtAlergi": "Allergy",
|
||||
"txtDiagnosis": "Diagnosis",
|
||||
"txtObat": "Medicine",
|
||||
"txtSigna": "Signa",
|
||||
"txtWaktu": "Time",
|
||||
"txtDurasi": "Duration",
|
||||
"txtJumlah": "Quantity",
|
||||
"txtCatatanObat": "Medicine Notes",
|
||||
"txtDiterima": "Received",
|
||||
"txtNamaPasien": "Patient Name",
|
||||
"txtTanggalLahirUmur": "Date of Birth / Age",
|
||||
"txtJenisKelamin": "Gender",
|
||||
"txtTinggi" : "Height / Weight",
|
||||
"txtLabelNew": "New",
|
||||
"txtLabelAccepted": "Accepted",
|
||||
"txtLabelReady": "Ready",
|
||||
"txtLabelWaitingCourir": "Waiting Courir",
|
||||
"txtLabelPackagePickedUp": "Package Picked Up",
|
||||
"txtLabelPackageOnDelivery": "Package On Delivery",
|
||||
"txtLabelPackageDelivered": "Package Delivered",
|
||||
"txtLabelWaitingForPayment": "Waiting For Payment",
|
||||
"txtOK": "Yes",
|
||||
"txtFindingDriver": "Finding a driver...",
|
||||
"txtDriverFound": "The driver’s been grabbed with the ID",
|
||||
"txtButtonClose": "Close",
|
||||
"txtLabelFailed": "Failed"
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"greeting": "Halo",
|
||||
"buttonText": "Klik Saya",
|
||||
"infoLogin": "Masukan akun yang telah terdaftar",
|
||||
"txtLogin1" : "Masuk ke Hospital Portal",
|
||||
"txtLogin1" : "Sign in",
|
||||
"txtLogin2" : "Masukkan detail Anda di bawah ini",
|
||||
"txtCardSearchMember1" : "Pengajuan Jaminan",
|
||||
"txtCardSearchMember2" : "Cari Anggota",
|
||||
@@ -28,13 +28,14 @@
|
||||
"txtRequestCode" : "Kode Pengajuan",
|
||||
"txtName" : "Nama",
|
||||
"txtStatus" : "Status",
|
||||
"txtSearch" : "Cari Nama atau ID Anggota...",
|
||||
"txtSearch" : "Cari...",
|
||||
"txtAll" : "Semua",
|
||||
"txtSubmissionDate" : "Tanggal Masuk",
|
||||
"txtDataNotFound" : "Data Tidak Ditemukan",
|
||||
"txtConditionDocument" : "Dokumen Kondisi",
|
||||
"txtBillingDocument" : "Dokumen Billing",
|
||||
"txtDiagnosisDokument" : "Dokumen Diagnosis",
|
||||
"txtSupportingResultDocument" : "Dokumen Pendukung",
|
||||
"txtSupportingResultDocument" : "Dokumen Pendukung Medis",
|
||||
"txtAddResult" : "Tambah Hasil",
|
||||
"txtServiceType" : "Tipe Layanan",
|
||||
"txtAdditionalDocuments" : "Dokumen Tambahan",
|
||||
@@ -77,5 +78,62 @@
|
||||
"txtSecond": "Detik",
|
||||
"txtPleaseInput": "Mohon masukan kata sandi baru Anda.",
|
||||
"txtNewPassword": "Kata Sandi Baru",
|
||||
"txtConfPassword": "Konfirmasi Kata Sandi"
|
||||
"txtConfPassword": "Konfirmasi Kata Sandi",
|
||||
"txtPrescriptionNumber" : "No Resep",
|
||||
"txtPrescriptionDate" : "Tanggal",
|
||||
"txtPrescriptionPatient" : "Pasien",
|
||||
"txtPrescriptionPharmacy" : "Apotek",
|
||||
"txtPrescriptionDetail" : "Detail",
|
||||
"txtPrescriptionDownload" : "Download Resep",
|
||||
"txtProviderDoctorInformation" : "Informasi Provider & Dokter",
|
||||
"txtInformasiPasien" : "Informasi Pasien",
|
||||
"txtNamaDokter" : "Nama Dokter",
|
||||
"txtSpesialisasiDokter" : "Spesialisasi Dokter",
|
||||
"txtNoPonsel" : "No Ponsel",
|
||||
"txtInformasiAsuransi": "Informasi Asuransi",
|
||||
"txtNomorKartu": "Nomor Kartu",
|
||||
"txtAsuransi": "Asuransi",
|
||||
"txtPerusahaan": "Perusahaan",
|
||||
"txtTipeAsuransi": "Tipe Asuransi",
|
||||
"txtKelasAsuransi": "Kelas Asuransi",
|
||||
"txtTipeMember": "Tipe Member",
|
||||
"txtInformasiOrder": "Informasi Order",
|
||||
"txtNamaPenerima": "Nama Penerima",
|
||||
"txtAlamatPenerima": "Alamat Penerima",
|
||||
"txtPengiriman": "Pengiriman",
|
||||
"txtTotal": "Total",
|
||||
"txtInformasiResep": "Informasi Resep",
|
||||
"txtNomorResep": "Nomor Resep",
|
||||
"txtNomorRefDokter": "Nomor Ref Dokter",
|
||||
"txtTanggalTerbitResep": "Tanggal Terbit Resep",
|
||||
"txtTanggalKedaluwarsa": "Tanggal Kedaluwarsa",
|
||||
"txtInformasiKonsultasi": "Informasi Konsultasi",
|
||||
"txtNomorPenjamin": "Nomor Penjamin",
|
||||
"txtTanggalKonsultasi": "Tanggal Konsultasi",
|
||||
"txtAlergi": "Alergi",
|
||||
"txtDiagnosis": "Diagnosis",
|
||||
"txtObat": "Obat",
|
||||
"txtSigna": "Signa",
|
||||
"txtWaktu": "Waktu",
|
||||
"txtDurasi": "Durasi",
|
||||
"txtJumlah": "Jumlah",
|
||||
"txtCatatanObat": "Catatan Obat",
|
||||
"txtDiterima": "Diterima",
|
||||
"txtNamaPasien": "Nama Pasien",
|
||||
"txtTanggalLahirUmur": "Tanggal Lahir / Umur",
|
||||
"txtJenisKelamin": "Jenis Kelamin",
|
||||
"txtTinggi" : "Tinggi / Berat",
|
||||
"txtLabelNew": "Baru",
|
||||
"txtLabelAccepted": "Diterima Apotek",
|
||||
"txtLabelReady": "Pesanan Siap Diambil",
|
||||
"txtLabelWaitingCourir": "Menunggu Kurir",
|
||||
"txtLabelPackagePickedUp": "Paket Sudah Diambil",
|
||||
"txtLabelPackageOnDelivery": "Sedang Diantar ke Alamat Tujuan",
|
||||
"txtLabelPackageDelivered": "Sudah diterima Pasien",
|
||||
"txtLabelWaitingForPayment": "Menunggu Pembayaran",
|
||||
"txtOK": "Ya",
|
||||
"txtFindingDriver" : "Sedang mencari driver...",
|
||||
"txtDriverFound" : "Driver sudah didapat dengan ID",
|
||||
"txtButtonClose": "Tutup",
|
||||
"txtLabelFailed": "Gagal Pengiriman"
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import useAuth from '@/hooks/useAuth';
|
||||
|
||||
import { getUser } from '@/utils/token';
|
||||
|
||||
// Join the words with a space
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const MENU_OPTIONS = [
|
||||
@@ -34,6 +36,12 @@ export default function AccountPopover() {
|
||||
const navigate = useNavigate();
|
||||
const { logout } = useAuth();
|
||||
|
||||
const {user} = useAuth();
|
||||
const formattedRoleName = user?.role.name
|
||||
.split('-') // Split the string by '-'
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize the first letter of each word
|
||||
.join(' ');
|
||||
|
||||
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setOpen(event.currentTarget);
|
||||
};
|
||||
@@ -70,7 +78,7 @@ export default function AccountPopover() {
|
||||
>
|
||||
<Avatar
|
||||
src=""
|
||||
alt="Hospital Portal"
|
||||
alt="Portal"
|
||||
/>
|
||||
</IconButtonAnimate>
|
||||
|
||||
@@ -90,7 +98,7 @@ export default function AccountPopover() {
|
||||
>
|
||||
<Box sx={{ my: 1.5, px: 2.5 }}>
|
||||
<Typography variant="subtitle2" noWrap>
|
||||
Hospital Admin
|
||||
{formattedRoleName}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
|
||||
{storedUser?.email}
|
||||
@@ -99,7 +107,7 @@ export default function AccountPopover() {
|
||||
|
||||
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||
|
||||
<Stack sx={{ p: 1 }}>
|
||||
{/* <Stack sx={{ p: 1 }}>
|
||||
{MENU_OPTIONS.map((option) => (
|
||||
<MenuItem
|
||||
key={option.label}
|
||||
@@ -111,7 +119,7 @@ export default function AccountPopover() {
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack> */}
|
||||
|
||||
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||
|
||||
|
||||
@@ -29,15 +29,18 @@ import axios from '@/utils/axios';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||
|
||||
import useAuth from '@/hooks/useAuth';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function NotificationsPopover() {
|
||||
const { localeData }: any = useContext(LanguageContext);
|
||||
const [notifications, setNotifications] = useState([]);
|
||||
const {user} = useAuth();
|
||||
const {enqueueSnackbar} = useSnackbar();
|
||||
const getDataNotifications = async () => {
|
||||
axios
|
||||
.get('notifications/1')
|
||||
.get('notifications/'+user?.id)
|
||||
.then((response) => {
|
||||
setNotifications(response.data.data.notifications);
|
||||
})
|
||||
@@ -47,7 +50,7 @@ export default function NotificationsPopover() {
|
||||
};
|
||||
useEffect(() => {
|
||||
getDataNotifications();
|
||||
}, []);
|
||||
}, []);
|
||||
|
||||
const totalUnRead = notifications.filter((item) => item.isUnRead === 1).length;
|
||||
|
||||
@@ -137,7 +140,7 @@ export default function NotificationsPopover() {
|
||||
</List>
|
||||
</>
|
||||
): ''}
|
||||
|
||||
|
||||
</Scrollbar>
|
||||
|
||||
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||
@@ -256,12 +259,12 @@ function renderContent(notification: NotificationItemProps) {
|
||||
title,
|
||||
};
|
||||
}
|
||||
if (notification.type === 'mail' || notification.type === 'request_document') {
|
||||
if (notification.type === 'mail' || notification.type === 'request_document' || notification.type === 'grab_status') {
|
||||
return {
|
||||
avatar: (
|
||||
<img
|
||||
alt={notification.title}
|
||||
src="https://minimal-assets-api.vercel.app/assets/icons/ic_notification_mail.svg"
|
||||
src="/icons/ic_mail.svg"
|
||||
/>
|
||||
),
|
||||
title,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
// @mui
|
||||
import { styled, useTheme } from '@mui/material/styles';
|
||||
@@ -15,10 +15,26 @@ import Logo from '@/components/Logo';
|
||||
import Scrollbar from '@/components/Scrollbar';
|
||||
import { NavSectionVertical } from '@/components/nav-section';
|
||||
//
|
||||
import navConfig from './NavConfig';
|
||||
// import navConfig from './NavConfig';
|
||||
import NavbarDocs from './NavbarDocs';
|
||||
import useAuth from '@/hooks/useAuth';
|
||||
import NavbarAccount from './NavbarAccount';
|
||||
import CollapseButton from './CollapseButton';
|
||||
import axios from '@/utils/axios';
|
||||
import SvgIconStyle from '@/components/SvgIconStyle';
|
||||
|
||||
|
||||
const getIcon = (name: string) => (
|
||||
<SvgIconStyle src={`/image/${name}.svg`} sx={{ width: 1, height: 1 }} />
|
||||
);
|
||||
|
||||
const ICONS = {
|
||||
user: getIcon('ic_user'),
|
||||
ecommerce: getIcon('ic_ecommerce'),
|
||||
analytics: getIcon('ic_analytics'),
|
||||
dashboard: getIcon('ic_dashboard'),
|
||||
ic_booking: getIcon('ic_booking'),
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -43,11 +59,76 @@ export default function NavbarVertical({ isOpenSidebar, onCloseSidebar }: Props)
|
||||
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const {user} = useAuth();
|
||||
const formattedRoleName = user?.full_name
|
||||
.split('-') // Split the string by '-'
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize the first letter of each word
|
||||
.join(' '); // Join the words with a space
|
||||
|
||||
const isDesktop = useResponsive('up', 'lg');
|
||||
|
||||
const { isCollapse, collapseClick, collapseHover, onToggleCollapse, onHoverEnter, onHoverLeave } =
|
||||
useCollapseDrawer();
|
||||
|
||||
const [navConfig, setNavConfig] = useState([]);
|
||||
// console.log(navConfig);
|
||||
useEffect(() => {
|
||||
const fetchNavConfig = async () => {
|
||||
try {
|
||||
const response = await axios.get('/navigations');
|
||||
const data = response.data.items;
|
||||
// console.log(data);
|
||||
|
||||
// Pastikan user dan user.permissions terdefinisi dan merupakan array
|
||||
const userPermissions = user?.permissions?.map(permission => permission.name) || [];
|
||||
|
||||
// Fungsi untuk memeriksa apakah pengguna memiliki izin untuk item tertentu
|
||||
const hasPermission = (permission) => {
|
||||
return userPermissions.includes(permission);
|
||||
};
|
||||
|
||||
// Filter data berdasarkan izin pengguna
|
||||
const filteredNavConfig = data.map(section => {
|
||||
if (section.children && section.children.length > 0) {
|
||||
// Cek apakah ada satu atau lebih children yang memiliki izin
|
||||
const filteredChildren = section.children.filter(child => hasPermission(child.permission));
|
||||
|
||||
if (filteredChildren.length > 0) {
|
||||
return {
|
||||
...section,
|
||||
children: filteredChildren
|
||||
};
|
||||
} else {
|
||||
return null; // Lewati bagian yang tidak memiliki children dengan izin
|
||||
}
|
||||
}
|
||||
// Jika tidak ada children, cek izin untuk section itu sendiri
|
||||
// console.log(section.permission);
|
||||
return hasPermission(section.permission) ? section : null;
|
||||
}).filter(section => section !== null);
|
||||
|
||||
// console.log(filteredNavConfig);
|
||||
|
||||
const formattedNavConfig = filteredNavConfig.map(item => ({
|
||||
|
||||
items: [{
|
||||
title: item.title,
|
||||
path: item.path,
|
||||
icon: ICONS[item.icon]
|
||||
}]
|
||||
}));
|
||||
|
||||
setNavConfig(formattedNavConfig);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Gagal mengambil konfigurasi navigasi:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchNavConfig();
|
||||
}, [user]);
|
||||
console.log(navConfig);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpenSidebar) {
|
||||
onCloseSidebar();
|
||||
@@ -76,10 +157,10 @@ export default function NavbarVertical({ isOpenSidebar, onCloseSidebar }: Props)
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
||||
<Stack direction="row" alignItems="center">
|
||||
<Logo />
|
||||
<Typography ml={3}>Hospital Portal</Typography>
|
||||
<Typography ml={3}>{formattedRoleName}</Typography>
|
||||
</Stack>
|
||||
<CollapseButton onToggleCollapse={onToggleCollapse} collapseClick={collapseClick} />
|
||||
</Stack>)
|
||||
</Stack>)
|
||||
: (
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
||||
<Logo />
|
||||
|
||||
119
frontend/hospital-portal/src/pages/DashboardApotek.tsx
Normal file
119
frontend/hospital-portal/src/pages/DashboardApotek.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
// @mui
|
||||
import { Typography, Container, Grid, Card } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '@/hooks/useSettings';
|
||||
// components
|
||||
import Page from '@/components/Page';
|
||||
// theme
|
||||
import CardNotification from '@/sections/dashboard/CardNotification';
|
||||
import CardSearchMember from '@/sections/dashboard/CardSearchMember'
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import axios from '@/utils/axios';
|
||||
import { Stack } from '@mui/system';
|
||||
import { Input } from '@mui/material';
|
||||
//sections
|
||||
import TableList from '@/sections/dashboardApotek/TableList';
|
||||
import { fDate } from '@/utils/formatTime';
|
||||
import DialogDetailClaim from '@/components/dialogs/DialogDetailClaim';
|
||||
import HeaderBreadcrumbs from "@/components/HeaderBreadcrumbs";
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// const [notifications, setNotifications] = useState([])
|
||||
|
||||
const itemList = [
|
||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '08:00 WIB' },
|
||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '09:00 WIB' },
|
||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '10:00 WIB' },
|
||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '11:00 WIB' },
|
||||
];
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* ---------------------------------- types --------------------------------- */
|
||||
|
||||
type PolicyProps = {
|
||||
myLimit: {
|
||||
balance: number;
|
||||
total: number;
|
||||
percentage: number;
|
||||
};
|
||||
lockLimit: {
|
||||
balance: number;
|
||||
percentage: number;
|
||||
};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ default data ------------------------------ */
|
||||
const defaultPolicyData = {
|
||||
myLimit: {
|
||||
balance: 0,
|
||||
total: 0,
|
||||
percentage: 0,
|
||||
},
|
||||
lockLimit: {
|
||||
balance: 0,
|
||||
percentage: 0,
|
||||
},
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
export default function Claim() {
|
||||
const { themeStretch } = useSettings();
|
||||
|
||||
// const [tableData, setTableData] = useState([]);
|
||||
const [policyData, setPolicyData] = useState<PolicyProps>(defaultPolicyData);
|
||||
|
||||
// TODO Remove This
|
||||
//const [itemList, setItemList] = useState([]);
|
||||
function handleDataLoaded(dataTable:any) {
|
||||
let dummyData = [];
|
||||
dataTable.map(function(data:any) {
|
||||
if (data.status == 'approved') {
|
||||
dummyData.push({
|
||||
info: `LOG Approved for member ${data.member.full_name}`,
|
||||
date: fDate(data.created_at, "dd MMMM"),
|
||||
time: fDate(data.created_at, "HH:mm")
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
//setItemList(dummyData);
|
||||
}
|
||||
|
||||
return (
|
||||
<Page title="Dashboard">
|
||||
<Container maxWidth={themeStretch ? false : 'xl'}>
|
||||
<Grid container spacing={2}>
|
||||
{/* <Grid item xs={12} lg={12} md={12}>
|
||||
<CardSearchMember/>
|
||||
</Grid> */}
|
||||
{/*<Grid item xs={12} lg={6} md={6}>
|
||||
<CardNotification data={itemList} />
|
||||
</Grid>*/}
|
||||
<Grid item xs={12} lg={12} md={12}>
|
||||
{/* <HeaderBreadcrumbs
|
||||
heading={'Dashboard'}
|
||||
links={[
|
||||
{
|
||||
name: 'Dashboard',
|
||||
href: '/dashboard-apotek',
|
||||
},
|
||||
{
|
||||
name: 'Dashboard',
|
||||
href: '/list',
|
||||
},
|
||||
]}
|
||||
/> */}
|
||||
<Card>
|
||||
<TableList/>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
@@ -11,12 +11,16 @@ import Register from '@/pages/auth/Register';
|
||||
import VerifyCode from '@/pages/auth/VerifyCode';
|
||||
import { AuthProvider } from '@/contexts/LaravelAuthContext';
|
||||
import AuthGuard from '@/guards/AuthGuard';
|
||||
import useAuth from '@/hooks/useAuth';
|
||||
import RoleBasedGuard from '@/guards/RoleBasedGuard';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const Loadable = (Component: ElementType) => (props: any) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const { pathname } = useLocation();
|
||||
const {user} = useAuth();
|
||||
const formattedRoleName = user?.role.name;
|
||||
|
||||
return (
|
||||
<Suspense fallback={<LoadingScreen isDashboard={pathname.includes('/dashboard')} />}>
|
||||
@@ -50,11 +54,35 @@ export default function Router() {
|
||||
</AuthProvider>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
element: (
|
||||
<AuthProvider>
|
||||
<ResetPassword />
|
||||
</AuthProvider>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'forget-password',
|
||||
element: (
|
||||
<AuthProvider>
|
||||
<ForgetPassword />
|
||||
</AuthProvider>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'verify',
|
||||
element: (
|
||||
<AuthProvider>
|
||||
<VerifyCode />
|
||||
</AuthProvider>
|
||||
),
|
||||
},
|
||||
// { path: 'login-unprotected', element: <Login /> },
|
||||
// { path: 'register-unprotected', element: <Register /> },
|
||||
{ path: 'reset-password', element: <ResetPassword /> },
|
||||
{ path: 'forget-password', element: <ForgetPassword /> },
|
||||
{ path: 'verify', element: <VerifyCode /> },
|
||||
// { path: 'reset-password', element: <ResetPassword /> },
|
||||
// { path: 'forget-password', element: <ForgetPassword /> },
|
||||
// { path: 'verify', element: <VerifyCode /> },
|
||||
],
|
||||
},
|
||||
// {
|
||||
@@ -74,11 +102,19 @@ export default function Router() {
|
||||
{ element: <Navigate to="/dashboard" replace />, index: true },
|
||||
{
|
||||
path: 'dashboard',
|
||||
element: <Dashboard />,
|
||||
element: (
|
||||
<RoleBasedGuard accessibleRoles={['hospital-admin']}>
|
||||
<Dashboard />
|
||||
</RoleBasedGuard>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: '/detail/:id',
|
||||
element: <DetailClaimReport />,
|
||||
element: (
|
||||
<RoleBasedGuard accessibleRoles={['hospital-admin']}>
|
||||
<DetailClaimReport />
|
||||
</RoleBasedGuard>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -95,18 +131,54 @@ export default function Router() {
|
||||
{ element: <Navigate to="/claim" replace />, index: true },
|
||||
{
|
||||
path: 'claim',
|
||||
element: <Claim />,
|
||||
element: (
|
||||
<RoleBasedGuard accessibleRoles={['hospital-admin']}>
|
||||
<Claim />
|
||||
</RoleBasedGuard>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: '/claim/detail/:id',
|
||||
element: <DetailClaim />,
|
||||
element: (
|
||||
<RoleBasedGuard accessibleRoles={['hospital-admin']}>
|
||||
<DetailClaim />
|
||||
</RoleBasedGuard>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: '/',
|
||||
element: (
|
||||
<AuthProvider>
|
||||
<AuthGuard>
|
||||
<DashboardLayout />
|
||||
</AuthGuard>
|
||||
</AuthProvider>
|
||||
),
|
||||
children: [
|
||||
{ element: <Navigate to="/prescription-orders" replace />, index: true },
|
||||
{
|
||||
path: 'prescription-orders',
|
||||
element: (
|
||||
<RoleBasedGuard accessibleRoles={['admin-apotek', 'cs-lms']}>
|
||||
<DashboardApotek />
|
||||
</RoleBasedGuard>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: '*',
|
||||
element: <LogoOnlyLayout />,
|
||||
element: (
|
||||
<AuthProvider>
|
||||
<AuthGuard>
|
||||
<LogoOnlyLayout />
|
||||
</AuthGuard>
|
||||
</AuthProvider>
|
||||
),
|
||||
children: [
|
||||
{ path: '404', element: <NotFound /> },
|
||||
{ path: '*', element: <Navigate to="/404" replace /> },
|
||||
@@ -123,6 +195,7 @@ const ForgetPassword = Loadable(lazy(() => import('@/pages/auth/ForgetPassword')
|
||||
// Dashboard
|
||||
const Dashboard = Loadable(lazy(() => import('@/pages/Dashboard')));
|
||||
const Claim = Loadable(lazy(() => import('@/pages/Claim')));
|
||||
const DashboardApotek = Loadable(lazy(() => import('@/pages/DashboardApotek')));
|
||||
const NotFound = Loadable(lazy(() => import('@/pages/Page404')));
|
||||
|
||||
const DetailClaimReport = Loadable(lazy(()=> import('@/sections/dashboard/Detail')));
|
||||
|
||||
@@ -148,7 +148,7 @@ export default function DialogFinalLog({ member, getData, onClose, handleSubmitS
|
||||
{/* -------------------------------Upload Dokumen Kondisi------------------------------- */}
|
||||
<Stack sx={{ marginTop: 2 }}>
|
||||
<Typography variant="body1" sx={{fontWeight:'bold'}}>
|
||||
{localeData.txtConditionDocument}
|
||||
{localeData.txtBillingDocument}
|
||||
</Typography>
|
||||
{/* <Typography variant="body2">Hasil Lab, </Typography> */}
|
||||
<Stack
|
||||
|
||||
@@ -0,0 +1,440 @@
|
||||
/* ---------------------------------- @mui ---------------------------------- */
|
||||
import { Stack, Button, MenuItem, SelectChangeEvent, Tab, Tabs, Card, Box } from '@mui/material';
|
||||
/* ---------------------------------- axios --------------------------------- */
|
||||
// import axios from 'axios';
|
||||
import axios from '../../utils/axios';
|
||||
import { styled } from '@mui/material/styles';
|
||||
/* ---------------------------------- react --------------------------------- */
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
|
||||
/* -------------------------------- component ------------------------------- */
|
||||
import Iconify from '../../components/Iconify';
|
||||
import TableComponent from '../../components/Table';
|
||||
/* ---------------------------------- theme --------------------------------- */
|
||||
import palette from '../../theme/palette';
|
||||
//import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||
import { HeadCell, Order, PaginationTableProps } from '../../@types/table';
|
||||
import { useSearchParams, useNavigate } from 'react-router-dom';
|
||||
import { fDate, fDateSuffix, fDateTime } from '../../utils/formatTime';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { format } from 'date-fns';
|
||||
import TableMoreMenu from '../../components/table/TableMoreMenu';
|
||||
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
|
||||
import HistoryIcon from '@mui/icons-material/History';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import Label from '../../components/Label';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { LoadingButton, TabPanel } from "@mui/lab";
|
||||
import { LanguageContext } from '@/contexts/LanguageContext';
|
||||
import MuiDialog from '@/components/MuiDialog';
|
||||
import DialogMember from '@/sections/dashboard/DialogMember';
|
||||
import DialogClaimSubmit from '@/sections/dashboard/DialogClaimSubmit';
|
||||
import { fPostFormat } from '@/utils/formatTime';
|
||||
|
||||
export default function TableList() {
|
||||
const navigate = useNavigate();
|
||||
const { localeData }: any = useContext(LanguageContext);
|
||||
|
||||
const [data, setData] = useState([]);
|
||||
|
||||
// Download Resep
|
||||
async function handleDownloadPrescription(link_download:any) {
|
||||
window.open(link_download, '_blank');
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* setting up for the table */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const loadings = {
|
||||
isLoading: isLoading,
|
||||
setIsLoading: setIsLoading,
|
||||
};
|
||||
|
||||
/* ------------------------------ handle params ----------------------------- */
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [appliedParams, setAppliedParams] = useState({});
|
||||
|
||||
const params = {
|
||||
searchParams: searchParams,
|
||||
setSearchParams: setSearchParams,
|
||||
appliedParams: appliedParams,
|
||||
setAppliedParams: setAppliedParams,
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ------------------------------ handle order ------------------------------ */
|
||||
const [order, setOrder] = useState<Order>('desc');
|
||||
const [orderBy, setOrderBy] = useState('dTanggalresep');
|
||||
|
||||
const orders = {
|
||||
order: order,
|
||||
setOrder: setOrder,
|
||||
orderBy: orderBy,
|
||||
setOrderBy: setOrderBy,
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------- handle pagination --------------------------- */
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
|
||||
const [paginationTable, setPaginationTable] = useState<PaginationTableProps>({
|
||||
current_page: 0,
|
||||
from: 0,
|
||||
last_page: 0,
|
||||
links: [],
|
||||
path: '',
|
||||
per_page: 0,
|
||||
to: 0,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
const paginations = {
|
||||
page: page,
|
||||
setPage: setPage,
|
||||
rowsPerPage: rowsPerPage,
|
||||
setRowsPerPage: setRowsPerPage,
|
||||
paginationTable: paginationTable,
|
||||
setPaginationTable: setPaginationTable,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
// ----------------------------------------- handle selected ---------------------
|
||||
const [selectAll, setSelectAll] = useState(false);
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const [dataTableData, setDataTableData] = useState<any>();
|
||||
const handleSelectAll = () => {
|
||||
setSelectAll(!selectAll);
|
||||
if (!selectAll) {
|
||||
const requestedIds = dataTableData?.data
|
||||
.filter((row: { status: string, check_claim:any }) => row.status === 'approved' && !row.check_claim)
|
||||
.map((row: { id: any }) => row.id);
|
||||
setSelectedRows(requestedIds);
|
||||
} else {
|
||||
setSelectedRows([]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCheckboxChange = (id: any) => {
|
||||
setSelectedRows(prevSelectedRows => {
|
||||
const isSelected = prevSelectedRows.includes(id);
|
||||
if (isSelected) {
|
||||
return prevSelectedRows.filter(rowId => rowId !== id);
|
||||
} else {
|
||||
return [...prevSelectedRows, id];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const [openDialogSubmit, setOpenDialogSubmit] = useState(false);
|
||||
const handleCloseDialogSubmit = () => {
|
||||
setOpenDialogSubmit(false);
|
||||
}
|
||||
const [valDialog, setValDialog] = useState('');
|
||||
const [reasonDecline, setReasonDecline] = useState('');
|
||||
const handleReasonDeclineChange = (event: { target: { value: SetStateAction<string>; }; }) => {
|
||||
setReasonDecline(event.target.value);
|
||||
};
|
||||
|
||||
const selected = {
|
||||
useSelected: false,
|
||||
selectAll: selectAll,
|
||||
handleSelectAll: handleSelectAll,
|
||||
selectedRows: selectedRows,
|
||||
handleCheckboxChange : handleCheckboxChange,
|
||||
totRows: 9,
|
||||
useDecline: false,
|
||||
txtDecline: 'Decline',
|
||||
useApprove:true,
|
||||
txtApprove: 'Submit Claim',
|
||||
setOpenDialogSubmit: setOpenDialogSubmit,
|
||||
setValDialog: setValDialog
|
||||
};
|
||||
|
||||
/* ------------------------------ handle search ----------------------------- */
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
const handleSearchSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (searchText === '') {
|
||||
searchParams.delete('search');
|
||||
const params = Object.fromEntries([...searchParams.entries()]);
|
||||
setAppliedParams(params);
|
||||
} else {
|
||||
const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]);
|
||||
setAppliedParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
const searchs = {
|
||||
useSearchs: true,
|
||||
searchText: searchText,
|
||||
setSearchText: setSearchText,
|
||||
handleSearchSubmit: handleSearchSubmit,
|
||||
};
|
||||
|
||||
/* ------------------------------ handle filter ----------------------------- */
|
||||
const [statusValue, setStatusValue] = useState('all');
|
||||
const [filterData, setStatusData] = useState([]);
|
||||
|
||||
// handle status
|
||||
const handleStatusChanges = (event: SelectChangeEvent) => {
|
||||
setStatusValue(event.target.value as string);
|
||||
|
||||
if (event.target.value === 'all') {
|
||||
searchParams.delete('status');
|
||||
const params = Object.fromEntries([...searchParams.entries()]);
|
||||
setAppliedParams(params);
|
||||
} else {
|
||||
const params = Object.fromEntries([
|
||||
...searchParams.entries(),
|
||||
['status', event.target.value as string],
|
||||
]);
|
||||
setAppliedParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
const filterStatus = {
|
||||
useFilter: true,
|
||||
config: {
|
||||
label: 'Status',
|
||||
statusValue: statusValue,
|
||||
filterData: filterData,
|
||||
handleStatusChange: handleStatusChanges,
|
||||
},
|
||||
};
|
||||
|
||||
// handle start date
|
||||
const [startDateValue, setStartDateValue] = useState('');
|
||||
|
||||
const handleStartDateChanges = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const newStartDateValue = event.currentTarget.elements['date-input'].value;
|
||||
setStartDateValue(newStartDateValue);
|
||||
if (newStartDateValue === '') {
|
||||
searchParams.delete('start_date');
|
||||
const params = Object.fromEntries([...searchParams.entries()]);
|
||||
setAppliedParams(params);
|
||||
} else {
|
||||
const params = Object.fromEntries([...searchParams.entries(), ['start_date', newStartDateValue]]);
|
||||
setAppliedParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
const filterStartDate = {
|
||||
useFilter: true,
|
||||
startDate: startDateValue,
|
||||
setStartDate: setStartDateValue,
|
||||
handleStartDateChange: handleStartDateChanges,
|
||||
};
|
||||
|
||||
// handle end date
|
||||
const [endDateValue, setEndDateValue] = useState('');
|
||||
|
||||
const handleEndDateChanges = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const newEndDateValue = event.currentTarget.elements['date-input'].value;
|
||||
setEndDateValue(newEndDateValue);
|
||||
if (newEndDateValue === '') {
|
||||
searchParams.delete('end_date');
|
||||
const params = Object.fromEntries([...searchParams.entries()]);
|
||||
setAppliedParams(params);
|
||||
} else {
|
||||
const params = Object.fromEntries([...searchParams.entries(), ['end_date', newEndDateValue]]);
|
||||
setAppliedParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
const filterEndDate = {
|
||||
useFilter: true,
|
||||
endDate: endDateValue,
|
||||
setEndDate: setEndDateValue,
|
||||
handleEndDateChange: handleEndDateChanges,
|
||||
};
|
||||
|
||||
/* -------------------------------- headCell Claim -------------------------------- */
|
||||
const headCells: HeadCell<never>[] = [
|
||||
{
|
||||
id: 'no_resep',
|
||||
align: 'left',
|
||||
label: localeData.txtPrescriptionNumber,
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'tanggal',
|
||||
align: 'left',
|
||||
label: localeData.txtPrescriptionDate,
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'pasien',
|
||||
align: 'center',
|
||||
label: localeData.txtPrescriptionPatient,
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'apotek',
|
||||
align: 'center',
|
||||
label: localeData.txtPrescriptionPharmacy,
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
align: 'center',
|
||||
label: localeData.txtStatus,
|
||||
isSort: true,
|
||||
},
|
||||
{
|
||||
id: 'action',
|
||||
align: 'right',
|
||||
label: '',
|
||||
isSort: false,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [appliedParams, searchParams, order, orderBy, setSearchParams]);
|
||||
const [openRowId, setOpenRowId] = useState<number | null>(null);
|
||||
function getData()
|
||||
{
|
||||
(async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
|
||||
const parameters =
|
||||
Object.keys(appliedParams).length !== 0
|
||||
? appliedParams
|
||||
: Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]);
|
||||
|
||||
const response = await axios.get(`/get-prescription-orders`, {
|
||||
params: { ...parameters, type: 'prescription-orders' },
|
||||
});
|
||||
setDataTableData(response.data);
|
||||
setData(
|
||||
response.data.data.map((obj: any) => ({
|
||||
...obj,
|
||||
status:
|
||||
obj.status === 'waiting_pharmacy' ? (
|
||||
<Label color='default'>
|
||||
{localeData.txtLabelNew}
|
||||
</Label>
|
||||
) : obj.status === 'order_prepared' ? (
|
||||
<Label color='primary' >
|
||||
{localeData.txtLabelAccepted}
|
||||
</Label>
|
||||
) : obj.status === 'ready' ? (
|
||||
<Label color='primary'>
|
||||
{localeData.txtLabelReady}
|
||||
</Label>
|
||||
) : obj.status === 'waiting_for_courir' ? (
|
||||
<Label color='primary'>
|
||||
{localeData.txtLabelWaitingCourir}
|
||||
</Label>
|
||||
) : obj.status === 'package_picked_up' ? (
|
||||
<Label color='primary'>
|
||||
{localeData.txtLabelPackagePickedUp}
|
||||
</Label>
|
||||
) : obj.status === 'package_on_delivery' ? (
|
||||
<Label color='primary'>
|
||||
{localeData.txtLabelPackageOnDelivery}
|
||||
</Label>
|
||||
) : obj.status === 'package_delivered' ? (
|
||||
<Label color='primary'>
|
||||
{localeData.txtLabelPackageDelivered}
|
||||
</Label>
|
||||
) : obj.status === 'waiting_for_payment' ? (
|
||||
<Label color='primary'>
|
||||
{localeData.txtLabelWaitingForPayment}
|
||||
</Label>
|
||||
): obj.status === 'failed' ? (
|
||||
<Label color='error'>
|
||||
{localeData.txtLabelFailed}
|
||||
</Label>
|
||||
) : (
|
||||
<Label color='primary'>
|
||||
Pending
|
||||
</Label>
|
||||
),
|
||||
tanggal:
|
||||
<Label>
|
||||
{obj.tanggal ? fDateTime(obj.tanggal) : ''}
|
||||
</Label>
|
||||
,
|
||||
valid_tanggal:
|
||||
<Label>
|
||||
{obj.valid_tanggal ? fDateTime(obj.valid_tanggal) : ''}
|
||||
</Label>
|
||||
,
|
||||
action:
|
||||
<TableMoreMenu actions={
|
||||
<>
|
||||
<MenuItem onClick={() => setOpenRowId(obj.id === openRowId ? null : obj.id)}>
|
||||
<Iconify icon="eva:eye-fill" />
|
||||
{localeData.txtPrescriptionDetail}
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => handleDownloadPrescription(obj.link_download)}>
|
||||
<Iconify icon="eva:download-fill" />
|
||||
{localeData.txtPrescriptionDownload}
|
||||
</MenuItem>
|
||||
</>
|
||||
} />
|
||||
}))
|
||||
);
|
||||
|
||||
setPaginationTable(response.data);
|
||||
setRowsPerPage(response.data.per_page);
|
||||
|
||||
if (searchParams.get('page')) {
|
||||
//@ts-ignore
|
||||
const currentPage = parseInt(searchParams.get('page')) - 1;
|
||||
|
||||
paginationTable.current_page = currentPage;
|
||||
setPage(currentPage);
|
||||
}
|
||||
|
||||
const status:any = [
|
||||
{"id": "waiting_for_payment", "name": localeData.txtLabelWaitingForPayment },
|
||||
{"id": "waiting_pharmacy", "name": localeData.txtLabelNew },
|
||||
{"id": "order_prepared", "name": localeData.txtLabelAccepted },
|
||||
{"id": "ready", "name": localeData.txtLabelReady },
|
||||
{"id": "waiting_for_courir", "name": localeData.txtLabelWaitingCourir },
|
||||
{"id": "package_picked_up", "name": localeData.txtLabelPackagePickedUp },
|
||||
{"id": "package_on_delivery", "name": localeData.txtLabelPackageOnDelivery },
|
||||
{"id": "package_delivered", "name": localeData.txtLabelPackageDelivered },
|
||||
{"id": "failed", "name": localeData.txtLabelFailed },
|
||||
];
|
||||
setStatusData(status)
|
||||
|
||||
setIsLoading(false);
|
||||
})();
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableComponent
|
||||
headCells={headCells}
|
||||
rows={data}
|
||||
orders={orders}
|
||||
paginations={paginations}
|
||||
loadings={loadings}
|
||||
params={params}
|
||||
searchs={searchs}
|
||||
filterStatus={filterStatus}
|
||||
selected={selected}
|
||||
// filterStartDate={filterStartDate}
|
||||
// filterEndDate={filterEndDate}
|
||||
openRowId={openRowId} // Pass the currently opened row ID
|
||||
setOpenRowId={setOpenRowId} // Pass the function to set the opened row ID
|
||||
reloadData={getData}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -11,6 +11,40 @@ export function fDateTime(date: Date | string | number) {
|
||||
return format(new Date(date), 'dd MMM yyyy HH:mm');
|
||||
}
|
||||
|
||||
// Function to calculate the age from the birthdate
|
||||
function calculateAge(birthDate: Date): number {
|
||||
const today = new Date();
|
||||
const age = today.getFullYear() - birthDate.getFullYear();
|
||||
const monthDifference = today.getMonth() - birthDate.getMonth();
|
||||
const dayDifference = today.getDate() - birthDate.getDate();
|
||||
|
||||
// Adjust age if birthday hasn't occurred yet this year
|
||||
if (monthDifference < 0 || (monthDifference === 0 && dayDifference < 0)) {
|
||||
return age - 1;
|
||||
}
|
||||
|
||||
return age;
|
||||
}
|
||||
|
||||
// Extended function to format the date and include the age if it's a birthdate
|
||||
export function fDateTimeWithAge(date: Date | string | number): string {
|
||||
const birthDate = new Date(date);
|
||||
const formattedDate = format(birthDate, 'dd MMM yyyy');
|
||||
const age = calculateAge(birthDate);
|
||||
|
||||
// If the age is 0, the output should be months instead of years
|
||||
let ageText = age > 0 ? `${age} years old` : '';
|
||||
|
||||
if (age === 0) {
|
||||
const monthsOld = new Date().getMonth() - birthDate.getMonth() +
|
||||
(12 * (new Date().getFullYear() - birthDate.getFullYear()));
|
||||
ageText = `${monthsOld} months old`;
|
||||
}
|
||||
|
||||
return `${formattedDate} / ${ageText}`;
|
||||
}
|
||||
|
||||
|
||||
export function fTimestamp(date: Date | string | number) {
|
||||
return getTime(new Date(date));
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
import{r,i as a,a as t}from"./jsx-runtime_commonjs-proxy.b87625c0.js";var e={},o=a.exports;Object.defineProperty(e,"__esModule",{value:!0});var u=e.default=void 0,i=o(r()),d=t,l=(0,i.default)((0,d.jsx)("path",{d:"M11.67 3.87 9.9 2.1 0 12l9.9 9.9 1.77-1.77L3.54 12z"}),"ArrowBackIos");u=e.default=l;export{u as d};
|
||||
@@ -1 +0,0 @@
|
||||
import{a as d,g as u,s as C,P as p,r as f,u as m,e as x,_ as n,j as h,h as y,i as g}from"./index.b0a49137.js";function v(s){return d("MuiCard",s)}u("MuiCard",["root"]);const w=["className","raised"],M=s=>{const{classes:e}=s;return g({root:["root"]},v,e)},P=C(p,{name:"MuiCard",slot:"Root",overridesResolver:(s,e)=>e.root})(()=>({overflow:"hidden"})),R=f.exports.forwardRef(function(e,t){const o=m({props:e,name:"MuiCard"}),{className:i,raised:r=!1}=o,l=x(o,w),a=n({},o,{raised:r}),c=M(a);return h(P,n({className:y(c.root,i),elevation:r?8:void 0,ref:t,ownerState:a},l))}),_=R;export{_ as C};
|
||||
@@ -1 +0,0 @@
|
||||
import{c as h,j as t,g as P,a as B,s as g,aQ as S,b as v,_ as n,a6 as M,r as d,u as _,e as H,h as R,i as O}from"./index.b0a49137.js";import{S as U}from"./SwitchBase.6ffeba1b.js";const V=h(t("path",{d:"M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"}),"CheckBoxOutlineBlank"),j=h(t("path",{d:"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"}),"CheckBox"),L=h(t("path",{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z"}),"IndeterminateCheckBox");function N(o){return B("MuiCheckbox",o)}const w=P("MuiCheckbox",["root","checked","disabled","indeterminate","colorPrimary","colorSecondary"]),p=w,E=["checkedIcon","color","icon","indeterminate","indeterminateIcon","inputProps","size","className"],F=o=>{const{classes:e,indeterminate:c,color:s}=o,r={root:["root",c&&"indeterminate",`color${v(s)}`]},a=O(r,N,e);return n({},e,a)},Q=g(U,{shouldForwardProp:o=>S(o)||o==="classes",name:"MuiCheckbox",slot:"Root",overridesResolver:(o,e)=>{const{ownerState:c}=o;return[e.root,c.indeterminate&&e.indeterminate,c.color!=="default"&&e[`color${v(c.color)}`]]}})(({theme:o,ownerState:e})=>n({color:(o.vars||o).palette.text.secondary},!e.disableRipple&&{"&:hover":{backgroundColor:o.vars?`rgba(${e.color==="default"?o.vars.palette.action.activeChannel:o.vars.palette.primary.mainChannel} / ${o.vars.palette.action.hoverOpacity})`:M(e.color==="default"?o.palette.action.active:o.palette[e.color].main,o.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}}},e.color!=="default"&&{[`&.${p.checked}, &.${p.indeterminate}`]:{color:(o.vars||o).palette[e.color].main},[`&.${p.disabled}`]:{color:(o.vars||o).palette.action.disabled}})),T=t(j,{}),W=t(V,{}),q=t(L,{}),A=d.exports.forwardRef(function(e,c){var s,r;const a=_({props:e,name:"MuiCheckbox"}),{checkedIcon:b=T,color:f="primary",icon:I=W,indeterminate:i=!1,indeterminateIcon:u=q,inputProps:z,size:l="medium",className:$}=a,y=H(a,E),m=i?u:I,C=i?u:b,k=n({},a,{color:f,indeterminate:i,size:l}),x=F(k);return t(Q,n({type:"checkbox",inputProps:n({"data-indeterminate":i},z),icon:d.exports.cloneElement(m,{fontSize:(s=m.props.fontSize)!=null?s:l}),checkedIcon:d.exports.cloneElement(C,{fontSize:(r=C.props.fontSize)!=null?r:l}),ownerState:k,ref:c,className:R(x.root,$)},y,{classes:x}))}),J=A;export{J as C};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
import{au as x,n as g,r as l,Z as b,a0 as v,f as i,F as y,S as n,T as a,j as e,B as w,D as s,q as D}from"./index.b0a49137.js";import{c as d,b as C}from"./formatTime.0646b9d0.js";import{S,a as j,b as I}from"./Stepper.49691c4e.js";import{C as p}from"./Card.a4168b31.js";import"./index.49ea62c1.js";const Y=["Review","Approval","Disbursement"],U=()=>{const{id:h}=x(),m=g(),{corporateValue:c}=l.exports.useContext(b),[f,k]=l.exports.useState(c),[t,u]=l.exports.useState(null);return l.exports.useEffect(()=>{v.get(`${c}/claim-report/${h}`).then(r=>{u(r.data.data)}).catch(r=>{console.error("Terjadi kesalahan:",r)})},[]),l.exports.useEffect(()=>{f!==c&&m("/claim-report")},[c]),i(y,{children:[i(n,{alignItems:"center",justifyContent:"space-between",direction:"row",sx:{marginTop:1},children:[i(a,{variant:"subtitle1",sx:{height:"max-content"},children:["Claim Request for ",t==null?void 0:t.fullName]}),i(n,{children:[e(a,{variant:"caption",children:"Submission date"}),e(a,{variant:"caption",children:d(t?t.submissionDate:new Date,"dd / MM / yyyy")})]})]}),e(w,{sx:{width:"100%",marginTop:2},children:e(S,{activeStep:(t==null?void 0:t.status)==="approved"?1:(t==null?void 0:t.status)==="requested"?0:2,alternativeLabel:!0,children:Y.map(r=>e(j,{children:e(I,{children:r})},r))})}),e(n,{marginTop:2,children:e(a,{variant:"subtitle1",paddingY:2,children:C(t?t==null?void 0:t.histories[0].created_at:new Date)})}),i(n,{direction:"row",spacing:2,children:[e(s,{orientation:"vertical",flexItem:!0,sx:{borderStyle:"dashed"}}),i(n,{spacing:2,sx:{flex:1,maxWidth:"100%"},children:[t==null?void 0:t.histories.map((r,o)=>i(p,{sx:{paddingY:2,paddingX:3},children:[e(n,{direction:"row",justifyContent:"space-between",alignItems:"center",children:i(a,{variant:"body1",children:[d(r.created_at,"HH:mm")," WIB"]})}),e(s,{sx:{marginY:2}}),i(n,{children:[i(a,{variant:"subtitle2",color:"#404040",children:["Details : ",r.description]}),e(a,{variant:"caption",color:"#757575",sx:{marginTop:2,marginBottom:1},children:r.title})]})]},`${r.title}-${o}`)),i(p,{sx:{paddingY:2,paddingX:3},children:[e(n,{direction:"row",justifyContent:"space-between",alignItems:"center",children:i(a,{variant:"body1",fontWeight:600,children:[e(D,{icon:"eva:file-text-fill"})," Dokumen Kelengkapan"]})}),e(s,{sx:{marginY:2}}),e(a,{fontWeight:"600",children:"Kondisi"}),i(n,{children:[e(n,{divider:e(s,{orientation:"horizontal",flexItem:!0}),spacing:1,sx:{marginY:2},children:t&&t.files.claimConditions.map((r,o)=>e(n,{direction:"row",justifyContent:"space-between",children:e("a",{href:r.fileUrl,target:"_blank",style:{textDecoration:"none"},rel:"noreferrer",children:i(a,{sx:{color:"text.secondary"},variant:"subtitle2",children:["- ",r.fileName]})})},o))}),e(a,{fontWeight:"600",children:"Diagnosa"}),e(n,{divider:e(s,{orientation:"horizontal",flexItem:!0}),spacing:1,sx:{marginY:2},children:t&&t.files.claimDiagnosis.map((r,o)=>e(n,{direction:"row",justifyContent:"space-between",children:e("a",{href:r.fileUrl,target:"_blank",style:{textDecoration:"none"},rel:"noreferrer",children:i(a,{sx:{color:"text.secondary"},variant:"subtitle2",children:["- ",r.fileName]})})},o))}),e(a,{fontWeight:"600",children:"Hasil"}),e(n,{divider:e(s,{orientation:"horizontal",flexItem:!0}),spacing:1,sx:{marginY:2},children:t&&t.files.claimResults.map((r,o)=>e(n,{direction:"row",justifyContent:"space-between",children:e("a",{href:r.fileUrl,target:"_blank",style:{textDecoration:"none"},rel:"noreferrer",children:i(a,{sx:{color:"text.secondary"},variant:"subtitle2",children:["- ",r.fileName]})})},o))})]})]})]})]})]})};export{U as default};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
import{g as A,a as C,s as I,_ as c,r as b,u as E,e as L,H as $,j as r,J as z,h as T,T as R,f as _,b as m,i as j}from"./index.b0a49137.js";function F(e){return C("MuiInputAdornment",e)}const M=A("MuiInputAdornment",["root","filled","standard","outlined","positionStart","positionEnd","disablePointerEvents","hiddenLabel","sizeSmall"]),f=M;var g;const N=["children","className","component","disablePointerEvents","disableTypography","position","variant"],S=(e,t)=>{const{ownerState:n}=e;return[t.root,t[`position${m(n.position)}`],n.disablePointerEvents===!0&&t.disablePointerEvents,t[n.variant]]},U=e=>{const{classes:t,disablePointerEvents:n,hiddenLabel:o,position:s,size:a,variant:l}=e,d={root:["root",n&&"disablePointerEvents",s&&`position${m(s)}`,l,o&&"hiddenLabel",a&&`size${m(a)}`]};return j(d,F,t)},w=I("div",{name:"MuiInputAdornment",slot:"Root",overridesResolver:S})(({theme:e,ownerState:t})=>c({display:"flex",height:"0.01em",maxHeight:"2em",alignItems:"center",whiteSpace:"nowrap",color:(e.vars||e).palette.action.active},t.variant==="filled"&&{[`&.${f.positionStart}&:not(.${f.hiddenLabel})`]:{marginTop:16}},t.position==="start"&&{marginRight:8},t.position==="end"&&{marginLeft:8},t.disablePointerEvents===!0&&{pointerEvents:"none"})),H=b.exports.forwardRef(function(t,n){const o=E({props:t,name:"MuiInputAdornment"}),{children:s,className:a,component:l="div",disablePointerEvents:d=!1,disableTypography:x=!1,position:u,variant:v}=o,P=L(o,N),i=$()||{};let p=v;v&&i.variant,i&&!p&&(p=i.variant);const h=c({},o,{hiddenLabel:i.hiddenLabel,size:i.size,disablePointerEvents:d,position:u,variant:p}),y=U(h);return r(z.Provider,{value:null,children:r(w,c({as:l,ownerState:h,className:T(y.root,a),ref:n},P,{children:typeof s=="string"&&!x?r(R,{color:"text.secondary",children:s}):_(b.exports.Fragment,{children:[u==="start"?g||(g=r("span",{className:"notranslate",children:"\u200B"})):null,s]})}))})}),J=H;export{J as I};
|
||||
@@ -1 +0,0 @@
|
||||
import{c as r,j as o}from"./index.b0a49137.js";const t=r(o("path",{d:"M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"}),"KeyboardArrowLeft"),e=r(o("path",{d:"M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"}),"KeyboardArrowRight");export{e as K,t as a};
|
||||
@@ -1 +0,0 @@
|
||||
import{v as p,j as d,s as g,a6 as c}from"./index.b0a49137.js";const y=g("span")(({theme:t,ownerState:r})=>{const n=t.palette.mode==="light",{color:l,variant:a}=r,e=o=>({color:t.palette[o].contrastText,backgroundColor:t.palette[o].main}),i=o=>({color:t.palette[o].main,backgroundColor:"transparent",border:`1px solid ${t.palette[o].main}`}),s=o=>({color:t.palette[o][n?"dark":"light"],backgroundColor:c(t.palette[o].main,.16)});return{height:22,minWidth:22,lineHeight:0,borderRadius:6,alignItems:"center",whiteSpace:"nowrap",display:"inline-flex",justifyContent:"center",padding:t.spacing(0,1),color:t.palette.grey[800],fontSize:t.typography.pxToRem(12),fontFamily:t.typography.fontFamily,backgroundColor:t.palette.grey[300],fontWeight:t.typography.fontWeightBold,...l!=="default"?{...a==="filled"&&{...e(l)},...a==="outlined"&&{...i(l)},...a==="ghost"&&{...s(l)}}:{...a==="outlined"&&{backgroundColor:"transparent",color:t.palette.text.primary,border:`1px solid ${t.palette.grey[50032]}`},...a==="ghost"&&{color:n?t.palette.text.secondary:t.palette.common.white,backgroundColor:t.palette.grey[50016]}}}});function f({color:t="default",variant:r="ghost",children:n,sx:l}){const a=p();return d(y,{ownerState:{color:t,variant:r},sx:l,theme:a,children:n})}export{f as L};
|
||||
@@ -1 +0,0 @@
|
||||
import{c as a,j as s}from"./index.b0a49137.js";const o=a(s("path",{d:"M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z"}),"FirstPage"),c=a(s("path",{d:"M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z"}),"LastPage");export{o as F,c as L};
|
||||
@@ -1,54 +0,0 @@
|
||||
import{g as q,a as M,C as h,s as b,b as t,_ as s,E as C,r as z,u as D,e as T,v as j,f as U,j as p,h as O,i as A,l as K,d as w}from"./index.b0a49137.js";function X(r){return M("MuiLinearProgress",r)}const E=q("MuiLinearProgress",["root","colorPrimary","colorSecondary","determinate","indeterminate","buffer","query","dashed","dashedColorPrimary","dashedColorSecondary","bar","barColorPrimary","barColorSecondary","bar1Indeterminate","bar1Determinate","bar1Buffer","bar2Indeterminate","bar2Buffer"]),er=E,S=["className","color","value","valueBuffer","variant"];let l=r=>r,x,L,k,B,I,_;const v=4,W=h(x||(x=l`
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%;
|
||||
}
|
||||
`)),F=h(L||(L=l`
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%;
|
||||
}
|
||||
`)),G=h(k||(k=l`
|
||||
0% {
|
||||
opacity: 1;
|
||||
background-position: 0 -23px;
|
||||
}
|
||||
|
||||
60% {
|
||||
opacity: 0;
|
||||
background-position: 0 -23px;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
background-position: -200px -23px;
|
||||
}
|
||||
`)),H=r=>{const{classes:e,variant:a,color:o}=r,m={root:["root",`color${t(o)}`,a],dashed:["dashed",`dashedColor${t(o)}`],bar1:["bar",`barColor${t(o)}`,(a==="indeterminate"||a==="query")&&"bar1Indeterminate",a==="determinate"&&"bar1Determinate",a==="buffer"&&"bar1Buffer"],bar2:["bar",a!=="buffer"&&`barColor${t(o)}`,a==="buffer"&&`color${t(o)}`,(a==="indeterminate"||a==="query")&&"bar2Indeterminate",a==="buffer"&&"bar2Buffer"]};return A(m,X,e)},P=(r,e)=>e==="inherit"?"currentColor":r.vars?r.vars.palette.LinearProgress[`${e}Bg`]:r.palette.mode==="light"?K(r.palette[e].main,.62):w(r.palette[e].main,.5),J=b("span",{name:"MuiLinearProgress",slot:"Root",overridesResolver:(r,e)=>{const{ownerState:a}=r;return[e.root,e[`color${t(a.color)}`],e[a.variant]]}})(({ownerState:r,theme:e})=>s({position:"relative",overflow:"hidden",display:"block",height:4,zIndex:0,"@media print":{colorAdjust:"exact"},backgroundColor:P(e,r.color)},r.color==="inherit"&&r.variant!=="buffer"&&{backgroundColor:"none","&::before":{content:'""',position:"absolute",left:0,top:0,right:0,bottom:0,backgroundColor:"currentColor",opacity:.3}},r.variant==="buffer"&&{backgroundColor:"transparent"},r.variant==="query"&&{transform:"rotate(180deg)"})),Q=b("span",{name:"MuiLinearProgress",slot:"Dashed",overridesResolver:(r,e)=>{const{ownerState:a}=r;return[e.dashed,e[`dashedColor${t(a.color)}`]]}})(({ownerState:r,theme:e})=>{const a=P(e,r.color);return s({position:"absolute",marginTop:0,height:"100%",width:"100%"},r.color==="inherit"&&{opacity:.3},{backgroundImage:`radial-gradient(${a} 0%, ${a} 16%, transparent 42%)`,backgroundSize:"10px 10px",backgroundPosition:"0 -23px"})},C(B||(B=l`
|
||||
animation: ${0} 3s infinite linear;
|
||||
`),G)),V=b("span",{name:"MuiLinearProgress",slot:"Bar1",overridesResolver:(r,e)=>{const{ownerState:a}=r;return[e.bar,e[`barColor${t(a.color)}`],(a.variant==="indeterminate"||a.variant==="query")&&e.bar1Indeterminate,a.variant==="determinate"&&e.bar1Determinate,a.variant==="buffer"&&e.bar1Buffer]}})(({ownerState:r,theme:e})=>s({width:"100%",position:"absolute",left:0,bottom:0,top:0,transition:"transform 0.2s linear",transformOrigin:"left",backgroundColor:r.color==="inherit"?"currentColor":(e.vars||e).palette[r.color].main},r.variant==="determinate"&&{transition:`transform .${v}s linear`},r.variant==="buffer"&&{zIndex:1,transition:`transform .${v}s linear`}),({ownerState:r})=>(r.variant==="indeterminate"||r.variant==="query")&&C(I||(I=l`
|
||||
width: auto;
|
||||
animation: ${0} 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
`),W)),Y=b("span",{name:"MuiLinearProgress",slot:"Bar2",overridesResolver:(r,e)=>{const{ownerState:a}=r;return[e.bar,e[`barColor${t(a.color)}`],(a.variant==="indeterminate"||a.variant==="query")&&e.bar2Indeterminate,a.variant==="buffer"&&e.bar2Buffer]}})(({ownerState:r,theme:e})=>s({width:"100%",position:"absolute",left:0,bottom:0,top:0,transition:"transform 0.2s linear",transformOrigin:"left"},r.variant!=="buffer"&&{backgroundColor:r.color==="inherit"?"currentColor":(e.vars||e).palette[r.color].main},r.color==="inherit"&&{opacity:.3},r.variant==="buffer"&&{backgroundColor:P(e,r.color),transition:`transform .${v}s linear`}),({ownerState:r})=>(r.variant==="indeterminate"||r.variant==="query")&&C(_||(_=l`
|
||||
width: auto;
|
||||
animation: ${0} 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) 1.15s infinite;
|
||||
`),F)),Z=z.exports.forwardRef(function(e,a){const o=D({props:e,name:"MuiLinearProgress"}),{className:m,color:N="primary",value:g,valueBuffer:y,variant:i="indeterminate"}=o,R=T(o,S),c=s({},o,{color:N,variant:i}),f=H(c),$=j(),u={},d={bar1:{},bar2:{}};if((i==="determinate"||i==="buffer")&&g!==void 0){u["aria-valuenow"]=Math.round(g),u["aria-valuemin"]=0,u["aria-valuemax"]=100;let n=g-100;$.direction==="rtl"&&(n=-n),d.bar1.transform=`translateX(${n}%)`}if(i==="buffer"&&y!==void 0){let n=(y||0)-100;$.direction==="rtl"&&(n=-n),d.bar2.transform=`translateX(${n}%)`}return U(J,s({className:O(f.root,m),ownerState:c,role:"progressbar"},u,{ref:a},R,{children:[i==="buffer"?p(Q,{className:f.dashed,ownerState:c}):null,p(V,{className:f.bar1,ownerState:c,style:d.bar1}),i==="determinate"?null:p(Y,{className:f.bar2,ownerState:c,style:d.bar2})]}))}),ar=Z;export{ar as L,er as l};
|
||||
@@ -1,28 +0,0 @@
|
||||
import{a as F,g as W,C as D,s as v,b as u,_ as r,E as U,r as L,u as N,e as z,j as h,h as j,i as G,G as K,f as B}from"./index.b0a49137.js";import{g as T,a as V,c as Z}from"./generateUtilityClasses.06032f54.js";import{u as q}from"./useId.c3f149cd.js";function A(t){return F("MuiCircularProgress",t)}W("MuiCircularProgress",["root","determinate","indeterminate","colorPrimary","colorSecondary","svg","circle","circleDeterminate","circleIndeterminate","circleDisableShrink"]);const H=["className","color","disableShrink","size","style","thickness","value","variant"];let $=t=>t,M,R,S,E;const g=44,J=D(M||(M=$`
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`)),O=D(R||(R=$`
|
||||
0% {
|
||||
stroke-dasharray: 1px, 200px;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
stroke-dasharray: 100px, 200px;
|
||||
stroke-dashoffset: -15px;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke-dasharray: 100px, 200px;
|
||||
stroke-dashoffset: -125px;
|
||||
}
|
||||
`)),Q=t=>{const{classes:o,variant:i,color:a,disableShrink:e}=t,c={root:["root",i,`color${u(a)}`],svg:["svg"],circle:["circle",`circle${u(i)}`,e&&"circleDisableShrink"]};return G(c,A,o)},X=v("span",{name:"MuiCircularProgress",slot:"Root",overridesResolver:(t,o)=>{const{ownerState:i}=t;return[o.root,o[i.variant],o[`color${u(i.color)}`]]}})(({ownerState:t,theme:o})=>r({display:"inline-block"},t.variant==="determinate"&&{transition:o.transitions.create("transform")},t.color!=="inherit"&&{color:(o.vars||o).palette[t.color].main}),({ownerState:t})=>t.variant==="indeterminate"&&U(S||(S=$`
|
||||
animation: ${0} 1.4s linear infinite;
|
||||
`),J)),Y=v("svg",{name:"MuiCircularProgress",slot:"Svg",overridesResolver:(t,o)=>o.svg})({display:"block"}),w=v("circle",{name:"MuiCircularProgress",slot:"Circle",overridesResolver:(t,o)=>{const{ownerState:i}=t;return[o.circle,o[`circle${u(i.variant)}`],i.disableShrink&&o.circleDisableShrink]}})(({ownerState:t,theme:o})=>r({stroke:"currentColor"},t.variant==="determinate"&&{transition:o.transitions.create("stroke-dashoffset")},t.variant==="indeterminate"&&{strokeDasharray:"80px, 200px",strokeDashoffset:0}),({ownerState:t})=>t.variant==="indeterminate"&&!t.disableShrink&&U(E||(E=$`
|
||||
animation: ${0} 1.4s ease-in-out infinite;
|
||||
`),O)),oo=L.exports.forwardRef(function(o,i){const a=N({props:o,name:"MuiCircularProgress"}),{className:e,color:c="primary",disableShrink:C=!1,size:l=40,style:I,thickness:p=3.6,value:m=0,variant:P="indeterminate"}=a,x=z(a,H),d=r({},a,{color:c,disableShrink:C,size:l,thickness:p,value:m,variant:P}),n=Q(d),f={},y={},k={};if(P==="determinate"){const b=2*Math.PI*((g-p)/2);f.strokeDasharray=b.toFixed(3),k["aria-valuenow"]=Math.round(m),f.strokeDashoffset=`${((100-m)/100*b).toFixed(3)}px`,y.transform="rotate(-90deg)"}return h(X,r({className:j(n.root,e),style:r({width:l,height:l},y,I),ownerState:d,ref:i,role:"progressbar"},k,x,{children:h(Y,{className:n.svg,ownerState:d,viewBox:`${g/2} ${g/2} ${g} ${g}`,children:h(w,{className:n.circle,style:f,ownerState:d,cx:g,cy:g,r:(g-p)/2,fill:"none",strokeWidth:p})})}))}),to=oo;function io(t){return V("MuiLoadingButton",t)}const ao=T("MuiLoadingButton",["root","loading","loadingIndicator","loadingIndicatorCenter","loadingIndicatorStart","loadingIndicatorEnd","endIconLoadingEnd","startIconLoadingStart"]),s=ao,ro=["children","disabled","id","loading","loadingIndicator","loadingPosition","variant"],no=t=>{const{loading:o,loadingPosition:i,classes:a}=t,e={root:["root",o&&"loading"],startIcon:[o&&`startIconLoading${u(i)}`],endIcon:[o&&`endIconLoading${u(i)}`],loadingIndicator:["loadingIndicator",o&&`loadingIndicator${u(i)}`]},c=Z(e,io,a);return r({},a,c)},so=t=>t!=="ownerState"&&t!=="theme"&&t!=="sx"&&t!=="as"&&t!=="classes",eo=v(K,{shouldForwardProp:t=>so(t)||t==="classes",name:"MuiLoadingButton",slot:"Root",overridesResolver:(t,o)=>[o.root,o.startIconLoadingStart&&{[`& .${s.startIconLoadingStart}`]:o.startIconLoadingStart},o.endIconLoadingEnd&&{[`& .${s.endIconLoadingEnd}`]:o.endIconLoadingEnd}]})(({ownerState:t,theme:o})=>r({[`& .${s.startIconLoadingStart}, & .${s.endIconLoadingEnd}`]:{transition:o.transitions.create(["opacity"],{duration:o.transitions.duration.short}),opacity:0}},t.loadingPosition==="center"&&{transition:o.transitions.create(["background-color","box-shadow","border-color"],{duration:o.transitions.duration.short}),[`&.${s.loading}`]:{color:"transparent"}},t.loadingPosition==="start"&&t.fullWidth&&{[`& .${s.startIconLoadingStart}, & .${s.endIconLoadingEnd}`]:{transition:o.transitions.create(["opacity"],{duration:o.transitions.duration.short}),opacity:0,marginRight:-8}},t.loadingPosition==="end"&&t.fullWidth&&{[`& .${s.startIconLoadingStart}, & .${s.endIconLoadingEnd}`]:{transition:o.transitions.create(["opacity"],{duration:o.transitions.duration.short}),opacity:0,marginLeft:-8}})),_=v("div",{name:"MuiLoadingButton",slot:"LoadingIndicator",overridesResolver:(t,o)=>{const{ownerState:i}=t;return[o.loadingIndicator,o[`loadingIndicator${u(i.loadingPosition)}`]]}})(({theme:t,ownerState:o})=>r({position:"absolute",visibility:"visible",display:"flex"},o.loadingPosition==="start"&&(o.variant==="outlined"||o.variant==="contained")&&{left:o.size==="small"?10:14},o.loadingPosition==="start"&&o.variant==="text"&&{left:6},o.loadingPosition==="center"&&{left:"50%",transform:"translate(-50%)",color:t.palette.action.disabled},o.loadingPosition==="end"&&(o.variant==="outlined"||o.variant==="contained")&&{right:o.size==="small"?10:14},o.loadingPosition==="end"&&o.variant==="text"&&{right:6},o.loadingPosition==="start"&&o.fullWidth&&{position:"relative",left:-10},o.loadingPosition==="end"&&o.fullWidth&&{position:"relative",right:-10})),co=L.exports.forwardRef(function(o,i){const a=N({props:o,name:"MuiLoadingButton"}),{children:e,disabled:c=!1,id:C,loading:l=!1,loadingIndicator:I,loadingPosition:p="center",variant:m="text"}=a,P=z(a,ro),x=q(C),d=I!=null?I:h(to,{"aria-labelledby":x,color:"inherit",size:16}),n=r({},a,{disabled:c,loading:l,loadingIndicator:d,loadingPosition:p,variant:m}),f=no(n);return h(eo,r({disabled:c||l,id:x,ref:i},P,{variant:m,classes:f,ownerState:n,children:n.loadingPosition==="end"?B(L.exports.Fragment,{children:[e,l&&h(_,{className:f.loadingIndicator,ownerState:n,children:d})]}):B(L.exports.Fragment,{children:[l&&h(_,{className:f.loadingIndicator,ownerState:n,children:d}),e]})}))}),fo=co;export{fo as L};
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
import{r as c,f as a,F as i,W as x,j as e,B as d}from"./index.b0a49137.js";const f=c.exports.forwardRef(({children:r,title:s="",meta:t,...o},n)=>a(i,{children:[a(x,{children:[e("title",{children:`${s} | LinkSehat`}),t]}),e(d,{ref:n,...o,children:r})]})),l=f;export{l as P};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
import{c,j as a}from"./index.b0a49137.js";const r=c(a("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),"Search");export{r as S};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,51 +0,0 @@
|
||||
import{a as y,g as x,C as b,s as R,_ as o,a6 as _,E as u,r as S,u as $,e as U,j as M,h as A,i as X}from"./index.b0a49137.js";function j(t){return String(t).match(/[\d.\-+]*\s*(.*)/)[1]||""}function N(t){return parseFloat(t)}function B(t){return y("MuiSkeleton",t)}x("MuiSkeleton",["root","text","rectangular","rounded","circular","pulse","wave","withChildren","fitContent","heightAuto"]);const F=["animation","className","component","height","style","variant","width"];let r=t=>t,p,g,m,f;const K=t=>{const{classes:a,variant:e,animation:i,hasChildren:n,width:l,height:s}=t;return X({root:["root",e,i,n&&"withChildren",n&&!l&&"fitContent",n&&!s&&"heightAuto"]},B,a)},P=b(p||(p=r`
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
`)),T=b(g||(g=r`
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
50% {
|
||||
/* +0.5s of delay between each loop */
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
`)),W=R("span",{name:"MuiSkeleton",slot:"Root",overridesResolver:(t,a)=>{const{ownerState:e}=t;return[a.root,a[e.variant],e.animation!==!1&&a[e.animation],e.hasChildren&&a.withChildren,e.hasChildren&&!e.width&&a.fitContent,e.hasChildren&&!e.height&&a.heightAuto]}})(({theme:t,ownerState:a})=>{const e=j(t.shape.borderRadius)||"px",i=N(t.shape.borderRadius);return o({display:"block",backgroundColor:t.vars?t.vars.palette.Skeleton.bg:_(t.palette.text.primary,t.palette.mode==="light"?.11:.13),height:"1.2em"},a.variant==="text"&&{marginTop:0,marginBottom:0,height:"auto",transformOrigin:"0 55%",transform:"scale(1, 0.60)",borderRadius:`${i}${e}/${Math.round(i/.6*10)/10}${e}`,"&:empty:before":{content:'"\\00a0"'}},a.variant==="circular"&&{borderRadius:"50%"},a.variant==="rounded"&&{borderRadius:(t.vars||t).shape.borderRadius},a.hasChildren&&{"& > *":{visibility:"hidden"}},a.hasChildren&&!a.width&&{maxWidth:"fit-content"},a.hasChildren&&!a.height&&{height:"auto"})},({ownerState:t})=>t.animation==="pulse"&&u(m||(m=r`
|
||||
animation: ${0} 1.5s ease-in-out 0.5s infinite;
|
||||
`),P),({ownerState:t,theme:a})=>t.animation==="wave"&&u(f||(f=r`
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
/* Fix bug in Safari https://bugs.webkit.org/show_bug.cgi?id=68196 */
|
||||
-webkit-mask-image: -webkit-radial-gradient(white, black);
|
||||
|
||||
&::after {
|
||||
animation: ${0} 1.6s linear 0.5s infinite;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
${0},
|
||||
transparent
|
||||
);
|
||||
content: '';
|
||||
position: absolute;
|
||||
transform: translateX(-100%); /* Avoid flash during server-side hydration */
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
`),T,(a.vars||a).palette.action.hover)),E=S.exports.forwardRef(function(a,e){const i=$({props:a,name:"MuiSkeleton"}),{animation:n="pulse",className:l,component:s="span",height:h,style:v,variant:C="text",width:k}=i,d=U(i,F),c=o({},i,{animation:n,component:s,variant:C,hasChildren:Boolean(d.children)}),w=K(c);return M(W,o({as:s,ref:e,className:A(w.root,l),ownerState:c},d,{style:o({width:k,height:h},v)}))}),O=E;export{O as S};
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
import{a as $,g as H,s as x,a3 as W,_ as d,r as A,e as D,ao as G,H as J,f as K,j as M,h as Q,b as T,i as V}from"./index.b0a49137.js";function X(e){return $("PrivateSwitchBase",e)}H("PrivateSwitchBase",["root","checked","disabled","input","edgeStart","edgeEnd"]);const Y=["autoFocus","checked","checkedIcon","className","defaultChecked","disabled","disableFocusRipple","edge","icon","id","inputProps","inputRef","name","onBlur","onChange","onFocus","readOnly","required","tabIndex","type","value"],Z=e=>{const{classes:a,checked:i,disabled:l,edge:o}=e,r={root:["root",i&&"checked",l&&"disabled",o&&`edge${T(o)}`],input:["input"]};return V(r,X,a)},ee=x(W)(({ownerState:e})=>d({padding:9,borderRadius:"50%"},e.edge==="start"&&{marginLeft:e.size==="small"?-3:-12},e.edge==="end"&&{marginRight:e.size==="small"?-3:-12})),se=x("input")({cursor:"inherit",position:"absolute",opacity:0,width:"100%",height:"100%",top:0,left:0,margin:0,padding:0,zIndex:1}),te=A.exports.forwardRef(function(a,i){const{autoFocus:l,checked:o,checkedIcon:r,className:F,defaultChecked:h,disabled:y,disableFocusRipple:p=!1,edge:w=!1,icon:S,id:R,inputProps:I,inputRef:P,name:j,onBlur:f,onChange:g,onFocus:b,readOnly:z,required:N=!1,tabIndex:U,type:c,value:m}=a,_=D(a,Y),[k,q]=G({controlled:o,default:Boolean(h),name:"SwitchBase",state:"checked"}),t=J(),v=s=>{b&&b(s),t&&t.onFocus&&t.onFocus(s)},L=s=>{f&&f(s),t&&t.onBlur&&t.onBlur(s)},O=s=>{if(s.nativeEvent.defaultPrevented)return;const C=s.target.checked;q(C),g&&g(s,C)};let n=y;t&&typeof n>"u"&&(n=t.disabled);const E=c==="checkbox"||c==="radio",u=d({},a,{checked:k,disabled:n,disableFocusRipple:p,edge:w}),B=Z(u);return K(ee,d({component:"span",className:Q(B.root,F),centerRipple:!0,focusRipple:!p,disabled:n,tabIndex:null,role:void 0,onFocus:v,onBlur:L,ownerState:u,ref:i},_,{children:[M(se,d({autoFocus:l,checked:o,defaultChecked:h,className:B.input,disabled:n,id:E?R:void 0,name:j,onChange:O,readOnly:z,ref:P,required:N,ownerState:u,tabIndex:U,type:c},c==="checkbox"&&m===void 0?{}:{value:m},I)),k?r:S]}))}),oe=te;export{oe as S};
|
||||
@@ -1 +0,0 @@
|
||||
import{a as u,g as p,s as C,r as m,u as T,e as b,_ as r,j as d,h as f,i as x}from"./index.b0a49137.js";function h(e){return u("MuiTableContainer",e)}p("MuiTableContainer",["root"]);const v=["className","component"],w=e=>{const{classes:s}=e;return x({root:["root"]},h,s)},y=C("div",{name:"MuiTableContainer",slot:"Root",overridesResolver:(e,s)=>s.root})({width:"100%",overflowX:"auto"}),g=m.exports.forwardRef(function(s,t){const o=T({props:s,name:"MuiTableContainer"}),{className:i,component:a="div"}=o,l=b(o,v),n=r({},o,{component:a}),c=w(n);return d(y,r({ref:t,as:a,className:f(c.root,i),ownerState:n},l))}),R=g;export{R as T};
|
||||
@@ -1 +0,0 @@
|
||||
import{a as u,g as m,s as b,r as T,u as h,e as H,_ as l,j as n,h as f,i as v}from"./index.b0a49137.js";import{d as x}from"./TableRow.41459f01.js";function C(e){return u("MuiTableHead",e)}m("MuiTableHead",["root"]);const g=["className","component"],y=e=>{const{classes:s}=e;return v({root:["root"]},C,s)},w=b("thead",{name:"MuiTableHead",slot:"Root",overridesResolver:(e,s)=>s.root})({display:"table-header-group"}),M={variant:"head"},c="thead",R=T.exports.forwardRef(function(s,a){const o=h({props:s,name:"MuiTableHead"}),{className:d,component:t=c}=o,i=H(o,g),r=l({},o,{component:t}),p=y(r);return n(x.Provider,{value:M,children:n(w,l({as:t,className:f(p.root,d),ref:a,role:t===c?null:"rowgroup",ownerState:r},i))})}),j=R;export{j as T};
|
||||
@@ -1 +0,0 @@
|
||||
import{r as n,f as h,F as c,j as o,I as p,q as u,af as d}from"./index.b0a49137.js";function f({actions:t,disableRipple:a}){const[r,e]=n.exports.useState(null);n.exports.useEffect(()=>{e(null)},[t]);const i=s=>{e(s.currentTarget)},l=()=>{e(null)};return h(c,{children:[o(p,{onClick:i,disableRipple:a,children:o(u,{icon:"eva:more-vertical-fill",width:20,height:20})}),o(d,{open:Boolean(r),anchorEl:r,onClose:l,anchorOrigin:{vertical:"top",horizontal:"left"},transformOrigin:{vertical:"top",horizontal:"right"},arrow:"right-top",sx:{mt:-1,width:"auto",minWidth:160,"& .MuiMenuItem-root":{px:1,typography:"body2",borderRadius:.75,"& svg":{mr:2,width:20,height:20}}},children:t}),"\xA0\xA0\xA0\xA0"]})}export{f as T};
|
||||
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
import{r as c,a as m,g as $,s as R,_ as i,u as h,e as k,j as y,h as w,i as H,b as u,l as W,a6 as T,d as L}from"./index.b0a49137.js";const I=c.exports.createContext(),j=I;function J(e){return m("MuiTable",e)}$("MuiTable",["root","stickyHeader"]);const q=["className","component","padding","size","stickyHeader"],E=e=>{const{classes:o,stickyHeader:t}=e;return H({root:["root",t&&"stickyHeader"]},J,o)},F=R("table",{name:"MuiTable",slot:"Root",overridesResolver:(e,o)=>{const{ownerState:t}=e;return[o.root,t.stickyHeader&&o.stickyHeader]}})(({theme:e,ownerState:o})=>i({display:"table",width:"100%",borderCollapse:"collapse",borderSpacing:0,"& caption":i({},e.typography.body2,{padding:e.spacing(2),color:(e.vars||e).palette.text.secondary,textAlign:"left",captionSide:"bottom"})},o.stickyHeader&&{borderCollapse:"separate"})),A="table",G=c.exports.forwardRef(function(o,t){const a=h({props:o,name:"MuiTable"}),{className:r,component:s=A,padding:l="normal",size:n="medium",stickyHeader:d=!1}=a,b=k(a,q),p=i({},a,{component:s,padding:l,size:n,stickyHeader:d}),v=E(p),M=c.exports.useMemo(()=>({padding:l,size:n,stickyHeader:d}),[l,n,d]);return y(j.Provider,{value:M,children:y(F,i({as:s,role:s===A?null:"table",ref:t,className:w(v.root,r),ownerState:p},b))})}),ye=G,K=c.exports.createContext(),z=K;function Q(e){return m("MuiTableBody",e)}$("MuiTableBody",["root"]);const V=["className","component"],X=e=>{const{classes:o}=e;return H({root:["root"]},Q,o)},Y=R("tbody",{name:"MuiTableBody",slot:"Root",overridesResolver:(e,o)=>o.root})({display:"table-row-group"}),Z={variant:"body"},_="tbody",ee=c.exports.forwardRef(function(o,t){const a=h({props:o,name:"MuiTableBody"}),{className:r,component:s=_}=a,l=k(a,V),n=i({},a,{component:s}),d=X(n);return y(z.Provider,{value:Z,children:y(Y,i({className:w(d.root,r),as:s,ref:t,role:s===_?null:"rowgroup",ownerState:n},l))})}),ve=ee;function oe(e){return m("MuiTableCell",e)}const te=$("MuiTableCell",["root","head","body","footer","sizeSmall","sizeMedium","paddingCheckbox","paddingNone","alignLeft","alignCenter","alignRight","alignJustify","stickyHeader"]),ae=te,se=["align","className","component","padding","scope","size","sortDirection","variant"],le=e=>{const{classes:o,variant:t,align:a,padding:r,size:s,stickyHeader:l}=e,n={root:["root",t,l&&"stickyHeader",a!=="inherit"&&`align${u(a)}`,r!=="normal"&&`padding${u(r)}`,`size${u(s)}`]};return H(n,oe,o)},re=R("td",{name:"MuiTableCell",slot:"Root",overridesResolver:(e,o)=>{const{ownerState:t}=e;return[o.root,o[t.variant],o[`size${u(t.size)}`],t.padding!=="normal"&&o[`padding${u(t.padding)}`],t.align!=="inherit"&&o[`align${u(t.align)}`],t.stickyHeader&&o.stickyHeader]}})(({theme:e,ownerState:o})=>i({},e.typography.body2,{display:"table-cell",verticalAlign:"inherit",borderBottom:e.vars?`1px solid ${e.vars.palette.TableCell.border}`:`1px solid
|
||||
${e.palette.mode==="light"?W(T(e.palette.divider,1),.88):L(T(e.palette.divider,1),.68)}`,textAlign:"left",padding:16},o.variant==="head"&&{color:(e.vars||e).palette.text.primary,lineHeight:e.typography.pxToRem(24),fontWeight:e.typography.fontWeightMedium},o.variant==="body"&&{color:(e.vars||e).palette.text.primary},o.variant==="footer"&&{color:(e.vars||e).palette.text.secondary,lineHeight:e.typography.pxToRem(21),fontSize:e.typography.pxToRem(12)},o.size==="small"&&{padding:"6px 16px",[`&.${ae.paddingCheckbox}`]:{width:24,padding:"0 12px 0 16px","& > *":{padding:0}}},o.padding==="checkbox"&&{width:48,padding:"0 0 0 4px"},o.padding==="none"&&{padding:0},o.align==="left"&&{textAlign:"left"},o.align==="center"&&{textAlign:"center"},o.align==="right"&&{textAlign:"right",flexDirection:"row-reverse"},o.align==="justify"&&{textAlign:"justify"},o.stickyHeader&&{position:"sticky",top:0,zIndex:2,backgroundColor:(e.vars||e).palette.background.default})),ne=c.exports.forwardRef(function(o,t){const a=h({props:o,name:"MuiTableCell"}),{align:r="inherit",className:s,component:l,padding:n,scope:d,size:b,sortDirection:p,variant:v}=a,M=k(a,se),g=c.exports.useContext(j),x=c.exports.useContext(z),N=x&&x.variant==="head";let f;l?f=l:f=N?"th":"td";let C=d;f==="td"?C=void 0:!C&&N&&(C="col");const B=v||x&&x.variant,U=i({},a,{align:r,component:f,padding:n||(g&&g.padding?g.padding:"normal"),size:b||(g&&g.size?g.size:"medium"),sortDirection:p,stickyHeader:B==="head"&&g&&g.stickyHeader,variant:B}),D=le(U);let P=null;return p&&(P=p==="asc"?"ascending":"descending"),y(re,i({as:f,ref:t,className:w(D.root,s),"aria-sort":P,scope:C,ownerState:U},M))}),fe=ne;function ie(e){return m("MuiTableRow",e)}const ce=$("MuiTableRow",["root","selected","hover","head","footer"]),O=ce,de=["className","component","hover","selected"],pe=e=>{const{classes:o,selected:t,hover:a,head:r,footer:s}=e;return H({root:["root",t&&"selected",a&&"hover",r&&"head",s&&"footer"]},ie,o)},be=R("tr",{name:"MuiTableRow",slot:"Root",overridesResolver:(e,o)=>{const{ownerState:t}=e;return[o.root,t.head&&o.head,t.footer&&o.footer]}})(({theme:e})=>({color:"inherit",display:"table-row",verticalAlign:"middle",outline:0,[`&.${O.hover}:hover`]:{backgroundColor:(e.vars||e).palette.action.hover},[`&.${O.selected}`]:{backgroundColor:e.vars?`rgba(${e.vars.palette.primary.mainChannel} / ${e.vars.palette.action.selectedOpacity})`:T(e.palette.primary.main,e.palette.action.selectedOpacity),"&:hover":{backgroundColor:e.vars?`rgba(${e.vars.palette.primary.mainChannel} / calc(${e.vars.palette.action.selectedOpacity} + ${e.vars.palette.action.hoverOpacity}))`:T(e.palette.primary.main,e.palette.action.selectedOpacity+e.palette.action.hoverOpacity)}}})),S="tr",ge=c.exports.forwardRef(function(o,t){const a=h({props:o,name:"MuiTableRow"}),{className:r,component:s=S,hover:l=!1,selected:n=!1}=a,d=k(a,de),b=c.exports.useContext(z),p=i({},a,{component:s,hover:l,selected:n,head:b&&b.variant==="head",footer:b&&b.variant==="footer"}),v=pe(p);return y(be,i({as:s,ref:t,className:w(v.root,r),role:s===S?null:"row",ownerState:p},d))}),xe=ge;export{ye as T,ve as a,xe as b,fe as c,z as d};
|
||||
@@ -1 +0,0 @@
|
||||
import{g as q,a as S,s as N,b as L,_ as l,r as U,u as _,e as B,H as se,K as le,j as c,h as W,i as j,M as ae,f as ie,N as ne,Q as de,U as ue,V as ce,O as pe}from"./index.b0a49137.js";import{u as fe}from"./useId.c3f149cd.js";function me(e){return S("MuiFormHelperText",e)}const xe=q("MuiFormHelperText",["root","error","disabled","sizeSmall","sizeMedium","contained","focused","filled","required"]),M=xe;var $;const Fe=["children","className","component","disabled","error","filled","focused","margin","required","variant"],he=e=>{const{classes:o,contained:t,size:s,disabled:i,error:n,filled:d,focused:p,required:u}=e,r={root:["root",i&&"disabled",n&&"error",s&&`size${L(s)}`,t&&"contained",p&&"focused",d&&"filled",u&&"required"]};return j(r,me,o)},be=N("p",{name:"MuiFormHelperText",slot:"Root",overridesResolver:(e,o)=>{const{ownerState:t}=e;return[o.root,t.size&&o[`size${L(t.size)}`],t.contained&&o.contained,t.filled&&o.filled]}})(({theme:e,ownerState:o})=>l({color:(e.vars||e).palette.text.secondary},e.typography.caption,{textAlign:"left",marginTop:3,marginRight:0,marginBottom:0,marginLeft:0,[`&.${M.disabled}`]:{color:(e.vars||e).palette.text.disabled},[`&.${M.error}`]:{color:(e.vars||e).palette.error.main}},o.size==="small"&&{marginTop:4},o.contained&&{marginLeft:14,marginRight:14})),Te=U.exports.forwardRef(function(o,t){const s=_({props:o,name:"MuiFormHelperText"}),{children:i,className:n,component:d="p"}=s,p=B(s,Fe),u=se(),r=le({props:s,muiFormControl:u,states:["variant","size","disabled","error","filled","focused","required"]}),f=l({},s,{component:d,contained:r.variant==="filled"||r.variant==="outlined",variant:r.variant,size:r.size,disabled:r.disabled,error:r.error,filled:r.filled,focused:r.focused,required:r.required}),F=he(f);return c(be,l({as:d,ownerState:f,className:W(F.root,n),ref:t},p,{children:i===" "?$||($=c("span",{className:"notranslate",children:"\u200B"})):i}))}),ve=Te;function Ce(e){return S("MuiTextField",e)}q("MuiTextField",["root"]);const ge=["autoComplete","autoFocus","children","className","color","defaultValue","disabled","error","FormHelperTextProps","fullWidth","helperText","id","InputLabelProps","inputProps","InputProps","inputRef","label","maxRows","minRows","multiline","name","onBlur","onChange","onFocus","placeholder","required","rows","select","SelectProps","type","value","variant"],Re={standard:ue,filled:ce,outlined:pe},we=e=>{const{classes:o}=e;return j({root:["root"]},Ce,o)},ye=N(ae,{name:"MuiTextField",slot:"Root",overridesResolver:(e,o)=>o.root})({}),Ie=U.exports.forwardRef(function(o,t){const s=_({props:o,name:"MuiTextField"}),{autoComplete:i,autoFocus:n=!1,children:d,className:p,color:u="primary",defaultValue:r,disabled:f=!1,error:F=!1,FormHelperTextProps:V,fullWidth:T=!1,helperText:v,id:O,InputLabelProps:h,inputProps:k,InputProps:A,inputRef:E,label:m,maxRows:K,minRows:Q,multiline:w=!1,name:D,onBlur:G,onChange:J,onFocus:X,placeholder:Y,required:y=!1,rows:Z,select:C=!1,SelectProps:g,type:ee,value:I,variant:b="outlined"}=s,oe=B(s,ge),H=l({},s,{autoFocus:n,color:u,disabled:f,error:F,fullWidth:T,multiline:w,required:y,select:C,variant:b}),re=we(H),x={};b==="outlined"&&(h&&typeof h.shrink<"u"&&(x.notched=h.shrink),x.label=m),C&&((!g||!g.native)&&(x.id=void 0),x["aria-describedby"]=void 0);const a=fe(O),R=v&&a?`${a}-helper-text`:void 0,P=m&&a?`${a}-label`:void 0,te=Re[b],z=c(te,l({"aria-describedby":R,autoComplete:i,autoFocus:n,defaultValue:r,fullWidth:T,multiline:w,name:D,rows:Z,maxRows:K,minRows:Q,type:ee,value:I,id:a,inputRef:E,onBlur:G,onChange:J,onFocus:X,placeholder:Y,inputProps:k},x,A));return ie(ye,l({className:W(re.root,p),disabled:f,error:F,fullWidth:T,ref:t,required:y,color:u,variant:b,ownerState:H},oe,{children:[m!=null&&m!==""&&c(ne,l({htmlFor:a,id:P},h,{children:m})),C?c(de,l({"aria-describedby":R,id:a,labelId:P,value:I,input:z},g,{children:d})):z,v&&c(ve,l({id:R},V,{children:v}))]}))}),ze=Ie;export{ve as F,ze as T};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
public/files/Report-Resep-Online.xlsx
Normal file
BIN
public/files/Report-Resep-Online.xlsx
Normal file
Binary file not shown.
BIN
public/files/Report-Riwayat-Rekam-Medis.xlsx
Normal file
BIN
public/files/Report-Riwayat-Rekam-Medis.xlsx
Normal file
Binary file not shown.
Reference in New Issue
Block a user