diff --git a/README.md b/README.md index 3ed385a..f43a750 100644 --- a/README.md +++ b/README.md @@ -1,66 +1 @@ -

Laravel Logo

- -

-Build Status -Total Downloads -Latest Stable Version -License -

- -## About Laravel - -Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: - -- [Simple, fast routing engine](https://laravel.com/docs/routing). -- [Powerful dependency injection container](https://laravel.com/docs/container). -- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. -- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). -- Database agnostic [schema migrations](https://laravel.com/docs/migrations). -- [Robust background job processing](https://laravel.com/docs/queues). -- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). - -Laravel is accessible, powerful, and provides tools required for large, robust applications. - -## Learning Laravel - -Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. - -You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch. - -If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 2000 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. - -## Laravel Sponsors - -We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell). - -### Premium Partners - -- **[Vehikl](https://vehikl.com/)** -- **[Tighten Co.](https://tighten.co)** -- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** -- **[64 Robots](https://64robots.com)** -- **[Cubet Techno Labs](https://cubettech.com)** -- **[Cyber-Duck](https://cyber-duck.co.uk)** -- **[Many](https://www.many.co.uk)** -- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)** -- **[DevSquad](https://devsquad.com)** -- **[Curotec](https://www.curotec.com/services/technologies/laravel/)** -- **[OP.GG](https://op.gg)** -- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)** -- **[Lendio](https://lendio.com)** - -## Contributing - -Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). - -## Code of Conduct - -In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). - -## Security Vulnerabilities - -If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. - -## License - -The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). +# Yamato Cash Management - Laravel Inertijs \ No newline at end of file diff --git a/app/Exports/BookingsExport.php b/app/Exports/BookingsExport.php new file mode 100644 index 0000000..c103b54 --- /dev/null +++ b/app/Exports/BookingsExport.php @@ -0,0 +1,36 @@ +orderBy('departure', 'ASC'); + + if (request('ids')) { + $bookingIds = request('ids'); + $query->whereIn('id', $bookingIds); + } + + $bookings = $query->get()->map(function ($item, $key) { + $item->departure = Carbon::parse($item->departure)->format('Y-m-d'); + return $item; + }); + + return view('exports.bookings_export', [ + 'bookings' => $bookings, + ]); + } +} diff --git a/app/Exports/ExpensesExport.php b/app/Exports/ExpensesExport.php new file mode 100644 index 0000000..59d126a --- /dev/null +++ b/app/Exports/ExpensesExport.php @@ -0,0 +1,89 @@ +begining_balance = 0; + $expenses = Expense::all(); + $today = \Carbon\Carbon::now(); + + $query = Expense::query()->orderBy('date_expense', 'ASC'); + + if (request('start_date') && request('end_date')) { + $startDate = Carbon::parse(request('start_date')); + $endDate = Carbon::parse(request('end_date')); + + $query->whereDate('date_expense', '<=', request('end_date')) + ->whereDate('date_expense', '>=', request('start_date')); + } + + if (!request('start_date')) { + $endDate = Carbon::now(); + $startDate = $today->subDays(30); + + $query->whereDate('date_expense', '<=', $endDate) + ->whereDate('date_expense', '>=', $startDate); + } + + if (request('ids')) { + $expenseIds = request('ids'); + $query->whereIn('id', $expenseIds); + } + + $endBalanceDate = $startDate->subDay(); + $beginingBalance = Expense::select(['amount', 'isIncome'])->whereDate('date_expense', '<=', $endBalanceDate); + + $this->begining_balance = $beginingBalance->get()->map(function ($expense, $key) { + return (!$expense->isIncome) ? $expense->amount * -1 : $expense->amount; + })->sum(); + + $beginingBalance = $this->begining_balance; + + $expenseAndBalance = $query->get()->map(function ($item, $key) { + if ($item->isIncome) { + $item->subBalance = $this->begining_balance + $item->amount; + $this->begining_balance = $item->subBalance; + $item->date_expense = Carbon::parse($item->date_expense)->format('d - m - Y'); + return $item; + } + + $item->subBalance = $this->begining_balance - $item->amount; + $this->begining_balance = $item->subBalance; + $item->date_expense = Carbon::parse($item->date_expense)->format('d - m - Y'); + return $item; + }); + + return view('exports.expense_export', [ + 'expenses' => $expenseAndBalance, + 'beginingBalance' => $beginingBalance, + 'startDate' => $startDate->format('d/m/Y'), + 'endDate' => $endDate->format('d/m/Y'), + ]); + } + + public function headings(): array + { + return [ + 'NO', + 'VOUCHER', + 'DATE', + 'NAME', + 'JOB NUMBER', + 'DESCRIPTION', + 'ESTIMATION', + 'DEBET', + 'KREDIT', + 'BALANCE', + ]; + } +} diff --git a/app/Http/Controllers/BookingController.php b/app/Http/Controllers/BookingController.php index e33d7a3..50ce045 100644 --- a/app/Http/Controllers/BookingController.php +++ b/app/Http/Controllers/BookingController.php @@ -2,14 +2,17 @@ namespace App\Http\Controllers; +use App\Exports\BookingsExport; +use App\Imports\BookingsImport; use App\Models\Booking; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; +use Maatwebsite\Excel\Facades\Excel; class BookingController extends Controller { - public function index(Request $request) + public function index(Request $request) { Booking::where('is_available', 0) ->where(DB::raw('DATE(departure)'), '<', now()->toDateString()) @@ -53,4 +56,77 @@ class BookingController extends Controller '_limit' => $limit ]); } + + public function store(Request $request) + { + $request->validate([ + 'booked' => ['required', 'numeric'], + 'departure' => ['required'], + 'destination' => ['required'], + 'flight_number' => ['required'], + 'kemasan' => ['required'], + 'master_awb' => ['required'], + 'used' => ['required', 'numeric'], + 'is_available' => ['required', 'in:0,1'] + ]); + + Booking::create([ + 'master_awb' => $request->master_awb, + 'flight_number' => $request->flight_number, + 'departure' => $request->departure, + 'destination' => $request->destination, + 'kemasan' => $request->kemasan, + 'booked' => $request->booked, + 'used' => $request->used, + 'is_available' => $request->is_available, + ]); + + return redirect()->back()->with('success', 'Booking created.'); + } + + public function update(Request $request, Booking $booking) + { + $request->validate([ + 'booked' => ['required', 'numeric'], + 'departure' => ['required'], + 'destination' => ['required'], + 'flight_number' => ['required'], + 'kemasan' => ['required'], + 'master_awb' => ['required'], + 'used' => ['required', 'numeric'], + 'is_available' => ['required', 'in:0,1'] + ]); + + $booking->update([ + 'master_awb' => $request->master_awb, + 'flight_number' => $request->flight_number, + 'departure' => $request->departure, + 'destination' => $request->destination, + 'kemasan' => $request->kemasan, + 'booked' => $request->booked, + 'used' => $request->used, + 'is_available' => $request->is_available, + ]); + + return redirect()->back()->with('success', 'Booking updated.'); + } + + public function destroy(Booking $booking) + { + $booking->delete(); + } + + public function export() + { + return Excel::download(new BookingsExport, 'bookings.xlsx'); + } + + public function import(Request $request) + { + if (request()->file('file_booking_import') != null) { + Excel::import(new BookingsImport, request()->file('file_booking_import')); + } + + return redirect()->route('monitoring-booking.index'); + } } diff --git a/app/Imports/BookingsImport.php b/app/Imports/BookingsImport.php new file mode 100644 index 0000000..cb04225 --- /dev/null +++ b/app/Imports/BookingsImport.php @@ -0,0 +1,59 @@ +count(); + + if ($exists > 0) { + return null; + } + + return new Booking([ + 'master_awb' => $row[0], + 'flight_number' => $row[1], + 'departure' => $row[2], + 'destination' => $row[3], + 'jumlah_koli' => $row[4], + 'kemasan' => $row[5], + 'booked' => $row[6], + 'used' => $row[7], + ]); + } + + public function startRow(): int + { + return 2; + } + + public function uniqueBy() + { + return 'master_awb'; + } +} diff --git a/composer.json b/composer.json index 88ae8d2..8d9ac11 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "laravel/framework": "^9.19", "laravel/sanctum": "^2.8", "laravel/tinker": "^2.7", + "maatwebsite/excel": "^3.1", "tightenco/ziggy": "^1.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 345ad39..59c8718 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1ee03d2fb00e2aedbc2df7a80942c34a", + "content-hash": "9c6dec10b54235ded9ea393f87ce68e8", "packages": [ { "name": "brick/math", @@ -62,6 +62,87 @@ ], "time": "2022-08-10T22:54:19+00:00" }, + { + "name": "composer/semver", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-04-01T19:23:25+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.2", @@ -477,6 +558,67 @@ ], "time": "2023-01-02T17:26:14+00:00" }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.16.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/523407fb06eb9e5f3d59889b3978d5bfe94299c8", + "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8", + "shasum": "" + }, + "require": { + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" + }, + "require-dev": { + "cerdic/css-tidy": "^1.7 || ^2.0", + "simpletest/simpletest": "dev-master" + }, + "suggest": { + "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", + "ext-bcmath": "Used for unit conversion and imagecrash protection", + "ext-iconv": "Converts text to and from non-UTF-8 encodings", + "ext-tidy": "Used for pretty-printing HTML" + }, + "type": "library", + "autoload": { + "files": [ + "library/HTMLPurifier.composer.php" + ], + "psr-0": { + "HTMLPurifier": "library/" + }, + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.16.0" + }, + "time": "2022-09-18T07:06:19+00:00" + }, { "name": "fruitcake/php-cors", "version": "v1.2.0", @@ -1724,6 +1866,271 @@ ], "time": "2022-04-17T13:12:02+00:00" }, + { + "name": "maatwebsite/excel", + "version": "3.1.45", + "source": { + "type": "git", + "url": "https://github.com/SpartnerNL/Laravel-Excel.git", + "reference": "80627071a8cebb3c1119f1d2881bb6a03a8f9152" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/80627071a8cebb3c1119f1d2881bb6a03a8f9152", + "reference": "80627071a8cebb3c1119f1d2881bb6a03a8f9152", + "shasum": "" + }, + "require": { + "composer/semver": "^3.3", + "ext-json": "*", + "illuminate/support": "5.8.*|^6.0|^7.0|^8.0|^9.0", + "php": "^7.0|^8.0", + "phpoffice/phpspreadsheet": "^1.18", + "psr/simple-cache": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "orchestra/testbench": "^6.0|^7.0", + "predis/predis": "^1.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Maatwebsite\\Excel\\ExcelServiceProvider" + ], + "aliases": { + "Excel": "Maatwebsite\\Excel\\Facades\\Excel" + } + } + }, + "autoload": { + "psr-4": { + "Maatwebsite\\Excel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Patrick Brouwers", + "email": "patrick@spartner.nl" + } + ], + "description": "Supercharged Excel exports and imports in Laravel", + "keywords": [ + "PHPExcel", + "batch", + "csv", + "excel", + "export", + "import", + "laravel", + "php", + "phpspreadsheet" + ], + "support": { + "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.45" + }, + "funding": [ + { + "url": "https://laravel-excel.com/commercial-support", + "type": "custom" + }, + { + "url": "https://github.com/patrickbrouwers", + "type": "github" + } + ], + "time": "2023-01-02T17:17:56+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "myclabs/php-enum": "^1.5", + "php": "^8.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.9", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.4", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", + "vimeo/psalm": "^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://github.com/maennchen", + "type": "github" + }, + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" + } + ], + "time": "2022-12-08T12:29:14+00:00" + }, + { + "name": "markbaker/complex", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "^9.3", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPComplex/issues", + "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2" + }, + "time": "2022-12-06T16:21:08+00:00" + }, + { + "name": "markbaker/matrix", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "728434227fe21be27ff6d86621a1b13107a2562c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c", + "reference": "728434227fe21be27ff6d86621a1b13107a2562c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "^9.3", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "^4.0", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "sebastian/phpcpd": "^4.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matrix\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@demon-angel.eu" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPMatrix/issues", + "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1" + }, + "time": "2022-12-02T22:17:43+00:00" + }, { "name": "monolog/monolog", "version": "2.8.0", @@ -1826,6 +2233,69 @@ ], "time": "2022-07-24T11:55:47+00:00" }, + { + "name": "myclabs/php-enum", + "version": "1.8.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483", + "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.4" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "time": "2022-08-04T09:53:51+00:00" + }, { "name": "nesbot/carbon", "version": "2.65.0", @@ -2217,6 +2687,111 @@ ], "time": "2022-12-20T19:00:15+00:00" }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.26.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "5b6ceea9705b068f993e268e4debc566c2637063" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/5b6ceea9705b068f993e268e4debc566c2637063", + "reference": "5b6ceea9705b068f993e268e4debc566c2637063", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "ezyang/htmlpurifier": "^4.15", + "maennchen/zipstream-php": "^2.1", + "markbaker/complex": "^3.0", + "markbaker/matrix": "^3.0", + "php": "^7.4 || ^8.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dompdf/dompdf": "^1.0 || ^2.0", + "friendsofphp/php-cs-fixer": "^3.2", + "mitoteam/jpgraph": "^10.2.4", + "mpdf/mpdf": "^8.1.1", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.7", + "tecnickcom/tcpdf": "^6.5" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer", + "ext-intl": "PHP Internationalization Functions", + "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.26.0" + }, + "time": "2022-12-21T12:22:06+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.0", diff --git a/config/app.php b/config/app.php index ef76a7e..7a3ea32 100644 --- a/config/app.php +++ b/config/app.php @@ -69,7 +69,7 @@ return [ | */ - 'timezone' => 'UTC', + 'timezone' => 'Asia/Jakarta', /* |-------------------------------------------------------------------------- diff --git a/package-lock.json b/package-lock.json index e041f45..fb40d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "pettycash", + "name": "petty-cash-new", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/public/awb-format.csv b/public/awb-format.csv new file mode 100644 index 0000000..8969889 --- /dev/null +++ b/public/awb-format.csv @@ -0,0 +1,2 @@ +MASTER AWB,FLIGHT NUMBER,DEPARTURE,DESTINATION,JUMLAH KOLI,JENIS KEMASAN,BOOKED,USED +YIF210200012.,NH836,2022-01-08,Jakarta,10,PK,10,8 \ No newline at end of file diff --git a/resources/css/app.css b/resources/css/app.css index b8ff5d4..c903134 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -97,4 +97,26 @@ .react-datepicker__day--range-end { @apply bg-blue-500 text-white hover:text-gray-700 hover:bg-white; +} + + +/* width */ +::-webkit-scrollbar { + width: 10px; + height: 70%; +} + +/* Track */ +::-webkit-scrollbar-track { + background: rgb(136 136 136 / 28%); +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #888; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: rgb(241 241 241 / 12%); } \ No newline at end of file diff --git a/resources/js/Components/DatePickerInput.jsx b/resources/js/Components/DatePickerInput.jsx index 85c1a04..eab2a28 100644 --- a/resources/js/Components/DatePickerInput.jsx +++ b/resources/js/Components/DatePickerInput.jsx @@ -1,30 +1,32 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import DatePicker from "react-datepicker"; export const DatePickerRangeInput = ({ startDate, - setStartDate, endDate, - setEndDate, + setFilterDate }) => { - - if(typeof(endDate) === 'string') { - endDate = new Date(endDate) + const [_startDate, setStartDate] = useState(startDate) + const [_endDate, setEndDate] = useState(typeof(endDate) === 'string' ? new Date(endDate) : endDate) + + const handleDateChanges = (dates) => { + const [start, end] = dates; + setStartDate(start); + setEndDate(end); + if (end !== null) { + setFilterDate(dates) + } } return (
{ - const [start, end] = dates; - setStartDate(start); - setEndDate(end); - }} + selected={_startDate} + onChange={handleDateChanges} selectsRange - startDate={startDate} - endDate={endDate} + startDate={_startDate} + endDate={_endDate} nextMonthButtonLabel=">" previousMonthButtonLabel="<" popperClassName="react-datepicker-left" diff --git a/resources/js/Components/ModalConfirm.jsx b/resources/js/Components/ModalConfirm.jsx new file mode 100644 index 0000000..5bfcfed --- /dev/null +++ b/resources/js/Components/ModalConfirm.jsx @@ -0,0 +1,37 @@ +import React from "react"; + +export default function ModalConfirm(props) { + const { isOpen, toggle, onConfirm = () => {} } = props; + + const handleConfirm = () => { + onConfirm(); + toggle(); + }; + + return ( +
+
+

Hapus Item ?

+
+
+ Ya +
+
+ Batal +
+
+
+
+ ); +} diff --git a/resources/js/Pages/Booking/DetailModal.jsx b/resources/js/Pages/Booking/DetailModal.jsx new file mode 100644 index 0000000..84416df --- /dev/null +++ b/resources/js/Pages/Booking/DetailModal.jsx @@ -0,0 +1,191 @@ +import React, { useEffect, useState } from "react"; +import { formatDate } from "@/Utils"; + +export default function DetailModal(props) { + const { isOpen, toggle = () => {}, booking = null, title } = props; + const [data, setData] = useState({}); + + const handleCancel = () => { + toggle(); + }; + + useEffect(() => { + setData({ + booked: booking?.booked ? booking.booked : '', + departure: booking?.departure + ? formatDate(booking.departure).format('yyyy-MM-DD') + : '', + destination: booking?.destination ? booking.destination : '', + flight_number: booking?.flight_number ? booking.flight_number : '', + jumlah_koli: booking?.jumlah_koli ? booking.jumlah_koli : '', + kemasan: booking?.kemasan ? booking.kemasan : '', + master_awb: booking?.master_awb ? booking.master_awb : '', + used: booking?.used ? booking.used : '', + is_available: booking?.is_available ? booking.is_available : '', + }) + }, [booking]); + + return ( +
+
+

{title}

+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+
+ ) +}; diff --git a/resources/js/Pages/Booking/FormModal.jsx b/resources/js/Pages/Booking/FormModal.jsx new file mode 100644 index 0000000..4731716 --- /dev/null +++ b/resources/js/Pages/Booking/FormModal.jsx @@ -0,0 +1,270 @@ +import { useForm } from "@inertiajs/inertia-react"; +import React, { useEffect } from "react"; +import { formatDate } from "@/Utils"; + +export default function FormModal(props) { + const { isOpen, toggle = () => {}, booking = null } = props; + + const { data, setData, post, put, processing, errors, clearErrors } = + useForm({ + booked: "", + departure: "", + destination: "", + flight_number: "", + jumlah_koli: 0, + kemasan: "", + master_awb: "", + used: 0, + is_available: 0, + }); + + const handleOnChange = (event) => { + setData(event.target.name, event.target.value); + }; + + const handleReset = () => { + setData({ + booked: '', + departure: '', + destination: '', + flight_number: '', + jumlah_koli: 0, + kemasan: '', + master_awb: '', + used: 0, + is_available: 0, + }) + + clearErrors(); + }; + + const handleCancel = () => { + handleReset(); + toggle(); + }; + + const handleSubmit = () => { + if (booking !== null) { + put(route("monitoring-booking.update", booking), { + onSuccess: () => Promise.all([handleReset(), toggle()]), + }); + return; + } + + post(route("monitoring-booking.store"), { + onSuccess: () => Promise.all([handleReset(), toggle()]), + }); + }; + + useEffect(() => { + setData({ + booked: booking?.booked ? booking.booked : '', + departure: booking?.departure + ? formatDate(booking.departure).format('yyyy-MM-DD') + : '', + destination: booking?.destination ? booking.destination : '', + flight_number: booking?.flight_number ? booking.flight_number : '', + jumlah_koli: booking?.jumlah_koli ? booking.jumlah_koli : '', + kemasan: booking?.kemasan ? booking.kemasan : '', + master_awb: booking?.master_awb ? booking.master_awb : '', + used: booking?.used ? booking.used : '', + is_available: booking?.is_available ? booking.is_available : 0, + }) + }, [booking]); + + return ( +
+
+

+ Monitoring Booking Slot +

+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + +
+
+
+ ) +} diff --git a/resources/js/Pages/Booking/ImportModal.jsx b/resources/js/Pages/Booking/ImportModal.jsx new file mode 100644 index 0000000..026bdc9 --- /dev/null +++ b/resources/js/Pages/Booking/ImportModal.jsx @@ -0,0 +1,95 @@ +import { useForm } from "@inertiajs/inertia-react"; +import React, { useRef } from "react"; + +export default function ImportModal(props) { + const { isOpen, toggle = () => {}, booking = null } = props; + + const { data, setData, post, progress, errors, clearErrors } = useForm({ + file_booking_import: null, + }); + + const inputFileImport = useRef(); + + const handleReset = () => { + setData({ + file_booking_import: "", + }); + + clearErrors(); + }; + + const handleCancel = () => { + toggle(); + handleReset(); + }; + + function handleSubmit(e) { + e.preventDefault(); + post(route("monitoring-booking.import"), { + forceFormData: false, + onSuccess: () => Promise.all([handleReset(), toggle()]), + }); + return; + } + + return ( +
+
+

Import File Booking

+

+ Unduh format file import{" "} + + disini + +

+
handleSubmit(e)}> + + setData("file_booking_import", e.target.files[0]) + } + /> + {progress && ( + + {progress.percentage}% + + )} +
+ + +
+
+
+
+ ); +}; diff --git a/resources/js/Pages/Booking/Index.jsx b/resources/js/Pages/Booking/Index.jsx index ed3439a..bb8a9a0 100644 --- a/resources/js/Pages/Booking/Index.jsx +++ b/resources/js/Pages/Booking/Index.jsx @@ -1,9 +1,14 @@ import React, { useState, useEffect } from 'react' import { usePrevious } from "react-use"; import { Inertia } from "@inertiajs/inertia"; +import qs from 'qs' import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; import Pagination from "@/Components/Pagination"; +import ModalConfirm from "@/Components/ModalConfirm"; +import FormModal from './FormModal'; +import DetailModal from './DetailModal'; +import ImportModal from './ImportModal'; import { DatePickerRangeInput } from "@/Components/DatePickerInput"; import { useModalState } from "@/Hook"; import { Head } from '@inertiajs/inertia-react'; @@ -13,8 +18,9 @@ import { toast } from 'react-toastify'; export default function Dashboard(props) { const { _startDate, _endDate, _limit } = props - const [startDate, setStartDate] = useState(_startDate) - const [endDate, setEndDate] = useState(_endDate) + const [startDate] = useState(_startDate) + const [endDate] = useState(_endDate) + const [filterDate, setFilterDate] = useState([_startDate, _endDate]) const { data: bookings, links } = props.booking; const [bookingsChecked, setBookingsChecked] = useState( @@ -28,13 +34,12 @@ export default function Dashboard(props) { const [search, setSearch] = useState(""); const [limit, setLimit] = useState(_limit) - const preValue = usePrevious(`${search}-${startDate}-${endDate}-${limit}`); - const [booking, setBooking] = useState(null); - const [ids, setIds] = useState({}); + const preValue = usePrevious(`${search}-${filterDate[0]}-${filterDate[1]}-${limit}`); + const [booking, setBooking] = useState(null); const formModal = useModalState(false); - const handleEdit = (booking = null) => { + const handleToggleForm = (booking = null) => { setBooking(booking); formModal.toggle(); }; @@ -52,7 +57,7 @@ export default function Dashboard(props) { }; const bookingModal = useModalState(false); - const handleBooking = () => { + const handleImport = () => { bookingModal.toggle(); }; @@ -82,8 +87,8 @@ export default function Dashboard(props) { ); }; - const handleMouseOverExport = () => { - let params = bookingsChecked + const handleExport = () => { + const params = bookingsChecked .map((booking) => { if (booking.isChecked) { return booking.id; @@ -93,7 +98,17 @@ export default function Dashboard(props) { return isChecked !== undefined; }); - setIds(params); + fetch(route('monitoring-booking.export') +'?'+ qs.stringify({ids: params}, { encodeValuesOnly:true })) + .then( res => res.blob() ) + .then( blob => { + var file = window.URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = file; + a.download = "bookings.xlsx"; + document.body.appendChild(a); + a.click(); + a.remove(); + }); }; const handleCheckAll = (e) => { @@ -107,7 +122,12 @@ export default function Dashboard(props) { }); }; - const params = { ids }; + const params = { + q: search, + startDate: filterDate[0], + endDate: filterDate[1], + limit, + }; useEffect(() => { setBookingsChecked( @@ -124,14 +144,14 @@ export default function Dashboard(props) { if (preValue) { Inertia.get( route(route().current()), - { q: search, startDate, endDate, limit }, + { q: search, startDate: filterDate[0], endDate: filterDate[1], limit }, { replace: true, preserveState: true, } ) } - }, [search, startDate, endDate, limit]) + }, [search, filterDate, limit]) return (
-
+
-
Tambah
-
Import Excel
+
handleToggleForm()}>Tambah
+
Import
-
Export Excel
+
handleExport()}>Export
@@ -159,13 +179,17 @@ export default function Dashboard(props) {
- + setSearch(e.target.value)} + />
@@ -226,7 +250,7 @@ export default function Dashboard(props) { @@ -246,12 +270,7 @@ export default function Dashboard(props) {