[WIP] Import Plans

This commit is contained in:
2022-07-07 10:17:46 +07:00
parent f18bb85b94
commit 574004d408
146 changed files with 28928 additions and 71 deletions

View File

View File

@@ -0,0 +1,5 @@
<?php
return [
'name' => 'Internal'
];

View File

View File

@@ -0,0 +1,21 @@
<?php
namespace Modules\Internal\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class InternalDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
// $this->call("OthersTableSeeder");
}
}

View File

View File

@@ -0,0 +1,46 @@
<?php
namespace Modules\Internal\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required'
]);
$user = User::query()
->where('email', $request->email)
->first();
if (!$user) {
return response(['message' => 'User Tidak Ditemukan'], 404);
}
if (!Hash::check($request->password, $user->password)) {
return response(['message' => 'Password Salah'], 403);
}
return response([
'message' => 'Selamat Datang',
'user' => $user,
'token' => $user->createToken('app')->plainTextToken
]);
}
public function logout(Request $request)
{
$token = $request->bearerToken();
Auth::user()->tokens()->where('id', $token)->delete();
return response(['message' => 'Berhasil Logout.']);
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace Modules\Internal\Http\Controllers\Api;
use App\Imports\PlansImport;
use App\Models\Corporate;
use DB;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Maatwebsite\Excel\Facades\Excel;
class CorporateController extends Controller
{
/**
* Display a listing of the resource.
* @return Renderable
*/
public function index()
{
$corporates = Corporate::query()
->paginate();
return $corporates;
}
/**
* Show the form for creating a new resource.
* @return Renderable
*/
public function create()
{
return view('internal::create');
}
/**
* Store a newly created resource in storage.
* @param Request $request
* @return Renderable
*/
public function store(Request $request)
{
$request->validate([
'code' => 'required',
'name' => 'required',
// 'logo' => 'required',
'policy_code' => 'required_with:policy_id',
'policy_total_premi' => 'required_with:policy_code',
'policy_minimal_deposit_percentage' => 'required_with:policy_code',
'policy_minimal_deposit_net' => 'required_with:policy_code',
'policy_minimal_alert_percentage' => 'required_with:policy_code',
'policy_minimal_alert_net' => 'required_with:policy_code',
'policy_stop_service_percentage' => 'required_with:policy_code',
'policy_stop_service_net' => 'required_with:policy_code',
]);
try {
DB::beginTransaction();
$newCorporate = Corporate::create($request->all());
$newCorporate->policies()->create([
'code' => $request->policy_code ?? NULL,
'total_premi' => $request->policy_total_premi ?? NULL,
'minimal_deposit_percentage' => $request->policy_minimal_deposit_percentage ?? NULL,
'minimal_deposit_net' => $request->policy_minimal_deposit_net ?? NULL,
'minimal_alert_percentage' => $request->policy_minimal_alert_percentage ?? NULL,
'minimal_alert_net' => $request->policy_minimal_alert_net ?? NULL,
'minimal_stop_service_percentage' => $request->policy_stop_service_percentage ?? NULL,
'minimal_stop_service_net' => $request->policy_stop_service_net ?? NULL,
'start' => $request->policy_start ?? NULL,
'end' => $request->policy_end ?? NULL,
'active' => $request->policy_active ?? true,
]);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
return $newCorporate;
}
/**
* Show the specified resource.
* @param int $id
* @return Renderable
*/
public function show($id)
{
return view('internal::show');
}
/**
* Show the form for editing the specified resource.
* @param int $id
* @return Renderable
*/
public function edit($id)
{
$corporate = Corporate::findOrFail($id)->load('currentPolicy');
return $corporate;
}
/**
* Update the specified resource in storage.
* @param Request $request
* @param int $id
* @return Renderable
*/
public function update(Request $request, $id)
{
$request->validate([
'code' => 'required',
'name' => 'required',
'policy_code' => 'required_with:policy_id',
'policy_total_premi' => 'required_with:policy_code',
'policy_minimal_deposit_percentage' => 'required_with:policy_code',
'policy_minimal_deposit_net' => 'required_with:policy_code',
'policy_minimal_alert_percentage' => 'required_with:policy_code',
'policy_minimal_alert_net' => 'required_with:policy_code',
'policy_stop_service_percentage' => 'required_with:policy_code',
'policy_stop_service_net' => 'required_with:policy_code',
]);
try {
DB::beginTransaction();
$corporate = Corporate::findOrFail($id);
$corporate->fill($request->toArray());
$corporate->save();
$corporate->policies()->updateOrCreate(
['id' => $request->policy_id],
[
'code' => $request->policy_code ?? NULL,
'total_premi' => $request->policy_total_premi ?? NULL,
'minimal_deposit_percentage' => $request->policy_minimal_deposit_percentage ?? NULL,
'minimal_deposit_net' => $request->policy_minimal_deposit_net ?? NULL,
'minimal_alert_percentage' => $request->policy_minimal_alert_percentage ?? NULL,
'minimal_alert_net' => $request->policy_minimal_alert_net ?? NULL,
'minimal_stop_service_percentage' => $request->policy_stop_service_percentage ?? NULL,
'minimal_stop_service_net' => $request->policy_stop_service_net ?? NULL,
'start' => $request->policy_start ?? NULL,
'end' => $request->policy_end ?? NULL,
'active' => $request->policy_active ?? true,
]
);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
return $corporate;
}
/**
* Remove the specified resource from storage.
* @param int $id
* @return Renderable
*/
public function destroy($id)
{
//
}
public function planImport(Request $request, $id)
{
$request->validate([
'file' => 'required|file|mimes:xls,xlsx,csv,txt',
]);
$data = Excel::toArray(new PlansImport, $request->file('file'));
dd($data);
return 'OK';
dd($id, $request->hasFile('file'));
}
}

View File

@@ -0,0 +1,79 @@
<?php
namespace Modules\Internal\Http\Controllers;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class InternalController extends Controller
{
/**
* Display a listing of the resource.
* @return Renderable
*/
public function index()
{
return view('internal::index');
}
/**
* Show the form for creating a new resource.
* @return Renderable
*/
public function create()
{
return view('internal::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('internal::show');
}
/**
* Show the form for editing the specified resource.
* @param int $id
* @return Renderable
*/
public function edit($id)
{
return view('internal::edit');
}
/**
* Update the specified resource in storage.
* @param Request $request
* @param int $id
* @return Renderable
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
* @param int $id
* @return Renderable
*/
public function destroy($id)
{
//
}
}

View File

View File

View File

@@ -0,0 +1,112 @@
<?php
namespace Modules\Internal\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Factory;
class InternalServiceProvider extends ServiceProvider
{
/**
* @var string $moduleName
*/
protected $moduleName = 'Internal';
/**
* @var string $moduleNameLower
*/
protected $moduleNameLower = 'internal';
/**
* Boot the application events.
*
* @return void
*/
public function boot()
{
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->register(RouteServiceProvider::class);
}
/**
* Register config.
*
* @return void
*/
protected function registerConfig()
{
$this->publishes([
module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'),
], 'config');
$this->mergeConfigFrom(
module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower
);
}
/**
* Register views.
*
* @return void
*/
public function registerViews()
{
$viewPath = resource_path('views/modules/' . $this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'Resources/views');
$this->publishes([
$sourcePath => $viewPath
], ['views', $this->moduleNameLower . '-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
}
/**
* Register translations.
*
* @return void
*/
public function registerTranslations()
{
$langPath = resource_path('lang/modules/' . $this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'Resources/lang'), $this->moduleNameLower);
}
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (\Config::get('view.paths') as $path) {
if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
$paths[] = $path . '/modules/' . $this->moduleNameLower;
}
}
return $paths;
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace Modules\Internal\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* The module namespace to assume when generating URLs to actions.
*
* @var string
*/
protected $moduleNamespace = 'Modules\Internal\Http\Controllers';
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*
* @return void
*/
public function boot()
{
parent::boot();
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->moduleNamespace)
->group(module_path('Internal', '/Routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->moduleNamespace)
->group(module_path('Internal', '/Routes/api.php'));
}
}

View File

View File

@@ -0,0 +1,9 @@
@extends('internal::layouts.master')
@section('content')
<h1>Hello World</h1>
<p>
This view is loaded from module: {!! config('internal.name') !!}
</p>
@endsection

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module Internal</title>
{{-- Laravel Mix - CSS File --}}
{{-- <link rel="stylesheet" href="{{ mix('css/internal.css') }}"> --}}
</head>
<body>
@yield('content')
{{-- Laravel Mix - JS File --}}
{{-- <script src="{{ mix('js/internal.js') }}"></script> --}}
</body>
</html>

View File

View File

@@ -0,0 +1,38 @@
<?php
use Modules\Internal\Http\Controllers\Api\AuthController;
use Illuminate\Http\Request;
use Modules\Internal\Http\Controllers\Api\CorporateController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::prefix('internal')->group(function () {
Route::post('login', [AuthController::class, 'login'])->name('login');
Route::post('forget-password', [AuthController::class, 'forgetPassword'])->name('forget-password');
Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email');
Route::middleware('auth:sanctum')->group(function () {
Route::post('logout', [AuthController::class, 'logout'])->name('logout');
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::resource('corporates', CorporateController::class);
// Route::post('corporates/{id}/plans', [CorporateController::class, 'planImport']);
Route::post('corporates/{id}/plans/import', [CorporateController::class, 'planImport']);
});
});
// Route::resource('corporates', CorporateController::class);

View File

@@ -0,0 +1,16 @@
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::prefix('internal')->group(function() {
Route::get('/', 'InternalController@index');
});

View File

View File

View File

@@ -0,0 +1,23 @@
{
"name": "nwidart/internal",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\Internal\\": ""
}
}
}

View File

@@ -0,0 +1,13 @@
{
"name": "Internal",
"alias": "internal",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\Internal\\Providers\\InternalServiceProvider"
],
"aliases": {},
"files": [],
"requires": []
}

View File

@@ -0,0 +1,21 @@
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "mix --production"
},
"devDependencies": {
"axios": "^0.21.4",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"laravel-mix": "^6.0.31",
"laravel-mix-merge-manifest": "^2.0.0",
"lodash": "^4.17.21",
"postcss": "^8.3.7"
}
}

View File

@@ -0,0 +1,14 @@
const dotenvExpand = require('dotenv-expand');
dotenvExpand(require('dotenv').config({ path: '../../.env'/*, debug: true*/}));
const mix = require('laravel-mix');
require('laravel-mix-merge-manifest');
mix.setPublicPath('../../public').mergeManifest();
mix.js(__dirname + '/Resources/assets/js/app.js', 'js/internal.js')
.sass( __dirname + '/Resources/assets/sass/app.scss', 'css/internal.css');
if (mix.inProduction()) {
mix.version();
}

21038
_ide_helper.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Imports;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class PlansImport implements ToArray, WithHeadingRow
{
/**
* @param Collection $collection
*/
// public function collection(Collection $collection)
// {
// foreach ($collection as $row)
// {
// User::create([
// 'name' => $row[0],
// ]);
// }
// }
public function array($row)
{
return [
// 'first' => $row[0],
// 'kajsdnkjasnd' => 'henlo'
];
}
}

11
app/Models/Benefit.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Benefit extends Model
{
use HasFactory;
}

45
app/Models/Corporate.php Normal file
View File

@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use App\Traits\Blameable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Corporate extends Model
{
use HasFactory, SoftDeletes, Blameable;
protected $fillable = [
'code',
'name',
'welcome_message',
'help_text',
'active'
];
public function imports()
{
return $this->morphMany(ImportLog::class, 'importable');
}
public function files()
{
return $this->morphMany(File::class, 'fileable');
}
public function policies()
{
return $this->hasMany(CorporatePolicy::class);
}
public function currentPolicy()
{
return $this->hasOne(CorporatePolicy::class)
// ->where('start', '<=', now())
// ->where('end', '>=', now())
->where('active', true)
->latestOfMany();
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CorporateDivision extends Model
{
use HasFactory;
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CorporateEmployees extends Model
{
use HasFactory;
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CorporatePolicy extends Model
{
use HasFactory;
protected $fillable = [
'corporate_id',
'code',
'total_premi',
'minimal_deposit_percentage',
'minimal_deposit_net',
'minimal_alert_percentage',
'minimal_alert_net',
'minimal_stop_service_percentage',
'minimal_stop_service_net',
'start',
'end',
'active',
];
public function corporate()
{
return $this->belongsTo(Corporate::class);
}
}

61
app/Models/File.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class File extends Model
{
use HasFactory;
protected $fillable = [
'fileable_type',
'fileable_id',
'type',
'name',
'extension',
'path',
];
protected $appends = [
'url'
];
public static $file_directories = [
'import-temp' => 'import-temp/',
];
public function fileable()
{
return $this->morphTo();
}
public function getUrlAttribute()
{
return Storage::url($this->path);
}
public function getDirectory($type)
{
return self::$file_directories[$type] ?? 'any';
}
public static function getFileName($type, $id, $file)
{
$extension = $file->getClientOriginalExtension();
return $type . '-' . $id .'-'.Str::random(10).'.'.$extension;
}
public static function storeFile($type, $id, $file)
{
$fileName = self::getFileName($type, $id, $file);
$directory = self::getDirectory($type);
$path = $directory . $fileName;
$file->storeAs($directory, $fileName);
return $path;
}
}

25
app/Models/ImportLog.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ImportLog extends Model
{
use HasFactory;
protected $fillable = [
'importable_type',
'importable_id',
'type',
'file_path',
'status',
'progress',
];
public function files()
{
return $this->morphMany(File::class, 'fileable');
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MemberBenefit extends Model
{
use HasFactory;
protected $fillable = [
'service_code',
'plan_code',
'benefit_code',
'description',
'budget',
'budget_conditions',
'budget_code',
'primary_benefit_code',
'room_class_coverage',
'max_bed_coverage',
'tolerance_parameter',
'max_room_class',
'limit_amount',
'area_limit',
'shared_benefit',
'msc',
'genders',
'min_age',
'max_age',
'max_frequency_period',
'daily_frequency',
'weekly_frequency',
'monthly_frequency',
'custom_frequency_days',
'custom_duration_value',
'allowed_transaction_types',
'high_plan_factor',
'pre_post_treatment',
'pre_treatment_days',
'post_treatment_days',
'layer_type_1',
'layer_value_1',
'layer_type_2',
'layer_value_2',
'cashless_percentage',
'reimbursement_percentage',
'digital_percentage',
'co_share_m_percentage',
'co_share_s_percentage',
'co_share_c_percentage',
'cashless_deductible',
'reimbursement_deductible',
'co_share_m_deductible',
'co_share_s_deductible',
'co_share_c_deductible',
'prorate_type',
'prorate_lookup',
'max_days_for_disability',
'max_period_for_disability',
'currency',
'show_benefit_item',
'show_benefit_value',
];
}

11
app/Models/Plan.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Plan extends Model
{
use HasFactory;
}

11
app/Models/Services.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Services extends Model
{
use HasFactory;
}

21
app/Traits/Blameable.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
namespace App\Traits;
trait Blameable {
public static function bootBlameable() {
static::creating(function ($model) {
$model->created_by = auth()->id() ?? NULL;
});
static::updating(function ($model) {
$model->updated_by = auth()->id() ?? NULL;
});
static::deleting((function ($model) {
$model->deleted_by = auth()->id() ?? NULL;
}));
}
}

View File

@@ -9,9 +9,13 @@
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^9.11",
"laravel/sanctum": "^2.15",
"laravel/tinker": "^2.7"
"laravel/tinker": "^2.7",
"maatwebsite/excel": "^3.1",
"nwidart/laravel-modules": "^9.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.12",
"fakerphp/faker": "^1.9.1",
"laravel/sail": "^1.0.1",
"mockery/mockery": "^1.4.4",
@@ -23,7 +27,8 @@
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
"Database\\Seeders\\": "database/seeders/",
"Modules\\": "Modules/"
}
},
"autoload-dev": {

1181
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -185,6 +185,8 @@ return [
/*
* Package Service Providers...
*/
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
Maatwebsite\Excel\ExcelServiceProvider::class,
/*
* Application Service Providers...
@@ -210,6 +212,7 @@ return [
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
])->toArray(),
];

332
config/excel.php Normal file
View File

@@ -0,0 +1,332 @@
<?php
use Maatwebsite\Excel\Excel;
return [
'exports' => [
/*
|--------------------------------------------------------------------------
| Chunk size
|--------------------------------------------------------------------------
|
| When using FromQuery, the query is automatically chunked.
| Here you can specify how big the chunk should be.
|
*/
'chunk_size' => 1000,
/*
|--------------------------------------------------------------------------
| Pre-calculate formulas during export
|--------------------------------------------------------------------------
*/
'pre_calculate_formulas' => false,
/*
|--------------------------------------------------------------------------
| Enable strict null comparison
|--------------------------------------------------------------------------
|
| When enabling strict null comparison empty cells ('') will
| be added to the sheet.
*/
'strict_null_comparison' => false,
/*
|--------------------------------------------------------------------------
| CSV Settings
|--------------------------------------------------------------------------
|
| Configure e.g. delimiter, enclosure and line ending for CSV exports.
|
*/
'csv' => [
'delimiter' => ',',
'enclosure' => '"',
'line_ending' => PHP_EOL,
'use_bom' => false,
'include_separator_line' => false,
'excel_compatibility' => false,
'output_encoding' => '',
],
/*
|--------------------------------------------------------------------------
| Worksheet properties
|--------------------------------------------------------------------------
|
| Configure e.g. default title, creator, subject,...
|
*/
'properties' => [
'creator' => '',
'lastModifiedBy' => '',
'title' => '',
'description' => '',
'subject' => '',
'keywords' => '',
'category' => '',
'manager' => '',
'company' => '',
],
],
'imports' => [
/*
|--------------------------------------------------------------------------
| Read Only
|--------------------------------------------------------------------------
|
| When dealing with imports, you might only be interested in the
| data that the sheet exists. By default we ignore all styles,
| however if you want to do some logic based on style data
| you can enable it by setting read_only to false.
|
*/
'read_only' => true,
/*
|--------------------------------------------------------------------------
| Ignore Empty
|--------------------------------------------------------------------------
|
| When dealing with imports, you might be interested in ignoring
| rows that have null values or empty strings. By default rows
| containing empty strings or empty values are not ignored but can be
| ignored by enabling the setting ignore_empty to true.
|
*/
'ignore_empty' => false,
/*
|--------------------------------------------------------------------------
| Heading Row Formatter
|--------------------------------------------------------------------------
|
| Configure the heading row formatter.
| Available options: none|slug|custom
|
*/
'heading_row' => [
'formatter' => 'slug',
],
/*
|--------------------------------------------------------------------------
| CSV Settings
|--------------------------------------------------------------------------
|
| Configure e.g. delimiter, enclosure and line ending for CSV imports.
|
*/
'csv' => [
'delimiter' => null,
'enclosure' => '"',
'escape_character' => '\\',
'contiguous' => false,
'input_encoding' => 'UTF-8',
],
/*
|--------------------------------------------------------------------------
| Worksheet properties
|--------------------------------------------------------------------------
|
| Configure e.g. default title, creator, subject,...
|
*/
'properties' => [
'creator' => '',
'lastModifiedBy' => '',
'title' => '',
'description' => '',
'subject' => '',
'keywords' => '',
'category' => '',
'manager' => '',
'company' => '',
],
],
/*
|--------------------------------------------------------------------------
| Extension detector
|--------------------------------------------------------------------------
|
| Configure here which writer/reader type should be used when the package
| needs to guess the correct type based on the extension alone.
|
*/
'extension_detector' => [
'xlsx' => Excel::XLSX,
'xlsm' => Excel::XLSX,
'xltx' => Excel::XLSX,
'xltm' => Excel::XLSX,
'xls' => Excel::XLS,
'xlt' => Excel::XLS,
'ods' => Excel::ODS,
'ots' => Excel::ODS,
'slk' => Excel::SLK,
'xml' => Excel::XML,
'gnumeric' => Excel::GNUMERIC,
'htm' => Excel::HTML,
'html' => Excel::HTML,
'csv' => Excel::CSV,
'tsv' => Excel::TSV,
/*
|--------------------------------------------------------------------------
| PDF Extension
|--------------------------------------------------------------------------
|
| Configure here which Pdf driver should be used by default.
| Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF
|
*/
'pdf' => Excel::DOMPDF,
],
/*
|--------------------------------------------------------------------------
| Value Binder
|--------------------------------------------------------------------------
|
| PhpSpreadsheet offers a way to hook into the process of a value being
| written to a cell. In there some assumptions are made on how the
| value should be formatted. If you want to change those defaults,
| you can implement your own default value binder.
|
| Possible value binders:
|
| [x] Maatwebsite\Excel\DefaultValueBinder::class
| [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class
| [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class
|
*/
'value_binder' => [
'default' => Maatwebsite\Excel\DefaultValueBinder::class,
],
'cache' => [
/*
|--------------------------------------------------------------------------
| Default cell caching driver
|--------------------------------------------------------------------------
|
| By default PhpSpreadsheet keeps all cell values in memory, however when
| dealing with large files, this might result into memory issues. If you
| want to mitigate that, you can configure a cell caching driver here.
| When using the illuminate driver, it will store each value in a the
| cache store. This can slow down the process, because it needs to
| store each value. You can use the "batch" store if you want to
| only persist to the store when the memory limit is reached.
|
| Drivers: memory|illuminate|batch
|
*/
'driver' => 'memory',
/*
|--------------------------------------------------------------------------
| Batch memory caching
|--------------------------------------------------------------------------
|
| When dealing with the "batch" caching driver, it will only
| persist to the store when the memory limit is reached.
| Here you can tweak the memory limit to your liking.
|
*/
'batch' => [
'memory_limit' => 60000,
],
/*
|--------------------------------------------------------------------------
| Illuminate cache
|--------------------------------------------------------------------------
|
| When using the "illuminate" caching driver, it will automatically use
| your default cache store. However if you prefer to have the cell
| cache on a separate store, you can configure the store name here.
| You can use any store defined in your cache config. When leaving
| at "null" it will use the default store.
|
*/
'illuminate' => [
'store' => null,
],
],
/*
|--------------------------------------------------------------------------
| Transaction Handler
|--------------------------------------------------------------------------
|
| By default the import is wrapped in a transaction. This is useful
| for when an import may fail and you want to retry it. With the
| transactions, the previous import gets rolled-back.
|
| You can disable the transaction handler by setting this to null.
| Or you can choose a custom made transaction handler here.
|
| Supported handlers: null|db
|
*/
'transactions' => [
'handler' => 'db',
'db' => [
'connection' => null,
],
],
'temporary_files' => [
/*
|--------------------------------------------------------------------------
| Local Temporary Path
|--------------------------------------------------------------------------
|
| When exporting and importing files, we use a temporary file, before
| storing reading or downloading. Here you can customize that path.
|
*/
'local_path' => storage_path('framework/cache/laravel-excel'),
/*
|--------------------------------------------------------------------------
| Remote Temporary Disk
|--------------------------------------------------------------------------
|
| When dealing with a multi server setup with queues in which you
| cannot rely on having a shared local temporary path, you might
| want to store the temporary file on a shared disk. During the
| queue executing, we'll retrieve the temporary file from that
| location instead. When left to null, it will always use
| the local path. This setting only has effect when using
| in conjunction with queued imports and exports.
|
*/
'remote_disk' => null,
'remote_prefix' => null,
/*
|--------------------------------------------------------------------------
| Force Resync
|--------------------------------------------------------------------------
|
| When dealing with a multi server setup as above, it's possible
| for the clean up that occurs after entire queue has been run to only
| cleanup the server that the last AfterImportJob runs on. The rest of the server
| would still have the local temporary file stored on it. In this case your
| local storage limits can be exceeded and future imports won't be processed.
| To mitigate this you can set this config value to be true, so that after every
| queued chunk is processed the local temporary file is deleted on the server that
| processed it.
|
*/
'force_resync_remote' => null,
],
];

275
config/modules.php Normal file
View File

@@ -0,0 +1,275 @@
<?php
use Nwidart\Modules\Activators\FileActivator;
use Nwidart\Modules\Commands;
return [
/*
|--------------------------------------------------------------------------
| Module Namespace
|--------------------------------------------------------------------------
|
| Default module namespace.
|
*/
'namespace' => 'Modules',
/*
|--------------------------------------------------------------------------
| Module Stubs
|--------------------------------------------------------------------------
|
| Default module stubs.
|
*/
'stubs' => [
'enabled' => false,
'path' => base_path('vendor/nwidart/laravel-modules/src/Commands/stubs'),
'files' => [
'routes/web' => 'Routes/web.php',
'routes/api' => 'Routes/api.php',
'views/index' => 'Resources/views/index.blade.php',
'views/master' => 'Resources/views/layouts/master.blade.php',
'scaffold/config' => 'Config/config.php',
'composer' => 'composer.json',
'assets/js/app' => 'Resources/assets/js/app.js',
'assets/sass/app' => 'Resources/assets/sass/app.scss',
'webpack' => 'webpack.mix.js',
'package' => 'package.json',
],
'replacements' => [
'routes/web' => ['LOWER_NAME', 'STUDLY_NAME'],
'routes/api' => ['LOWER_NAME'],
'webpack' => ['LOWER_NAME'],
'json' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'PROVIDER_NAMESPACE'],
'views/index' => ['LOWER_NAME'],
'views/master' => ['LOWER_NAME', 'STUDLY_NAME'],
'scaffold/config' => ['STUDLY_NAME'],
'composer' => [
'LOWER_NAME',
'STUDLY_NAME',
'VENDOR',
'AUTHOR_NAME',
'AUTHOR_EMAIL',
'MODULE_NAMESPACE',
'PROVIDER_NAMESPACE',
],
],
'gitkeep' => true,
],
'paths' => [
/*
|--------------------------------------------------------------------------
| Modules path
|--------------------------------------------------------------------------
|
| This path used for save the generated module. This path also will be added
| automatically to list of scanned folders.
|
*/
'modules' => base_path('Modules'),
/*
|--------------------------------------------------------------------------
| Modules assets path
|--------------------------------------------------------------------------
|
| Here you may update the modules assets path.
|
*/
'assets' => public_path('modules'),
/*
|--------------------------------------------------------------------------
| The migrations path
|--------------------------------------------------------------------------
|
| Where you run 'module:publish-migration' command, where do you publish the
| the migration files?
|
*/
'migration' => base_path('database/migrations'),
/*
|--------------------------------------------------------------------------
| Generator path
|--------------------------------------------------------------------------
| Customise the paths where the folders will be generated.
| Set the generate key to false to not generate that folder
*/
'generator' => [
'config' => ['path' => 'Config', 'generate' => true],
'command' => ['path' => 'Console', 'generate' => true],
'migration' => ['path' => 'Database/Migrations', 'generate' => true],
'seeder' => ['path' => 'Database/Seeders', 'generate' => true],
'factory' => ['path' => 'Database/factories', 'generate' => true],
'model' => ['path' => 'Entities', 'generate' => true],
'routes' => ['path' => 'Routes', 'generate' => true],
'controller' => ['path' => 'Http/Controllers', 'generate' => true],
'filter' => ['path' => 'Http/Middleware', 'generate' => true],
'request' => ['path' => 'Http/Requests', 'generate' => true],
'provider' => ['path' => 'Providers', 'generate' => true],
'assets' => ['path' => 'Resources/assets', 'generate' => true],
'lang' => ['path' => 'Resources/lang', 'generate' => true],
'views' => ['path' => 'Resources/views', 'generate' => true],
'test' => ['path' => 'Tests/Unit', 'generate' => true],
'test-feature' => ['path' => 'Tests/Feature', 'generate' => true],
'repository' => ['path' => 'Repositories', 'generate' => false],
'event' => ['path' => 'Events', 'generate' => false],
'listener' => ['path' => 'Listeners', 'generate' => false],
'policies' => ['path' => 'Policies', 'generate' => false],
'rules' => ['path' => 'Rules', 'generate' => false],
'jobs' => ['path' => 'Jobs', 'generate' => false],
'emails' => ['path' => 'Emails', 'generate' => false],
'notifications' => ['path' => 'Notifications', 'generate' => false],
'resource' => ['path' => 'Transformers', 'generate' => false],
'component-view' => ['path' => 'Resources/views/components', 'generate' => false],
'component-class' => ['path' => 'View/Components', 'generate' => false],
],
],
/*
|--------------------------------------------------------------------------
| Package commands
|--------------------------------------------------------------------------
|
| Here you can define which commands will be visible and used in your
| application. If for example you don't use some of the commands provided
| you can simply comment them out.
|
*/
'commands' => [
Commands\CommandMakeCommand::class,
Commands\ComponentClassMakeCommand::class,
Commands\ComponentViewMakeCommand::class,
Commands\ControllerMakeCommand::class,
Commands\DisableCommand::class,
Commands\DumpCommand::class,
Commands\EnableCommand::class,
Commands\EventMakeCommand::class,
Commands\JobMakeCommand::class,
Commands\ListenerMakeCommand::class,
Commands\MailMakeCommand::class,
Commands\MiddlewareMakeCommand::class,
Commands\NotificationMakeCommand::class,
Commands\ProviderMakeCommand::class,
Commands\RouteProviderMakeCommand::class,
Commands\InstallCommand::class,
Commands\ListCommand::class,
Commands\ModuleDeleteCommand::class,
Commands\ModuleMakeCommand::class,
Commands\FactoryMakeCommand::class,
Commands\PolicyMakeCommand::class,
Commands\RequestMakeCommand::class,
Commands\RuleMakeCommand::class,
Commands\MigrateCommand::class,
Commands\MigrateRefreshCommand::class,
Commands\MigrateResetCommand::class,
Commands\MigrateRollbackCommand::class,
Commands\MigrateStatusCommand::class,
Commands\MigrationMakeCommand::class,
Commands\ModelMakeCommand::class,
Commands\PublishCommand::class,
Commands\PublishConfigurationCommand::class,
Commands\PublishMigrationCommand::class,
Commands\PublishTranslationCommand::class,
Commands\SeedCommand::class,
Commands\SeedMakeCommand::class,
Commands\SetupCommand::class,
Commands\UnUseCommand::class,
Commands\UpdateCommand::class,
Commands\UseCommand::class,
Commands\ResourceMakeCommand::class,
Commands\TestMakeCommand::class,
Commands\LaravelModulesV6Migrator::class,
],
/*
|--------------------------------------------------------------------------
| Scan Path
|--------------------------------------------------------------------------
|
| Here you define which folder will be scanned. By default will scan vendor
| directory. This is useful if you host the package in packagist website.
|
*/
'scan' => [
'enabled' => false,
'paths' => [
base_path('vendor/*/*'),
],
],
/*
|--------------------------------------------------------------------------
| Composer File Template
|--------------------------------------------------------------------------
|
| Here is the config for composer.json file, generated by this package
|
*/
'composer' => [
'vendor' => 'nwidart',
'author' => [
'name' => 'Nicolas Widart',
'email' => 'n.widart@gmail.com',
],
'composer-output' => false,
],
/*
|--------------------------------------------------------------------------
| Caching
|--------------------------------------------------------------------------
|
| Here is the config for setting up caching feature.
|
*/
'cache' => [
'enabled' => false,
'key' => 'laravel-modules',
'lifetime' => 60,
],
/*
|--------------------------------------------------------------------------
| Choose what laravel-modules will register as custom namespaces.
| Setting one to false will require you to register that part
| in your own Service Provider class.
|--------------------------------------------------------------------------
*/
'register' => [
'translations' => true,
/**
* load files on boot or register method
*
* Note: boot not compatible with asgardcms
*
* @example boot|register
*/
'files' => 'register',
],
/*
|--------------------------------------------------------------------------
| Activators
|--------------------------------------------------------------------------
|
| You can define new types of activators here, file, database etc. The only
| required parameter is 'class'.
| The file activator will store the activation status in storage/installed_modules
*/
'activators' => [
'file' => [
'class' => FileActivator::class,
'statuses-file' => base_path('modules_statuses.json'),
'cache-key' => 'activator.installed',
'cache-lifetime' => 604800,
],
],
'activator' => 'file',
];

View File

@@ -15,7 +15,7 @@ return new class extends Migration
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
// $table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');

View File

@@ -15,14 +15,20 @@ return new class extends Migration
{
Schema::create('members', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id')->nullable();
$table->unsignedBigInteger('corporate_id')->nullable();
$table->string('name_prefix');
$table->foreignId('user_id')->nullable();
$table->string('name_prefix')->nullable();
$table->string('name');
$table->string('name_suffix');
$table->date('birth_date');
$table->string('gender');
$table->boolean('active');
$table->string('name_suffix')->nullable();
// $table->string('nik');
$table->date('birth_date')->nullable();
$table->string('gender')->nullable();
$table->string('language')->nullable();
$table->string('race')->nullable();
$table->string('marital_status')->nullable();
$table->foreignId('principle_id')->nullable();
$table->string('relation_with_principle')->nullable();
$table->date('bpjs_class')->nullable();
$table->boolean('active')->default(true);
$table->timestamps();
$table->softDeletes();

View File

@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('corporates', function (Blueprint $table) {
$table->id();
$table->string('code');
$table->string('name')->nullable();
$table->text('welcome_message')->nullable();
$table->text('help_text')->nullable();
$table->boolean('active')->default(true);
$table->timestamps();
$table->softDeletes();
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('corporates');
}
};

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('corporate_divisions', function (Blueprint $table) {
$table->id();
$table->foreignId('corporate_id')->nullable();
$table->string('code');
$table->string('name')->nullable();
$table->timestamps();
$table->softDeletes();
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('corporate_divisions');
}
};

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('corporate_employees', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('corporate_employees');
}
};

View File

@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('corporate_policies', function (Blueprint $table) {
$table->id();
$table->string('corporate_id');
$table->string('code')->unique();
$table->decimal('total_premi', 15, 2)->nullable();
$table->decimal('minimal_deposit_percentage', 15, 2)->nullable();
$table->decimal('minimal_deposit_net', 15, 2)->nullable();
$table->decimal('minimal_alert_percentage', 7, 4)->nullable();
$table->decimal('minimal_alert_net', 15, 2)->nullable();
$table->decimal('minimal_stop_service_percentage', 7, 4)->nullable();
$table->decimal('minimal_stop_service_net', 15, 2)->nullable();
$table->date('start')->nullable();
$table->date('end')->nullable();
$table->boolean('active')->default(false);
$table->timestamps();
$table->softDeletes();
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('corporate_policies');
}
};

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('benefits', function (Blueprint $table) {
$table->id();
$table->string('code')->unique();
$table->string('name');
$table->text('description')->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreignId('created_by')->nullable()->index();
$table->foreignId('updated_by')->nullable()->index();
$table->foreignId('deleted_by')->nullable()->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('benefits');
}
};

View File

@@ -0,0 +1,81 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('plans', function (Blueprint $table) {
$table->id();
$table->string('service_code')->index();
$table->string('code')->index();
$table->string('type')->nullable();
$table->dateTime('start')->nullable();
$table->dateTime('end')->nullable();
$table->string('require_referral')->nullable();
$table->string('referral_source')->nullable();
$table->string('referral_duration')->nullable();
$table->string('family_plan')->nullable();
$table->string('family_plan_share_rules')->nullable();
$table->string('limit_rules')->nullable(); // Annual Limit
$table->string('layer')->nullable();
$table->string('layer_conditions')->nullable();
$table->string('budget_type')->nullable();
$table->string('budget_code')->nullable();
$table->string('budget_conditions')->nullable();
$table->decimal('surgery_limit', 15, 2)->nullable();
$table->decimal('non_surgery_limit', 15, 2)->nullable();
$table->decimal('max_claim_limit', 15, 2)->nullable();
$table->integer('max_claim_count')->nullable();
$table->boolean('area_limit')->nullable();
$table->string('limit_shared_plans')->nullable();
$table->string('limit_shared_plan_type')->nullable();
$table->tinyInteger('cashless_percentage')->default(100)->nullable();
$table->tinyInteger('reimbursement_percentage')->default(100)->nullable();
$table->tinyInteger('digital_percentage')->default(100)->nullable();
$table->tinyInteger('co_share_m_percentage')->default(100)->nullable();
$table->tinyInteger('co_share_s_percentage')->default(100)->nullable();
$table->tinyInteger('co_share_c_percentage')->default(100)->nullable();
$table->decimal('cashless_deductible', 15, 2)->nullable();
$table->decimal('reimbursement_deductible', 15, 2)->nullable();
$table->decimal('co_share_m_deductible', 15, 2)->nullable();
$table->decimal('co_share_s_eductible', 15, 2)->nullable();
$table->decimal('co_share_c_eductible', 15, 2)->nullable();
$table->string('co_share_deductible_condition')->nullable();
$table->string('msc')->nullable();
$table->string('genders')->nullable();
$table->string('min_age')->nullable();
$table->string('max_age')->nullable();
$table->string('rule_of_excess')->nullable();
$table->string('max_excess_covered')->nullable();
$table->string('prorate_type')->nullable();
$table->string('prorate_lookup')->nullable();
$table->string('currency')->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreignId('created_by')->nullable()->index();
$table->foreignId('updated_by')->nullable()->index();
$table->foreignId('deleted_by')->nullable()->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('plans');
}
};

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('services', function (Blueprint $table) {
$table->id();
$table->string('code')->index();
$table->string('name');
$table->text('description')->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreignId('created_by')->nullable()->index();
$table->foreignId('updated_by')->nullable()->index();
$table->foreignId('deleted_by')->nullable()->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('services');
}
};

View File

@@ -0,0 +1,89 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('member_benefits', function (Blueprint $table) {
$table->id();
$table->string('service_code')->index()->nullable();
$table->string('plan_code')->index()->nullable();
$table->string('benefit_code')->index()->nullable();
$table->text('description')->nullable();
$table->string('budget')->nullable();
$table->string('budget_conditions')->nullable();
$table->string('budget_code')->nullable();
$table->string('primary_benefit_code')->index()->nullable();
$table->string('room_class_coverage')->nullable();
$table->string('max_bed_coverage')->nullable();
$table->string('tolerance_parameter')->nullable();
$table->string('max_room_class')->nullable();
$table->decimal('limit_amount', 15, 2)->nullable();
$table->boolean('area_limit')->default(false)->nullable();
$table->string('shared_benefit')->nullable();
$table->string('msc')->nullable();
$table->string('genders')->nullable();
$table->string('min_age')->nullable();
$table->string('max_age')->nullable();
$table->string('max_frequency_period')->nullable();
$table->string('daily_frequency')->nullable();
$table->string('weekly_frequency')->nullable();
$table->string('monthly_frequency')->nullable();
$table->string('custom_frequency_days')->nullable();
$table->string('custom_duration_value')->nullable();
$table->string('allowed_transaction_types')->nullable();
$table->string('high_plan_factor')->nullable();
$table->boolean('pre_post_treatment')->nullable();
$table->string('pre_treatment_days')->nullable();
$table->string('post_treatment_days')->nullable();
$table->string('layer_type_1')->nullable();
$table->string('layer_value_1')->nullable();
$table->string('layer_type_2')->nullable();
$table->string('layer_value_2')->nullable();
$table->tinyInteger('cashless_percentage')->default(100)->nullable();
$table->tinyInteger('reimbursement_percentage')->default(100)->nullable();
$table->tinyInteger('digital_percentage')->default(100)->nullable();
$table->tinyInteger('co_share_m_percentage')->default(100)->nullable();
$table->tinyInteger('co_share_s_percentage')->default(100)->nullable();
$table->tinyInteger('co_share_c_percentage')->default(100)->nullable();
$table->decimal('cashless_deductible', 15, 2)->nullable();
$table->decimal('reimbursement_deductible', 15, 2)->nullable();
$table->decimal('co_share_m_deductible', 15, 2)->nullable();
$table->decimal('co_share_s_deductible', 15, 2)->nullable();
$table->decimal('co_share_c_deductible', 15, 2)->nullable();
$table->string('prorate_type')->nullable();
$table->string('prorate_lookup')->nullable();
$table->string('max_days_for_disability')->nullable();
$table->string('max_period_for_disability')->nullable();
$table->string('currency')->nullable();
$table->string('show_benefit_item')->nullable();
$table->string('show_benefit_value')->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreignId('created_by')->nullable()->index();
$table->foreignId('updated_by')->nullable()->index();
$table->foreignId('deleted_by')->nullable()->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('member_benefits');
}
};

View File

@@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('import_logs', function (Blueprint $table) {
$table->uuid();
$table->morphs('importable');
$table->string('type')->nullable();
$table->string('file_path')->nullable();
$table->string('status')->nullable();
$table->string('progress')->nullable()->default(0);
$table->timestamps();
$table->softDeletes();
$table->foreignId('created_by')->nullable()->index();
$table->foreignId('updated_by')->nullable()->index();
$table->foreignId('deleted_by')->nullable()->index();
$table->index(['importable_id', 'importable_type']);
$table->index(['importable_id', 'importable_type', 'type']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('import_logs');
}
};

View File

@@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('files', function (Blueprint $table) {
$table->id();
$table->morphs('fileable');
$table->string('type')->nullable();
$table->string('name')->nullable();
$table->string('extension')->nullable();
$table->string('path')->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreignId('created_by')->nullable()->index();
$table->foreignId('updated_by')->nullable()->index();
$table->foreignId('deleted_by')->nullable()->index();
$table->index(['fileable_id', 'fileable_type']);
$table->index(['fileable_id', 'fileable_type', 'type']);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('files');
}
};

View File

@@ -0,0 +1,50 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class BenefitSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$listOfBenefit = [
[
"service_code" => 'OP',
"code" => "GP",
"name" => "General Practitioner",
"description" => "Consultation With General Practitioner"
],
[
"service_code" => 'OP',
"code" => "GP",
"name" => "General Practitioner",
"description" => "Consultation With General Practitioner"
],
[
"service_code" => 'OP',
"code" => "GP",
"name" => "General Practitioner",
"description" => "Consultation With General Practitioner"
],
[
"service_code" => 'OP',
"code" => "GP",
"name" => "General Practitioner",
"description" => "Consultation With General Practitioner"
],
[
"service_code" => 'OP',
"code" => "GP",
"name" => "General Practitioner",
"description" => "Consultation With General Practitioner"
],
];
}
}

View File

@@ -2,6 +2,8 @@
namespace Database\Seeders;
use App\Models\User;
use Hash;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
@@ -14,6 +16,9 @@ class DummyMemberSeeder extends Seeder
*/
public function run()
{
//
User::create([
'email' => 'admin@linksehat.dev',
'password' => Hash::make('password')
]);
}
}

View File

@@ -1,8 +1,4 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
</IfModule>

View File

@@ -4,4 +4,4 @@ PORT=8083
REACT_APP_HOST_API_URL="http://localhost:8000"
VITE_API_URL="http://localhost:8000/api"
VITE_API_URL="http://localhost:8000/api/internal"

View File

@@ -42,9 +42,9 @@
"@emotion/styled": "^11.8.1",
"@hookform/resolvers": "^2.8.8",
"@iconify/react": "^3.2.1",
"@mui/icons-material": "^5.8.0",
"@mui/lab": "5.0.0-alpha.80",
"@mui/material": "^5.6.4",
"@mui/icons-material": "^5.8.0",
"@mui/system": "^5.6.4",
"@mui/x-data-grid": "^5.10.0",
"@vitejs/plugin-react": "^1.3.2",
@@ -52,6 +52,7 @@
"change-case": "^4.1.2",
"date-fns": "^2.28.0",
"framer-motion": "^6.3.3",
"highlight.js": "^11.5.1",
"history": "^5.3.0",
"jsx-runtime": "^1.2.0",
"lodash": "^4.17.21",
@@ -81,6 +82,7 @@
"@babel/eslint-parser": "^7.17.0",
"@babel/plugin-syntax-flow": "^7.16.7",
"@babel/plugin-transform-react-jsx": "^7.17.3",
"@types/lodash": "^4.14.182",
"@types/nprogress": "^0.2.0",
"@types/react": "^17.0.44",
"@types/react-dom": "^17.0.16",

View File

@@ -15,6 +15,7 @@ specifiers:
'@mui/material': ^5.6.4
'@mui/system': ^5.6.4
'@mui/x-data-grid': ^5.10.0
'@types/lodash': ^4.14.182
'@types/nprogress': ^0.2.0
'@types/react': ^17.0.44
'@types/react-dom': ^17.0.16
@@ -39,6 +40,7 @@ specifiers:
eslint-plugin-react: ^7.29.4
eslint-plugin-react-hooks: 4.3.0
framer-motion: ^6.3.3
highlight.js: ^11.5.1
history: ^5.3.0
jsx-runtime: ^1.2.0
lodash: ^4.17.21
@@ -82,6 +84,7 @@ dependencies:
change-case: 4.1.2
date-fns: 2.28.0
framer-motion: 6.3.3_sfoxds7t5ydpegc3knd667wn6m
highlight.js: 11.5.1
history: 5.3.0
jsx-runtime: 1.2.0
lodash: 4.17.21
@@ -111,6 +114,7 @@ devDependencies:
'@babel/eslint-parser': 7.17.0_3jmbb74oue544vtiil27ushva4
'@babel/plugin-syntax-flow': 7.17.12_@babel+core@7.18.0
'@babel/plugin-transform-react-jsx': 7.17.12_@babel+core@7.18.0
'@types/lodash': 4.14.182
'@types/nprogress': 0.2.0
'@types/react': 17.0.45
'@types/react-dom': 17.0.17
@@ -2267,7 +2271,6 @@ packages:
/@types/lodash/4.14.182:
resolution: {integrity: sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==}
dev: false
/@types/node/17.0.35:
resolution: {integrity: sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==}
@@ -4076,6 +4079,11 @@ packages:
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
dev: false
/highlight.js/11.5.1:
resolution: {integrity: sha512-LKzHqnxr4CrD2YsNoIf/o5nJ09j4yi/GcH5BnYz9UnVpZdS4ucMgvP61TDty5xJcFGRjnH4DpujkS9bHT3hq0Q==}
engines: {node: '>=12.0.0'}
dev: false
/history/5.3.0:
resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==}
dependencies:

View File

@@ -0,0 +1,42 @@
// ----------------------------------------------------------------------
export type Corporate = {
id: number;
code: string;
name?: string;
welcome_message?: string;
help_text?: string;
logo?: any;
logo_url?: string;
active: boolean | number;
divisions?: Division[];
employees?: Employee[];
current_policy?: Policy;
};
export type Division = {
id: number;
corporate_id: number;
code: string;
name?: string;
}
export type Employee = {
id: number;
name: string;
}
export type Policy = {
id: number;
corporate_id: number;
code: string;
total_premi: number;
minimal_deposit_percentage: number;
minimal_deposit_net: number;
minimal_alert_percentage: number;
minimal_alert_net: number;
minimal_stop_service_percentage: number;
minimal_stop_service_net: number;
start: string | Date;
end: string | Date;
}

View File

@@ -0,0 +1,14 @@
export type LaravelPaginatedData = {
current_page: number;
data: any[];
path: string;
first_page_url: string;
last_page: number;
last_page_url: string;
next_page_url?: string;
prev_page_url?: string;
per_page: number;
from?: number;
to?: number;
total: number;
}

View File

@@ -9,22 +9,25 @@ import ScrollToTop from './components/ScrollToTop';
import { ProgressBarStyle } from './components/ProgressBar';
import ThemeColorPresets from './components/ThemeColorPresets';
import MotionLazyContainer from './components/animate/MotionLazyContainer';
import { SnackbarProvider } from 'notistack';
// ----------------------------------------------------------------------
export default function App() {
return (
<ThemeProvider>
<ThemeColorPresets>
<RtlLayout>
<MotionLazyContainer>
<ProgressBarStyle />
{/* <Settings /> */}
<ScrollToTop />
<Router />
</MotionLazyContainer>
</RtlLayout>
</ThemeColorPresets>
</ThemeProvider>
<ThemeProvider>
<SnackbarProvider>
<ThemeColorPresets>
<RtlLayout>
<MotionLazyContainer>
<ProgressBarStyle />
{/* <Settings /> */}
<ScrollToTop />
<Router />
</MotionLazyContainer>
</RtlLayout>
</ThemeColorPresets>
</SnackbarProvider>
</ThemeProvider>
);
}

View File

@@ -0,0 +1,92 @@
import { ReactElement } from 'react';
import { Link as RouterLink } from 'react-router-dom';
// @mui
import {
Box,
Link,
Typography,
BreadcrumbsProps,
Breadcrumbs as MUIBreadcrumbs,
} from '@mui/material';
// ----------------------------------------------------------------------
type TLink = {
href?: string;
name: string;
icon?: ReactElement;
};
export interface Props extends BreadcrumbsProps {
links: TLink[];
activeLast?: boolean;
}
export default function Breadcrumbs({ links, activeLast = false, ...other }: Props) {
const currentLink = links[links.length - 1].name;
const listDefault = links.map((link) => <LinkItem key={link.name} link={link} />);
const listActiveLast = links.map((link) => (
<div key={link.name}>
{link.name !== currentLink ? (
<LinkItem link={link} />
) : (
<Typography
variant="body2"
sx={{
maxWidth: 260,
overflow: 'hidden',
whiteSpace: 'nowrap',
color: 'text.disabled',
textOverflow: 'ellipsis',
}}
>
{currentLink}
</Typography>
)}
</div>
));
return (
<MUIBreadcrumbs
separator={
<Box
component="span"
sx={{ width: 4, height: 4, borderRadius: '50%', bgcolor: 'text.disabled' }}
/>
}
{...other}
>
{activeLast ? listDefault : listActiveLast}
</MUIBreadcrumbs>
);
}
// ----------------------------------------------------------------------
type LinkItemProps = {
link: TLink;
};
function LinkItem({ link }: LinkItemProps) {
const { href, name, icon } = link;
return (
<Link
key={name}
variant="body2"
component={RouterLink}
to={href || '#'}
sx={{
lineHeight: 2,
display: 'flex',
alignItems: 'center',
color: 'text.primary',
'& > div': { display: 'inherit' },
}}
>
{icon && <Box sx={{ mr: 1, '& svg': { width: 20, height: 20 } }}>{icon}</Box>}
{name}
</Link>
);
}

View File

@@ -0,0 +1,60 @@
import { ReactNode } from 'react';
import { isString } from 'lodash';
// @mui
import { Box, Typography, Link } from '@mui/material';
//
import Breadcrumbs, { Props as BreadcrumbsProps } from './Breadcrumbs';
// ----------------------------------------------------------------------
interface Props extends BreadcrumbsProps {
action?: ReactNode;
heading: string;
moreLink?: string | string[];
}
export default function HeaderBreadcrumbs({
links,
action,
heading,
moreLink = '' || [],
sx,
...other
}: Props) {
return (
<Box sx={{ mb: 5, ...sx }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Box sx={{ flexGrow: 1 }}>
<Typography variant="h4" gutterBottom>
{heading}
</Typography>
<Breadcrumbs links={links} {...other} />
</Box>
{action && <Box sx={{ flexShrink: 0 }}>{action}</Box>}
</Box>
<Box sx={{ mt: 2 }}>
{isString(moreLink) ? (
<Link href={moreLink} target="_blank" rel="noopener" variant="body2">
{moreLink}
</Link>
) : (
moreLink.map((href) => (
<Link
noWrap
key={href}
href={href}
variant="body2"
target="_blank"
rel="noopener"
sx={{ display: 'table' }}
>
{href}
</Link>
))
)}
</Box>
</Box>
);
}

View File

@@ -1,5 +1,5 @@
import { ReactNode } from 'react';
import ReactQuill, { ReactQuillProps } from 'react-quill';
import ReactQuill from 'react-quill';
// @mui
import { styled } from '@mui/material/styles';
import { Box, BoxProps } from '@mui/material';
@@ -33,9 +33,11 @@ const RootStyle = styled(Box)(({ theme }) => ({
// ----------------------------------------------------------------------
export interface Props extends ReactQuillProps {
export interface Props {
id?: string;
error?: boolean;
value?: string;
onChange?: (value: string) => void;
simple?: boolean;
helperText?: ReactNode;
sx?: BoxProps;
@@ -64,7 +66,7 @@ export default function Editor({
maxStack: 100,
userOnly: true,
},
syntax: true,
syntax: false, // need highlightjs
clipboard: {
matchVisual: false,
},

View File

@@ -83,7 +83,7 @@ function NavListSub({ list }: NavListSubProps) {
const { pathname } = useLocation();
const active = getActive(list.path, pathname);
const active = getActive(list.path, pathname, list.openWhen);
const [open, setOpen] = useState(false);

View File

@@ -9,6 +9,9 @@ export function isExternalLink(path: string) {
return path.includes('http');
}
export function getActive(path: string, pathname: string) {
return path ? !!matchPath({ path: path, end: false }, pathname) : false;
export function getActive(path: string, pathname: string, openWhen?: string[]) {
const listPathWhenActive = [ ...openWhen ?? [], path ];
return listPathWhenActive.includes(pathname);
// return path ? !!matchPath({ path: path, end: false }, pathname) : false;
}

View File

@@ -8,6 +8,7 @@ export type NavListProps = {
path: string;
icon?: ReactElement;
info?: ReactElement;
openWhen? : string[];
children?: {
title: string;
path: string;

View File

@@ -18,7 +18,7 @@ type NavListRootProps = {
export function NavListRoot({ list, isCollapse }: NavListRootProps) {
const { pathname } = useLocation();
const active = getActive(list.path, pathname);
const active = getActive(list.path, pathname, list.openWhen);
const [open, setOpen] = useState(active);

View File

@@ -36,8 +36,6 @@ const navConfig = [
// },
{
title: 'DOCTORS & HOSPITALS',
// path: '/',
// icon: ICONS.user,
children: [
{ title: 'Doctors', path: '/doctors' },
{ title: 'Hospitals', path: '/hospitals' },
@@ -52,8 +50,10 @@ const navConfig = [
},
{
title: 'STATION BENEFIT & MEMBERSHIP',
openWhen: ['/corporates', '/formularium', '/diagnosis', '/hospitals'],
children: [
{ title: 'Corporate', path: '/corporates' },
{ title: 'Corporate Create', path: '/corporates/create' },
{ title: 'Formularium', path: '/formularium' },
{ title: 'Diagnosis Library (ICD-X)', path: '/diagnosis' },
{ title: 'Hospitals', path: '/hospitals' },

View File

@@ -0,0 +1,241 @@
import * as Yup from 'yup';
import { yupResolver } from "@hookform/resolvers/yup";
import { Card, Collapse, Divider, Grid, Stack, Typography } from "@mui/material";
import { useForm } from "react-hook-form";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from "../../../components/hook-form";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
import { useMemo, useState } from 'react';
export default function Divisions() {
const { themeStretch } = useSettings();
const { id } = useParams();
const NewDivisionSchema = Yup.object().shape({
name: Yup.string().required('Name is required'),
code: Yup.string().required('Corporate Code is required'),
active: Yup.boolean().required('Corporate Status is required'),
});
const defaultValues = useMemo(
() => ({
code: '',
}),
[]
);
const methods = useForm({
resolver: yupResolver(NewDivisionSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const onSubmit = async (data: any) => {
console.log(data);
};
const [open, setOpen] = useState(false);
const benefits = [
{
'category' : 'General Practitioner',
'childs' : [
{
'name' : 'External Doctor Online',
'code' : 'gp-external-doctor-online'
},
{
'name' : 'External Doctor Offline',
'code' : 'gp-external-doctor-offline'
},
{
'name' : 'Internal Doctor Online',
'code' : 'gp-internal-doctor-online'
},
{
'name' : 'Internal Doctor Offline',
'code' : 'gp-internal-doctor-offline'
},
]
},
{
'category' : 'Specialist',
'childs' : [
{
'name' : 'External Doctor Online',
'code' : 'sp-external-doctor-online'
},
{
'name' : 'External Doctor Offline',
'code' : 'sp-external-doctor-offline'
},
{
'name' : 'Internal Doctor Online',
'code' : 'sp-internal-doctor-online'
},
{
'name' : 'Internal Doctor Offline',
'code' : 'sp-internal-doctor-offline'
},
]
},
{
'category' : 'Medicines',
'childs' : [
{
'name' : 'Vitamins',
'code' : 'medicines-vitamins'
},
{
'name' : 'Delivery Fee',
'code' : 'medicines-delivery-fee'
},
]
},
];
const products = [
{
'name' : 'Inpatient',
'code' : 'IP',
},
{
'name' : 'Outpatient',
'code' : 'OP',
},
{
'name' : 'Dental',
'code' : 'DT',
},
{
'name' : 'Dental',
'code' : 'DTL',
},
{
'name' : 'Matternity',
'code' : 'MT',
},
{
'name' : 'Special Benefit',
'code' : 'SB',
},
];
return (
<Page title="Create Benefit">
<HeaderBreadcrumbs
heading={'Create Benefit'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Benefits',
href: '/corporates/'+id+'/benefits',
},
{
name: 'Create',
href: '/corporates/'+id+'/benefits/create',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={12}>
<Card sx={{ p: 2 }}>
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={3}>
<Typography variant="h6">Benefit Detail</Typography>
<RHFTextField name="name" label="Benefit Name" />
<RHFTextField name="code" label="Benefit Code" />
<Typography variant="h6">Benefit Configuration</Typography>
<Divider orientation="horizontal" flexItem />
<Stack spacing={3} divider={<Divider orientation="horizontal" flexItem />}>
<Stack spacing={2}>
<RHFCheckbox name="a" label='Outpatient'/>
{benefits.map(row => (
<Collapse in={true} timeout="auto" unmountOnExit >
<Typography>{row.category}</Typography>
<Grid container>
{row.childs.map(benefit => (
<Grid item xs={6}>
<RHFCheckbox name={benefit.code} label={benefit.name}/>
</Grid>
))}
</Grid>
</Collapse>
))}
<Typography>Admin Fee</Typography>
<Grid container>
{benefits.map(row => (
<Grid item xs={4}>
<RHFCheckbox name="cat" label={row.category}/>
</Grid>
))}
</Grid>
</Stack>
<Stack spacing={2}>
<RHFCheckbox name="a" label='Inpatient'/>
{benefits.map(row => (
<Collapse in={true} timeout="auto" unmountOnExit >
<Typography>{row.category}</Typography>
<Grid container>
{row.childs.map(benefit => (
<Grid item xs={6}>
<RHFCheckbox name={benefit.code} label={benefit.name}/>
</Grid>
))}
</Grid>
</Collapse>
))}
<Typography>Admin Fee</Typography>
<Grid container>
{benefits.map(row => (
<Grid item xs={4}>
<RHFCheckbox name="cat" label={row.category}/>
</Grid>
))}
</Grid>
</Stack>
</Stack>
</Stack>
</FormProvider>
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,55 @@
import { Card, Grid } from "@mui/material";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
export default function Divisions() {
const { themeStretch } = useSettings();
const { id } = useParams();
const pageTitle = 'Benefit List';
return (
<Page title={ pageTitle }>
<HeaderBreadcrumbs
heading={ pageTitle }
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Benefits',
href: '/corporates/'+id+'/benefits',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={8}>
<Card>
<CorporateTabNavigations position={'divisions'} />
<DivisionsList />
</Card>
</Grid>
<Grid item xs={4}>
<Card sx={{ p: 2 }}>
Corporate Detail Goes Here
&nbsp;
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,244 @@
// @mui
import { Box, Button, Card, Collapse, Container, FormControl, Grid, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack } from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import PublishIcon from '@mui/icons-material/Publish';
import AddIcon from '@mui/icons-material/Add';
// hooks
import useSettings from '../../../hooks/useSettings';
// components
import Page from '../../../components/Page';
import axios from '../../../utils/axios';
import useAuth from '../../../hooks/useAuth';
import { Link , NavLink as RouterLink, useParams } from 'react-router-dom';
import React, { useEffect, useRef } from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import { Corporate } from '../../../@types/corporates';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
import CorporateTabNavigations from '../CorporateTabNavigations';
export default function DivisionsList() {
const { themeStretch } = useSettings();
// Called on every row to map the data to the columns
function createData( corporate: Corporate ): Corporate {
return {
...corporate,
}
}
// Generate the every row of the table
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.code}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"><Button variant="outlined" color="success" size="small">Active</Button></TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Customer</TableCell>
<TableCell align="right">Amount</TableCell>
<TableCell align="right">Total price ($)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history ? row.history.map(( historyRow ) => (
<TableRow key={historyRow?.date}>
<TableCell component="th" scope="row">
{historyRow?.date}
</TableCell>
<TableCell>{historyRow?.customerId}</TableCell>
<TableCell align="right">{historyRow?.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow?.amount * 1000 * 100) / 100}
</TableCell>
</TableRow>
))
: (
<TableRow>
<TableCell colSpan={8}>No Data</TableCell>
</TableRow>
)
}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = React.useState(true);
const [dataTableData, setDataTableData] = React.useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: "",
first_page_url: "",
last_page: 1,
last_page_url: "",
next_page_url: "",
prev_page_url: "",
per_page: 10,
from: 0,
to: 0,
total: 0
});
const loadDataTableData = async () => {
setDataTableLoading(true);
const response = await axios.get('/corporates');
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
}
useEffect(() => {
loadDataTableData();
}, [])
const headStyle = {
fontWeight: 'bold',
};
// FILTER SELECT
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const names = [
'PLAN001',
'PLAN002',
'PLAN003',
'PLAN004',
'PLAN005',
];
function getStyles(name: string, personName: string[], theme: Theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}
const theme = useTheme();
const [planIdFilter, setPlanIdFilter] = React.useState<string[]>([]);
const handleChangePlanID = (event: SelectChangeEvent<typeof planIdFilter>) => {
const {
target: { value },
} = event;
setPlanIdFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
const [statusFilter, setStatusFilter] = React.useState<string[]>([]);
const handleChangeStatus = (event: SelectChangeEvent<typeof statusFilter>) => {
const {
target: { value },
} = event;
setStatusFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
// END FILTER SELECT
// IMPORT
const importMember = React.useRef(null);
const handleImportButton = (event: any) => {
if (importMember?.current)
importMember.current ? importMember.current.click() : console.log('fuck');
else
alert('No file selected')
}
const { id } = useParams();
return (
<Stack>
<Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
<TextField id="outlined-basic" label="Search" variant="outlined" fullWidth />
<Link to={"/corporates/"+id+"/divisions/create"}>
<Button variant="outlined" startIcon={<AddIcon />} sx={{ p: 1.8 }} >Create</ Button>
</Link>
</Stack>
<Card>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableBody>
<TableRow>
<TableCell style={headStyle} align="left">#</TableCell>
<TableCell style={headStyle} align="left">Code</TableCell>
<TableCell style={headStyle} align="left">Name</TableCell>
<TableCell style={headStyle} align="right">Action</TableCell>
</TableRow>
</TableBody>
{dataTableIsLoading ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">Loading</TableCell>
</TableRow>
</TableBody>
) : (
dataTableData.data.length == 0 ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">No Data</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData.data.map(row => (
<Row key={row.code} row={row} />
))}
</TableBody>
)
)}
</Table>
</TableContainer>
</Card>
</Stack>
);
}

View File

@@ -0,0 +1,65 @@
import { Tab, Tabs } from "@mui/material";
import { useTheme } from "@mui/system";
import React, { useEffect } from "react";
import { Link, useParams } from "react-router-dom";
type Props = {
position: string
}
export default function CorporateTabNavigations({ position }: Props) {
const theme = useTheme();
const { id } = useParams();
const [currentTab, setCurrentTab] = React.useState(0);
const mainTabItems = [
{
'path' : 'members',
'label': 'Member List',
},
{
'path' : 'claim-history',
'label': 'Claim History',
},
{
'path' : 'divisions',
'label': 'Divisions',
},
{
'path' : 'plans',
'label': 'Plans',
},
{
'path' : 'benefits',
'label': 'Benefit & Exclusion',
},
{
'path' : 'hospitals',
'label': 'Hospital',
},
{
'path' : 'formularium',
'label': 'Formularium',
},
];
useEffect(() => {
let currentIndex = mainTabItems.findIndex(item => item.path === position);
setCurrentTab(currentIndex);
}, [])
return (
<Tabs
theme={theme}
value={currentTab}
onChange={(event, newValue) => false}
variant="scrollable"
scrollButtons
allowScrollButtonsMobile
aria-label="scrollable force tabs example"
>
{mainTabItems.map((tabItem, index) => (<Tab key={index} label={(<Link to={"/corporates/"+id+"/"+mainTabItems[index].path}>{tabItem.label}</Link>)} />))}
</Tabs>
)
}

View File

@@ -0,0 +1,56 @@
import { useEffect, useState } from 'react';
import { paramCase } from 'change-case';
import { useParams, useLocation } from 'react-router-dom';
// @mui
import { Container } from '@mui/material';
import useSettings from '../../hooks/useSettings';
import Page from '../../components/Page';
import Form from './Form';
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
import axios from '../../utils/axios';
import { Corporate } from '../../@types/corporates';
// ----------------------------------------------------------------------
export default function Create() {
const { themeStretch } = useSettings();
const { id } = useParams();
const isEdit = id ? true : false;
// const corporates = [{ id: 1, name: 'Product 1', code: 'Code' }];
const [ currentCorporate, setCurrentCorporate ] = useState<Corporate>();
// const name = "Henlooooo";
useEffect(() => {
if (isEdit) {
axios.get('/corporates/'+id+'/edit')
.then((res) => {
setCurrentCorporate(res.data);
})
}
}, [id]);
return (
<Page title="Membership: Create a new corporate">
<Container maxWidth={themeStretch ? false : 'lg'}>
<HeaderBreadcrumbs
heading={!isEdit ? 'Create a new corporate' : 'Edit corporate'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{ name: !isEdit ? 'Create' : currentCorporate?.name ?? '' },
]}
/>
<Form isEdit={isEdit} currentCorporate={currentCorporate} />
</Container>
</Page>
);
}

View File

@@ -0,0 +1,212 @@
import * as Yup from 'yup';
import { yupResolver } from "@hookform/resolvers/yup";
import { Card, Collapse, Divider, Grid, Stack, Typography } from "@mui/material";
import { useForm } from "react-hook-form";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from "../../../components/hook-form";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
import { useMemo, useState } from 'react';
export default function Divisions() {
const { themeStretch } = useSettings();
const { id } = useParams();
const NewDivisionSchema = Yup.object().shape({
name: Yup.string().required('Name is required'),
code: Yup.string().required('Corporate Code is required'),
active: Yup.boolean().required('Corporate Status is required'),
});
const defaultValues = useMemo(
() => ({
code: '',
}),
[]
);
const methods = useForm({
resolver: yupResolver(NewDivisionSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const onSubmit = async (data: any) => {
console.log(data);
};
const [open, setOpen] = useState(false);
const benefits = [
{
'category' : 'General Practitioner',
'childs' : [
{
'name' : 'External Doctor Online',
'code' : 'gp-external-doctor-online'
},
{
'name' : 'External Doctor Offline',
'code' : 'gp-external-doctor-offline'
},
{
'name' : 'Internal Doctor Online',
'code' : 'gp-internal-doctor-online'
},
{
'name' : 'Internal Doctor Offline',
'code' : 'gp-internal-doctor-offline'
},
]
},
{
'category' : 'Specialist',
'childs' : [
{
'name' : 'External Doctor Online',
'code' : 'sp-external-doctor-online'
},
{
'name' : 'External Doctor Offline',
'code' : 'sp-external-doctor-offline'
},
{
'name' : 'Internal Doctor Online',
'code' : 'sp-internal-doctor-online'
},
{
'name' : 'Internal Doctor Offline',
'code' : 'sp-internal-doctor-offline'
},
]
},
{
'category' : 'Medicines',
'childs' : [
{
'name' : 'Vitamins',
'code' : 'medicines-vitamins'
},
{
'name' : 'Delivery Fee',
'code' : 'medicines-delivery-fee'
},
]
},
];
return (
<Page title="Create Division">
<HeaderBreadcrumbs
heading={'Create Division'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Divisions',
href: '/corporates/'+id+'/divisions',
},
{
name: 'Create',
href: '/corporates/'+id+'/divisions/create',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={12}>
<Card sx={{ p: 2 }}>
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={3}>
<Typography variant="h6">Division Detail</Typography>
<RHFTextField name="name" label="Corporate Name" />
<Typography variant="h6">Benefit Configuration</Typography>
<Divider orientation="horizontal" flexItem />
<Stack spacing={3} divider={<Divider orientation="horizontal" flexItem />}>
<Stack spacing={2}>
<RHFCheckbox name="a" label='Outpatient'/>
{benefits.map(row => (
<Collapse in={true} timeout="auto" unmountOnExit >
<Typography>{row.category}</Typography>
<Grid container>
{row.childs.map(benefit => (
<Grid item xs={6}>
<RHFCheckbox name={benefit.code} label={benefit.name}/>
</Grid>
))}
</Grid>
</Collapse>
))}
<Typography>Admin Fee</Typography>
<Grid container>
{benefits.map(row => (
<Grid item xs={4}>
<RHFCheckbox name="cat" label={row.category}/>
</Grid>
))}
</Grid>
</Stack>
<Stack spacing={2}>
<RHFCheckbox name="a" label='Inpatient'/>
{benefits.map(row => (
<Collapse in={true} timeout="auto" unmountOnExit >
<Typography>{row.category}</Typography>
<Grid container>
{row.childs.map(benefit => (
<Grid item xs={6}>
<RHFCheckbox name={benefit.code} label={benefit.name}/>
</Grid>
))}
</Grid>
</Collapse>
))}
<Typography>Admin Fee</Typography>
<Grid container>
{benefits.map(row => (
<Grid item xs={4}>
<RHFCheckbox name="cat" label={row.category}/>
</Grid>
))}
</Grid>
</Stack>
</Stack>
</Stack>
</FormProvider>
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,54 @@
import { Card, Grid } from "@mui/material";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
export default function Divisions() {
const { themeStretch } = useSettings();
const { id } = useParams();
return (
<Page title="Division List">
<HeaderBreadcrumbs
heading={'Division List'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Divisions',
href: '/corporates/'+id+'/divisions',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={8}>
<Card>
<CorporateTabNavigations position={'divisions'} />
<DivisionsList />
</Card>
</Grid>
<Grid item xs={4}>
<Card sx={{ p: 2 }}>
Corporate Detail Goes Here
&nbsp;
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,248 @@
// @mui
import { Box, Button, Card, Collapse, Container, FormControl, Grid, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack } from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import PublishIcon from '@mui/icons-material/Publish';
import AddIcon from '@mui/icons-material/Add';
// hooks
import useSettings from '../../../hooks/useSettings';
// components
import Page from '../../../components/Page';
import axios from '../../../utils/axios';
import useAuth from '../../../hooks/useAuth';
import { Link , NavLink as RouterLink, useParams } from 'react-router-dom';
import React, { useEffect, useRef } from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import { Corporate } from '../../../@types/corporates';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
import CorporateTabNavigations from '../CorporateTabNavigations';
export default function DivisionsList() {
const { themeStretch } = useSettings();
// Called on every row to map the data to the columns
function createData( corporate: Corporate ): Corporate {
return {
...corporate,
}
}
// Generate the every row of the table
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.code}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"><Button variant="outlined" color="success" size="small">Active</Button></TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Customer</TableCell>
<TableCell align="right">Amount</TableCell>
<TableCell align="right">Total price ($)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history ? row.history.map((historyRow) => (
<TableRow key={historyRow?.date}>
<TableCell component="th" scope="row">
{historyRow?.date}
</TableCell>
<TableCell>{historyRow?.customerId}</TableCell>
<TableCell align="right">{historyRow?.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow?.amount * 1000 * 100) / 100}
</TableCell>
</TableRow>
))
: (
<TableRow>
<TableCell colSpan={8}>No Data</TableCell>
</TableRow>
)
}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = React.useState(true);
const [dataTableData, setDataTableData] = React.useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: "",
first_page_url: "",
last_page: 1,
last_page_url: "",
next_page_url: "",
prev_page_url: "",
per_page: 10,
from: 0,
to: 0,
total: 0
});
const loadDataTableData = async () => {
setDataTableLoading(true);
const response = await axios.get('/corporates');
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
}
useEffect(() => {
loadDataTableData();
}, [])
const headStyle = {
fontWeight: 'bold',
};
// FILTER SELECT
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const names = [
'PLAN001',
'PLAN002',
'PLAN003',
'PLAN004',
'PLAN005',
];
function getStyles(name: string, personName: string[], theme: Theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}
const theme = useTheme();
const [planIdFilter, setPlanIdFilter] = React.useState<string[]>([]);
const handleChangePlanID = (event: SelectChangeEvent<typeof planIdFilter>) => {
const {
target: { value },
} = event;
setPlanIdFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
const [statusFilter, setStatusFilter] = React.useState<string[]>([]);
const handleChangeStatus = (event: SelectChangeEvent<typeof statusFilter>) => {
const {
target: { value },
} = event;
setStatusFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
// END FILTER SELECT
// IMPORT
const importMember = React.useRef(null);
const handleImportButton = (event: any) => {
if (importMember?.current)
importMember.current ? importMember.current.click() : console.log('fuck');
else
alert('No file selected')
}
const { id } = useParams();
return (
<Stack>
<Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
<TextField id="outlined-basic" label="Search" variant="outlined" fullWidth />
{/* <input id="importMember" ref={importMember} style={{ display: 'none' }} type="file" accept='.csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, text/plain' />
<Button variant="outlined" startIcon={<PublishIcon />} sx={{ p: 1.8 }} onClick={handleImportButton}>
Import
</Button> */}
<Link to={"/corporates/"+id+"/divisions/create"}>
<Button variant="outlined" startIcon={<AddIcon />} sx={{ p: 1.8 }} >Create</ Button>
</Link>
</Stack>
<Card>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableBody>
<TableRow>
<TableCell style={headStyle} align="left">#</TableCell>
<TableCell style={headStyle} align="left">Code</TableCell>
<TableCell style={headStyle} align="left">Name</TableCell>
<TableCell style={headStyle} align="right">Action</TableCell>
</TableRow>
</TableBody>
{dataTableIsLoading ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">Loading</TableCell>
</TableRow>
</TableBody>
) : (
dataTableData.data.length == 0 ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">No Data</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData.data.map(row => (
<Row key={row.code} row={row} />
))}
</TableBody>
)
)}
</Table>
</TableContainer>
</Card>
</Stack>
);
}

View File

@@ -0,0 +1,278 @@
import * as Yup from 'yup';
import { useSnackbar } from 'notistack';
import { useNavigate } from 'react-router-dom';
import { useCallback, useEffect, useMemo, useState } from 'react';
// form
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
// @mui
import { styled } from '@mui/material/styles';
import { LoadingButton } from '@mui/lab';
import {
Card,
FormHelperText,
Grid,
Stack,
Typography,
} from '@mui/material';
// components
import {
FormProvider,
RHFTextField,
RHFRadioGroup,
RHFUploadAvatar,
RHFSwitch,
} from '../../components/hook-form';
import { Corporate } from '../../@types/corporates';
import axios from '../../utils/axios';
const LabelStyle = styled(Typography)(({ theme }) => ({
...theme.typography.subtitle2,
color: theme.palette.text.secondary,
marginBottom: theme.spacing(1),
}));
interface FormValuesProps extends Partial<Corporate> {
taxes: boolean;
inStock: boolean;
}
type Props = {
isEdit: boolean;
currentCorporate?: Corporate;
};
export default function CorporateForm({ isEdit, currentCorporate }: Props) {
const navigate = useNavigate();
// const [ errors, setErrors ] = useState<{ [key: string]: string }>({});
const { enqueueSnackbar } = useSnackbar();
const NewCorporateSchema = Yup.object().shape({
name: Yup.string().required('Name is required'),
code: Yup.string().required('Corporate Code is required'),
active: Yup.boolean().required('Corporate Status is required'),
});
const defaultValues = useMemo(
() => ({
code: currentCorporate?.code || '',
name: currentCorporate?.name || '',
welcome_message: currentCorporate?.welcome_message || '',
help_text: currentCorporate?.help_text || '',
active: currentCorporate?.id ? currentCorporate?.active === 1 : true,
policy_id: currentCorporate?.current_policy?.id || '',
policy_code: currentCorporate?.current_policy?.code || '',
policy_total_premi: currentCorporate?.current_policy?.total_premi || '',
policy_minimal_deposit_percentage: currentCorporate?.current_policy?.minimal_deposit_percentage || 50,
policy_minimal_deposit_net: currentCorporate?.current_policy?.minimal_deposit_net || '',
policy_minimal_alert_percentage: currentCorporate?.current_policy?.minimal_alert_percentage || 25,
policy_minimal_alert_net: currentCorporate?.current_policy?.minimal_alert_net || '',
policy_stop_service_percentage: currentCorporate?.current_policy?.minimal_stop_service_percentage || 25,
policy_stop_service_net: currentCorporate?.current_policy?.minimal_stop_service_net || '',
policy_start: currentCorporate?.current_policy?.start || '',
policy_end: currentCorporate?.current_policy?.end || '',
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[currentCorporate]
);
const methods = useForm<FormValuesProps>({
resolver: yupResolver(NewCorporateSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const values = watch();
useEffect(() => {
if (isEdit && currentCorporate) {
reset(defaultValues);
}
if (!isEdit) {
reset(defaultValues);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isEdit, currentCorporate]);
const onSubmit = async (data: FormValuesProps) => {
try {
if (!isEdit) {
const response = await axios.post('/corporates', data);
} else {
const response = await axios.put('/corporates/' + currentCorporate?.id ?? '', data);
}
reset();
enqueueSnackbar(!isEdit ? 'Corporate Created Successfully!' : 'Corporate Udpated Successfully!', { variant: 'success' });
navigate('/corporates');
} catch (error: any) {
if (error && error.response.status === 422) {
for (const [key, value] of Object.entries(error.response.data.errors)) {
setError(key, { message: value[0] });
enqueueSnackbar(value[0] ?? 'Failed Processing Request', { variant: 'error' });
}
}
else {
enqueueSnackbar(error.message ?? 'Failed Processing Request', { variant: 'error' });
}
}
};
const handleDrop = useCallback(
(acceptedFiles) => {
setValue(
'logo',
acceptedFiles.map((file: Blob | MediaSource) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
})
)
);
},
[setValue]
);
const handleRemove = (file: File | string) => {
setValue('logo', null);
};
return (
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
{/* <Card sx={{ p:3, mb:3, background: 'gray', color: 'white' }}><Typography>Corporate Detail</Typography></Card> */}
<Grid container spacing={3}>
<Grid item xs={12} md={8}>
<Card sx={{ p: 3 }}>
<Stack spacing={3}>
<Grid item xs={12}><Typography variant='h5'>Corporate Profile</Typography></Grid>
<RHFTextField name="code" label="Corporate Code" />
<RHFTextField name="name" label="Corporate Name" />
<RHFTextField name="welcome_message" label="Welcome Message" />
<RHFTextField name="help_text" label="Help Text" />
{/* <div>
<LabelStyle>Images</LabelStyle>
<RHFUploadMultiFile
name="images"
files={[]}
showPreview
accept="image/*"
maxSize={3145728}
onDrop={handleDrop}
onRemove={handleRemove}
onRemoveAll={handleRemoveAll}
/>
</div> */}
</Stack>
</Card>
</Grid>
<Grid item xs={12} md={4}>
<Stack spacing={3}>
<Card sx={{ p: 3 }}>
<RHFSwitch name="active" label="Is Company Active" />
<Stack spacing={3} mt={2}>
<Typography align="center">Company Logo</Typography>
<RHFUploadAvatar name="logo"
showPreview
accept={'image/*'}
maxSize={3145728}
onDrop={handleDrop}
onRemove={handleRemove}
/>
</Stack>
</Card>
</Stack>
</Grid>
<Grid item xs={12} md={12}>
{/* <Card sx={{ p:3, mb:3, background: 'gray', color: 'white' }}><Typography>Policy Detail</Typography></Card> */}
<Card sx={{ p: 3 }}>
<Stack spacing={3} mt={2}>
<Grid item xs={12}><Typography variant='h5'>Policy Detail</Typography></Grid>
<input type="hidden" name="policy_id" />
<Stack spacing={1}>
<RHFTextField name="policy_code" label="Policy Number" />
{(!(currentCorporate?.id) && <Typography variant="caption">Will be generated if empty</Typography>)}
</Stack>
{/* <Typography>Minimal Deposit Policy Level</Typography> */}
<Grid container>
<Grid item xs={12} md={6}>
<RHFTextField name="policy_start" label="Start Date (YYYY-MM-DD)" />
</Grid>
<Grid item xs={12} md={6}>
<RHFTextField name="policy_end" label="End Date (YYYY-MM-DD)" />
</Grid>
</Grid>
<RHFTextField name="policy_total_premi" label="Total Premi" />
<Stack spacing={1}>
<Typography>Minimal Deposit Policy Level</Typography>
<Grid container>
<Grid item xs={12} md={3}>
<RHFTextField name="policy_minimal_deposit_percentage" label="Percentage (%)" />
</Grid>
<Grid item xs={12} md={9}>
<RHFTextField name="policy_minimal_deposit_net" label="Net (Rp)" />
</Grid>
</Grid>
</Stack>
<Stack spacing={1}>
<Typography>Minimal Alert Level</Typography>
<Grid container>
<Grid item xs={12} md={3}>
<RHFTextField name="policy_minimal_alert_percentage" label="Percentage (%)" />
</Grid>
<Grid item xs={12} md={9}>
<RHFTextField name="policy_minimal_alert_net" label="Net (Rp)" />
</Grid>
</Grid>
</Stack>
<Stack spacing={1}>
<Typography>Stop Service Level</Typography>
<Grid container>
<Grid item xs={12} md={3}>
<RHFTextField name="policy_stop_service_percentage" label="Percentage (%)" />
</Grid>
<Grid item xs={12} md={9}>
<RHFTextField name="policy_stop_service_net" label="Net (Rp)" />
</Grid>
</Grid>
</Stack>
</Stack>
</Card>
</Grid>
<Grid item xs={12} md={4}>
<LoadingButton type="submit" variant="contained" size="large" fullWidth={true} loading={isSubmitting}>
{!isEdit ? 'Create Product' : 'Save Changes'}
</LoadingButton>
</Grid>
</Grid>
</FormProvider>
);
};

View File

@@ -0,0 +1,321 @@
// @mui
import { Box, Button, Card, Collapse, Container, FormControl, Grid, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Stack } from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import PublishIcon from '@mui/icons-material/Publish';
import AddIcon from '@mui/icons-material/Add';
// hooks
import useSettings from '../../hooks/useSettings';
// components
import Page from '../../components/Page';
import axios from '../../utils/axios';
import useAuth from '../../hooks/useAuth';
import { Link , NavLink as RouterLink } from 'react-router-dom';
import React, { useEffect, useRef } from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import { Corporate } from '../../@types/corporates';
import { LaravelPaginatedData } from '../../@types/paginated-data';
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
export default function Corporates() {
const { themeStretch } = useSettings();
// Called on every row to map the data to the columns
function createData( corporate: Corporate ): Corporate {
return {
...corporate,
}
}
// Generate the every row of the table
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.code}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="left"><Button variant="outlined" color="success" size="small">Active</Button></TableCell>
<TableCell align="right">
<Stack direction="row" justifyContent="flex-end" spacing={1}>
<Link to={"/corporates/" + row.id + "/edit"}><Button variant="outlined" color="primary" size="small">Edit</Button></ Link>
<Link to={"/corporates/" + row.id + ""}><Button variant="outlined" color="primary" size="small">Config</Button></ Link>
</Stack>
</TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Customer</TableCell>
<TableCell align="right">Amount</TableCell>
<TableCell align="right">Total price ($)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history ? row.history.map((historyRow) => (
<TableRow key={historyRow?.date}>
<TableCell component="th" scope="row">
{historyRow?.date}
</TableCell>
<TableCell>{historyRow?.customerId}</TableCell>
<TableCell align="right">{historyRow?.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow?.amount * 1000 * 100) / 100}
</TableCell>
</TableRow>
))
: (
<TableRow>
<TableCell colSpan={8}>No Data</TableCell>
</TableRow>
)
}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = React.useState(true);
const [dataTableData, setDataTableData] = React.useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: "",
first_page_url: "",
last_page: 1,
last_page_url: "",
next_page_url: "",
prev_page_url: "",
per_page: 10,
from: 0,
to: 0,
total: 0
});
const loadDataTableData = async () => {
setDataTableLoading(true);
const response = await axios.get('/corporates');
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
}
useEffect(() => {
loadDataTableData();
}, [])
const headStyle = {
fontWeight: 'bold',
};
// FILTER SELECT
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const names = [
'PLAN001',
'PLAN002',
'PLAN003',
'PLAN004',
'PLAN005',
];
function getStyles(name: string, personName: string[], theme: Theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}
const theme = useTheme();
const [planIdFilter, setPlanIdFilter] = React.useState<string[]>([]);
const handleChangePlanID = (event: SelectChangeEvent<typeof planIdFilter>) => {
const {
target: { value },
} = event;
setPlanIdFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
const [statusFilter, setStatusFilter] = React.useState<string[]>([]);
const handleChangeStatus = (event: SelectChangeEvent<typeof statusFilter>) => {
const {
target: { value },
} = event;
setStatusFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
// END FILTER SELECT
// IMPORT
const importMember = React.useRef(null);
const handleImportButton = (event: any) => {
if (importMember?.current)
importMember.current ? importMember.current.click() : console.log('fuck');
else
alert('No file selected')
}
return (
<Page title="Membership : Corporate List">
<Container maxWidth={themeStretch ? false : 'xl'}>
<HeaderBreadcrumbs
heading={'Coporate List'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
]}
/>
<Grid container spacing={3} sx={{ mb: 2 }} justifyContent="flex-end">
<Grid item>
<TextField id="outlined-basic" label="Search" variant="outlined" sx={{ width: 400 }}/>
</Grid>
<Grid item>
<FormControl sx={{ width: 200 }}>
<InputLabel id="plan-id-label">PlanID</InputLabel>
<Select
labelId="plan-id-label"
id="plan-id"
multiple
value={planIdFilter}
onChange={handleChangePlanID}
input={<OutlinedInput label="PlanID" />}
MenuProps={MenuProps}
>
{names.map((name) => (
<MenuItem
key={name}
value={name}
style={getStyles(name, planIdFilter, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item>
<FormControl sx={{ width: 200 }}>
<InputLabel id="status-filter-label">Status</InputLabel>
<Select
labelId="status-filter-label"
id="status-filter"
multiple
value={statusFilter}
onChange={handleChangeStatus}
input={<OutlinedInput label="Status" />}
MenuProps={MenuProps}
>
{['Active', 'Suspended'].map((name) => (
<MenuItem
key={name}
value={name}
style={getStyles(name, statusFilter, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item>
{/* <input id="importMember" ref={importMember} style={{ display: 'none' }} type="file" accept='.csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, text/plain' />
<Button variant="outlined" startIcon={<PublishIcon />} sx={{ p: 1.8 }} onClick={handleImportButton}>
Import
</Button> */}
<Link to={"/corporates/create"}>
<Button variant="outlined" startIcon={<AddIcon />} sx={{ p: 1.8 }} >Create</ Button>
</Link>
</Grid>
</Grid>
<Card>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableBody>
<TableRow>
<TableCell style={headStyle} align="left">#</TableCell>
<TableCell style={headStyle} align="left">Code</TableCell>
<TableCell style={headStyle} align="left">Name</TableCell>
<TableCell style={headStyle} align="left">Status</TableCell>
<TableCell style={headStyle} align="right">Action</TableCell>
</TableRow>
</TableBody>
{dataTableIsLoading ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">Loading</TableCell>
</TableRow>
</TableBody>
) : (
dataTableData.data.length == 0 ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">No Data</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData.data.map(row => (
<Row key={row.code} row={row} />
))}
</TableBody>
)
)}
</Table>
</TableContainer>
</Card>
</Container>
</Page>
);
}

View File

@@ -0,0 +1,54 @@
import { Card, Grid } from "@mui/material";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
export default function Divisions() {
const { themeStretch } = useSettings();
const { id } = useParams();
return (
<Page title="Division List">
<HeaderBreadcrumbs
heading={'Division List'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Divisions',
href: '/corporates/'+id+'/divisions',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={8}>
<Card>
<CorporateTabNavigations position={'divisions'} />
<DivisionsList />
</Card>
</Grid>
<Grid item xs={4}>
<Card sx={{ p: 2 }}>
Corporate Detail Goes Here
&nbsp;
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,248 @@
// @mui
import { Box, Button, Card, Collapse, Container, FormControl, Grid, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack } from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import PublishIcon from '@mui/icons-material/Publish';
import AddIcon from '@mui/icons-material/Add';
// hooks
import useSettings from '../../../hooks/useSettings';
// components
import Page from '../../../components/Page';
import axios from '../../../utils/axios';
import useAuth from '../../../hooks/useAuth';
import { Link , NavLink as RouterLink, useParams } from 'react-router-dom';
import React, { useEffect, useRef } from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import { Corporate } from '../../../@types/corporates';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
import CorporateTabNavigations from '../CorporateTabNavigations';
export default function DivisionsList() {
const { themeStretch } = useSettings();
// Called on every row to map the data to the columns
function createData( corporate: Corporate ): Corporate {
return {
...corporate,
}
}
// Generate the every row of the table
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.code}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"><Button variant="outlined" color="success" size="small">Active</Button></TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Customer</TableCell>
<TableCell align="right">Amount</TableCell>
<TableCell align="right">Total price ($)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history ? row.history.map((historyRow) => (
<TableRow key={historyRow?.date}>
<TableCell component="th" scope="row">
{historyRow?.date}
</TableCell>
<TableCell>{historyRow?.customerId}</TableCell>
<TableCell align="right">{historyRow?.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow?.amount * 1000 * 100) / 100}
</TableCell>
</TableRow>
))
: (
<TableRow>
<TableCell colSpan={8}>No Data</TableCell>
</TableRow>
)
}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = React.useState(true);
const [dataTableData, setDataTableData] = React.useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: "",
first_page_url: "",
last_page: 1,
last_page_url: "",
next_page_url: "",
prev_page_url: "",
per_page: 10,
from: 0,
to: 0,
total: 0
});
const loadDataTableData = async () => {
setDataTableLoading(true);
const response = await axios.get('/corporates');
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
}
useEffect(() => {
loadDataTableData();
}, [])
const headStyle = {
fontWeight: 'bold',
};
// FILTER SELECT
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const names = [
'PLAN001',
'PLAN002',
'PLAN003',
'PLAN004',
'PLAN005',
];
function getStyles(name: string, personName: string[], theme: Theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}
const theme = useTheme();
const [planIdFilter, setPlanIdFilter] = React.useState<string[]>([]);
const handleChangePlanID = (event: SelectChangeEvent<typeof planIdFilter>) => {
const {
target: { value },
} = event;
setPlanIdFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
const [statusFilter, setStatusFilter] = React.useState<string[]>([]);
const handleChangeStatus = (event: SelectChangeEvent<typeof statusFilter>) => {
const {
target: { value },
} = event;
setStatusFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
// END FILTER SELECT
// IMPORT
const importMember = React.useRef(null);
const handleImportButton = (event: any) => {
if (importMember?.current)
importMember.current ? importMember.current.click() : console.log('fuck');
else
alert('No file selected')
}
const { id } = useParams();
return (
<Stack>
<Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
<TextField id="outlined-basic" label="Search" variant="outlined" fullWidth />
{/* <input id="importMember" ref={importMember} style={{ display: 'none' }} type="file" accept='.csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, text/plain' />
<Button variant="outlined" startIcon={<PublishIcon />} sx={{ p: 1.8 }} onClick={handleImportButton}>
Import
</Button> */}
<Link to={"/corporates/"+id+"/divisions/create"}>
<Button variant="outlined" startIcon={<AddIcon />} sx={{ p: 1.8 }} >Create</ Button>
</Link>
</Stack>
<Card>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableBody>
<TableRow>
<TableCell style={headStyle} align="left">#</TableCell>
<TableCell style={headStyle} align="left">Code</TableCell>
<TableCell style={headStyle} align="left">Name</TableCell>
<TableCell style={headStyle} align="right">Action</TableCell>
</TableRow>
</TableBody>
{dataTableIsLoading ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">Loading</TableCell>
</TableRow>
</TableBody>
) : (
dataTableData.data.length == 0 ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">No Data</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData.data.map(row => (
<Row key={row.code} row={row} />
))}
</TableBody>
)
)}
</Table>
</TableContainer>
</Card>
</Stack>
);
}

View File

@@ -0,0 +1,247 @@
import * as Yup from 'yup';
import { yupResolver } from "@hookform/resolvers/yup";
import { Card, Collapse, Divider, Grid, Stack, Typography } from "@mui/material";
import { useForm } from "react-hook-form";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from "../../../components/hook-form";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
import { useMemo, useState } from 'react';
export default function PlanCreate() {
const { themeStretch } = useSettings();
const { id } = useParams();
const NewDivisionSchema = Yup.object().shape({
name: Yup.string().required('Name is required'),
code: Yup.string().required('Corporate Code is required'),
active: Yup.boolean().required('Corporate Status is required'),
});
const defaultValues = useMemo(
() => ({
code: '',
}),
[]
);
const methods = useForm({
resolver: yupResolver(NewDivisionSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const onSubmit = async (data: any) => {
console.log(data);
};
const [open, setOpen] = useState(false);
const benefits = [
{
'category' : 'General Practitioner',
'childs' : [
{
'name' : 'External Doctor Online',
'code' : 'gp-external-doctor-online'
},
{
'name' : 'External Doctor Offline',
'code' : 'gp-external-doctor-offline'
},
{
'name' : 'Internal Doctor Online',
'code' : 'gp-internal-doctor-online'
},
{
'name' : 'Internal Doctor Offline',
'code' : 'gp-internal-doctor-offline'
},
]
},
{
'category' : 'Specialist',
'childs' : [
{
'name' : 'External Doctor Online',
'code' : 'sp-external-doctor-online'
},
{
'name' : 'External Doctor Offline',
'code' : 'sp-external-doctor-offline'
},
{
'name' : 'Internal Doctor Online',
'code' : 'sp-internal-doctor-online'
},
{
'name' : 'Internal Doctor Offline',
'code' : 'sp-internal-doctor-offline'
},
]
},
{
'category' : 'Medicines',
'childs' : [
{
'name' : 'Vitamins',
'code' : 'medicines-vitamins'
},
{
'name' : 'Delivery Fee',
'code' : 'medicines-delivery-fee'
},
]
},
];
const products = [
{
'name' : 'Inpatient',
'code' : 'IP',
},
{
'name' : 'Outpatient',
'code' : 'OP',
},
{
'name' : 'Dental',
'code' : 'DT',
},
{
'name' : 'Dental',
'code' : 'DTL',
},
{
'name' : 'Matternity',
'code' : 'MT',
},
{
'name' : 'Special Benefit',
'code' : 'SB',
},
];
return (
<Page title="Create Plan">
<HeaderBreadcrumbs
heading={'Create Plan'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Plans',
href: '/corporates/'+id+'/plans',
},
{
name: 'Create',
href: '/corporates/'+id+'/plans/create',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={12}>
<Card sx={{ p: 2 }}>
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={3}>
<Typography variant="h6">Plan Detail</Typography>
<RHFTextField name="name" label="Name" />
<RHFTextField name="code" label="Code" />
<RHFTextField name="limit" label="Limit" />
<RHFTextField name="start" label="Start (YYYY-MM-DD)" />
<RHFTextField name="end" label="End (YYYY-MM-DD)" />
<Typography variant="h6">Benefit Configuration</Typography>
<Divider orientation="horizontal" flexItem />
<Stack spacing={3} divider={<Divider orientation="horizontal" flexItem />}>
<Stack spacing={2}>
<RHFCheckbox name="a" label='Outpatient'/>
{benefits.map(row => (
<Collapse in={true} timeout="auto" unmountOnExit >
<Typography>{row.category}</Typography>
<Grid container>
{row.childs.map(benefit => (
<Grid item xs={6}>
<RHFCheckbox name={benefit.code} label={benefit.name}/>
</Grid>
))}
</Grid>
</Collapse>
))}
<Typography>Admin Fee</Typography>
<Grid container>
{benefits.map(row => (
<Grid item xs={4}>
<RHFCheckbox name="cat" label={row.category}/>
</Grid>
))}
</Grid>
</Stack>
<Stack spacing={2}>
<RHFCheckbox name="a" label='Inpatient'/>
{benefits.map(row => (
<Collapse in={true} timeout="auto" unmountOnExit >
<Typography>{row.category}</Typography>
<Grid container>
{row.childs.map(benefit => (
<Grid item xs={6}>
<RHFCheckbox name={benefit.code} label={benefit.name}/>
</Grid>
))}
</Grid>
</Collapse>
))}
<Typography>Admin Fee</Typography>
<Grid container>
{benefits.map(row => (
<Grid item xs={4}>
<RHFCheckbox name="cat" label={row.category}/>
</Grid>
))}
</Grid>
</Stack>
</Stack>
</Stack>
</FormProvider>
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,54 @@
import { Card, Grid } from "@mui/material";
import { useParams } from "react-router-dom";
import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs";
import Page from "../../../components/Page";
import useSettings from "../../../hooks/useSettings";
import CorporateTabNavigations from "../CorporateTabNavigations";
import DivisionsList from "./List";
export default function Divisions() {
const { themeStretch } = useSettings();
const { id } = useParams();
return (
<Page title="Corporate Plan">
<HeaderBreadcrumbs
heading={'Corporate Plan'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
{
name: 'Plans',
href: '/corporates/'+id+'/divisions',
},
]}
/>
<Grid container spacing={2}>
<Grid item xs={8}>
<Card>
<CorporateTabNavigations position={'plans'} />
<DivisionsList />
</Card>
</Grid>
<Grid item xs={4}>
<Card sx={{ p: 2 }}>
Corporate Detail Goes Here
&nbsp;
</Card>
</Grid>
</Grid>
</Page>
);
}

View File

@@ -0,0 +1,270 @@
// @mui
import { Box, Button, Card, Collapse, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack, Menu, ButtonGroup } from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import AddIcon from '@mui/icons-material/Add';
import UploadIcon from '@mui/icons-material/Upload';
import CancelIcon from '@mui/icons-material/Cancel';
// hooks
import React, { useEffect, useRef, useState } from 'react';
import useSettings from '../../../hooks/useSettings';
import { useParams } from 'react-router-dom';
// components
import axios from '../../../utils/axios';
import { Corporate } from '../../../@types/corporates';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
export default function DivisionsList() {
const { themeStretch } = useSettings();
// Called on every row to map the data to the columns
function createData( corporate: Corporate ): Corporate {
return {
...corporate,
}
}
// Generate the every row of the table
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.code}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"><Button variant="outlined" color="success" size="small">Active</Button></TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Customer</TableCell>
<TableCell align="right">Amount</TableCell>
<TableCell align="right">Total price ($)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history ? row.history.map((historyRow) => (
<TableRow key={historyRow?.date}>
<TableCell component="th" scope="row">
{historyRow?.date}
</TableCell>
<TableCell>{historyRow?.customerId}</TableCell>
<TableCell align="right">{historyRow?.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow?.amount * 1000 * 100) / 100}
</TableCell>
</TableRow>
))
: (
<TableRow>
<TableCell colSpan={8}>No Data</TableCell>
</TableRow>
)
}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = React.useState(true);
const [dataTableData, setDataTableData] = React.useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: "",
first_page_url: "",
last_page: 1,
last_page_url: "",
next_page_url: "",
prev_page_url: "",
per_page: 10,
from: 0,
to: 0,
total: 0
});
const loadDataTableData = async () => {
setDataTableLoading(true);
const response = await axios.get('/corporates');
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
}
useEffect(() => {
loadDataTableData();
}, [])
const headStyle = {
fontWeight: 'bold',
};
const { id } = useParams();
// SEARCH
const searchInput = useRef<HTMLInputElement>(null);
// IMPORT
// Create Button Menu
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const createMenu = Boolean(anchorEl);
const importPlan = useRef<HTMLInputElement>(null)
const [currentImportFileName, setCurrentImportFileName] = useState(null)
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleImportButton = (event: any) => {
if (importPlan?.current) {
handleClose();
importPlan.current ? importPlan.current.click() : console.log('No File selected');
} else {
alert('No file selected')
}
}
const handleCancelImportButton = (event: any) => {
// setCurrentImportFileName(null)
importPlan.current.value = "";
// console.log(importPlan.current?.value)
importPlan.current.dispatchEvent(new Event("change", { bubbles: true }));
}
const handleImportChange = (event: any) => {
if (event.target.files[0]) {
setCurrentImportFileName(event.target.files[0].name)
} else {
setCurrentImportFileName(null);
}
}
const handleUpload = () => {
if (importPlan.current?.files.length) {
const formData = new FormData();
formData.append("file", importPlan.current?.files[0])
axios.post(`corporates/${id}/plans/import`, formData )
} else {
alert('No File Selected')
}
}
return (
<Stack>
<input type='file' id='file' ref={importPlan} style={{ display: 'none' }} onChange={handleImportChange} accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain" />
{( !currentImportFileName && <Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
<TextField id="search-input" ref={searchInput} label="Search" variant="outlined" fullWidth />
<Button
id="import-button"
variant='outlined'
startIcon={<AddIcon />} sx={{ p: 1.8 }}
aria-controls={createMenu ? 'basic-menu' : undefined}
aria-haspopup="true"
aria-expanded={createMenu ? 'true' : undefined}
onClick={handleClick}
>
Import
</Button>
<Menu
id="import-button"
anchorEl={anchorEl}
open={createMenu}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={handleImportButton}>Import</MenuItem>
<MenuItem onClick={handleClose}>Download Template</MenuItem>
</Menu>
</Stack>
)}
{( currentImportFileName && <Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
<ButtonGroup variant="outlined" aria-label="outlined button group" fullWidth>
<Button onClick={handleImportButton} fullWidth>{currentImportFileName ?? "No File Selected"}</Button>
<Button onClick={handleCancelImportButton} size="small" fullWidth={false} sx={{ p: 1.8 }}><CancelIcon color="error"/></Button>
</ButtonGroup>
<Button
id="upload-button"
variant='outlined'
startIcon={<UploadIcon />} sx={{ p: 1.8 }}
onClick={handleUpload}
>
Upload
</Button>
</Stack>
)}
<Card>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableBody>
<TableRow>
<TableCell style={headStyle} align="left">#</TableCell>
<TableCell style={headStyle} align="left">Code</TableCell>
<TableCell style={headStyle} align="left">Name</TableCell>
<TableCell style={headStyle} align="right">Action</TableCell>
</TableRow>
</TableBody>
{dataTableIsLoading ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">Loading</TableCell>
</TableRow>
</TableBody>
) : (
dataTableData.data.length == 0 ?
(
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">No Data</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData.data.map(row => (
<Row key={row.code} row={row} />
))}
</TableBody>
)
)}
</Table>
</TableContainer>
</Card>
</Stack>
);
}

View File

@@ -0,0 +1,231 @@
// @mui
import { Box, Button, Card, Collapse, Container, FormControl, Grid, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Stack } from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import PublishIcon from '@mui/icons-material/Publish';
import AddIcon from '@mui/icons-material/Add';
// hooks
import useSettings from '../../hooks/useSettings';
// components
import Page from '../../components/Page';
import axios from '../../utils/axios';
import useAuth from '../../hooks/useAuth';
import { Link , NavLink as RouterLink, useParams } from 'react-router-dom';
import React, { useEffect, useRef } from 'react';
import { Theme, useTheme } from '@mui/material/styles';
import { Corporate } from '../../@types/corporates';
import { LaravelPaginatedData } from '../../@types/paginated-data';
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
import CorporateTabNavigations from './CorporateTabNavigations';
export default function Corporates() {
const { themeStretch } = useSettings();
// Called on every row to map the data to the columns
function createData( corporate: Corporate ): Corporate {
return {
...corporate,
}
}
// Generate the every row of the table
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
return (
<React.Fragment>
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.code}</TableCell>
<TableCell align="left">{row.name}</TableCell>
<TableCell align="right"><Button variant="outlined" color="success" size="small">Active</Button></TableCell>
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>Date</TableCell>
<TableCell>Customer</TableCell>
<TableCell align="right">Amount</TableCell>
<TableCell align="right">Total price ($)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history ? row.history.map((historyRow) => (
<TableRow key={historyRow?.date}>
<TableCell component="th" scope="row">
{historyRow?.date}
</TableCell>
<TableCell>{historyRow?.customerId}</TableCell>
<TableCell align="right">{historyRow?.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow?.amount * 1000 * 100) / 100}
</TableCell>
</TableRow>
))
: (
<TableRow>
<TableCell colSpan={8}>No Data</TableCell>
</TableRow>
)
}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = React.useState(true);
const [dataTableData, setDataTableData] = React.useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: "",
first_page_url: "",
last_page: 1,
last_page_url: "",
next_page_url: "",
prev_page_url: "",
per_page: 10,
from: 0,
to: 0,
total: 0
});
const loadDataTableData = async () => {
setDataTableLoading(true);
const response = await axios.get('/corporates');
// console.log(response.data);
setDataTableLoading(false);
setDataTableData(response.data);
}
useEffect(() => {
loadDataTableData();
}, [])
const headStyle = {
fontWeight: 'bold',
};
// FILTER SELECT
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const names = [
'PLAN001',
'PLAN002',
'PLAN003',
'PLAN004',
'PLAN005',
];
function getStyles(name: string, personName: string[], theme: Theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}
const theme = useTheme();
const [planIdFilter, setPlanIdFilter] = React.useState<string[]>([]);
const handleChangePlanID = (event: SelectChangeEvent<typeof planIdFilter>) => {
const {
target: { value },
} = event;
setPlanIdFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
const [statusFilter, setStatusFilter] = React.useState<string[]>([]);
const handleChangeStatus = (event: SelectChangeEvent<typeof statusFilter>) => {
const {
target: { value },
} = event;
setStatusFilter(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
// END FILTER SELECT
// IMPORT
const importMember = React.useRef(null);
const handleImportButton = (event: any) => {
if (importMember?.current)
importMember.current ? importMember.current.click() : console.log('fuck');
else
alert('No file selected')
}
const { id } = useParams();
return (
<Page title="Corporate Detail">
<HeaderBreadcrumbs
heading={'Corporate Detail'}
links={[
{ name: 'Dashboard', href: '/dashboard' },
{
name: 'Corporates',
href: '/corporates',
},
{
name: 'Corporate Name',
href: '/corporates/'+id,
},
]}
/>
{/* <Container maxWidth={themeStretch ? false : 'xl'}> */}
<Card>
<Stack spacing="3">
<CorporateTabNavigations position="any"/>
<Grid container spacing={3}>
<Grid item xs={12} sx={{ p:2 }}>
Corporate Dashboard / Report Goes Here
&nbsp;
</Grid>
</Grid>
</Stack>
</Card>
{/* </Container> */}
</Page>
);
}

View File

@@ -79,6 +79,50 @@ export default function Router() {
path: 'members',
element: <Members />,
},
{
path: 'corporates',
element: <Corporate />,
},
{
path: 'corporates/create',
element: <CorporateCreate />,
},
{
path: 'corporates/:id',
element: <CorporateShow />,
},
{
path: 'corporates/:id/edit',
element: <CorporateCreate />,
},
{
path: 'corporates/:id/divisions',
element: <CorporateDivisions />,
},
{
path: 'corporates/:id/divisions/create',
element: <CorporateDivisionsCreate />,
},
{
path: 'corporates/:id/members',
element: <CorporateMembers />,
},
{
path: 'corporates/:id/plans/create',
element: <CorporatePlansCreate />,
},
{
path: 'corporates/:id/plans',
element: <CorporatePlans />,
},
{
path: 'corporates/:id/benefits/create',
element: <CorporateBenefitsCreate />,
},
{
path: 'corporates/:id/benefits',
element: <CorporateBenefits />,
},
]
},
// {
@@ -123,3 +167,14 @@ const NotFound = Loadable(lazy(() => import('../pages/Page404')));
// Members
const Members = Loadable(lazy(() => import('../pages/Members/Index')));
const MedicinesCreate = Loadable(lazy(() => import('../pages/Medicines/Create')));
const Corporate = Loadable(lazy(() => import('../pages/Corporates/Index')));
const CorporateCreate = Loadable(lazy(() => import('../pages/Corporates/Create')));
const CorporateShow = Loadable(lazy(() => import('../pages/Corporates/Show')));
const CorporateDivisions = Loadable(lazy(() => import('../pages/Corporates/Division/Index')));
const CorporateDivisionsCreate = Loadable(lazy(() => import('../pages/Corporates/Division/Create')));
const CorporateMembers = Loadable(lazy(() => import('../pages/Corporates/Member/Index')));
const CorporateBenefitsCreate = Loadable(lazy(() => import('../pages/Corporates/Benefit/Create')));
const CorporateBenefits = Loadable(lazy(() => import('../pages/Corporates/Benefit/Index')));
const CorporatePlansCreate = Loadable(lazy(() => import('../pages/Corporates/Plan/Create')));
const CorporatePlans = Loadable(lazy(() => import('../pages/Corporates/Plan/Index')));

View File

@@ -1,4 +1,4 @@
import axios from 'axios';
import { default as defaultAxios } from 'axios';
// config
import { HOST_API } from '../config';
@@ -8,7 +8,7 @@ import { getSession } from './token';
const token = getSession();
const axiosInstance = axios.create({
const axios = defaultAxios.create({
baseURL: HOST_API,
// headers: {
// 'X-Requested-With': 'XMLHttpRequest',
@@ -19,9 +19,9 @@ const axiosInstance = axios.create({
// }
});
axiosInstance.interceptors.response.use(
axios.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error) || 'Something went wrong')
);
export default axiosInstance;
export default axios;

3
modules_statuses.json Normal file
View File

@@ -0,0 +1,3 @@
{
"Internal": true
}

View File

@@ -1,8 +1,13 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
#RewriteRule ^index\.html$ - [L]
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule . /index.html [L]
RewriteCond %{HTTP_HOST} ^aso.local$
RewriteRule ^fuck? http://dashboard.kavacare.id/berobat-ke-luar-negeri$1 [L,NE,P]
#RewriteRule ^berobat-ke-luar-negeri? http://dashboard.kavacare.id/berobat-ke-luar-negeri [L,NE,P]
</IfModule>

Some files were not shown because too many files have changed in this diff Show More