commit d8eadb7e63e30fcfcb34363256c68799554b4870 Author: iawwaluddin Date: Wed Jun 26 12:58:17 2024 +0700 first commit diff --git a/api-inforasia/.editorconfig b/api-inforasia/.editorconfig new file mode 100644 index 0000000..8f0de65 --- /dev/null +++ b/api-inforasia/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 + +[docker-compose.yml] +indent_size = 4 diff --git a/api-inforasia/.env.example b/api-inforasia/.env.example new file mode 100644 index 0000000..ea0665b --- /dev/null +++ b/api-inforasia/.env.example @@ -0,0 +1,59 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=laravel +DB_USERNAME=root +DB_PASSWORD= + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_APP_NAME="${APP_NAME}" +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/api-inforasia/.gitattributes b/api-inforasia/.gitattributes new file mode 100644 index 0000000..fcb21d3 --- /dev/null +++ b/api-inforasia/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +CHANGELOG.md export-ignore +.styleci.yml export-ignore diff --git a/api-inforasia/.gitignore b/api-inforasia/.gitignore new file mode 100644 index 0000000..7fe978f --- /dev/null +++ b/api-inforasia/.gitignore @@ -0,0 +1,19 @@ +/.phpunit.cache +/node_modules +/public/build +/public/hot +/public/storage +/storage/*.key +/vendor +.env +.env.backup +.env.production +.phpunit.result.cache +Homestead.json +Homestead.yaml +auth.json +npm-debug.log +yarn-error.log +/.fleet +/.idea +/.vscode diff --git a/api-inforasia/README.md b/api-inforasia/README.md new file mode 100644 index 0000000..1a4c26b --- /dev/null +++ b/api-inforasia/README.md @@ -0,0 +1,66 @@ +

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 thousands of 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 Partners program](https://partners.laravel.com). + +### Premium Partners + +- **[Vehikl](https://vehikl.com/)** +- **[Tighten Co.](https://tighten.co)** +- **[WebReinvent](https://webreinvent.com/)** +- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** +- **[64 Robots](https://64robots.com)** +- **[Curotec](https://www.curotec.com/services/technologies/laravel/)** +- **[Cyber-Duck](https://cyber-duck.co.uk)** +- **[DevSquad](https://devsquad.com/hire-laravel-developers)** +- **[Jump24](https://jump24.co.uk)** +- **[Redberry](https://redberry.international/laravel/)** +- **[Active Logic](https://activelogic.com)** +- **[byte5](https://byte5.de)** +- **[OP.GG](https://op.gg)** + +## 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). diff --git a/api-inforasia/app/Console/Kernel.php b/api-inforasia/app/Console/Kernel.php new file mode 100644 index 0000000..e6b9960 --- /dev/null +++ b/api-inforasia/app/Console/Kernel.php @@ -0,0 +1,27 @@ +command('inspire')->hourly(); + } + + /** + * Register the commands for the application. + */ + protected function commands(): void + { + $this->load(__DIR__.'/Commands'); + + require base_path('routes/console.php'); + } +} diff --git a/api-inforasia/app/Exceptions/Handler.php b/api-inforasia/app/Exceptions/Handler.php new file mode 100644 index 0000000..56af264 --- /dev/null +++ b/api-inforasia/app/Exceptions/Handler.php @@ -0,0 +1,30 @@ + + */ + protected $dontFlash = [ + 'current_password', + 'password', + 'password_confirmation', + ]; + + /** + * Register the exception handling callbacks for the application. + */ + public function register(): void + { + $this->reportable(function (Throwable $e) { + // + }); + } +} diff --git a/api-inforasia/app/Helpers/ApiFormatter.php b/api-inforasia/app/Helpers/ApiFormatter.php new file mode 100644 index 0000000..b24458a --- /dev/null +++ b/api-inforasia/app/Helpers/ApiFormatter.php @@ -0,0 +1,21 @@ + null, + 'success' => null, + 'data' => null + ]; + + public static function createApi($code = null, $message = null, $data = null) + { + self::$response['code'] = $code; + self::$response['success'] = $message; + self::$response['data'] = $data; + + return response()->json(self::$response, self::$response['code']); + } +} diff --git a/api-inforasia/app/Http/Controllers/Controller.php b/api-inforasia/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..77ec359 --- /dev/null +++ b/api-inforasia/app/Http/Controllers/Controller.php @@ -0,0 +1,12 @@ +query('proyek_id'); + + if ($proyek_id){ + $penerimaProyeks = penerima_proyek::where('proyek_id', $proyek_id)->get(); + }else{ + $penerimaProyeks = penerima_proyek::all(); + } + return response()->json(['penerimaProyeks' => $penerimaProyeks], 200); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $request->validate([ + 'user_id' => 'required', + 'proyek_id' => 'required', + 'nama_penerima' => 'required' + + ]); + + $penerima = penerima_proyek::create($request->all()); + + return response()->json(['message' => 'penerima proyek berhasil disimpan', 'role' => $penerima], 201); + + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + $penerimaProyek = penerima_proyek::find($id); + + if(!$penerimaProyek) { + return response()->json(['message' => 'Penerima proyek tidak ditemukan'], 404); + } + + return response()->json(['penerimaProyek' => $penerimaProyek], 200); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, string $id) + { + $penerimaProyek = penerima_proyek::find($id); + + if(!$penerimaProyek) { + return response()->json(['message' => 'Penerima proyek tidak ditemukan'], 404); + } + + $penerimaProyek->fill($request->all()); + $penerimaProyek->updated_at = now(); // Atur updated_at secara manual + $penerimaProyek->save(); + + return response()->json(['message' => 'Penerima proyek berhasil diperbarui', 'penerimaProyek' => $penerimaProyek], 200); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $id) + { + $penerimaProyek = penerima_proyek::find($id); + + if(!$penerimaProyek) { + return response()->json(['message' => 'Penerima proyek tidak ditemukan'], 404); + } + + $penerimaProyek->delete(); + + return response()->json(['message' => 'Penerima proyek berhasil dihapus'], 200); + } +} diff --git a/api-inforasia/app/Http/Controllers/ProyekController.php b/api-inforasia/app/Http/Controllers/ProyekController.php new file mode 100644 index 0000000..00eaa6b --- /dev/null +++ b/api-inforasia/app/Http/Controllers/ProyekController.php @@ -0,0 +1,209 @@ +role_id == 1 || $user->role_id == 2){ + $data = Proyek::all(); + }else{ + $data = Proyek::where('user_id', $user->id) + ->orWhereHas('taskProyek.penerimaProyek', function ($query) use ($user) { + $query->where('user_id', $user->id); + }) + ->get(); + } + return response()->json(['proyek' => $data]); + } + + public function recent() + { + $user = FacadesAuth::user(); + // if ($user->role_id == 1 || $user->role_id == 2){ + // $data = Proyek::all(); + // }else{ + // $data = Proyek::where('user_id', $user->id) + // ->orWhereHas('taskProyek.penerimaProyek', function ($query) use ($user) { + // $query->where('user_id', $user->id); + // }) + // ->get(); + // } + // return response()->json(['proyek' => $data]); + if ($user->role_id == 4 || $user->role_id == 3) { + $data = proyek::whereHas('taskProyek.penerimaProyek', function ($query) use ($user) { + $query->where('user_id', $user->id); + })->OrderByDesc('id')->take(5)->get(); + } else { + $data = proyek::OrderByDesc('id')->take(5)->get(); + } + + return response()->json(['proyek' => $data]); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $request->validate([ + 'nama' => 'required', + 'detail' => 'required', + 'manager' => 'required', + 'start' => 'required|date', + 'finish' => 'required|date', + 'klien' => 'required', + ]); + + $userId = auth()->user()->id; + // Create the proyek + $proyek = Proyek::create([ + 'nama' => $request->nama, + 'user_id' => $userId, + 'detail' => $request->detail, + 'manager' => $request->manager, + 'nilai' => "0", + 'start' => $request->start, + 'finish' => $request->finish, + 'klien' => $request->klien, + ]); + + // Add entries in task_proyek for each user_id + // $taskProyeks = []; + // foreach ($request->input('user_ids') as $userId) { + // $taskProyeks[] = task_proyek::create([ + // 'proyek_id' => $proyek->id, + // 'user_id' => $userId, + // ]); + // } + + return response()->json([ + 'message' => 'Proyek berhasil disimpan', + 'proyek' => $proyek, + // 'task_proyeks' => $taskProyeks, + ], 201); + } + + + /** + * Display the specified resource. + */ + public function show(string $id) + { + $proyek = proyek::with(['user', 'taskProyek', 'taskProyek.penerimaProyek.user'])->find($id); + + if (!$proyek) { + return response()->json(['message' => 'Proyek tidak ditemukan'], 404); + } + + return response()->json(['proyek' => $proyek], 200); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, $id) + { + $request->validate([ + 'nama' => 'required', + 'detail' => 'required', + 'manager' => 'required', + // 'nilai' => 'required', + 'start' => 'required|date', + 'finish' => 'required|date', + 'klien' => 'required', + ]); + + // Find the proyek by id + $proyek = Proyek::findOrFail($id); + + $proyek->update([ + 'nama' => $request->nama, + 'detail' => $request->detail, + 'manager' => $request->manager, + // 'nilai' => $request->nilai, + 'start' => $request->start, + 'finish' => $request->finish, + 'klien' => $request->klien, + ]); + + return response()->json([ + 'message' => 'Proyek berhasil diperbarui', + 'proyek' => $proyek, + ], 200); + } + + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $id) + { + $proyek = proyek::find($id); + + if (!$proyek) { + return response()->json(['message' => 'Proyek tidak ditemukan'], 404); + } + + $proyek->delete(); + + return response()->json(['message' => 'Proyek berhasil dihapus'], 200); + } + + public function getProyek() + { + $user = auth()->user(); + if ($user->role_id == 4 || $user->role_id == 3) { + $completedProyekCount = Proyek::where('user_id', $user->id)->orWhereHas('taskProyek.penerimaProyek', function ($query) use ($user) { + $query->where('user_id', $user->id); + })->where('nilai', 100)->count(); + + $onProgressProyekCount = Proyek::where('user_id', $user->id)->orWhereHas('taskProyek.penerimaProyek', function ($query) use ($user) { + $query->where('user_id', $user->id); + })->where('nilai', '!=', 100)->count(); + } else { + $completedProyekCount = proyek::where('nilai', 100)->count(); + $onProgressProyekCount = proyek::where('nilai', '!=', 100)->count(); + } + + return response()->json([ + 'totalProyekSelesai' => $completedProyekCount, + 'onProgress' => $onProgressProyekCount + ]); + } + + public function getProyekChart() + { + $user = auth()->user(); + if ($user->role_id == 4 || $user->role_id == 3) { + $projects = proyek::whereHas('taskProyek.penerimaProyek', function ($query) use ($user) { + $query->where('user_id', $user->id); + })->get(); + } else { + $projects = proyek::all(); + } + + $projectData = []; + foreach ($projects as $project) { + $projectData[] = [ + 'projectName' => $project->nama, + 'value' => $project->nilai, + ]; + } + + return response()->json($projectData); + } +} diff --git a/api-inforasia/app/Http/Controllers/RoleController.php b/api-inforasia/app/Http/Controllers/RoleController.php new file mode 100644 index 0000000..c95420b --- /dev/null +++ b/api-inforasia/app/Http/Controllers/RoleController.php @@ -0,0 +1,81 @@ +json(['roles' => $roles], 200); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|unique:roles,name', + + ]); + + $role = role::create($request->all()); + + return response()->json(['message' => 'Role berhasil disimpan', 'role' => $role], 201); + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + $role = role::find($id); + + if(!$role) { + return response()->json(['message' => 'Role tidak ditemukan'], 404); + } + + return response()->json(['role' => $role], 200); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, string $id) + { + $role = role::find($id); + + if(!$role) { + return response()->json(['message' => 'Role tidak ditemukan'], 404); + } + + $role->fill($request->all()); + $role->updated_at = now(); // Atur updated_at secara manual + $role->save(); + + return response()->json(['message' => 'Role berhasil diperbarui', 'role' => $role], 200); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $id) + { + $role = role::find($id); + + if(!$role) { + return response()->json(['message' => 'Role tidak ditemukan'], 404); + } + + $role->delete(); + + return response()->json(['message' => 'Role berhasil dihapus'], 200); + } +} diff --git a/api-inforasia/app/Http/Controllers/TaskProyekController.php b/api-inforasia/app/Http/Controllers/TaskProyekController.php new file mode 100644 index 0000000..ed3e8c6 --- /dev/null +++ b/api-inforasia/app/Http/Controllers/TaskProyekController.php @@ -0,0 +1,137 @@ +query('proyek_id'); + + if ($proyek_id) { + $tasks = task_proyek::with('user')->where('proyek_id', $proyek_id)->get(); + } else { + $tasks = task_proyek::all(); + } + + return response()->json(['tasks' => $tasks], 200); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $request->validate([ + 'proyek_id' => 'required', + 'user_ids' => 'required|array', + 'user_ids.*' => 'exists:users,id', + 'tugas' => 'required', + 'catatan' => 'required', + 'start' => 'required', + 'deadline' => 'required', + 'status' => 'required', + 'nilai' => 'required' + ]); + + $task = task_proyek::create([ + 'proyek_id' => $request->proyek_id, + 'tugas' => $request->tugas, + 'catatan' => $request->catatan, + 'start' => $request->start, + 'deadline' => $request->deadline, + 'status' => $request->status, + 'nilai' => $request->nilai, + ]); + + $taskProyeks = []; + foreach ($request->input('user_ids') as $userId) { + $taskProyeks[] = penerima_proyek::create([ + 'task_proyek_id' => $task->id, + 'user_id' => $userId, + ]); + } + + return response()->json(['message' => 'Task proyek berhasil disimpan', 'task' => $task], 201); + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + $task = task_proyek::with('penerimaProyek')->find($id); + + if (!$task) { + return response()->json(['message' => 'Task proyek tidak ditemukan'], 404); + } + + return response()->json(['task' => $task], 200); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, string $id) + { + $task = task_proyek::find($id); + + $request->validate([ + 'proyek_id' => 'required', + 'user_ids' => 'required|array', + 'user_ids.*' => 'exists:users,id', + 'tugas' => 'required', + 'catatan' => 'required', + 'start' => 'required|date', + 'deadline' => 'required|date', + 'status' => 'required', + 'nilai' => 'required' + ]); + + $task->update([ + 'proyek_id' => $request->proyek_id, + 'tugas' => $request->tugas, + 'catatan' => $request->catatan, + 'start' => $request->start, + 'deadline' => $request->deadline, + 'status' => $request->status, + 'nilai' => $request->nilai, + ]); + + // Delete existing penerima_proyek records for the task + penerima_proyek::where('task_proyek_id', $task->id)->delete(); + + // Add new penerima_proyek records + foreach ($request->input('user_ids') as $userId) { + penerima_proyek::create([ + 'task_proyek_id' => $task->id, + 'user_id' => $userId, + ]); + } + + return response()->json(['message' => 'Task proyek berhasil diperbarui', 'task' => $task], 200); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $id) + { + $task = task_proyek::find($id); + + if (!$task) { + return response()->json(['message' => 'Task proyek tidak ditemukan'], 404); + } + + $task->delete(); + + return response()->json(['message' => 'Task proyek berhasil dihapus'], 200); + } +} diff --git a/api-inforasia/app/Http/Controllers/UserController.php b/api-inforasia/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..90725bd --- /dev/null +++ b/api-inforasia/app/Http/Controllers/UserController.php @@ -0,0 +1,176 @@ +get(); + // dd($users); + return response()->json(['users' => $users], 200); + } + + /** + * Store a newly created resource in storage. + */ + + public function getManager() + { + $user = User::where('role_id', 3)->OrderByDesc('id')->get(); + + return response()->json(['users' => $user], 200); + } + + public function getUserData() + { + $userId = auth()->id(); + $user = User::with('role')->find($userId); + + if (!$user) { + return response()->json(['message' => 'Pengguna tidak ditemukan'], 404); + } + + return response()->json(['user' => $user], 200); + } + + + + public function store(Request $request) + { + $request->validate([ + 'role_id' => 'required', + 'name' => 'required', + 'nip' => 'required', + 'email' => 'required|email|unique:users,email', + 'username' => 'required', + 'password' => 'required|string|min:8', + 'jenis_kelamin' => 'required', + 'tanggal_lahir' => 'required', + 'no_telp' => 'required', + 'alamat' => 'required', + // 'foto_profile' => 'image|mimes:jpeg,png,jpg,gif|max:2048', + ]); + + // $fileNameImage = time() . '.' . $request->foto_profile->extension(); + // $request->foto_profile->move(public_path('foto/'), $fileNameImage); + + $user = User::create([ + 'role_id' => $request->role_id, + 'name' => $request->name, + 'nip' => $request->nip, + 'email' => $request->email, + 'username' => $request->username, + 'password' => Hash::make($request->password), + 'jenis_kelamin' => $request->jenis_kelamin, + 'tanggal_lahir' => $request->tanggal_lahir, + 'no_telp' => $request->no_telp, + 'email_verified_at' => now(), + 'alamat' => $request->alamat, + 'remember_token' => rand(10, 100), + // 'foto_profile' => $fileNameImage, + ]); + + $user->save(); + + return response()->json(['message' => 'Pengguna berhasil disimpan', 'user' => $user], 201); + } + + /** + * Display the specified resource. + */ + public function show(string $userId) + { + $user = User::with('role')->find($userId); + + if (!$user) { + return response()->json(['message' => 'Pengguna tidak ditemukan'], 404); + } + + return response()->json(['user' => $user], 200); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, string $id) + { + $user = User::find($id); + + if (!$user) { + return response()->json(['message' => 'Pengguna tidak ditemukan'], 404); + } + $request->validate([ + 'role_id' => 'required', + 'name' => 'required', + 'nip' => 'required', + 'email' => 'required|email', + 'username' => 'required', + 'password' => 'nullable|string|min:8', + 'jenis_kelamin' => 'required', + 'tanggal_lahir' => 'required', + 'no_telp' => 'required', + 'alamat' => 'required', + // 'foto_profile' => 'image|mimes:jpeg,png,jpg,gif|max:2048', + ]); + + // if ($request->hasFile('image')) { + // $deleteimage = $user->foto_profile; + // if ($deleteimage) { + // File::delete(public_path('foto/') . '/' . $deleteimage); + // } + + // $fileNameImage = time() . '.' . $request->foto_profile->extension(); + // $request->foto_profile->move(public_path('foto/product/'), $fileNameImage); + // $validateData['foto_profile'] = $fileNameImage; + // } + + // Check if password needs to be updated + if ($request->has('password') && $request->password) { + $user->password = Hash::make($request->password); + } + + // Handle foto_profile update + $user->update([ + 'role_id' => $request->role_id, + 'name' => $request->name, + 'nip' => $request->nip, + 'email' => $request->email, + 'username' => $request->username, + 'jenis_kelamin' => $request->jenis_kelamin, + 'tanggal_lahir' => $request->tanggal_lahir, + 'no_telp' => $request->no_telp, + 'email_verified_at' => now(), + 'alamat' => $request->alamat, + 'remember_token' => rand(10, 100), + // 'foto_profile' => $fileNameImage, + ]); + + return response()->json(['message' => 'Pengguna berhasil diperbarui', 'user' => $user], 200); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(string $id) + { + $user = User::find($id); + + if (!$user) { + return response()->json(['message' => 'Pengguna tidak ditemukan'], 404); + } + + $user->delete(); + + return response()->json(['message' => 'Pengguna berhasil dihapus'], 200); + } +} diff --git a/api-inforasia/app/Http/Controllers/authentication.php b/api-inforasia/app/Http/Controllers/authentication.php new file mode 100644 index 0000000..3a378ed --- /dev/null +++ b/api-inforasia/app/Http/Controllers/authentication.php @@ -0,0 +1,65 @@ +validate([ + 'email' => 'required|email', + 'password' => 'required', + ]); + + $user = User::where('email', $request->email)->first(); + + + if (!$user) { + return response()->json([ + 'message' => 'User tidak ditemukan. Cek kembali email Anda.', + ], 404); // Not Found + } + + if (!Hash::check($request->password, $user->password)) { + return response()->json([ + 'message' => 'Password salah. Cek kembali password Anda.', + ], 401); // Unauthorized + } + + $token = $user->createToken('auth')->plainTextToken; + return response()->json([ + "message" => "success", + "data" => $user, + "token" => $token + ], 200); + } + + + // logout + public function logout(Request $request) + { + $request->user()->currentAccessToken()->delete(); + } + + + //aktif + public function aktif(Request $request) + { + if (Auth::check()) { + return response()->json(['message' => 'user aktif']); + } else { + return response()->json(['message' => 'user nonaktif']); + } + } + + public function index() + { + echo "tes api"; + } +} diff --git a/api-inforasia/app/Http/Kernel.php b/api-inforasia/app/Http/Kernel.php new file mode 100644 index 0000000..494c050 --- /dev/null +++ b/api-inforasia/app/Http/Kernel.php @@ -0,0 +1,68 @@ + + */ + protected $middleware = [ + // \App\Http\Middleware\TrustHosts::class, + \App\Http\Middleware\TrustProxies::class, + \Illuminate\Http\Middleware\HandleCors::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, + \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, + \App\Http\Middleware\TrimStrings::class, + \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + ]; + + /** + * The application's route middleware groups. + * + * @var array> + */ + protected $middlewareGroups = [ + 'web' => [ + \App\Http\Middleware\EncryptCookies::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\VerifyCsrfToken::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + + 'api' => [ + // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, + \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + ]; + + /** + * The application's middleware aliases. + * + * Aliases may be used instead of class names to conveniently assign middleware to routes and groups. + * + * @var array + */ + protected $middlewareAliases = [ + 'auth' => \App\Http\Middleware\Authenticate::class, + 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, + 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, + 'can' => \Illuminate\Auth\Middleware\Authorize::class, + 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, + 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, + 'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, + 'signed' => \App\Http\Middleware\ValidateSignature::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + ]; +} diff --git a/api-inforasia/app/Http/Middleware/Authenticate.php b/api-inforasia/app/Http/Middleware/Authenticate.php new file mode 100644 index 0000000..d4ef644 --- /dev/null +++ b/api-inforasia/app/Http/Middleware/Authenticate.php @@ -0,0 +1,17 @@ +expectsJson() ? null : route('login'); + } +} diff --git a/api-inforasia/app/Http/Middleware/EncryptCookies.php b/api-inforasia/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 0000000..867695b --- /dev/null +++ b/api-inforasia/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/api-inforasia/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/api-inforasia/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 0000000..74cbd9a --- /dev/null +++ b/api-inforasia/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/api-inforasia/app/Http/Middleware/RedirectIfAuthenticated.php b/api-inforasia/app/Http/Middleware/RedirectIfAuthenticated.php new file mode 100644 index 0000000..afc78c4 --- /dev/null +++ b/api-inforasia/app/Http/Middleware/RedirectIfAuthenticated.php @@ -0,0 +1,30 @@ +check()) { + return redirect(RouteServiceProvider::HOME); + } + } + + return $next($request); + } +} diff --git a/api-inforasia/app/Http/Middleware/TrimStrings.php b/api-inforasia/app/Http/Middleware/TrimStrings.php new file mode 100644 index 0000000..88cadca --- /dev/null +++ b/api-inforasia/app/Http/Middleware/TrimStrings.php @@ -0,0 +1,19 @@ + + */ + protected $except = [ + 'current_password', + 'password', + 'password_confirmation', + ]; +} diff --git a/api-inforasia/app/Http/Middleware/TrustHosts.php b/api-inforasia/app/Http/Middleware/TrustHosts.php new file mode 100644 index 0000000..c9c58bd --- /dev/null +++ b/api-inforasia/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ + + */ + public function hosts(): array + { + return [ + $this->allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/api-inforasia/app/Http/Middleware/TrustProxies.php b/api-inforasia/app/Http/Middleware/TrustProxies.php new file mode 100644 index 0000000..3391630 --- /dev/null +++ b/api-inforasia/app/Http/Middleware/TrustProxies.php @@ -0,0 +1,28 @@ +|string|null + */ + protected $proxies; + + /** + * The headers that should be used to detect proxies. + * + * @var int + */ + protected $headers = + Request::HEADER_X_FORWARDED_FOR | + Request::HEADER_X_FORWARDED_HOST | + Request::HEADER_X_FORWARDED_PORT | + Request::HEADER_X_FORWARDED_PROTO | + Request::HEADER_X_FORWARDED_AWS_ELB; +} diff --git a/api-inforasia/app/Http/Middleware/ValidateSignature.php b/api-inforasia/app/Http/Middleware/ValidateSignature.php new file mode 100644 index 0000000..093bf64 --- /dev/null +++ b/api-inforasia/app/Http/Middleware/ValidateSignature.php @@ -0,0 +1,22 @@ + + */ + protected $except = [ + // 'fbclid', + // 'utm_campaign', + // 'utm_content', + // 'utm_medium', + // 'utm_source', + // 'utm_term', + ]; +} diff --git a/api-inforasia/app/Http/Middleware/VerifyCsrfToken.php b/api-inforasia/app/Http/Middleware/VerifyCsrfToken.php new file mode 100644 index 0000000..9e86521 --- /dev/null +++ b/api-inforasia/app/Http/Middleware/VerifyCsrfToken.php @@ -0,0 +1,17 @@ + + */ + protected $except = [ + // + ]; +} diff --git a/api-inforasia/app/Models/User.php b/api-inforasia/app/Models/User.php new file mode 100644 index 0000000..c01afab --- /dev/null +++ b/api-inforasia/app/Models/User.php @@ -0,0 +1,77 @@ +belongsTo(role::class, 'role_id'); + } + + public function proyek() + { + return $this->hasMany(proyek::class); + } + + public function taskProyek() + { + return $this->hasMany(task_proyek::class); + } + + public function penerimaProyek() + { + return $this->hasMany(penerima_proyek::class); + } + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'name', + 'email', + 'nip', + 'username', + 'password', + 'jenis_kelamin', + 'tanggal_lahir', + 'no_telp', + 'alamat', + 'role_id', + 'remember_token', + 'email_verified_at', + 'foto_profile', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; +} diff --git a/api-inforasia/app/Models/penerima_proyek.php b/api-inforasia/app/Models/penerima_proyek.php new file mode 100644 index 0000000..19103be --- /dev/null +++ b/api-inforasia/app/Models/penerima_proyek.php @@ -0,0 +1,23 @@ +belongsTo(User::class); + } + + public function taskProyek() + { + return $this->belongsTo(task_proyek::class, 'task_proyek_id'); + } +} diff --git a/api-inforasia/app/Models/proyek.php b/api-inforasia/app/Models/proyek.php new file mode 100644 index 0000000..34df565 --- /dev/null +++ b/api-inforasia/app/Models/proyek.php @@ -0,0 +1,30 @@ +belongsTo(User::class); + } + + public function taskProyek() + { + return $this->hasMany(task_proyek::class); + } + + public function updateAverageNilai() + { + $averageNilai = $this->taskProyek()->avg('nilai'); + $this->nilai = $averageNilai; + $this->save(); + } +} diff --git a/api-inforasia/app/Models/role.php b/api-inforasia/app/Models/role.php new file mode 100644 index 0000000..2fa1e96 --- /dev/null +++ b/api-inforasia/app/Models/role.php @@ -0,0 +1,18 @@ +hasMany(User::class); + } +} diff --git a/api-inforasia/app/Models/task_proyek.php b/api-inforasia/app/Models/task_proyek.php new file mode 100644 index 0000000..1a2874c --- /dev/null +++ b/api-inforasia/app/Models/task_proyek.php @@ -0,0 +1,36 @@ +hasMany(penerima_proyek::class); + } + + public function proyek() + { + return $this->belongsTo(proyek::class); + } + + protected static function boot() + { + parent::boot(); + + static::saved(function ($taskProyek) { + $taskProyek->proyek->updateAverageNilai(); + }); + + static::deleted(function ($taskProyek) { + $taskProyek->proyek->updateAverageNilai(); + }); + } +} diff --git a/api-inforasia/app/Providers/AppServiceProvider.php b/api-inforasia/app/Providers/AppServiceProvider.php new file mode 100644 index 0000000..452e6b6 --- /dev/null +++ b/api-inforasia/app/Providers/AppServiceProvider.php @@ -0,0 +1,24 @@ + + */ + protected $policies = [ + // + ]; + + /** + * Register any authentication / authorization services. + */ + public function boot(): void + { + // + } +} diff --git a/api-inforasia/app/Providers/BroadcastServiceProvider.php b/api-inforasia/app/Providers/BroadcastServiceProvider.php new file mode 100644 index 0000000..2be04f5 --- /dev/null +++ b/api-inforasia/app/Providers/BroadcastServiceProvider.php @@ -0,0 +1,19 @@ +> + */ + protected $listen = [ + Registered::class => [ + SendEmailVerificationNotification::class, + ], + ]; + + /** + * Register any events for your application. + */ + public function boot(): void + { + // + } + + /** + * Determine if events and listeners should be automatically discovered. + */ + public function shouldDiscoverEvents(): bool + { + return false; + } +} diff --git a/api-inforasia/app/Providers/RouteServiceProvider.php b/api-inforasia/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..1cf5f15 --- /dev/null +++ b/api-inforasia/app/Providers/RouteServiceProvider.php @@ -0,0 +1,40 @@ +by($request->user()?->id ?: $request->ip()); + }); + + $this->routes(function () { + Route::middleware('api') + ->prefix('api') + ->group(base_path('routes/api.php')); + + Route::middleware('web') + ->group(base_path('routes/web.php')); + }); + } +} diff --git a/api-inforasia/artisan b/api-inforasia/artisan new file mode 100644 index 0000000..67a3329 --- /dev/null +++ b/api-inforasia/artisan @@ -0,0 +1,53 @@ +#!/usr/bin/env php +make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); + +/* +|-------------------------------------------------------------------------- +| Shutdown The Application +|-------------------------------------------------------------------------- +| +| Once Artisan has finished running, we will fire off the shutdown events +| so that any final work may be done by the application before we shut +| down the process. This is the last thing to happen to the request. +| +*/ + +$kernel->terminate($input, $status); + +exit($status); diff --git a/api-inforasia/bootstrap/app.php b/api-inforasia/bootstrap/app.php new file mode 100644 index 0000000..037e17d --- /dev/null +++ b/api-inforasia/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + App\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + App\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + App\Exceptions\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/api-inforasia/bootstrap/cache/.gitignore b/api-inforasia/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/api-inforasia/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/api-inforasia/composer.json b/api-inforasia/composer.json new file mode 100644 index 0000000..8a3d72d --- /dev/null +++ b/api-inforasia/composer.json @@ -0,0 +1,66 @@ +{ + "name": "laravel/laravel", + "type": "project", + "description": "The skeleton application for the Laravel framework.", + "keywords": ["laravel", "framework"], + "license": "MIT", + "require": { + "php": "^8.1", + "guzzlehttp/guzzle": "^7.2", + "laravel/framework": "^10.10", + "laravel/sanctum": "^3.3", + "laravel/tinker": "^2.8" + }, + "require-dev": { + "fakerphp/faker": "^1.9.1", + "laravel/pint": "^1.0", + "laravel/sail": "^1.18", + "mockery/mockery": "^1.4.4", + "nunomaduro/collision": "^7.0", + "phpunit/phpunit": "^10.1", + "spatie/laravel-ignition": "^2.0" + }, + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Factories\\": "database/factories/", + "Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "scripts": { + "post-autoload-dump": [ + "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", + "@php artisan package:discover --ansi" + ], + "post-update-cmd": [ + "@php artisan vendor:publish --tag=laravel-assets --ansi --force" + ], + "post-root-package-install": [ + "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" + ], + "post-create-project-cmd": [ + "@php artisan key:generate --ansi" + ] + }, + "extra": { + "laravel": { + "dont-discover": [] + } + }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true, + "php-http/discovery": true + } + }, + "minimum-stability": "stable", + "prefer-stable": true +} diff --git a/api-inforasia/composer.lock b/api-inforasia/composer.lock new file mode 100644 index 0000000..72ac72d --- /dev/null +++ b/api-inforasia/composer.lock @@ -0,0 +1,8129 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "9c491b8531eec05ba41a11d9276a5749", + "packages": [ + { + "name": "brick/math", + "version": "0.12.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.12.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-11-29T23:19:16+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.7.0 || >=4.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-12-11T17:09:12+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "f41715465d65213d644d3141a6a93081be5d3549" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", + "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" + }, + "time": "2022-10-27T11:44:00+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2023-08-10T19:36:49+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2023-10-06T06:47:41+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.2", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2023-11-12T22:16:48+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2023-12-03T19:50:20+00:00" + }, + { + "name": "laravel/framework", + "version": "v10.48.11", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "afdc2b03bd8d126446583da5414d659491aa4f54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/afdc2b03bd8d126446583da5414d659491aa4f54", + "reference": "afdc2b03bd8d126446583da5414d659491aa4f54", + "shasum": "" + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.3.2", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.1.9", + "laravel/serializable-closure": "^1.3", + "league/commonmark": "^2.2.1", + "league/flysystem": "^3.8.0", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.67", + "nunomaduro/termwind": "^1.13", + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^6.2", + "symfony/error-handler": "^6.2", + "symfony/finder": "^6.2", + "symfony/http-foundation": "^6.4", + "symfony/http-kernel": "^6.2", + "symfony/mailer": "^6.2", + "symfony/mime": "^6.2", + "symfony/process": "^6.2", + "symfony/routing": "^6.2", + "symfony/uid": "^6.2", + "symfony/var-dumper": "^6.2", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.4.1", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "carbonphp/carbon-doctrine-types": ">=3.0", + "doctrine/dbal": ">=4.0", + "mockery/mockery": "1.6.8", + "phpunit/phpunit": ">=11.0.0", + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.235.5", + "doctrine/dbal": "^3.5.1", + "ext-gmp": "*", + "fakerphp/faker": "^1.21", + "guzzlehttp/guzzle": "^7.5", + "league/flysystem-aws-s3-v3": "^3.0", + "league/flysystem-ftp": "^3.0", + "league/flysystem-path-prefixing": "^3.3", + "league/flysystem-read-only": "^3.3", + "league/flysystem-sftp-v3": "^3.0", + "mockery/mockery": "^1.5.1", + "nyholm/psr7": "^1.2", + "orchestra/testbench-core": "^8.23.4", + "pda/pheanstalk": "^4.0", + "phpstan/phpstan": "^1.4.7", + "phpunit/phpunit": "^10.0.7", + "predis/predis": "^2.0.2", + "symfony/cache": "^6.2", + "symfony/http-client": "^6.2.4", + "symfony/psr-http-message-bridge": "^2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", + "league/flysystem-read-only": "Required to use read-only disks (^3.3)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "mockery/mockery": "Required to use mocking (^1.5.1).", + "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8|^10.0.7).", + "predis/predis": "Required to use the predis connector (^2.0.2).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^6.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-05-21T17:53:51+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.1.22", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/37f94de71758dbfbccc9d299b0e5eb76e02a40f5", + "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/collections": "^10.0|^11.0", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.1.22" + }, + "time": "2024-05-10T19:22:18+00:00" + }, + { + "name": "laravel/sanctum", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "reference": "8c104366459739f3ada0e994bcd3e6fd681ce3d5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9.21|^10.0", + "illuminate/contracts": "^9.21|^10.0", + "illuminate/database": "^9.21|^10.0", + "illuminate/support": "^9.21|^10.0", + "php": "^8.0.2" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.28.2|^8.8.3", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2023-12-19T18:44:48+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v1.3.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754", + "reference": "3dbf8a8e914634c48d389c1234552666b3d43754", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "nesbot/carbon": "^2.61", + "pestphp/pest": "^1.21.3", + "phpstan/phpstan": "^1.8.2", + "symfony/var-dumper": "^5.4.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2023-11-08T14:08:06+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.9.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "502e0fe3f0415d06d5db1f83a472f0f3b754bafe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/502e0fe3f0415d06d5db1f83a472f0f3b754bafe", + "reference": "502e0fe3f0415d06d5db1f83a472f0f3b754bafe", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.9.0" + }, + "time": "2024-01-04T16:10:04+00:00" + }, + { + "name": "league/commonmark", + "version": "2.4.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "91c24291965bd6d7c46c46a12ba7492f83b1cadf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/91c24291965bd6d7c46c46a12ba7492f83b1cadf", + "reference": "91c24291965bd6d7c46c46a12ba7492f83b1cadf", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.30.3", + "commonmark/commonmark.js": "0.30.0", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 || ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2024-02-02T11:59:32+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.28.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c", + "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.28.0" + }, + "time": "2024-05-22T10:09:12+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.28.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/13f22ea8be526ea58c2ddff9e158ef7c296e4f40", + "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.28.0" + }, + "time": "2024-05-06T20:05:52+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.15.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301", + "reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.15.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-01-28T23:22:08+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.6.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^10.5.17", + "predis/predis": "^1.1 || ^2", + "ruflin/elastica": "^7", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.6.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2024-04-12T21:02:21+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.72.3", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "*", + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "psr/clock": "^1.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2024-01-25T10:35:09+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.3" + }, + "require-dev": { + "nette/tester": "^2.4", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.0" + }, + "time": "2023-12-11T11:54:22+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.4", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "d3ad0aa3b9f934602cb3e3902ebccf10be34d218" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/d3ad0aa3b9f934602cb3e3902ebccf10be34d218", + "reference": "d3ad0aa3b9f934602cb3e3902ebccf10be34d218", + "shasum": "" + }, + "require": { + "php": ">=8.0 <8.4" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.5", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.4" + }, + "time": "2024-01-17T16:50:36+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", + "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + }, + "time": "2024-03-05T20:51:40+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v1.15.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.0", + "symfony/console": "^5.3.0|^6.0.0" + }, + "require-dev": { + "ergebnis/phpstan-rules": "^1.0.", + "illuminate/console": "^8.0|^9.0", + "illuminate/support": "^8.0|^9.0", + "laravel/pint": "^1.0.0", + "pestphp/pest": "^1.21.0", + "pestphp/pest-plugin-mock": "^1.0", + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-strict-rules": "^1.1.0", + "symfony/var-dumper": "^5.2.7|^6.0.0", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v1.15.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2023-02-08T01:06:31+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.2", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-11-12T21:59:55+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.3", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73", + "reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.12.x-dev" + }, + "bamarni-bin": { + "bin-links": false, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.3" + }, + "time": "2024-04-02T15:57:53+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2022-12-31T21:50:55+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.6", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.6" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2024-04-27T21:32:50+00:00" + }, + { + "name": "symfony/console", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "1c5d5c2103c3762aff27a27e1e2409e30a79083b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/1c5d5c2103c3762aff27a27e1e2409e30a79083b", + "reference": "1c5d5c2103c3762aff27a27e1e2409e30a79083b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "667a072466c6a53827ed7b119af93806b884cbb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/667a072466c6a53827ed7b119af93806b884cbb3", + "reference": "667a072466c6a53827ed7b119af93806b884cbb3", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d84384f3f67de3cb650db64d685d70395dacfc3f", + "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "511c48990be17358c23bf45c5d71ab85d40fb764" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/511c48990be17358c23bf45c5d71ab85d40fb764", + "reference": "511c48990be17358c23bf45c5d71ab85d40fb764", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-23T10:36:43+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b4db6b833035477cb70e18d0ae33cb7c2b521759", + "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "symfony/cache": "<6.3" + }, + "require-dev": { + "doctrine/dbal": "^2.13.1|^3|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.3|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "b7b5e6cdef670a0c82d015a966ffc7e855861a98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b7b5e6cdef670a0c82d015a966ffc7e855861a98", + "reference": "b7b5e6cdef670a0c82d015a966ffc7e855861a98", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<5.4", + "symfony/cache": "<5.4", + "symfony/config": "<6.1", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<5.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.3", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.5|^6.0.5|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.4|^7.0", + "symfony/var-exporter": "^6.2|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-29T11:24:44+00:00" + }, + { + "name": "symfony/mailer", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "2c446d4e446995bed983c0b5bb9ff837e8de7dbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/2c446d4e446995bed983c0b5bb9ff837e8de7dbd", + "reference": "2c446d4e446995bed983c0b5bb9ff837e8de7dbd", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/mime", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "decadcf3865918ecfcbfa90968553994ce935a5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/decadcf3865918ecfcbfa90968553994ce935a5e", + "reference": "decadcf3865918ecfcbfa90968553994ce935a5e", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.3.2" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3.2|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "a287ed7475f85bf6f61890146edbc932c0fff919" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919", + "reference": "a287ed7475f85bf6f61890146edbc932c0fff919", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", + "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/process", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "cdb1c81c145fd5aa9b0038bab694035020943381" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/cdb1c81c145fd5aa9b0038bab694035020943381", + "reference": "cdb1c81c145fd5aa9b0038bab694035020943381", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "276e06398f71fa2a973264d94f28150f93cfb907" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/276e06398f71fa2a973264d94f28150f93cfb907", + "reference": "276e06398f71fa2a973264d94f28150f93cfb907", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "symfony/config": "<6.2", + "symfony/dependency-injection": "<5.4", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.2|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/string", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69", + "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "7495687c58bfd88b7883823747b0656d90679123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/7495687c58bfd88b7883823747b0656d90679123", + "reference": "7495687c58bfd88b7883823747b0656d90679123", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.18|^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/uid", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "a66efcb71d8bc3a207d9d78e0bd67f3321510355" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/a66efcb71d8bc3a207d9d78e0bd67f3321510355", + "reference": "a66efcb71d8bc3a207d9d78e0bd67f3321510355", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7a9cd977cd1c5fed3694bee52990866432af07d7", + "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.2.7", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb", + "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^5.5 || ^7.0 || ^8.0", + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.2.7" + }, + "time": "2023-12-08T13:03:43+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.2", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2023-11-12T22:43:29+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b56450eed252f6801410d810c8e1727224ae0743" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "fakerphp/faker", + "version": "v1.23.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" + }, + "time": "2024-01-02T13:46:09+00:00" + }, + { + "name": "filp/whoops", + "version": "2.15.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.15.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2023-11-03T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, + "time": "2020-07-09T08:09:16+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98", + "reference": "1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.57.1", + "illuminate/view": "^10.48.10", + "larastan/larastan": "^2.9.6", + "laravel-zero/framework": "^10.4.0", + "mockery/mockery": "^1.6.12", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^2.34.7" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2024-05-21T18:08:25+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.29.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "a8e4e749735ba2f091856eafeb3f99db8cd6b621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/a8e4e749735ba2f091856eafeb3f99db8cd6b621", + "reference": "a8e4e749735ba2f091856eafeb3f99db8cd6b621", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.52.16|^10.0|^11.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0", + "illuminate/support": "^9.52.16|^10.0|^11.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2024-05-16T21:39:11+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v7.10.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2", + "reference": "49ec67fa7b002712da8526678abd651c09f375b2", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.15.3", + "nunomaduro/termwind": "^1.15.1", + "php": "^8.1.0", + "symfony/console": "^6.3.4" + }, + "conflict": { + "laravel/framework": ">=11.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.3.0", + "laravel/framework": "^10.28.0", + "laravel/pint": "^1.13.3", + "laravel/sail": "^1.25.0", + "laravel/sanctum": "^3.3.1", + "laravel/tinker": "^2.8.2", + "nunomaduro/larastan": "^2.6.4", + "orchestra/testbench-core": "^8.13.0", + "pestphp/pest": "^2.23.2", + "phpunit/phpunit": "^10.4.1", + "sebastian/environment": "^6.0.1", + "spatie/laravel-ignition": "^2.3.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2023-10-11T15:45:01+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.14", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", + "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.14" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-12T15:33:41+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T06:24:48+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.20", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/547d314dc24ec1e177720d45c6263fb226cc2ae3", + "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.5", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.1", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.20" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-04-24T06:32:35+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:12:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-14T13:18:12+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:37:17+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:15:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-23T08:47:14+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:17:12+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:19:19+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:38:20+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "spatie/backtrace", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/backtrace.git", + "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8373b9d51638292e3bfd736a9c19a654111b4a23", + "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "ext-json": "*", + "laravel/serializable-closure": "^1.3", + "phpunit/phpunit": "^9.3", + "spatie/phpunit-snapshot-assertions": "^4.2", + "symfony/var-dumper": "^5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Backtrace\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van de Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A better backtrace", + "homepage": "https://github.com/spatie/backtrace", + "keywords": [ + "Backtrace", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/backtrace/tree/1.6.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/spatie", + "type": "github" + }, + { + "url": "https://spatie.be/open-source/support-us", + "type": "other" + } + ], + "time": "2024-04-24T13:22:11+00:00" + }, + { + "name": "spatie/flare-client-php", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/flare-client-php.git", + "reference": "220a7c8745e9fa427d54099f47147c4b97fe6462" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/220a7c8745e9fa427d54099f47147c4b97fe6462", + "reference": "220a7c8745e9fa427d54099f47147c4b97fe6462", + "shasum": "" + }, + "require": { + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", + "php": "^8.0", + "spatie/backtrace": "^1.5.2", + "symfony/http-foundation": "^5.2|^6.0|^7.0", + "symfony/mime": "^5.2|^6.0|^7.0", + "symfony/process": "^5.2|^6.0|^7.0", + "symfony/var-dumper": "^5.2|^6.0|^7.0" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.5.0", + "pestphp/pest": "^1.20|^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "spatie/phpunit-snapshot-assertions": "^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\FlareClient\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Send PHP errors to Flare", + "homepage": "https://github.com/spatie/flare-client-php", + "keywords": [ + "exception", + "flare", + "reporting", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/flare-client-php/issues", + "source": "https://github.com/spatie/flare-client-php/tree/1.6.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-05-22T09:45:39+00:00" + }, + { + "name": "spatie/ignition", + "version": "1.14.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/ignition.git", + "reference": "c23cc018c5f423d2f413b99f84655fceb6549811" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/ignition/zipball/c23cc018c5f423d2f413b99f84655fceb6549811", + "reference": "c23cc018c5f423d2f413b99f84655fceb6549811", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0", + "spatie/backtrace": "^1.5.3", + "spatie/flare-client-php": "^1.4.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "illuminate/cache": "^9.52|^10.0|^11.0", + "mockery/mockery": "^1.4", + "pestphp/pest": "^1.20|^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "psr/simple-cache-implementation": "*", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "simple-cache-implementation": "To cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Spatie\\Ignition\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for PHP applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/spatie/ignition/issues", + "source": "https://github.com/spatie/ignition" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-05-03T15:56:16+00:00" + }, + { + "name": "spatie/laravel-ignition", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-ignition.git", + "reference": "f52124d50122611e8a40f628cef5c19ff6cc5b57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/f52124d50122611e8a40f628cef5c19ff6cc5b57", + "reference": "f52124d50122611e8a40f628cef5c19ff6cc5b57", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/support": "^10.0|^11.0", + "php": "^8.1", + "spatie/flare-client-php": "^1.5", + "spatie/ignition": "^1.14", + "symfony/console": "^6.2.3|^7.0", + "symfony/var-dumper": "^6.2.3|^7.0" + }, + "require-dev": { + "livewire/livewire": "^2.11|^3.3.5", + "mockery/mockery": "^1.5.1", + "openai-php/client": "^0.8.1", + "orchestra/testbench": "8.22.3|^9.0", + "pestphp/pest": "^2.34", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.16", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "psr/simple-cache-implementation": "Needed to cache solutions from OpenAI" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelIgnition\\IgnitionServiceProvider" + ], + "aliases": { + "Flare": "Spatie\\LaravelIgnition\\Facades\\Flare" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\LaravelIgnition\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spatie", + "email": "info@spatie.be", + "role": "Developer" + } + ], + "description": "A beautiful error page for Laravel applications.", + "homepage": "https://flareapp.io/ignition", + "keywords": [ + "error", + "flare", + "laravel", + "page" + ], + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/spatie/laravel-ignition/issues", + "source": "https://github.com/spatie/laravel-ignition" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-05-02T13:42:49+00:00" + }, + { + "name": "symfony/yaml", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "53e8b1ef30a65f78eac60fddc5ee7ebbbdb1dee0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/53e8b1ef30a65f78eac60fddc5ee7ebbbdb1dee0", + "reference": "53e8b1ef30a65f78eac60fddc5ee7ebbbdb1dee0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-28T10:28:08+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.1" + }, + "platform-dev": [], + "plugin-api-version": "2.2.0" +} diff --git a/api-inforasia/config/app.php b/api-inforasia/config/app.php new file mode 100644 index 0000000..9207160 --- /dev/null +++ b/api-inforasia/config/app.php @@ -0,0 +1,188 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + 'asset_url' => env('ASSET_URL'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Faker Locale + |-------------------------------------------------------------------------- + | + | This locale will be used by the Faker PHP library when generating fake + | data for your database seeds. For example, this will be used to get + | localized telephone numbers, street address information and more. + | + */ + + 'faker_locale' => 'en_US', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => 'file', + // 'store' => 'redis', + ], + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => ServiceProvider::defaultProviders()->merge([ + /* + * Package Service Providers... + */ + + /* + * Application Service Providers... + */ + App\Providers\AppServiceProvider::class, + App\Providers\AuthServiceProvider::class, + // App\Providers\BroadcastServiceProvider::class, + App\Providers\EventServiceProvider::class, + App\Providers\RouteServiceProvider::class, + ])->toArray(), + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => Facade::defaultAliases()->merge([ + // 'Example' => App\Facades\Example::class, + ])->toArray(), + +]; diff --git a/api-inforasia/config/auth.php b/api-inforasia/config/auth.php new file mode 100644 index 0000000..9548c15 --- /dev/null +++ b/api-inforasia/config/auth.php @@ -0,0 +1,115 @@ + [ + 'guard' => 'web', + 'passwords' => 'users', + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => App\Models\User::class, + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => 'password_reset_tokens', + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the amount of seconds before a password confirmation + | times out and the user is prompted to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => 10800, + +]; diff --git a/api-inforasia/config/broadcasting.php b/api-inforasia/config/broadcasting.php new file mode 100644 index 0000000..2410485 --- /dev/null +++ b/api-inforasia/config/broadcasting.php @@ -0,0 +1,71 @@ + env('BROADCAST_DRIVER', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'secret' => env('PUSHER_APP_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'cluster' => env('PUSHER_APP_CLUSTER'), + 'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com', + 'port' => env('PUSHER_PORT', 443), + 'scheme' => env('PUSHER_SCHEME', 'https'), + 'encrypted' => true, + 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', + ], + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + ], + + 'ably' => [ + 'driver' => 'ably', + 'key' => env('ABLY_KEY'), + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', + ], + + ], + +]; diff --git a/api-inforasia/config/cache.php b/api-inforasia/config/cache.php new file mode 100644 index 0000000..d4171e2 --- /dev/null +++ b/api-inforasia/config/cache.php @@ -0,0 +1,111 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'cache', + 'lock_connection' => 'default', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, or DynamoDB cache + | stores there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), + +]; diff --git a/api-inforasia/config/cors.php b/api-inforasia/config/cors.php new file mode 100644 index 0000000..8a39e6d --- /dev/null +++ b/api-inforasia/config/cors.php @@ -0,0 +1,34 @@ + ['api/*', 'sanctum/csrf-cookie'], + + 'allowed_methods' => ['*'], + + 'allowed_origins' => ['*'], + + 'allowed_origins_patterns' => [], + + 'allowed_headers' => ['*'], + + 'exposed_headers' => [], + + 'max_age' => 0, + + 'supports_credentials' => false, + +]; diff --git a/api-inforasia/config/database.php b/api-inforasia/config/database.php new file mode 100644 index 0000000..137ad18 --- /dev/null +++ b/api-inforasia/config/database.php @@ -0,0 +1,151 @@ + env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DATABASE_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/api-inforasia/config/filesystems.php b/api-inforasia/config/filesystems.php new file mode 100644 index 0000000..e9d9dbd --- /dev/null +++ b/api-inforasia/config/filesystems.php @@ -0,0 +1,76 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been set up for each driver as an example of the required values. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'throw' => false, + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/api-inforasia/config/hashing.php b/api-inforasia/config/hashing.php new file mode 100644 index 0000000..0e8a0bb --- /dev/null +++ b/api-inforasia/config/hashing.php @@ -0,0 +1,54 @@ + 'bcrypt', + + /* + |-------------------------------------------------------------------------- + | Bcrypt Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Bcrypt algorithm. This will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'bcrypt' => [ + 'rounds' => env('BCRYPT_ROUNDS', 12), + 'verify' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Argon Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Argon algorithm. These will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'argon' => [ + 'memory' => 65536, + 'threads' => 1, + 'time' => 4, + 'verify' => true, + ], + +]; diff --git a/api-inforasia/config/logging.php b/api-inforasia/config/logging.php new file mode 100644 index 0000000..c44d276 --- /dev/null +++ b/api-inforasia/config/logging.php @@ -0,0 +1,131 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + + 'channels' => [ + 'stack' => [ + 'driver' => 'stack', + 'channels' => ['single'], + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 14, + 'replace_placeholders' => true, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Laravel Log', + 'emoji' => ':boom:', + 'level' => env('LOG_LEVEL', 'critical'), + 'replace_placeholders' => true, + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + 'facility' => LOG_USER, + 'replace_placeholders' => true, + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + ], + +]; diff --git a/api-inforasia/config/mail.php b/api-inforasia/config/mail.php new file mode 100644 index 0000000..e894b2e --- /dev/null +++ b/api-inforasia/config/mail.php @@ -0,0 +1,134 @@ + env('MAIL_MAILER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers to be used while + | sending an e-mail. You will specify which one you are using for your + | mailers below. You are free to add additional mailers as required. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", + | "postmark", "log", "array", "failover", "roundrobin" + | + */ + + 'mailers' => [ + 'smtp' => [ + 'transport' => 'smtp', + 'url' => env('MAIL_URL'), + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'port' => env('MAIL_PORT', 587), + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'local_domain' => env('MAIL_EHLO_DOMAIN'), + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'postmark' => [ + 'transport' => 'postmark', + // 'message_stream_id' => null, + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'mailgun' => [ + 'transport' => 'mailgun', + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + ], + + 'roundrobin' => [ + 'transport' => 'roundrobin', + 'mailers' => [ + 'ses', + 'postmark', + ], + ], + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), + 'name' => env('MAIL_FROM_NAME', 'Example'), + ], + + /* + |-------------------------------------------------------------------------- + | Markdown Mail Settings + |-------------------------------------------------------------------------- + | + | If you are using Markdown based email rendering, you may configure your + | theme and component paths here, allowing you to customize the design + | of the emails. Or, you may simply stick with the Laravel defaults! + | + */ + + 'markdown' => [ + 'theme' => 'default', + + 'paths' => [ + resource_path('views/vendor/mail'), + ], + ], + +]; diff --git a/api-inforasia/config/queue.php b/api-inforasia/config/queue.php new file mode 100644 index 0000000..01c6b05 --- /dev/null +++ b/api-inforasia/config/queue.php @@ -0,0 +1,109 @@ + env('QUEUE_CONNECTION', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Laravel. You are free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + 'after_commit' => false, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + 'block_for' => 0, + 'after_commit' => false, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'after_commit' => false, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + 'block_for' => null, + 'after_commit' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/api-inforasia/config/sanctum.php b/api-inforasia/config/sanctum.php new file mode 100644 index 0000000..35d75b3 --- /dev/null +++ b/api-inforasia/config/sanctum.php @@ -0,0 +1,83 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort() + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. This will override any values set in the token's + | "expires_at" attribute, but first-party sessions are not affected. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Token Prefix + |-------------------------------------------------------------------------- + | + | Sanctum can prefix new tokens in order to take advantage of numerous + | security scanning initiatives maintained by open source platforms + | that notify developers if they commit tokens into repositories. + | + | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning + | + */ + + 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, + 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, + 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, + ], + +]; diff --git a/api-inforasia/config/services.php b/api-inforasia/config/services.php new file mode 100644 index 0000000..0ace530 --- /dev/null +++ b/api-inforasia/config/services.php @@ -0,0 +1,34 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'scheme' => 'https', + ], + + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + +]; diff --git a/api-inforasia/config/session.php b/api-inforasia/config/session.php new file mode 100644 index 0000000..e738cb3 --- /dev/null +++ b/api-inforasia/config/session.php @@ -0,0 +1,214 @@ + env('SESSION_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => env('SESSION_LIFETIME', 120), + + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | While using one of the framework's cache driven session backends you may + | list a cache store that should be used for these sessions. This value + | must match with one of the application's configured cache "stores". + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. You are free to modify this option if needed. + | + */ + + 'http_only' => true, + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" since this is a secure default value. + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => 'lax', + + /* + |-------------------------------------------------------------------------- + | Partitioned Cookies + |-------------------------------------------------------------------------- + | + | Setting this value to true will tie the cookie to the top-level site for + | a cross-site context. Partitioned cookies are accepted by the browser + | when flagged "secure" and the Same-Site attribute is set to "none". + | + */ + + 'partitioned' => false, + +]; diff --git a/api-inforasia/config/view.php b/api-inforasia/config/view.php new file mode 100644 index 0000000..22b8a18 --- /dev/null +++ b/api-inforasia/config/view.php @@ -0,0 +1,36 @@ + [ + resource_path('views'), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => env( + 'VIEW_COMPILED_PATH', + realpath(storage_path('framework/views')) + ), + +]; diff --git a/api-inforasia/database/.gitignore b/api-inforasia/database/.gitignore new file mode 100644 index 0000000..9b19b93 --- /dev/null +++ b/api-inforasia/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/api-inforasia/database/factories/UserFactory.php b/api-inforasia/database/factories/UserFactory.php new file mode 100644 index 0000000..584104c --- /dev/null +++ b/api-inforasia/database/factories/UserFactory.php @@ -0,0 +1,44 @@ + + */ +class UserFactory extends Factory +{ + /** + * The current password being used by the factory. + */ + protected static ?string $password; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::$password ??= Hash::make('password'), + 'remember_token' => Str::random(10), + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/api-inforasia/database/migrations/2014_10_12_000000_create_users_table.php b/api-inforasia/database/migrations/2014_10_12_000000_create_users_table.php new file mode 100644 index 0000000..3651cd2 --- /dev/null +++ b/api-inforasia/database/migrations/2014_10_12_000000_create_users_table.php @@ -0,0 +1,40 @@ +id(); + $table->string('name'); + $table->string('nip'); + $table->string('email')->unique(); + $table->timestamp('email_verified_at')->nullable(); + $table->string('username'); + $table->string('password'); + $table->string('jenis_kelamin'); + $table->date('tanggal_lahir'); + $table->string('no_telp'); + $table->string('alamat'); + + + $table->rememberToken(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users'); + } +}; diff --git a/api-inforasia/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php b/api-inforasia/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php new file mode 100644 index 0000000..81a7229 --- /dev/null +++ b/api-inforasia/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php @@ -0,0 +1,28 @@ +string('email')->primary(); + $table->string('token'); + $table->timestamp('created_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('password_reset_tokens'); + } +}; diff --git a/api-inforasia/database/migrations/2019_08_19_000000_create_failed_jobs_table.php b/api-inforasia/database/migrations/2019_08_19_000000_create_failed_jobs_table.php new file mode 100644 index 0000000..249da81 --- /dev/null +++ b/api-inforasia/database/migrations/2019_08_19_000000_create_failed_jobs_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/api-inforasia/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/api-inforasia/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php new file mode 100644 index 0000000..e828ad8 --- /dev/null +++ b/api-inforasia/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('tokenable'); + $table->string('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/api-inforasia/database/migrations/2024_05_09_181009_create_roles_table.php b/api-inforasia/database/migrations/2024_05_09_181009_create_roles_table.php new file mode 100644 index 0000000..9445d82 --- /dev/null +++ b/api-inforasia/database/migrations/2024_05_09_181009_create_roles_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('name')->unique(); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('roles'); + } +}; diff --git a/api-inforasia/database/migrations/2024_05_09_181043_create_proyeks_table.php b/api-inforasia/database/migrations/2024_05_09_181043_create_proyeks_table.php new file mode 100644 index 0000000..eeb6366 --- /dev/null +++ b/api-inforasia/database/migrations/2024_05_09_181043_create_proyeks_table.php @@ -0,0 +1,37 @@ +id(); + $table->foreignId('user_id')->references('id')->on('users'); + $table->string('nama'); + $table->longText('detail'); + $table->string('manager'); + $table->string('file')->nullable(); + $table->date('start'); + $table->date('finish'); + $table->integer('nilai'); + $table->string('klien'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('proyeks'); + } +}; diff --git a/api-inforasia/database/migrations/2024_05_09_181049_create_task_proyeks_table.php b/api-inforasia/database/migrations/2024_05_09_181049_create_task_proyeks_table.php new file mode 100644 index 0000000..d389dca --- /dev/null +++ b/api-inforasia/database/migrations/2024_05_09_181049_create_task_proyeks_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('proyek_id')->references('id')->on('proyeks')->onDelete('cascade'); + $table->string('tugas')->nullable(); + $table->longText('catatan')->nullable(); + $table->string('pekerja')->nullable(); + $table->date('start')->nullable(); + $table->date('deadline')->nullable(); + $table->string('status')->nullable(); + $table->integer('nilai')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('task_proyeks'); + } +}; diff --git a/api-inforasia/database/migrations/2024_05_09_181114_create_penerima_proyeks_table.php b/api-inforasia/database/migrations/2024_05_09_181114_create_penerima_proyeks_table.php new file mode 100644 index 0000000..04ede51 --- /dev/null +++ b/api-inforasia/database/migrations/2024_05_09_181114_create_penerima_proyeks_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreignId('task_proyek_id')->references('id')->on('task_proyeks')->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('penerima_proyeks'); + } +}; diff --git a/api-inforasia/database/migrations/2024_05_09_181822_add_column_to_users_table.php b/api-inforasia/database/migrations/2024_05_09_181822_add_column_to_users_table.php new file mode 100644 index 0000000..7313d55 --- /dev/null +++ b/api-inforasia/database/migrations/2024_05_09_181822_add_column_to_users_table.php @@ -0,0 +1,30 @@ +unsignedBigInteger('role_id')->nullable(); + $table->foreign('role_id')->references('id')->on('roles')->onDelete('restrict'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropForeign(['role_id']); + $table->dropColumn('role_id'); + }); + } +}; diff --git a/api-inforasia/database/migrations/2024_05_17_165255_add_foto_profile_users_table.php b/api-inforasia/database/migrations/2024_05_17_165255_add_foto_profile_users_table.php new file mode 100644 index 0000000..47503d0 --- /dev/null +++ b/api-inforasia/database/migrations/2024_05_17_165255_add_foto_profile_users_table.php @@ -0,0 +1,28 @@ +string('foto_profile')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + // + }); + } +}; diff --git a/api-inforasia/database/seeders/DatabaseSeeder.php b/api-inforasia/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..a9f4519 --- /dev/null +++ b/api-inforasia/database/seeders/DatabaseSeeder.php @@ -0,0 +1,22 @@ +create(); + + // \App\Models\User::factory()->create([ + // 'name' => 'Test User', + // 'email' => 'test@example.com', + // ]); + } +} diff --git a/api-inforasia/package.json b/api-inforasia/package.json new file mode 100644 index 0000000..56f5ddc --- /dev/null +++ b/api-inforasia/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "devDependencies": { + "axios": "^1.6.4", + "laravel-vite-plugin": "^1.0.0", + "vite": "^5.0.0" + } +} diff --git a/api-inforasia/phpunit.xml b/api-inforasia/phpunit.xml new file mode 100644 index 0000000..bc86714 --- /dev/null +++ b/api-inforasia/phpunit.xml @@ -0,0 +1,32 @@ + + + + + tests/Unit + + + tests/Feature + + + + + app + + + + + + + + + + + + + + + diff --git a/api-inforasia/public/.htaccess b/api-inforasia/public/.htaccess new file mode 100644 index 0000000..3aec5e2 --- /dev/null +++ b/api-inforasia/public/.htaccess @@ -0,0 +1,21 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Send Requests To Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + diff --git a/api-inforasia/public/favicon.ico b/api-inforasia/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/api-inforasia/public/foto/1716230714.png b/api-inforasia/public/foto/1716230714.png new file mode 100644 index 0000000..a40a9e4 Binary files /dev/null and b/api-inforasia/public/foto/1716230714.png differ diff --git a/api-inforasia/public/foto/1716230747.png b/api-inforasia/public/foto/1716230747.png new file mode 100644 index 0000000..a40a9e4 Binary files /dev/null and b/api-inforasia/public/foto/1716230747.png differ diff --git a/api-inforasia/public/foto/1716230765.png b/api-inforasia/public/foto/1716230765.png new file mode 100644 index 0000000..a40a9e4 Binary files /dev/null and b/api-inforasia/public/foto/1716230765.png differ diff --git a/api-inforasia/public/foto/1716230804.png b/api-inforasia/public/foto/1716230804.png new file mode 100644 index 0000000..a40a9e4 Binary files /dev/null and b/api-inforasia/public/foto/1716230804.png differ diff --git a/api-inforasia/public/foto/1716230845.png b/api-inforasia/public/foto/1716230845.png new file mode 100644 index 0000000..a40a9e4 Binary files /dev/null and b/api-inforasia/public/foto/1716230845.png differ diff --git a/api-inforasia/public/foto/1716238421.jpg b/api-inforasia/public/foto/1716238421.jpg new file mode 100644 index 0000000..72165d5 Binary files /dev/null and b/api-inforasia/public/foto/1716238421.jpg differ diff --git a/api-inforasia/public/foto/1716239395.jpg b/api-inforasia/public/foto/1716239395.jpg new file mode 100644 index 0000000..72165d5 Binary files /dev/null and b/api-inforasia/public/foto/1716239395.jpg differ diff --git a/api-inforasia/public/foto/1716239446.jpg b/api-inforasia/public/foto/1716239446.jpg new file mode 100644 index 0000000..72165d5 Binary files /dev/null and b/api-inforasia/public/foto/1716239446.jpg differ diff --git a/api-inforasia/public/foto/1716239738.jpg b/api-inforasia/public/foto/1716239738.jpg new file mode 100644 index 0000000..72165d5 Binary files /dev/null and b/api-inforasia/public/foto/1716239738.jpg differ diff --git a/api-inforasia/public/foto/1716239899.jpg b/api-inforasia/public/foto/1716239899.jpg new file mode 100644 index 0000000..72165d5 Binary files /dev/null and b/api-inforasia/public/foto/1716239899.jpg differ diff --git a/api-inforasia/public/foto/th.jfif b/api-inforasia/public/foto/th.jfif new file mode 100644 index 0000000..2fdb061 Binary files /dev/null and b/api-inforasia/public/foto/th.jfif differ diff --git a/api-inforasia/public/index.php b/api-inforasia/public/index.php new file mode 100644 index 0000000..1d69f3a --- /dev/null +++ b/api-inforasia/public/index.php @@ -0,0 +1,55 @@ +make(Kernel::class); + +$response = $kernel->handle( + $request = Request::capture() +)->send(); + +$kernel->terminate($request, $response); diff --git a/api-inforasia/public/robots.txt b/api-inforasia/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/api-inforasia/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/api-inforasia/resources/css/app.css b/api-inforasia/resources/css/app.css new file mode 100644 index 0000000..e69de29 diff --git a/api-inforasia/resources/js/app.js b/api-inforasia/resources/js/app.js new file mode 100644 index 0000000..e59d6a0 --- /dev/null +++ b/api-inforasia/resources/js/app.js @@ -0,0 +1 @@ +import './bootstrap'; diff --git a/api-inforasia/resources/js/bootstrap.js b/api-inforasia/resources/js/bootstrap.js new file mode 100644 index 0000000..846d350 --- /dev/null +++ b/api-inforasia/resources/js/bootstrap.js @@ -0,0 +1,32 @@ +/** + * We'll load the axios HTTP library which allows us to easily issue requests + * to our Laravel back-end. This library automatically handles sending the + * CSRF token as a header based on the value of the "XSRF" token cookie. + */ + +import axios from 'axios'; +window.axios = axios; + +window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; + +/** + * Echo exposes an expressive API for subscribing to channels and listening + * for events that are broadcast by Laravel. Echo and event broadcasting + * allows your team to easily build robust real-time web applications. + */ + +// import Echo from 'laravel-echo'; + +// import Pusher from 'pusher-js'; +// window.Pusher = Pusher; + +// window.Echo = new Echo({ +// broadcaster: 'pusher', +// key: import.meta.env.VITE_PUSHER_APP_KEY, +// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1', +// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`, +// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, +// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, +// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https', +// enabledTransports: ['ws', 'wss'], +// }); diff --git a/api-inforasia/resources/views/welcome.blade.php b/api-inforasia/resources/views/welcome.blade.php new file mode 100644 index 0000000..3353350 --- /dev/null +++ b/api-inforasia/resources/views/welcome.blade.php @@ -0,0 +1,133 @@ + + + + + + + Laravel + + + + + + + + + + + + diff --git a/api-inforasia/routes/api.php b/api-inforasia/routes/api.php new file mode 100644 index 0000000..f8e4420 --- /dev/null +++ b/api-inforasia/routes/api.php @@ -0,0 +1,78 @@ +get('/user', function (Request $request) { + return $request->user(); +}); + +// view +Route::get('/tes', [authentication::class, 'index']); + +// login +Route::post('/login', [authentication::class, 'login']); + +//logout +Route::get('/logout', [authentication::class, 'logout'])->middleware(['auth:sanctum']); + +//cek user on +Route::get('/aktif', [authentication::class, 'aktif'])->middleware(['auth:sanctum']); + +//user API +Route::get('/users', [UserController::class, 'index'])->middleware(['auth:sanctum']); +Route::get('/user-data', [UserController::class, 'getUserData'])->middleware(['auth:sanctum']); +Route::get('/users-manager', [UserController::class, 'getManager'])->middleware(['auth:sanctum']); +Route::get('/users/{id}', [UserController::class, 'show'])->middleware(['auth:sanctum']); +Route::post('/users', [UserController::class, 'store'])->middleware(['auth:sanctum']); +Route::post('/users-update/{id}', [UserController::class, 'update'])->middleware(['auth:sanctum']); +Route::post('/users-delete/{id}', [UserController::class, 'destroy'])->middleware(['auth:sanctum']); + +// proyek api +Route::get('/proyeks', [ProyekController::class, 'index'])->middleware(['auth:sanctum']); +Route::get('/recent', [ProyekController::class, 'recent'])->middleware(['auth:sanctum']); +Route::get('/proyeks/{id}', [ProyekController::class, 'show'])->middleware(['auth:sanctum']); +Route::post('/proyeks', [ProyekController::class, 'store'])->middleware(['auth:sanctum']); +Route::get('/proyeks-count', [ProyekController::class, 'getProyek'])->middleware(['auth:sanctum']); +Route::get('/proyeks-chart', [ProyekController::class, 'getProyekChart'])->middleware(['auth:sanctum']); +Route::post('/proyeks-update/{id}', [ProyekController::class, 'update'])->middleware(['auth:sanctum']); +Route::post('/proyeks-delete/{id}', [ProyekController::class, 'destroy'])->middleware(['auth:sanctum']); + +// task Proyek API +Route::get('/tasks', [TaskProyekController::class, 'index'])->middleware(['auth:sanctum']); +Route::get('/tasks/{id}', [TaskProyekController::class, 'show'])->middleware(['auth:sanctum']); +Route::post('/tasks', [TaskProyekController::class, 'store'])->middleware(['auth:sanctum']); +Route::post('/tasks-update/{id}', [TaskProyekController::class, 'update'])->middleware(['auth:sanctum']); +Route::post('/tasks-delete/{id}', [TaskProyekController::class, 'destroy'])->middleware(['auth:sanctum']); + +//penerima Proyek API +Route::get('/penerima-proyeks', [PenerimaProyekController::class, 'index'])->middleware(['auth:sanctum']); +Route::get('/penerima-proyeks/{id}', [PenerimaProyekController::class, 'show'])->middleware(['auth:sanctum']); +Route::post('/penerima-proyeks', [PenerimaProyekController::class, 'store'])->middleware(['auth:sanctum']); +Route::put('/penerima-proyeks/{id}', [PenerimaProyekController::class, 'update'])->middleware(['auth:sanctum']); +Route::delete('/penerima-proyeks/{id}', [PenerimaProyekController::class, 'destroy'])->middleware(['auth:sanctum']); + +//role API +Route::get('/roles', [RoleController::class, 'index'])->middleware(['auth:sanctum']); +Route::get('/roles/{id}', [RoleController::class, 'show'])->middleware(['auth:sanctum']); +Route::post('/roles', [RoleController::class, 'store'])->middleware(['auth:sanctum']); +Route::put('/roles/{id}', [RoleController::class, 'update'])->middleware(['auth:sanctum']); +Route::delete('/roles/{id}', [RoleController::class, 'destroy'])->middleware(['auth:sanctum']); diff --git a/api-inforasia/routes/channels.php b/api-inforasia/routes/channels.php new file mode 100644 index 0000000..5d451e1 --- /dev/null +++ b/api-inforasia/routes/channels.php @@ -0,0 +1,18 @@ +id === (int) $id; +}); diff --git a/api-inforasia/routes/console.php b/api-inforasia/routes/console.php new file mode 100644 index 0000000..e05f4c9 --- /dev/null +++ b/api-inforasia/routes/console.php @@ -0,0 +1,19 @@ +comment(Inspiring::quote()); +})->purpose('Display an inspiring quote'); diff --git a/api-inforasia/routes/web.php b/api-inforasia/routes/web.php new file mode 100644 index 0000000..d259f33 --- /dev/null +++ b/api-inforasia/routes/web.php @@ -0,0 +1,18 @@ +make(Kernel::class)->bootstrap(); + + return $app; + } +} diff --git a/api-inforasia/tests/Feature/ExampleTest.php b/api-inforasia/tests/Feature/ExampleTest.php new file mode 100644 index 0000000..8364a84 --- /dev/null +++ b/api-inforasia/tests/Feature/ExampleTest.php @@ -0,0 +1,19 @@ +get('/'); + + $response->assertStatus(200); + } +} diff --git a/api-inforasia/tests/TestCase.php b/api-inforasia/tests/TestCase.php new file mode 100644 index 0000000..2932d4a --- /dev/null +++ b/api-inforasia/tests/TestCase.php @@ -0,0 +1,10 @@ +assertTrue(true); + } +} diff --git a/api-inforasia/vite.config.js b/api-inforasia/vite.config.js new file mode 100644 index 0000000..421b569 --- /dev/null +++ b/api-inforasia/vite.config.js @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; + +export default defineConfig({ + plugins: [ + laravel({ + input: ['resources/css/app.css', 'resources/js/app.js'], + refresh: true, + }), + ], +}); diff --git a/dashboard_sim/.gitignore b/dashboard_sim/.gitignore new file mode 100644 index 0000000..29a3a50 --- /dev/null +++ b/dashboard_sim/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/dashboard_sim/.metadata b/dashboard_sim/.metadata new file mode 100644 index 0000000..32dc8a5 --- /dev/null +++ b/dashboard_sim/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "300451adae589accbece3490f4396f10bdf15e6e" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + - platform: android + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + - platform: ios + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + - platform: linux + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + - platform: macos + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + - platform: web + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + - platform: windows + create_revision: 300451adae589accbece3490f4396f10bdf15e6e + base_revision: 300451adae589accbece3490f4396f10bdf15e6e + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/dashboard_sim/.vscode/settings.json b/dashboard_sim/.vscode/settings.json new file mode 100644 index 0000000..05f8880 --- /dev/null +++ b/dashboard_sim/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "proyekfile" + ] +} \ No newline at end of file diff --git a/dashboard_sim/README.md b/dashboard_sim/README.md new file mode 100644 index 0000000..2d8e663 --- /dev/null +++ b/dashboard_sim/README.md @@ -0,0 +1,16 @@ +# drawer + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/dashboard_sim/analysis_options.yaml b/dashboard_sim/analysis_options.yaml new file mode 100644 index 0000000..0d29021 --- /dev/null +++ b/dashboard_sim/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/dashboard_sim/android/.gitignore b/dashboard_sim/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/dashboard_sim/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/dashboard_sim/android/app/build.gradle b/dashboard_sim/android/app/build.gradle new file mode 100644 index 0000000..cd91c8e --- /dev/null +++ b/dashboard_sim/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "com.example.drawer" + compileSdk flutter.compileSdkVersion + ndkVersion "25.1.8937393" + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.drawer" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/dashboard_sim/android/app/src/debug/AndroidManifest.xml b/dashboard_sim/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/dashboard_sim/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/dashboard_sim/android/app/src/main/AndroidManifest.xml b/dashboard_sim/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f2255d1 --- /dev/null +++ b/dashboard_sim/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard_sim/android/app/src/main/kotlin/com/example/drawer/MainActivity.kt b/dashboard_sim/android/app/src/main/kotlin/com/example/drawer/MainActivity.kt new file mode 100644 index 0000000..a50a3f2 --- /dev/null +++ b/dashboard_sim/android/app/src/main/kotlin/com/example/drawer/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.drawer + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/dashboard_sim/android/app/src/main/res/drawable-v21/launch_background.xml b/dashboard_sim/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/dashboard_sim/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/dashboard_sim/android/app/src/main/res/drawable/launch_background.xml b/dashboard_sim/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/dashboard_sim/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/dashboard_sim/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dashboard_sim/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/dashboard_sim/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/dashboard_sim/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dashboard_sim/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/dashboard_sim/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/dashboard_sim/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dashboard_sim/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/dashboard_sim/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/dashboard_sim/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dashboard_sim/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/dashboard_sim/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/dashboard_sim/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dashboard_sim/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/dashboard_sim/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/dashboard_sim/android/app/src/main/res/values-night/styles.xml b/dashboard_sim/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/dashboard_sim/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/dashboard_sim/android/app/src/main/res/values/styles.xml b/dashboard_sim/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/dashboard_sim/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/dashboard_sim/android/app/src/profile/AndroidManifest.xml b/dashboard_sim/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/dashboard_sim/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/dashboard_sim/android/build.gradle b/dashboard_sim/android/build.gradle new file mode 100644 index 0000000..bc157bd --- /dev/null +++ b/dashboard_sim/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/dashboard_sim/android/gradle.properties b/dashboard_sim/android/gradle.properties new file mode 100644 index 0000000..598d13f --- /dev/null +++ b/dashboard_sim/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/dashboard_sim/android/gradle/wrapper/gradle-wrapper.properties b/dashboard_sim/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e1ca574 --- /dev/null +++ b/dashboard_sim/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/dashboard_sim/android/settings.gradle b/dashboard_sim/android/settings.gradle new file mode 100644 index 0000000..1d6d19b --- /dev/null +++ b/dashboard_sim/android/settings.gradle @@ -0,0 +1,26 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/dashboard_sim/assets/icons/Documents.svg b/dashboard_sim/assets/icons/Documents.svg new file mode 100644 index 0000000..d75aece --- /dev/null +++ b/dashboard_sim/assets/icons/Documents.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dashboard_sim/assets/icons/Figma_file.svg b/dashboard_sim/assets/icons/Figma_file.svg new file mode 100644 index 0000000..d3a765a --- /dev/null +++ b/dashboard_sim/assets/icons/Figma_file.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/dashboard_sim/assets/icons/Search.svg b/dashboard_sim/assets/icons/Search.svg new file mode 100644 index 0000000..6d39436 --- /dev/null +++ b/dashboard_sim/assets/icons/Search.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dashboard_sim/assets/icons/doc_file.svg b/dashboard_sim/assets/icons/doc_file.svg new file mode 100644 index 0000000..fd703d1 --- /dev/null +++ b/dashboard_sim/assets/icons/doc_file.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/dashboard_sim/assets/icons/drop_box.svg b/dashboard_sim/assets/icons/drop_box.svg new file mode 100644 index 0000000..ab39e74 --- /dev/null +++ b/dashboard_sim/assets/icons/drop_box.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dashboard_sim/assets/icons/excel_file.svg b/dashboard_sim/assets/icons/excel_file.svg new file mode 100644 index 0000000..c954345 --- /dev/null +++ b/dashboard_sim/assets/icons/excel_file.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/dashboard_sim/assets/icons/finish.png b/dashboard_sim/assets/icons/finish.png new file mode 100644 index 0000000..d6c3e00 Binary files /dev/null and b/dashboard_sim/assets/icons/finish.png differ diff --git a/dashboard_sim/assets/icons/folder.svg b/dashboard_sim/assets/icons/folder.svg new file mode 100644 index 0000000..e475ed3 --- /dev/null +++ b/dashboard_sim/assets/icons/folder.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/google_drive.svg b/dashboard_sim/assets/icons/google_drive.svg new file mode 100644 index 0000000..b39a432 --- /dev/null +++ b/dashboard_sim/assets/icons/google_drive.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dashboard_sim/assets/icons/logo.svg b/dashboard_sim/assets/icons/logo.svg new file mode 100644 index 0000000..e1a8244 --- /dev/null +++ b/dashboard_sim/assets/icons/logo.svg @@ -0,0 +1,11 @@ + + + + + + + + Shop + + + diff --git a/dashboard_sim/assets/icons/media.svg b/dashboard_sim/assets/icons/media.svg new file mode 100644 index 0000000..ddbd1ef --- /dev/null +++ b/dashboard_sim/assets/icons/media.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/media_file.svg b/dashboard_sim/assets/icons/media_file.svg new file mode 100644 index 0000000..472b6fb --- /dev/null +++ b/dashboard_sim/assets/icons/media_file.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dashboard_sim/assets/icons/menu_dashboard.svg b/dashboard_sim/assets/icons/menu_dashboard.svg new file mode 100644 index 0000000..b5af92c --- /dev/null +++ b/dashboard_sim/assets/icons/menu_dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_doc.svg b/dashboard_sim/assets/icons/menu_doc.svg new file mode 100644 index 0000000..840fe8a --- /dev/null +++ b/dashboard_sim/assets/icons/menu_doc.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_notification.svg b/dashboard_sim/assets/icons/menu_notification.svg new file mode 100644 index 0000000..4096020 --- /dev/null +++ b/dashboard_sim/assets/icons/menu_notification.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_profile.svg b/dashboard_sim/assets/icons/menu_profile.svg new file mode 100644 index 0000000..8ba6115 --- /dev/null +++ b/dashboard_sim/assets/icons/menu_profile.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_setting.svg b/dashboard_sim/assets/icons/menu_setting.svg new file mode 100644 index 0000000..0b1e4dd --- /dev/null +++ b/dashboard_sim/assets/icons/menu_setting.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_store.svg b/dashboard_sim/assets/icons/menu_store.svg new file mode 100644 index 0000000..29dff7c --- /dev/null +++ b/dashboard_sim/assets/icons/menu_store.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_task.svg b/dashboard_sim/assets/icons/menu_task.svg new file mode 100644 index 0000000..ae05cbd --- /dev/null +++ b/dashboard_sim/assets/icons/menu_task.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/menu_tran.svg b/dashboard_sim/assets/icons/menu_tran.svg new file mode 100644 index 0000000..b5ab36a --- /dev/null +++ b/dashboard_sim/assets/icons/menu_tran.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/one_drive.svg b/dashboard_sim/assets/icons/one_drive.svg new file mode 100644 index 0000000..c828b74 --- /dev/null +++ b/dashboard_sim/assets/icons/one_drive.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dashboard_sim/assets/icons/pdf_file.svg b/dashboard_sim/assets/icons/pdf_file.svg new file mode 100644 index 0000000..7427394 --- /dev/null +++ b/dashboard_sim/assets/icons/pdf_file.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/dashboard_sim/assets/icons/progres.png b/dashboard_sim/assets/icons/progres.png new file mode 100644 index 0000000..19da335 Binary files /dev/null and b/dashboard_sim/assets/icons/progres.png differ diff --git a/dashboard_sim/assets/icons/sound_file.svg b/dashboard_sim/assets/icons/sound_file.svg new file mode 100644 index 0000000..523c9ba --- /dev/null +++ b/dashboard_sim/assets/icons/sound_file.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/dashboard_sim/assets/icons/unknown.svg b/dashboard_sim/assets/icons/unknown.svg new file mode 100644 index 0000000..1783722 --- /dev/null +++ b/dashboard_sim/assets/icons/unknown.svg @@ -0,0 +1,3 @@ + + + diff --git a/dashboard_sim/assets/icons/xd_file.svg b/dashboard_sim/assets/icons/xd_file.svg new file mode 100644 index 0000000..b001e25 --- /dev/null +++ b/dashboard_sim/assets/icons/xd_file.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/dashboard_sim/assets/images/logo.png b/dashboard_sim/assets/images/logo.png new file mode 100644 index 0000000..d90b3c0 Binary files /dev/null and b/dashboard_sim/assets/images/logo.png differ diff --git a/dashboard_sim/assets/images/profile_pic.png b/dashboard_sim/assets/images/profile_pic.png new file mode 100644 index 0000000..a5cdfe7 Binary files /dev/null and b/dashboard_sim/assets/images/profile_pic.png differ diff --git a/dashboard_sim/assets/photos/dashboard.png b/dashboard_sim/assets/photos/dashboard.png new file mode 100644 index 0000000..a2706fa Binary files /dev/null and b/dashboard_sim/assets/photos/dashboard.png differ diff --git a/dashboard_sim/assets/photos/dots.png b/dashboard_sim/assets/photos/dots.png new file mode 100644 index 0000000..6e7910f Binary files /dev/null and b/dashboard_sim/assets/photos/dots.png differ diff --git a/dashboard_sim/assets/photos/finish.png b/dashboard_sim/assets/photos/finish.png new file mode 100644 index 0000000..9890ec2 Binary files /dev/null and b/dashboard_sim/assets/photos/finish.png differ diff --git a/dashboard_sim/assets/photos/karyawan.png b/dashboard_sim/assets/photos/karyawan.png new file mode 100644 index 0000000..15c41a9 Binary files /dev/null and b/dashboard_sim/assets/photos/karyawan.png differ diff --git a/dashboard_sim/assets/photos/karyawan2.png b/dashboard_sim/assets/photos/karyawan2.png new file mode 100644 index 0000000..8f05fae Binary files /dev/null and b/dashboard_sim/assets/photos/karyawan2.png differ diff --git a/dashboard_sim/assets/photos/login1.jpg b/dashboard_sim/assets/photos/login1.jpg new file mode 100644 index 0000000..0363606 Binary files /dev/null and b/dashboard_sim/assets/photos/login1.jpg differ diff --git a/dashboard_sim/assets/photos/login10.jpg b/dashboard_sim/assets/photos/login10.jpg new file mode 100644 index 0000000..de34374 Binary files /dev/null and b/dashboard_sim/assets/photos/login10.jpg differ diff --git a/dashboard_sim/assets/photos/login2.png b/dashboard_sim/assets/photos/login2.png new file mode 100644 index 0000000..8e84b1b Binary files /dev/null and b/dashboard_sim/assets/photos/login2.png differ diff --git a/dashboard_sim/assets/photos/login3.jpg b/dashboard_sim/assets/photos/login3.jpg new file mode 100644 index 0000000..8adc79f Binary files /dev/null and b/dashboard_sim/assets/photos/login3.jpg differ diff --git a/dashboard_sim/assets/photos/login4.jpg b/dashboard_sim/assets/photos/login4.jpg new file mode 100644 index 0000000..bd903cd Binary files /dev/null and b/dashboard_sim/assets/photos/login4.jpg differ diff --git a/dashboard_sim/assets/photos/login5.jpg b/dashboard_sim/assets/photos/login5.jpg new file mode 100644 index 0000000..e341254 Binary files /dev/null and b/dashboard_sim/assets/photos/login5.jpg differ diff --git a/dashboard_sim/assets/photos/login6.png b/dashboard_sim/assets/photos/login6.png new file mode 100644 index 0000000..f1e7086 Binary files /dev/null and b/dashboard_sim/assets/photos/login6.png differ diff --git a/dashboard_sim/assets/photos/login7.jpg b/dashboard_sim/assets/photos/login7.jpg new file mode 100644 index 0000000..b973978 Binary files /dev/null and b/dashboard_sim/assets/photos/login7.jpg differ diff --git a/dashboard_sim/assets/photos/login8.jpg b/dashboard_sim/assets/photos/login8.jpg new file mode 100644 index 0000000..bbe5ba9 Binary files /dev/null and b/dashboard_sim/assets/photos/login8.jpg differ diff --git a/dashboard_sim/assets/photos/login9.jpg b/dashboard_sim/assets/photos/login9.jpg new file mode 100644 index 0000000..172b40f Binary files /dev/null and b/dashboard_sim/assets/photos/login9.jpg differ diff --git a/dashboard_sim/assets/photos/logo.png b/dashboard_sim/assets/photos/logo.png new file mode 100644 index 0000000..aa48fab Binary files /dev/null and b/dashboard_sim/assets/photos/logo.png differ diff --git a/dashboard_sim/assets/photos/logo2.png b/dashboard_sim/assets/photos/logo2.png new file mode 100644 index 0000000..e7dbee6 Binary files /dev/null and b/dashboard_sim/assets/photos/logo2.png differ diff --git a/dashboard_sim/assets/photos/logout.png b/dashboard_sim/assets/photos/logout.png new file mode 100644 index 0000000..ac15d7f Binary files /dev/null and b/dashboard_sim/assets/photos/logout.png differ diff --git a/dashboard_sim/assets/photos/officer.png b/dashboard_sim/assets/photos/officer.png new file mode 100644 index 0000000..05f17cb Binary files /dev/null and b/dashboard_sim/assets/photos/officer.png differ diff --git a/dashboard_sim/assets/photos/profil.png b/dashboard_sim/assets/photos/profil.png new file mode 100644 index 0000000..317742e Binary files /dev/null and b/dashboard_sim/assets/photos/profil.png differ diff --git a/dashboard_sim/assets/photos/progress.png b/dashboard_sim/assets/photos/progress.png new file mode 100644 index 0000000..81a078a Binary files /dev/null and b/dashboard_sim/assets/photos/progress.png differ diff --git a/dashboard_sim/assets/photos/proyek.png b/dashboard_sim/assets/photos/proyek.png new file mode 100644 index 0000000..5e02278 Binary files /dev/null and b/dashboard_sim/assets/photos/proyek.png differ diff --git a/dashboard_sim/assets/photos/proyek2.png b/dashboard_sim/assets/photos/proyek2.png new file mode 100644 index 0000000..4a73dd3 Binary files /dev/null and b/dashboard_sim/assets/photos/proyek2.png differ diff --git a/dashboard_sim/assets/photos/search.png b/dashboard_sim/assets/photos/search.png new file mode 100644 index 0000000..8997044 Binary files /dev/null and b/dashboard_sim/assets/photos/search.png differ diff --git a/dashboard_sim/assets/photos/search2.png b/dashboard_sim/assets/photos/search2.png new file mode 100644 index 0000000..83abb15 Binary files /dev/null and b/dashboard_sim/assets/photos/search2.png differ diff --git a/dashboard_sim/assets/photos/search3.png b/dashboard_sim/assets/photos/search3.png new file mode 100644 index 0000000..f12779e Binary files /dev/null and b/dashboard_sim/assets/photos/search3.png differ diff --git a/dashboard_sim/assets/photos/user.png b/dashboard_sim/assets/photos/user.png new file mode 100644 index 0000000..b8a3c48 Binary files /dev/null and b/dashboard_sim/assets/photos/user.png differ diff --git a/dashboard_sim/config.json b/dashboard_sim/config.json new file mode 100644 index 0000000..8b3d807 --- /dev/null +++ b/dashboard_sim/config.json @@ -0,0 +1,12 @@ +{ + "modules": [], + "module_directory_name": "module", + "experimental_mode": false, + "learning_mode": false, + "unfreezed": true, + "use_cubit": false, + "ignore_core_generator_for_directories": [ + "lib/model", + "lib/models" + ] +} \ No newline at end of file diff --git a/dashboard_sim/ios/.gitignore b/dashboard_sim/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/dashboard_sim/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/dashboard_sim/ios/Flutter/AppFrameworkInfo.plist b/dashboard_sim/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..7c56964 --- /dev/null +++ b/dashboard_sim/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/dashboard_sim/ios/Flutter/Debug.xcconfig b/dashboard_sim/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/dashboard_sim/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/dashboard_sim/ios/Flutter/Release.xcconfig b/dashboard_sim/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/dashboard_sim/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/dashboard_sim/ios/Runner.xcodeproj/project.pbxproj b/dashboard_sim/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b361581 --- /dev/null +++ b/dashboard_sim/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,616 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/dashboard_sim/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/dashboard_sim/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/dashboard_sim/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..8e3ca5d --- /dev/null +++ b/dashboard_sim/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard_sim/ios/Runner.xcworkspace/contents.xcworkspacedata b/dashboard_sim/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/dashboard_sim/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/dashboard_sim/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dashboard_sim/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/dashboard_sim/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dashboard_sim/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/dashboard_sim/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/dashboard_sim/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/dashboard_sim/ios/Runner/AppDelegate.swift b/dashboard_sim/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/dashboard_sim/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..6ed2d93 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cd7b00 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..fe73094 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..502f463 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..e9f5fea Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..0467bf1 Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/dashboard_sim/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/dashboard_sim/ios/Runner/Base.lproj/LaunchScreen.storyboard b/dashboard_sim/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/dashboard_sim/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard_sim/ios/Runner/Base.lproj/Main.storyboard b/dashboard_sim/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/dashboard_sim/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard_sim/ios/Runner/Info.plist b/dashboard_sim/ios/Runner/Info.plist new file mode 100644 index 0000000..397eb2d --- /dev/null +++ b/dashboard_sim/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Drawer + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + drawer + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/dashboard_sim/ios/Runner/Runner-Bridging-Header.h b/dashboard_sim/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/dashboard_sim/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/dashboard_sim/ios/RunnerTests/RunnerTests.swift b/dashboard_sim/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/dashboard_sim/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/dashboard_sim/lib/constants/constants.dart b/dashboard_sim/lib/constants/constants.dart new file mode 100644 index 0000000..d38f7a3 --- /dev/null +++ b/dashboard_sim/lib/constants/constants.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +const primaryColor = Color(0xFF2697FF); +const secondaryColor = Color(0xFF2A2D3E); +const bgColor = Color(0xFF212332); + +const defaultPadding = 16.0; diff --git a/dashboard_sim/lib/constants/responsive.dart b/dashboard_sim/lib/constants/responsive.dart new file mode 100644 index 0000000..bb50df7 --- /dev/null +++ b/dashboard_sim/lib/constants/responsive.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; + +class Responsive extends StatelessWidget { + final Widget mobile; + final Widget? tablet; + final Widget desktop; + + const Responsive({ + Key? key, + required this.mobile, + this.tablet, + required this.desktop, + }) : super(key: key); + +// This size work fine on my design, maybe you need some customization depends on your design + + // This isMobile, isTablet, isDesktop help us later + static bool isMobile(BuildContext context) => + MediaQuery.of(context).size.width < 850; + + static bool isTablet(BuildContext context) => + MediaQuery.of(context).size.width < 1100 && + MediaQuery.of(context).size.width >= 850; + + static bool isDesktop(BuildContext context) => + MediaQuery.of(context).size.width >= 1100; + + @override + Widget build(BuildContext context) { + final Size _size = MediaQuery.of(context).size; + // If our width is more than 1100 then we consider it a desktop + if (_size.width >= 1100) { + return desktop; + } + // If width it less then 1100 and more then 850 we consider it as tablet + else if (_size.width >= 850 && tablet != null) { + return tablet!; + } + // Or less then that we called it mobile + else { + return mobile; + } + } +} diff --git a/dashboard_sim/lib/controller/MenuAppController.dart b/dashboard_sim/lib/controller/MenuAppController.dart new file mode 100644 index 0000000..ec77bb8 --- /dev/null +++ b/dashboard_sim/lib/controller/MenuAppController.dart @@ -0,0 +1,38 @@ +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/model/user.dart'; +import 'package:flutter/material.dart'; + +class MenuAppController extends ChangeNotifier { + final GlobalKey _scaffoldKey = GlobalKey(); + + String selectedItem = 'dashboard'; + String? selectedItemId; + Proyek? proyek; + User? user; + TaskProyek? task; + bool? isUpdateItem; + + GlobalKey get scaffoldKey => _scaffoldKey; + + void controlMenu() { + if (!_scaffoldKey.currentState!.isDrawerOpen) { + _scaffoldKey.currentState!.openDrawer(); + } + } + + void setSelectedItem(String item, + {String? id, + bool? isUpdate, + Proyek? proyeks, + User? users, + TaskProyek? tasks}) { + selectedItem = item; + selectedItemId = id; + isUpdateItem = isUpdate; + proyek = proyeks; + user = users; + task = tasks; + notifyListeners(); + } +} diff --git a/dashboard_sim/lib/data/model/penerima_proyek.dart b/dashboard_sim/lib/data/model/penerima_proyek.dart new file mode 100644 index 0000000..0ca72c3 --- /dev/null +++ b/dashboard_sim/lib/data/model/penerima_proyek.dart @@ -0,0 +1,43 @@ +import 'package:drawer/data/model/user.dart'; + +class PenerimaProyek { + int? id; + int? userId; + int? taskProyekId; + String? createdAt; + String? updatedAt; + User? user; + + PenerimaProyek({ + this.id, + this.userId, + this.taskProyekId, + this.createdAt, + this.updatedAt, + this.user, + }); + + factory PenerimaProyek.fromJson(Map json) { + return PenerimaProyek( + id: json['id'], + userId: json['user_id'], + taskProyekId: json['task_proyek_id'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + user: json['user'] != null ? User.fromJson(json['user']) : null, + ); + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['user_id'] = userId; + data['task_proyek_id'] = taskProyekId; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + if (user != null) { + data['user'] = user!.toJson(); + } + return data; + } +} diff --git a/dashboard_sim/lib/data/model/proyek-data.dart b/dashboard_sim/lib/data/model/proyek-data.dart new file mode 100644 index 0000000..a3ea175 --- /dev/null +++ b/dashboard_sim/lib/data/model/proyek-data.dart @@ -0,0 +1,13 @@ +class ProjectData { + final String projectName; + final int value; + + ProjectData({required this.projectName, required this.value}); + + factory ProjectData.fromJson(Map json) { + return ProjectData( + projectName: json['projectName'], + value: json['value'], + ); + } +} diff --git a/dashboard_sim/lib/data/model/proyek.dart b/dashboard_sim/lib/data/model/proyek.dart new file mode 100644 index 0000000..c9082ba --- /dev/null +++ b/dashboard_sim/lib/data/model/proyek.dart @@ -0,0 +1,83 @@ +import 'package:drawer/data/model/user.dart'; + +import 'task_proyek.dart'; + +class Proyek { + int? id; + int? userId; + String? nama; + String? detail; + String? manager; + String? file; + String? start; + String? finish; + int? nilai; + String? klien; + String? createdAt; + String? updatedAt; + User? user; + List? taskProyek; + + Proyek({ + this.id, + this.userId, + this.nama, + this.detail, + this.manager, + this.file, + this.start, + this.finish, + this.nilai, + this.klien, + this.createdAt, + this.updatedAt, + this.user, + this.taskProyek, + }); + + factory Proyek.fromJson(Map json) { + return Proyek( + id: json['id'], + userId: json['user_id'], + nama: json['nama'], + detail: json['detail'], + manager: json['manager'], + file: json['file'], + start: json['start'], + finish: json['finish'], + nilai: json['nilai'], + klien: json['klien'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + user: json['user'] != null ? User.fromJson(json['user']) : null, + taskProyek: json['task_proyek'] != null + ? (json['task_proyek'] as List) + .map((v) => TaskProyek.fromJson(v)) + .toList() + : [], + ); + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['user_id'] = userId; + data['nama'] = nama; + data['detail'] = detail; + data['manager'] = manager; + data['file'] = file; + data['start'] = start; + data['finish'] = finish; + data['nilai'] = nilai; + data['klien'] = klien; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + if (user != null) { + data['user'] = user!.toJson(); + } + if (taskProyek != null) { + data['task_proyek'] = taskProyek!.map((v) => v.toJson()).toList(); + } + return data; + } +} diff --git a/dashboard_sim/lib/data/model/role.dart b/dashboard_sim/lib/data/model/role.dart new file mode 100644 index 0000000..1cbcaf6 --- /dev/null +++ b/dashboard_sim/lib/data/model/role.dart @@ -0,0 +1,31 @@ +class Role { + int id; + String name; + DateTime createdAt; + DateTime updatedAt; + + Role({ + required this.id, + required this.name, + required this.createdAt, + required this.updatedAt, + }); + + factory Role.fromJson(Map json) { + return Role( + id: json['id'], + name: json['name'], + createdAt: DateTime.parse(json['created_at']), + updatedAt: DateTime.parse(json['updated_at']), + ); + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['name'] = name; + data['created_at'] = createdAt.toIso8601String(); + data['updated_at'] = updatedAt.toIso8601String(); + return data; + } +} diff --git a/dashboard_sim/lib/data/model/task_proyek.dart b/dashboard_sim/lib/data/model/task_proyek.dart new file mode 100644 index 0000000..037af63 --- /dev/null +++ b/dashboard_sim/lib/data/model/task_proyek.dart @@ -0,0 +1,86 @@ +import 'package:drawer/data/model/penerima_proyek.dart'; +import 'package:drawer/data/model/user.dart'; + +class TaskProyek { + int? id; + int? proyekId; + int? userId; + int? penerimaProyekId; + String? tugas; + String? catatan; + String? pekerja; + String? start; + String? deadline; + String? status; + int? nilai; + String? createdAt; + String? updatedAt; + User? user; + List? penerimaProyek; + + TaskProyek({ + this.id, + this.proyekId, + this.userId, + this.penerimaProyekId, + this.tugas, + this.catatan, + this.pekerja, + this.start, + this.deadline, + this.status, + this.nilai, + this.createdAt, + this.updatedAt, + this.user, + this.penerimaProyek, + }); + + factory TaskProyek.fromJson(Map json) { + return TaskProyek( + id: json['id'], + proyekId: json['proyek_id'], + userId: json['user_id'], + penerimaProyekId: json['penerimaProyek_id'], + tugas: json['tugas'], + catatan: json['catatan'], + pekerja: json['pekerja'], + start: json['start'], + deadline: json['deadline'], + status: json['status'], + nilai: json['nilai'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + user: json['user'] != null ? User.fromJson(json['user']) : null, + penerimaProyek: json['penerima_proyek'] != null + ? (json['penerima_proyek'] as List) + .map((v) => PenerimaProyek.fromJson(v)) + .toList() + : [], + ); + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['proyek_id'] = proyekId; + data['user_id'] = userId; + data['penerimaProyek_id'] = penerimaProyekId; + data['tugas'] = tugas; + data['catatan'] = catatan; + data['pekerja'] = pekerja; + data['start'] = start; + data['deadline'] = deadline; + data['status'] = status; + data['nilai'] = nilai; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + if (user != null) { + data['user'] = user!.toJson(); + } + if (penerimaProyek != null) { + data['penerima_proyek'] = penerimaProyek!.map((v) => v.toJson()).toList(); + } + return data; + } +} diff --git a/dashboard_sim/lib/data/model/user.dart b/dashboard_sim/lib/data/model/user.dart new file mode 100644 index 0000000..0606681 --- /dev/null +++ b/dashboard_sim/lib/data/model/user.dart @@ -0,0 +1,81 @@ +import 'package:drawer/data/model/role.dart'; + +class User { + final int? id; + final String? name; + final String? nip; + final String? email; + final DateTime? emailVerifiedAt; + final String? username; + final String? jenisKelamin; + final DateTime? tanggalLahir; + final String? noTelp; + final String? alamat; + final DateTime? createdAt; + final DateTime? updatedAt; + final int? roleId; + final String? fotoProfile; + final Role? role; + + User({ + this.id, + this.name, + this.nip, + this.email, + this.emailVerifiedAt, + this.username, + this.jenisKelamin, + this.tanggalLahir, + this.noTelp, + this.alamat, + this.createdAt, + this.updatedAt, + this.roleId, + this.fotoProfile, + this.role, + }); + + factory User.fromJson(Map json) { + return User( + id: json['id'], + name: json['name'], + nip: json['nip'], + email: json['email'], + emailVerifiedAt: json['email_verified_at'] != null + ? DateTime.parse(json['email_verified_at']) + : null, + username: json['username'], + jenisKelamin: json['jenis_kelamin'], + tanggalLahir: DateTime.parse(json['tanggal_lahir']), + noTelp: json['no_telp'], + alamat: json['alamat'], + createdAt: DateTime.parse(json['created_at']), + updatedAt: DateTime.parse(json['updated_at']), + roleId: json['role_id'], + fotoProfile: json['foto_profile'], + role: json['role'] != null ? Role.fromJson(json['role']) : null, + ); + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['name'] = name; + data['nip'] = nip; + data['email'] = email; + data['email_verified_at'] = emailVerifiedAt?.toIso8601String(); + data['username'] = username; + data['jenis_kelamin'] = jenisKelamin; + data['tanggal_lahir'] = tanggalLahir?.toIso8601String(); + data['no_telp'] = noTelp; + data['alamat'] = alamat; + data['created_at'] = createdAt?.toIso8601String(); + data['updated_at'] = updatedAt?.toIso8601String(); + data['role_id'] = roleId; + data['foto_profile'] = fotoProfile; + if (role != null) { + data['role'] = role!.toJson(); + } + return data; + } +} diff --git a/dashboard_sim/lib/data/services/api/api_services.dart b/dashboard_sim/lib/data/services/api/api_services.dart new file mode 100644 index 0000000..463a0c8 --- /dev/null +++ b/dashboard_sim/lib/data/services/api/api_services.dart @@ -0,0 +1,7 @@ +class ApiServices { + static String url = "192.168.165.47"; + static const int port = 8000; + + static String get baseUrl => "http://$url:$port/api"; + static String get imageUrl => "http://$url:$port/foto/"; +} diff --git a/dashboard_sim/lib/data/services/auth/auth_bloc.dart b/dashboard_sim/lib/data/services/auth/auth_bloc.dart new file mode 100644 index 0000000..b4f02bf --- /dev/null +++ b/dashboard_sim/lib/data/services/auth/auth_bloc.dart @@ -0,0 +1,70 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:drawer/data/services/auth/auth_event.dart'; +import 'package:drawer/data/services/auth/auth_state.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:drawer/data/services/api/api_services.dart'; + +class AuthenticationBloc + extends Bloc { + AuthenticationBloc() : super(AuthenticationInitial()) { + on(_onLoginButtonPressed); + } + + Future _onLoginButtonPressed( + LoginButtonPressed event, + Emitter emit, + ) async { + emit(AuthenticationLoading()); + try { + final response = await http.post( + Uri.parse('${ApiServices.baseUrl}/login'), + body: jsonEncode({ + 'email': event.email, + 'password': event.password, + }), + headers: {'Content-Type': 'application/json'}, + ); + + if (response.statusCode == 200) { + final jsonResponse = jsonDecode(response.body); + final token = jsonResponse['token']; + final roleId = jsonResponse['data']['role_id']; + final nama = jsonResponse['data']['name']; + + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('token', token); + await prefs.setInt('role_id', roleId); + await prefs.setString('name', nama); + + print("token : $token"); + print("role : $roleId"); + + Fluttertoast.showToast( + msg: "Login successful", + toastLength: Toast.LENGTH_SHORT, + ); + emit(AuthenticationSuccess()); + } else { + final jsonResponse = jsonDecode(response.body); + final error = jsonResponse['message']; + + Fluttertoast.showToast( + msg: error, + toastLength: Toast.LENGTH_SHORT, + ); + + emit(AuthenticationFailure(error: error)); + } + } catch (error) { + Fluttertoast.showToast( + msg: error.toString(), + toastLength: Toast.LENGTH_SHORT, + ); + + emit(AuthenticationFailure(error: error.toString())); + } + } +} diff --git a/dashboard_sim/lib/data/services/auth/auth_event.dart b/dashboard_sim/lib/data/services/auth/auth_event.dart new file mode 100644 index 0000000..9c5a74a --- /dev/null +++ b/dashboard_sim/lib/data/services/auth/auth_event.dart @@ -0,0 +1,21 @@ +import 'package:equatable/equatable.dart'; + +abstract class AuthenticationEvent extends Equatable { + const AuthenticationEvent(); + + @override + List get props => []; +} + +class LoginButtonPressed extends AuthenticationEvent { + final String email; + final String password; + + const LoginButtonPressed({ + required this.email, + required this.password, + }); + + @override + List get props => [email, password]; +} diff --git a/dashboard_sim/lib/data/services/auth/auth_state.dart b/dashboard_sim/lib/data/services/auth/auth_state.dart new file mode 100644 index 0000000..49d7a95 --- /dev/null +++ b/dashboard_sim/lib/data/services/auth/auth_state.dart @@ -0,0 +1,23 @@ +import 'package:equatable/equatable.dart'; + +abstract class AuthenticationState extends Equatable { + const AuthenticationState(); + + @override + List get props => []; +} + +class AuthenticationInitial extends AuthenticationState {} + +class AuthenticationLoading extends AuthenticationState {} + +class AuthenticationSuccess extends AuthenticationState {} + +class AuthenticationFailure extends AuthenticationState { + final String error; + + const AuthenticationFailure({required this.error}); + + @override + List get props => [error]; +} diff --git a/dashboard_sim/lib/data/services/proyek/proyek_bloc.dart b/dashboard_sim/lib/data/services/proyek/proyek_bloc.dart new file mode 100644 index 0000000..e4422c1 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/proyek_bloc.dart @@ -0,0 +1,102 @@ +import 'package:bloc/bloc.dart'; +import 'package:drawer/data/model/proyek-data.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:meta/meta.dart'; + +part 'proyek_event.dart'; +part 'proyek_state.dart'; + +class ProyekBloc extends Bloc { + final ProyekServices proyekServices; + + ProyekBloc({required this.proyekServices}) : super(ProyekInitial()) { + on((event, emit) async { + emit(ProyekLoading()); + try { + final res = await proyekServices.getProyek(); + emit(ProyekLoaded(res)); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProyekLoading()); + try { + final res = await proyekServices.getRecentProyek(); + emit(ProyekLoaded(res)); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProyekLoading()); + try { + final user = await proyekServices.getProyekById(event.userId); + emit(ProyekByIdLoaded(user)); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProyekStoring()); + try { + final Map proyekData = event.proyekData + .map((key, value) => MapEntry(key, value.toString())); + await proyekServices.storeProyek(proyekData); + emit(ProyekStored()); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProyekLoading()); + try { + final Map proyekData = event.proyekData + .map((key, value) => MapEntry(key, value.toString())); + await proyekServices.updateProyekById(event.userId, proyekData); + final updatedUser = await proyekServices.getProyekById(event.userId); + emit(ProyekUpdated(updatedUser)); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProyekLoading()); + try { + await proyekServices.deleteProyekById(event.proyekId); + emit(ProyekDeleted()); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProyekCountsLoading()); + try { + final counts = await proyekServices.getCountProyek(); + emit(ProyekCountsLoaded( + totalProyekSelesai: counts['totalProyekSelesai']!, + onProgress: counts['onProgress']!, + )); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + + on((event, emit) async { + emit(ProjectDataLoading()); + try { + final projects = await proyekServices.getProjectData(); + emit(ProjectDataLoaded(projects: projects)); + } catch (e) { + emit(ProyekError(e.toString())); + } + }); + } +} diff --git a/dashboard_sim/lib/data/services/proyek/proyek_event.dart b/dashboard_sim/lib/data/services/proyek/proyek_event.dart new file mode 100644 index 0000000..51e3e65 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/proyek_event.dart @@ -0,0 +1,40 @@ +part of 'proyek_bloc.dart'; + +@immutable +sealed class ProyekEvent {} + +class LoadProyek extends ProyekEvent {} + +class LoadRecentProyek extends ProyekEvent {} + +class GetProyekById extends ProyekEvent { + final String userId; + + GetProyekById({required this.userId}); +} + +class StoreProyek extends ProyekEvent { + final Map proyekData; + + StoreProyek({required this.proyekData}); +} + +class UpdateProyekById extends ProyekEvent { + final Map proyekData; + final String userId; + + UpdateProyekById({ + required this.userId, + required this.proyekData, + }); +} + +class DeleteProyekById extends ProyekEvent { + final String proyekId; + + DeleteProyekById({required this.proyekId}); +} + +class GetProyekCounts extends ProyekEvent {} + +class GetProjectData extends ProyekEvent {} diff --git a/dashboard_sim/lib/data/services/proyek/proyek_service.dart b/dashboard_sim/lib/data/services/proyek/proyek_service.dart new file mode 100644 index 0000000..9b43550 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/proyek_service.dart @@ -0,0 +1,250 @@ +import 'dart:convert'; + +import 'package:drawer/data/model/proyek-data.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/data/services/api/api_services.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; + +class ProyekServices { + Future> getProyek() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + print(token); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/proyeks'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + final data = jsonDecode(response.body); + print(data); + if (response.statusCode == 200) { + final List responseData = jsonDecode(response.body)['proyek']; + print(responseData); + return responseData.map((json) => Proyek.fromJson(json)).toList(); + } else { + throw Exception('Failed to load users: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load users: $e'); + } + } + + Future> getRecentProyek() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + print(token); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/recent'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + final data = jsonDecode(response.body); + print(data); + if (response.statusCode == 200) { + final List responseData = jsonDecode(response.body)['proyek']; + print(responseData); + return responseData.map((json) => Proyek.fromJson(json)).toList(); + } else { + throw Exception('Failed to load users: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load users: $e'); + } + } + + Future getProyekById(String userId) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/proyeks/$userId'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + final responseData = jsonDecode(response.body)['proyek']; + print(responseData); + return Proyek.fromJson(responseData); + } else { + print('Failed to load proyek: ${response.statusCode}'); + throw Exception('Failed to load proyek: ${response.statusCode}'); + } + } catch (e) { + print('Failed to load proyek: $e'); + throw Exception('Failed to load proyek: $e'); + } + } + + Future storeProyek(Map proyekData) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.post( + Uri.parse('${ApiServices.baseUrl}/proyeks'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode(proyekData), + ); + + if (response.statusCode != 201) { + final data = jsonDecode(response.body); + throw Exception( + 'Failed to store user: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to store user: $e'); + } + } + + Future updateProyekById( + String proyekId, Map proyekData) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final url = Uri.parse('${ApiServices.baseUrl}/proyeks-update/$proyekId'); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + final body = jsonEncode(proyekData); + + final response = await http.post( + url, + headers: headers, + body: body, + ); + + if (response.statusCode != 200) { + final data = jsonDecode(response.body); + print( + 'Failed to update proyek: ${data['message'] ?? response.statusCode}'); + throw Exception( + 'Failed to update proyek: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + print('Failed to update proyek: $e'); + throw Exception('Failed to update proyek: $e'); + } + } + + Future deleteProyekById(String proyekId) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final url = Uri.parse('${ApiServices.baseUrl}/proyeks-delete/$proyekId'); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + + final response = await http.post( + url, + headers: headers, + ); + + if (response.statusCode != 200) { + final data = jsonDecode(response.body); + print( + 'Failed to delete proyek: ${data['message'] ?? response.statusCode}'); + throw Exception( + 'Failed to delete proyek: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + print('Failed to delete proyek: $e'); + throw Exception('Failed to delete proyek: $e'); + } + } + + Future> getCountProyek() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/proyeks-count'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + return { + 'totalProyekSelesai': data['totalProyekSelesai'], + 'onProgress': data['onProgress'], + }; + } else { + throw Exception('Failed to load proyek counts: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load proyek counts: $e'); + } + } + + Future> getProjectData() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/proyeks-chart'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + final List data = jsonDecode(response.body); + return data.map((json) => ProjectData.fromJson(json)).toList(); + } else { + throw Exception('Failed to load project data: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load project data: $e'); + } + } +} diff --git a/dashboard_sim/lib/data/services/proyek/proyek_state.dart b/dashboard_sim/lib/data/services/proyek/proyek_state.dart new file mode 100644 index 0000000..80ff07d --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/proyek_state.dart @@ -0,0 +1,54 @@ +part of 'proyek_bloc.dart'; + +@immutable +sealed class ProyekState {} + +final class ProyekInitial extends ProyekState {} + +class ProyekLoading extends ProyekState {} + +class ProyekLoaded extends ProyekState { + final List proyeks; + ProyekLoaded(this.proyeks); +} + +class ProyekError extends ProyekState { + final String error; + ProyekError(this.error); +} + +class ProyekByIdLoaded extends ProyekState { + final Proyek proyek; + final bool loadedById; + ProyekByIdLoaded(this.proyek, {this.loadedById = true}); +} + +class ProyekStoring extends ProyekState {} + +class ProyekStored extends ProyekState {} + +class ProyekUpdated extends ProyekState { + final Proyek proyek; + + ProyekUpdated(this.proyek); +} + +class ProyekDeleted extends ProyekState {} + +class ProyekCountsLoading extends ProyekState {} + +class ProyekCountsLoaded extends ProyekState { + final int totalProyekSelesai; + final int onProgress; + + ProyekCountsLoaded( + {required this.totalProyekSelesai, required this.onProgress}); +} + +class ProjectDataLoading extends ProyekState {} + +class ProjectDataLoaded extends ProyekState { + final List projects; + + ProjectDataLoaded({required this.projects}); +} diff --git a/dashboard_sim/lib/data/services/proyek/task/task_bloc.dart b/dashboard_sim/lib/data/services/proyek/task/task_bloc.dart new file mode 100644 index 0000000..60012f8 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/task/task_bloc.dart @@ -0,0 +1,59 @@ +import 'package:bloc/bloc.dart'; +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/services/proyek/task/task_service.dart'; +import 'package:meta/meta.dart'; + +part 'task_event.dart'; +part 'task_state.dart'; + +class TaskBloc extends Bloc { + final TaskService taskService; + + TaskBloc({required this.taskService}) : super(TaskInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + on((event, emit) async { + emit(TaskLoading()); + try { + final user = await taskService.getTaskById(event.taskId); + emit(TaskByIdLoaded(user)); + } catch (e) { + emit(TaskError(e.toString())); + } + }); + on((event, emit) async { + emit(TaskStoring()); + try { + final Map taskData = + event.taskData.map((key, value) => MapEntry(key, value.toString())); + await taskService.storeTask(taskData); + emit(TaskStored()); + } catch (e) { + emit(TaskError(e.toString())); + } + }); + + on((event, emit) async { + emit(TaskLoading()); + try { + final Map proyekData = event.proyekData + .map((key, value) => MapEntry(key, value.toString())); + await taskService.updateTaskById(event.proyekId, proyekData); + emit(TaskUpdated()); + } catch (e) { + emit(TaskError(e.toString())); + } + }); + + on((event, emit) async { + emit(TaskLoading()); + try { + await taskService.deleteTasksById(event.proyekId); + emit(TaskDeleted()); + } catch (e) { + emit(TaskError(e.toString())); + } + }); + } +} diff --git a/dashboard_sim/lib/data/services/proyek/task/task_event.dart b/dashboard_sim/lib/data/services/proyek/task/task_event.dart new file mode 100644 index 0000000..8cb2612 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/task/task_event.dart @@ -0,0 +1,34 @@ +part of 'task_bloc.dart'; + +@immutable +sealed class TaskEvent {} + +class LoadTask extends TaskEvent {} + +class GetTaskById extends TaskEvent { + final String taskId; + + GetTaskById({required this.taskId}); +} + +class StoreTask extends TaskEvent { + final Map taskData; + + StoreTask({required this.taskData}); +} + +class UpdateTaskById extends TaskEvent { + final Map proyekData; + final String proyekId; + + UpdateTaskById({ + required this.proyekId, + required this.proyekData, + }); +} + +class DeleteTaskById extends TaskEvent { + final String proyekId; + + DeleteTaskById({required this.proyekId}); +} diff --git a/dashboard_sim/lib/data/services/proyek/task/task_service.dart b/dashboard_sim/lib/data/services/proyek/task/task_service.dart new file mode 100644 index 0000000..97db416 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/task/task_service.dart @@ -0,0 +1,132 @@ +import 'dart:convert'; + +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/services/api/api_services.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; + +class TaskService { + Future storeTask(Map taskData) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.post( + Uri.parse('${ApiServices.baseUrl}/tasks'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode(taskData), + ); + + if (response.statusCode != 201) { + final data = jsonDecode(response.body); + throw Exception( + 'Failed to store user: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to store user: $e'); + } + } + + Future updateTaskById( + String proyekId, Map proyekData) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final url = Uri.parse('${ApiServices.baseUrl}/tasks-update/$proyekId'); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + final body = jsonEncode(proyekData); + + final response = await http.post( + url, + headers: headers, + body: body, + ); + + if (response.statusCode != 200) { + final data = jsonDecode(response.body); + print( + 'Failed to update proyek: ${data['message'] ?? response.statusCode}'); + throw Exception( + 'Failed to update proyek: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + print('Failed to update proyek: $e'); + throw Exception('Failed to update proyek: $e'); + } + } + + Future deleteTasksById(String proyekId) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final url = Uri.parse('${ApiServices.baseUrl}/tasks-delete/$proyekId'); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + + final response = await http.post( + url, + headers: headers, + ); + + if (response.statusCode != 200) { + final data = jsonDecode(response.body); + print( + 'Failed to delete proyek: ${data['message'] ?? response.statusCode}'); + throw Exception( + 'Failed to delete proyek: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + print('Failed to delete proyek: $e'); + throw Exception('Failed to delete proyek: $e'); + } + } + + Future getTaskById(String taskId) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/tasks/$taskId'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + final responseData = jsonDecode(response.body)['task']; + print(responseData); + return TaskProyek.fromJson(responseData); + } else { + print('Failed to load proyek: ${response.statusCode}'); + throw Exception('Failed to load proyek: ${response.statusCode}'); + } + } catch (e) { + print('Failed to load proyek: $e'); + throw Exception('Failed to load proyek: $e'); + } + } +} diff --git a/dashboard_sim/lib/data/services/proyek/task/task_state.dart b/dashboard_sim/lib/data/services/proyek/task/task_state.dart new file mode 100644 index 0000000..5d05417 --- /dev/null +++ b/dashboard_sim/lib/data/services/proyek/task/task_state.dart @@ -0,0 +1,27 @@ +part of 'task_bloc.dart'; + +@immutable +sealed class TaskState {} + +final class TaskInitial extends TaskState {} + +class TaskLoading extends TaskState {} + +class TaskStoring extends TaskState {} + +class TaskStored extends TaskState {} + +class TaskError extends TaskState { + final String error; + TaskError(this.error); +} + +class TaskUpdated extends TaskState {} + +class TaskDeleted extends TaskState {} + +class TaskByIdLoaded extends TaskState { + final TaskProyek task; + final bool loadedById; + TaskByIdLoaded(this.task, {this.loadedById = true}); +} diff --git a/dashboard_sim/lib/data/services/roles/role_bloc.dart b/dashboard_sim/lib/data/services/roles/role_bloc.dart new file mode 100644 index 0000000..28acaee --- /dev/null +++ b/dashboard_sim/lib/data/services/roles/role_bloc.dart @@ -0,0 +1,24 @@ +import 'package:drawer/data/model/role.dart'; +import 'package:drawer/data/model/user.dart'; +import 'package:drawer/data/services/roles/role_services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'role_event.dart'; +part 'role_state.dart'; + +class RoleBloc extends Bloc { + final RoleServices roleServices; + + RoleBloc({required this.roleServices}) : super(RoleInitial()) { + on((event, emit) async { + emit(RoleLoading()); + try { + final result = await roleServices.getRoles(); + emit(RoleLoaded(result)); + } catch (e) { + emit(RoleError(e.toString())); + } + }); + } +} diff --git a/dashboard_sim/lib/data/services/roles/role_event.dart b/dashboard_sim/lib/data/services/roles/role_event.dart new file mode 100644 index 0000000..48f533e --- /dev/null +++ b/dashboard_sim/lib/data/services/roles/role_event.dart @@ -0,0 +1,6 @@ +part of 'role_bloc.dart'; + +@immutable +sealed class RoleEvent {} + +class LoadRole extends RoleEvent {} diff --git a/dashboard_sim/lib/data/services/roles/role_services.dart b/dashboard_sim/lib/data/services/roles/role_services.dart new file mode 100644 index 0000000..4612e90 --- /dev/null +++ b/dashboard_sim/lib/data/services/roles/role_services.dart @@ -0,0 +1,37 @@ +import 'package:drawer/data/model/role.dart'; +import 'package:drawer/data/services/api/api_services.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +class RoleServices { + Future> getRoles() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + print(token); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/roles'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + final data = jsonDecode(response.body); + print(data); + if (response.statusCode == 200) { + final List responseData = jsonDecode(response.body)['roles']; + print(responseData); + return responseData.map((json) => Role.fromJson(json)).toList(); + } else { + throw Exception('Failed to load users: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load users: $e'); + } + } +} diff --git a/dashboard_sim/lib/data/services/roles/role_state.dart b/dashboard_sim/lib/data/services/roles/role_state.dart new file mode 100644 index 0000000..04c07bd --- /dev/null +++ b/dashboard_sim/lib/data/services/roles/role_state.dart @@ -0,0 +1,18 @@ +part of 'role_bloc.dart'; + +@immutable +sealed class RoleState {} + +final class RoleInitial extends RoleState {} + +final class RoleLoading extends RoleState {} + +final class RoleLoaded extends RoleState { + final List roles; + RoleLoaded(this.roles); +} + +final class RoleError extends RoleState { + final String error; + RoleError(this.error); +} diff --git a/dashboard_sim/lib/data/services/users/user_services.dart b/dashboard_sim/lib/data/services/users/user_services.dart new file mode 100644 index 0000000..52f5d1e --- /dev/null +++ b/dashboard_sim/lib/data/services/users/user_services.dart @@ -0,0 +1,197 @@ +import 'package:drawer/data/model/user.dart'; +import 'package:drawer/data/services/api/api_services.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +import 'package:shared_preferences/shared_preferences.dart'; + +class UserService { + Future> getUsers() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + print(token); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/users'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + final data = jsonDecode(response.body); + print(data); + if (response.statusCode == 200) { + final List responseData = jsonDecode(response.body)['users']; + print(responseData); + return responseData.map((json) => User.fromJson(json)).toList(); + } else { + throw Exception('Failed to load users: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load users: $e'); + } + } + + Future> getUsersManager() async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + print(token); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/users-manager'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + final data = jsonDecode(response.body); + print(data); + if (response.statusCode == 200) { + final List responseData = jsonDecode(response.body)['users']; + print(responseData); + return responseData.map((json) => User.fromJson(json)).toList(); + } else { + throw Exception('Failed to load users: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load users: $e'); + } + } + + Future storeUser(Map userData) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.post( + Uri.parse('${ApiServices.baseUrl}/users'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode(userData), + ); + + if (response.statusCode != 201) { + final data = jsonDecode(response.body); + throw Exception( + 'Failed to store user: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to store user: $e'); + } + } + + Future getUserById(String userId) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final response = await http.get( + Uri.parse('${ApiServices.baseUrl}/users/$userId'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + + if (response.statusCode == 200) { + final responseData = jsonDecode(response.body)['user']; + print(responseData); + return User.fromJson(responseData); + } else { + throw Exception('Failed to load user: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load user: $e'); + } + } + + Future updateUserById( + String userId, Map userData) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final url = Uri.parse('${ApiServices.baseUrl}/users-update/$userId'); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + final body = jsonEncode(userData); + + print('URL: $url'); + print('Headers: $headers'); + print('Body: $body'); + + final response = await http.post( + url, + headers: headers, + body: body, + ); + + print('Response status: ${response.statusCode}'); + print('Response body: ${response.body}'); + + if (response.statusCode != 200) { + final data = jsonDecode(response.body); + print( + 'Failed to update user: ${data['message'] ?? response.statusCode}'); + throw Exception( + 'Failed to update user: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + print('Failed to update user: $e'); + throw Exception('Failed to update user: $e'); + } + } + + Future deleteUserById(String userId) async { + final prefs = await SharedPreferences.getInstance(); + final token = prefs.getString('token'); + if (token == null) { + throw Exception('Token not found in SharedPreferences'); + } + + try { + final url = Uri.parse('${ApiServices.baseUrl}/users-delete/$userId'); + final headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + + final response = await http.post( + url, + headers: headers, + ); + + if (response.statusCode != 200) { + final data = jsonDecode(response.body); + print( + 'Failed to delete proyek: ${data['message'] ?? response.statusCode}'); + throw Exception( + 'Failed to delete proyek: ${data['message'] ?? response.statusCode}'); + } + } catch (e) { + print('Failed to delete proyek: $e'); + throw Exception('Failed to delete proyek: $e'); + } + } +} diff --git a/dashboard_sim/lib/data/services/users/users_bloc.dart b/dashboard_sim/lib/data/services/users/users_bloc.dart new file mode 100644 index 0000000..c68e696 --- /dev/null +++ b/dashboard_sim/lib/data/services/users/users_bloc.dart @@ -0,0 +1,78 @@ +import 'package:drawer/data/model/user.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'users_event.dart'; +part 'users_state.dart'; + +class UsersBloc extends Bloc { + final UserService userService; + + UsersBloc({required this.userService}) : super(UsersInitial()) { + on((event, emit) async { + emit(UsersLoading()); + try { + final result = await userService.getUsers(); + emit(UsersLoaded(result)); + } catch (e) { + emit(UsersError(e.toString())); + } + }); + + on((event, emit) async { + emit(UsersLoading()); + try { + final result = await userService.getUsersManager(); + emit(UsersLoaded(result)); + } catch (e) { + emit(UsersError(e.toString())); + } + }); + + on((event, emit) async { + emit(UsersStoring()); + try { + final Map userData = + event.userData.map((key, value) => MapEntry(key, value.toString())); + await userService.storeUser(userData); + emit(UserStored()); + } catch (e) { + emit(UsersError(e.toString())); + } + }); + + on((event, emit) async { + emit(UsersLoading()); + try { + final user = await userService.getUserById(event.userId); + emit(UserByIdLoaded(user)); + } catch (e) { + emit(UsersError(e.toString())); + } + }); + + on((event, emit) async { + emit(UsersLoading()); + try { + final Map userData = + event.userData.map((key, value) => MapEntry(key, value.toString())); + await userService.updateUserById(event.userId, userData); + final updatedUser = await userService.getUserById(event.userId); + emit(UserUpdated(updatedUser)); + } catch (e) { + emit(UsersError(e.toString())); + } + }); + + on((event, emit) async { + emit(UsersLoading()); + try { + await userService.deleteUserById(event.userId); + emit(UserDeleted()); + } catch (e) { + emit(UsersError(e.toString())); + } + }); + } +} diff --git a/dashboard_sim/lib/data/services/users/users_event.dart b/dashboard_sim/lib/data/services/users/users_event.dart new file mode 100644 index 0000000..aa1aa26 --- /dev/null +++ b/dashboard_sim/lib/data/services/users/users_event.dart @@ -0,0 +1,38 @@ +part of 'users_bloc.dart'; + +@immutable +sealed class UsersEvent {} + +class LoadUser extends UsersEvent {} + +class LoadUserManager extends UsersEvent {} + +class StoreUser extends UsersEvent { + final Map userData; + + StoreUser({required this.userData}); +} + +class GetUserById extends UsersEvent { + final String userId; + + GetUserById({required this.userId}); +} + +class UpdateUserById extends UsersEvent { + final Map userData; + final String? imagePath; + final String userId; + + UpdateUserById({ + required this.userId, + required this.userData, + this.imagePath, + }); +} + +class DeleteUserById extends UsersEvent { + final String userId; + + DeleteUserById({required this.userId}); +} diff --git a/dashboard_sim/lib/data/services/users/users_state.dart b/dashboard_sim/lib/data/services/users/users_state.dart new file mode 100644 index 0000000..c628246 --- /dev/null +++ b/dashboard_sim/lib/data/services/users/users_state.dart @@ -0,0 +1,36 @@ +part of 'users_bloc.dart'; + +@immutable +sealed class UsersState {} + +class UsersInitial extends UsersState {} + +class UsersLoading extends UsersState {} + +class UsersLoaded extends UsersState { + final List users; + UsersLoaded(this.users); +} + +class UserByIdLoaded extends UsersState { + final User user; + final bool loadedById; + UserByIdLoaded(this.user, {this.loadedById = true}); +} + +class UsersError extends UsersState { + final String error; + UsersError(this.error); +} + +class UsersStoring extends UsersState {} + +class UserStored extends UsersState {} + +class UserUpdated extends UsersState { + final User user; + + UserUpdated(this.user); +} + +class UserDeleted extends UsersState {} diff --git a/dashboard_sim/lib/main.dart b/dashboard_sim/lib/main.dart new file mode 100644 index 0000000..90e611f --- /dev/null +++ b/dashboard_sim/lib/main.dart @@ -0,0 +1,79 @@ +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/page/karyawan/karyawan.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/services/auth/auth_bloc.dart'; +import 'package:drawer/page/login/login.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:drawer/page/sidebar/main_screen.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + SharedPreferences _prefs = await SharedPreferences.getInstance(); + runApp(MyApp(prefs: _prefs)); +} + +class MyApp extends StatelessWidget { + final SharedPreferences? prefs; + + const MyApp({Key? key, this.prefs}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (context) => MenuAppController(), + ), + BlocProvider(create: (context) => AuthenticationBloc()), + BlocProvider( + create: (context) => ProyekBloc(proyekServices: ProyekServices()), + ), + // BlocProvider( + // create: (context) => UserBloc(userService: UserService()), + // ), + ], + child: MaterialApp( + debugShowCheckedModeBanner: false, + title: 'Flutter Admin Panel', + theme: ThemeData.dark().copyWith( + scaffoldBackgroundColor: bgColor, + textTheme: GoogleFonts.poppinsTextTheme(Theme.of(context).textTheme) + .apply(bodyColor: Colors.white), + canvasColor: secondaryColor, + ), + // Set initialRoute berdasarkan apakah token sudah ada + initialRoute: + prefs!.getString('token') != null ? '/dashboard' : '/login', + onGenerateRoute: (settings) { + switch (settings.name) { + case '/login': + return MaterialPageRoute(builder: (context) => Login()); + case '/dashboard': + return MaterialPageRoute(builder: (context) => MainScreen()); + case '/proyek': + return MaterialPageRoute(builder: (context) => proyek()); + case '/karyawan': + return MaterialPageRoute(builder: (context) => karyawan()); + default: + return null; + } + }, + // home: MultiProvider( + // providers: [ + // ChangeNotifierProvider( + // create: (context) => MenuAppController(), + // ), + // ], + // child: login(), + // ), + ), + ); + } +} diff --git a/dashboard_sim/lib/models/MyFiles.dart b/dashboard_sim/lib/models/MyFiles.dart new file mode 100644 index 0000000..c0c3e55 --- /dev/null +++ b/dashboard_sim/lib/models/MyFiles.dart @@ -0,0 +1,34 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:flutter/material.dart'; + +class CloudStorageInfo { + final String? svgSrc, title, totalStorage; + final int? numOfFiles; + final Color? color; + + CloudStorageInfo({ + this.svgSrc, + this.title, + this.totalStorage, + this.numOfFiles, + // this.percentage, + this.color, + }); +} + +List demoMyFiles = [ + CloudStorageInfo( + title: "Progress", + numOfFiles: 5, + svgSrc: "assets/icons/Documents.svg", + color: primaryColor, + // percentage: 35, + ), + CloudStorageInfo( + title: "Finish", + numOfFiles: 10, + svgSrc: "assets/icons/drop_box.svg", + color: primaryColor, + // percentage: 78, + ), +]; diff --git a/dashboard_sim/lib/models/data.dart b/dashboard_sim/lib/models/data.dart new file mode 100644 index 0000000..134c902 --- /dev/null +++ b/dashboard_sim/lib/models/data.dart @@ -0,0 +1,238 @@ +class RecentFile { + final String? id, title, deadline, status; + + RecentFile({this.id, this.title, this.deadline, this.status}); +} + +List demoRecentFiles = [ + RecentFile( + id: "001", + title: "XD File", + deadline: "01-03-2021", + status: "90 %", + ), + RecentFile( + id: "002", + title: "rumah sakit dara", + deadline: "01-03-2021", + status: "85 %", + ), + RecentFile( + id: "003", + title: "dinas pendidikan", + deadline: "01-03-2021", + status: "70 %", + ), + RecentFile( + id: "004", + title: "percetakan", + deadline: "01-03-2021", + status: "95 %", + ), + RecentFile( + id: "005", + title: "cafe sodagar", + deadline: "01-03-2021", + status: "30 %", + ), + RecentFile( + id: "006", + title: "perikanan", + deadline: "01-03-2021", + status: "40 %", + ), +]; + +class proyekfiledata { + final String? id, title, klien, manager, start, finish, deadline, status; + + proyekfiledata({ + this.id, + this.title, + this.klien, + this.manager, + this.start, + this.deadline, + this.finish, + this.status, + }); +} + +List demoproyekfile = [ + proyekfiledata( + id: "001", + title: "XD File", + klien: "pt.kura-kura", + manager: "jonathan", + start: "25-08-2020", + deadline: "01-03-2021", + finish: "01-03-2021", + status: "90 %", + ), + proyekfiledata( + id: "002", + title: "rumah sakit dara", + klien: "pt.kura-kura", + manager: "jonathan", + start: "25-08-2020", + deadline: "01-03-2021", + finish: "01-03-2021", + status: "85 %", + ), + proyekfiledata( + id: "003", + title: "dinas pendidikan", + klien: "pt.kura-kura", + manager: "jonathan", + start: "25-08-2020", + deadline: "01-03-2021", + finish: "01-03-2021", + status: "70 %", + ), + proyekfiledata( + id: "004", + title: "percetakan", + klien: "pt.kura-kura", + manager: "jonathan", + start: "25-08-2020", + deadline: "01-03-2021", + finish: "01-03-2021", + status: "95 %", + ), + proyekfiledata( + id: "005", + title: "cafe sodagar", + klien: "pt.kura-kura", + manager: "jonathan", + start: "25-08-2020", + deadline: "01-03-2021", + finish: "01-03-2021", + status: "30 %", + ), + proyekfiledata( + id: "006", + title: "perikanan", + klien: "pt.kura-kura", + manager: "jonathan", + start: "25-08-2020", + deadline: "01-03-2021", + finish: "01-03-2021", + status: "40 %", + ), +]; + +class karyawanfiledata { + final String? id, title, position, birth, telp, email, gender, address; + + karyawanfiledata({ + this.id, + this.title, + this.position, + this.birth, + this.telp, + this.gender, + this.email, + this.address, + }); +} + +List demokaryawanfile = [ + karyawanfiledata( + id: "001", + title: "jonathan karim", + position: "manager", + birth: "25-08-2001", + telp: "089677548892", + email: "jo@gmail.com", + gender: "laki-laki", + address: "jln. kemundung Ds.Jajar Kec. kasih Kab. Pekalongan", + ), + karyawanfiledata( + id: "002", + title: "jonathan karim", + position: "manager", + birth: "25-08-2001", + telp: "089677548892", + email: "jo@gmail.com", + gender: "laki-laki", + address: "jln. kemundung Ds.Jajar Kec. kasih Kab. Pekalongan", + ), + karyawanfiledata( + id: "003", + title: "jonathan karim", + position: "manager", + birth: "25-08-2001", + telp: "089677548892", + email: "jo@gmail.com", + gender: "laki-laki", + address: "jln. kemundung Ds.Jajar Kec. kasih Kab. Pekalongan", + ), + karyawanfiledata( + id: "004", + title: "jonathan karim", + position: "manager", + birth: "25-08-2001", + telp: "089677548892", + email: "jo@gmail.com", + gender: "laki-laki", + address: "jln. kemundung Ds.Jajar Kec. kasih Kab. Pekalongan", + ), + karyawanfiledata( + id: "005", + title: "Arinfa Triasmana", + position: "Staff", + birth: "25-08-2001", + telp: "089677548892", + email: "Artri@gmail.com", + gender: "Perempuan", + address: "jln. kemundung Ds.Jajar Kec. kasih Kab. Pekalongan", + ), +]; + +class RecentTask { + final String? tugas, catatan, pekerja, start, deadline, status; + + RecentTask({ + this.tugas, + this.catatan, + this.pekerja, + this.start, + this.deadline, + this.status, + }); +} + +List demoRecentTask = [ + RecentTask( + tugas: "front end mobile developer", + catatan: "gunakan teknologi terbaru agar memudahkan maintenance", + pekerja: "alexander", + start: "28 Oktober 2020", + deadline: "01-03-2021", + status: "90 %", + ), + RecentTask( + tugas: "front end mobile developer", + catatan: "gunakan teknologi terbaru agar memudahkan maintenance", + pekerja: "alexander", + start: "28 Oktober 2020", + deadline: "01-03-2021", + status: "90 %", + ), + RecentTask( + tugas: "front end mobile developer", + catatan: "gunakan teknologi terbaru agar memudahkan maintenance", + pekerja: "alexander", + start: "28 Oktober 2020", + deadline: "01-03-2021", + status: "90 %", + ), + RecentTask( + tugas: "front end mobile developer", + catatan: "gunakan teknologi terbaru agar memudahkan maintenance", + pekerja: "alexander", + start: "28 Oktober 2020", + deadline: "01-03-2021", + status: "90 %", + ), +]; diff --git a/dashboard_sim/lib/page/dashboard/dashboard.dart b/dashboard_sim/lib/page/dashboard/dashboard.dart new file mode 100644 index 0000000..7b284ad --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/dashboard.dart @@ -0,0 +1,61 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/page/dashboard/widget/barchartcard.dart'; +import 'package:drawer/page/dashboard/widget/cardInfo.dart'; +import 'package:drawer/page/dashboard/widget/team.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:drawer/page/dashboard/widget/recent_project.dart'; +import 'package:drawer/page/sidebar/side_menu.dart'; +import 'package:flutter/material.dart'; + +class dashboard extends StatelessWidget { + const dashboard({super.key}); + + Widget build(BuildContext context) { + return Scaffold( + drawer: SideMenu(), + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + // MyFiles(), + cardView(), + SizedBox(height: defaultPadding), + barchartcard(), + SizedBox(height: defaultPadding), + RecentProject(), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + // if (Responsive.isMobile(context)) StorageDetails(), + if (Responsive.isMobile(context)) team(), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + // On Mobile means if the screen is less than 850 we don't want to show it + if (!Responsive.isMobile(context)) + Expanded( + flex: 2, + child: team(), + ), + ], + ) + ], + ), + ), + ), + ); + } +} diff --git a/dashboard_sim/lib/page/dashboard/widget/barchart.dart b/dashboard_sim/lib/page/dashboard/widget/barchart.dart new file mode 100644 index 0000000..5c6866c --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/barchart.dart @@ -0,0 +1,314 @@ +import 'dart:ui'; + +import 'package:drawer/data/model/proyek-data.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class barchart extends StatelessWidget { + const barchart({super.key}); + + @override + Widget build(BuildContext context) { + return BarChart( + BarChartData( + borderData: FlBorderData(border: Border.all(width: 0)), + groupsSpace: 15, + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ); + Widget text; + switch (value.toInt()) { + case 2: + text = Text('jan 6', style: style); + break; + case 4: + text = Text('jan 8', style: style); + break; + case 6: + text = Text('jan 10', style: style); + break; + case 8: + text = Text('jan 12', style: style); + break; + case 10: + text = Text('jan 14', style: style); + break; + case 12: + text = Text('jan 16', style: style); + break; + case 14: + text = Text('jan 18', style: style); + break; + default: + text = Text('', style: style); + break; + } + return SideTitleWidget( + axisSide: meta.axisSide, + space: 16.0, // like margin + child: text, + ); + }, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ); + Widget text; + switch (value.toInt()) { + case 2: + text = Text('25 %', style: style); + break; + case 6: + text = Text('50 %', style: style); + break; + case 10: + text = Text('75 %', style: style); + break; + case 14: + text = Text('100 %', style: style); + break; + default: + text = Text('', style: style); + break; + } + return SideTitleWidget( + axisSide: meta.axisSide, + space: 12.0, // like margin + child: text, + ); + }, + ), + ), + ), + // bottomTitles: SideTitles( + // showTitles: true, + // getTextStyles: (BuildContext, double value) => TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.bold, + // fontSize: 12, + // ), + // margin: 16, + // getTitles: (double value) { + // if (value == 2) { + // return 'jan 6'; + // } + // if (value == 4) { + // return 'jan 8'; + // } + // if (value == 6) { + // return 'jan 10'; + // } + // if (value == 8) { + // return 'jan 12'; + // } + // if (value == 10) { + // return 'jan 14'; + // } + // if (value == 12) { + // return 'jan 16'; + // } + // if (value == 14) { + // return 'jan 18'; + // } else { + // return ''; + // } + // }), + // leftTitles: SideTitles( + // showTitles: true, + // getTextStyles: (double, value) => TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.bold, + // fontSize: 12, + // ), + // margin: 16, + // getTitles: (double value) { + // if (value == 2) { + // return '25 %'; + // } + // if (value == 6) { + // return '50 %'; + // } + // if (value == 10) { + // return '75 %'; + // } + // if (value == 14) { + // return '100 %'; + // } else { + // return ''; + // } + // }), + barGroups: [ + BarChartGroupData(x: 1, barRods: [ + BarChartRodData( + toY: 10, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 2, barRods: [ + BarChartRodData( + toY: 3, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 3, barRods: [ + BarChartRodData( + toY: 12, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 4, barRods: [ + BarChartRodData( + toY: 8, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 5, barRods: [ + BarChartRodData( + toY: 6, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 6, barRods: [ + BarChartRodData( + toY: 10, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 7, barRods: [ + BarChartRodData( + toY: 16, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 8, barRods: [ + BarChartRodData( + toY: 6, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 9, barRods: [ + BarChartRodData( + toY: 4, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 10, barRods: [ + BarChartRodData( + toY: 9, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 11, barRods: [ + BarChartRodData( + toY: 12, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 12, barRods: [ + BarChartRodData( + toY: 2, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 13, barRods: [ + BarChartRodData( + toY: 13, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + BarChartGroupData(x: 14, barRods: [ + BarChartRodData( + toY: 15, + width: 20, + color: Colors.blue, + borderRadius: BorderRadius.circular(5)) + ]), + ]), + ); + } +} + +class BarChartWidget extends StatelessWidget { + final List projects; + + BarChartWidget({required this.projects}); + + @override + Widget build(BuildContext context) { + return BarChart( + BarChartData( + borderData: FlBorderData(border: Border.all(width: 0)), + groupsSpace: 15, + // alignment: BarChartAlignment.spaceEvenly, + maxY: 100, + // barTouchData: BarTouchData(enabled: false), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ); + int index = value.toInt(); + if (index >= 0 && index < projects.length) { + return Text( + projects[index].projectName, + style: style, + ); + } + return SizedBox(); + }, + ), + ), + ), + barGroups: projects.asMap().entries.map((entry) { + int index = entry.key; + ProjectData project = entry.value; + return BarChartGroupData( + x: index, + barRods: [ + BarChartRodData( + toY: project.value.toDouble(), + color: Colors.blue, + borderRadius: BorderRadius.circular(5), + width: 20, + ), + ], + ); + }).toList(), + ), + ); + } +} diff --git a/dashboard_sim/lib/page/dashboard/widget/barchartcard.dart b/dashboard_sim/lib/page/dashboard/widget/barchartcard.dart new file mode 100644 index 0000000..ee875af --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/barchartcard.dart @@ -0,0 +1,53 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/page/dashboard/widget/barchart.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class barchartcard extends StatelessWidget { + const barchartcard({super.key}); + + Widget build(BuildContext context) { + return Container( + height: 400, + width: double.infinity, + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Progress", + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 15, + color: Colors.white, + ), + ), + Expanded( + child: BlocProvider( + create: (context) => ProyekBloc(proyekServices: ProyekServices()) + ..add(GetProjectData()), + child: BlocBuilder( + builder: (context, state) { + if (state is ProjectDataLoading) { + return Center(child: const CircularProgressIndicator()); + } else if (state is ProjectDataLoaded) { + return BarChartWidget(projects: state.projects); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } else { + return Container(); + } + }, + ), + )) + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/dashboard/widget/cardInfo.dart b/dashboard_sim/lib/page/dashboard/widget/cardInfo.dart new file mode 100644 index 0000000..72324bc --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/cardInfo.dart @@ -0,0 +1,176 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class cardView extends StatelessWidget { + const cardView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + + return BlocProvider( + create: (context) => + ProyekBloc(proyekServices: ProyekServices())..add(GetProyekCounts()), + child: Container( + child: Responsive( + mobile: AnalyticInfoCardGridView( + crossAxisCount: size.width < 650 ? 2 : 4, + childAspectRatio: size.width < 650 ? 2 : 1.5, + ), + tablet: AnalyticInfoCardGridView( + childAspectRatio: size.width < 1000 ? 2 : 4, + ), + desktop: AnalyticInfoCardGridView( + childAspectRatio: size.width < 1400 ? 2 : 4, + ), + ), + ), + ); + } +} + +class AnalyticInfoCardGridView extends StatelessWidget { + const AnalyticInfoCardGridView({ + Key? key, + this.crossAxisCount = 2, + this.childAspectRatio = 1, + }) : super(key: key); + + final int crossAxisCount; + final double childAspectRatio; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + if (state is ProyekCountsLoading) { + return Center(child: CircularProgressIndicator()); + } else if (state is ProyekCountsLoaded) { + List analyticData = [ + cardInfo( + title: "On Progress", + count: state.onProgress, + image: "assets/icons/progres.png", + ), + cardInfo( + title: "Selesai", + count: state.totalProyekSelesai, + image: "assets/icons/finish.png", + ), + ]; + + return GridView.builder( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: analyticData.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: crossAxisCount, + crossAxisSpacing: defaultPadding, + mainAxisSpacing: defaultPadding, + childAspectRatio: childAspectRatio, + ), + itemBuilder: (context, index) => cardinfo( + info: analyticData[index], + ), + ); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } else { + return Container(); + } + }, + ); + } +} + +class cardinfo extends StatelessWidget { + const cardinfo({Key? key, required this.info}) : super(key: key); + + final cardInfo info; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding, + vertical: defaultPadding / 2, + ), + decoration: BoxDecoration( + color: secondaryColor, borderRadius: BorderRadius.circular(10)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${info.count}", + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.w800, + ), + ), + Text( + info.title!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Colors.white, + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ) + ], + ), + Container( + padding: EdgeInsets.all(16 / 2), + height: MediaQuery.of(context).size.width < 1400 ? 50 : 70, + width: MediaQuery.of(context).size.width < 1400 ? 50 : 70, + decoration: BoxDecoration(shape: BoxShape.circle), + child: Image.asset( + info.image!, + fit: BoxFit.fill, + ), + ) + ], + ), + ], + ), + ); + } +} + +class cardInfo { + final String? image, title; + final int? count; + + cardInfo({ + this.image, + this.title, + this.count, + }); +} + +// data masuk sini +List analyticData = [ + cardInfo( + title: "Pekerjaan", + count: 8, + image: "assets/icons/progres.png", + ), + cardInfo( + title: "selesai", + count: 3, + image: "assets/icons/finish.png", + ), +]; diff --git a/dashboard_sim/lib/page/dashboard/widget/file_info_card.dart b/dashboard_sim/lib/page/dashboard/widget/file_info_card.dart new file mode 100644 index 0000000..a602817 --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/file_info_card.dart @@ -0,0 +1,97 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/models/MyFiles.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class FileInfoCard extends StatelessWidget { + const FileInfoCard({ + Key? key, + required this.info, + }) : super(key: key); + + final CloudStorageInfo info; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.all(defaultPadding * 0.75), + height: 40, + width: 40, + decoration: BoxDecoration( + color: info.color!.withOpacity(0.1), + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: SvgPicture.asset( + info.svgSrc!, + colorFilter: ColorFilter.mode( + info.color ?? Colors.black, BlendMode.srcIn), + ), + ), + SizedBox( + width: 10, + ), + Text( + info.title!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + Text( + "${info.numOfFiles} Files", + ), + ], + ), + ); + } +} + +// class ProgressLine extends StatelessWidget { +// const ProgressLine({ +// Key? key, +// this.color = primaryColor, +// required this.percentage, +// }) : super(key: key); + +// final Color? color; +// final int? percentage; + +// @override +// Widget build(BuildContext context) { +// return Stack( +// children: [ +// Container( +// width: double.infinity, +// height: 5, +// decoration: BoxDecoration( +// color: color!.withOpacity(0.1), +// borderRadius: BorderRadius.all(Radius.circular(10)), +// ), +// ), +// LayoutBuilder( +// builder: (context, constraints) => Container( +// width: constraints.maxWidth * (percentage! / 100), +// height: 5, +// decoration: BoxDecoration( +// color: color, +// borderRadius: BorderRadius.all(Radius.circular(10)), +// ), +// ), +// ), +// ], +// ); +// } +// } diff --git a/dashboard_sim/lib/page/dashboard/widget/recent_project.dart b/dashboard_sim/lib/page/dashboard/widget/recent_project.dart new file mode 100644 index 0000000..3097722 --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/recent_project.dart @@ -0,0 +1,104 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/models/data.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; + +class RecentProject extends StatelessWidget { + const RecentProject({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Recent Project", + style: Theme.of(context).textTheme.titleMedium, + ), + SizedBox(height: defaultPadding), + BlocProvider( + create: (context) => ProyekBloc(proyekServices: ProyekServices()) + ..add(LoadRecentProyek()), + child: BlocBuilder( + builder: (context, state) { + if (state is ProyekLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } else if (state is ProyekLoaded) { + final proyeks = state.proyeks; + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: ScrollController(), + child: DataTable( + columnSpacing: defaultPadding, + columns: const [ + DataColumn( + label: Text("No"), + ), + DataColumn( + label: Text("Project Name"), + ), + DataColumn( + label: Text("Deadline"), + ), + DataColumn( + label: Text("Nilai"), + ), + ], + rows: List.generate( + proyeks.length, + (index) => + recentFileDataRow(proyeks[index], index + 1), + ), + ), + ); + } + + return SizedBox(); + }, + )), + ], + ), + ); + } +} + +DataRow recentFileDataRow(Proyek proyek, int id) { + return DataRow( + cells: [ + DataCell(Container( + width: 50, + child: Text(id.toString()), + )), + DataCell(Container( + width: 300, + child: Text(proyek.nama!), + )), + DataCell(Container( + width: 200, + child: Text(DateFormat('EEEE, MMMM d, y') + .format(DateTime.parse(proyek.finish!))), + )), + DataCell(Container( + width: 200, + child: Text("${proyek.nilai}%"), + )), + ], + ); +} diff --git a/dashboard_sim/lib/page/dashboard/widget/storage_details.dart b/dashboard_sim/lib/page/dashboard/widget/storage_details.dart new file mode 100644 index 0000000..fb22714 --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/storage_details.dart @@ -0,0 +1,59 @@ +// import 'package:drawer/constants/constants.dart'; +// import 'package:flutter/material.dart'; + +// import 'storage_info_card.dart'; + +// class StorageDetails extends StatelessWidget { +// const StorageDetails({ +// Key? key, +// }) : super(key: key); + +// @override +// Widget build(BuildContext context) { +// return Container( +// padding: EdgeInsets.all(defaultPadding), +// decoration: BoxDecoration( +// color: secondaryColor, +// borderRadius: const BorderRadius.all(Radius.circular(10)), +// ), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// "Storage Details", +// style: TextStyle( +// fontSize: 18, +// fontWeight: FontWeight.w500, +// ), +// ), +// SizedBox(height: defaultPadding), +// // Chart(), +// StorageInfoCard( +// svgSrc: "assets/icons/Documents.svg", +// title: "Documents Files", +// amountOfFiles: "1.3GB", +// numOfFiles: 1328, +// ), +// StorageInfoCard( +// svgSrc: "assets/icons/media.svg", +// title: "Media Files", +// amountOfFiles: "15.3GB", +// numOfFiles: 1328, +// ), +// StorageInfoCard( +// svgSrc: "assets/icons/folder.svg", +// title: "Other Files", +// amountOfFiles: "1.3GB", +// numOfFiles: 1328, +// ), +// StorageInfoCard( +// svgSrc: "assets/icons/unknown.svg", +// title: "Unknown", +// amountOfFiles: "1.3GB", +// numOfFiles: 140, +// ), +// ], +// ), +// ); +// } +// } diff --git a/dashboard_sim/lib/page/dashboard/widget/storage_info_card.dart b/dashboard_sim/lib/page/dashboard/widget/storage_info_card.dart new file mode 100644 index 0000000..983bbae --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/storage_info_card.dart @@ -0,0 +1,62 @@ +// import 'package:drawer/constants/constants.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_svg/flutter_svg.dart'; + +// class StorageInfoCard extends StatelessWidget { +// const StorageInfoCard({ +// Key? key, +// required this.title, +// required this.svgSrc, +// required this.amountOfFiles, +// required this.numOfFiles, +// }) : super(key: key); + +// final String title, svgSrc, amountOfFiles; +// final int numOfFiles; + +// @override +// Widget build(BuildContext context) { +// return Container( +// margin: EdgeInsets.only(top: defaultPadding), +// padding: EdgeInsets.all(defaultPadding), +// decoration: BoxDecoration( +// border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)), +// borderRadius: const BorderRadius.all( +// Radius.circular(defaultPadding), +// ), +// ), +// child: Row( +// children: [ +// SizedBox( +// height: 20, +// width: 20, +// child: SvgPicture.asset(svgSrc), +// ), +// Expanded( +// child: Padding( +// padding: const EdgeInsets.symmetric(horizontal: defaultPadding), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// title, +// maxLines: 1, +// overflow: TextOverflow.ellipsis, +// ), +// Text( +// "$numOfFiles Files", +// style: Theme.of(context) +// .textTheme +// .bodySmall! +// .copyWith(color: Colors.white70), +// ), +// ], +// ), +// ), +// ), +// Text(amountOfFiles) +// ], +// ), +// ); +// } +// } diff --git a/dashboard_sim/lib/page/dashboard/widget/team.dart b/dashboard_sim/lib/page/dashboard/widget/team.dart new file mode 100644 index 0000000..948aa09 --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/team.dart @@ -0,0 +1,63 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/page/dashboard/widget/team_info.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class team extends StatelessWidget { + const team({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: BlocProvider( + create: (context) => + ProyekBloc(proyekServices: ProyekServices())..add(LoadProyek()), + child: BlocBuilder( + builder: (context, state) { + if (state is ProyekLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } else if (state is ProyekLoaded) { + final proyeks = state.proyeks; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Project leaders", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: defaultPadding), + ListView.builder( + shrinkWrap: true, + itemCount: proyeks.length, + itemBuilder: (context, index) { + return teamInfo( + svgSrc: "assets/icons/media.svg", + proyek: proyeks[index], + ); + }, + ), + ], + ); + } + return SizedBox(); + }, + )), + ); + } +} diff --git a/dashboard_sim/lib/page/dashboard/widget/team_info.dart b/dashboard_sim/lib/page/dashboard/widget/team_info.dart new file mode 100644 index 0000000..4b7fcdc --- /dev/null +++ b/dashboard_sim/lib/page/dashboard/widget/team_info.dart @@ -0,0 +1,66 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class teamInfo extends StatelessWidget { + teamInfo({Key? key, required this.svgSrc, this.proyek}) : super(key: key); + + final String svgSrc; + Proyek? proyek; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(top: defaultPadding), + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)), + borderRadius: const BorderRadius.all( + Radius.circular(defaultPadding), + ), + ), + child: Row( + children: [ + SizedBox( + height: 20, + width: 20, + child: SvgPicture.asset(svgSrc), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: defaultPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + proyek!.manager!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + "manager", + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.white70), + ), + ], + ), + ), + ), + GestureDetector( + child: Icon( + Icons.more_vert_rounded, + color: Colors.white, + size: 18, + ), + onTap: () {}, + ) + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/karyawan/addKaryawan.dart b/dashboard_sim/lib/page/karyawan/addKaryawan.dart new file mode 100644 index 0000000..0718d4e --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/addKaryawan.dart @@ -0,0 +1,384 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/user.dart'; +import 'package:drawer/data/services/roles/role_bloc.dart'; +import 'package:drawer/data/services/roles/role_services.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:drawer/data/services/users/users_bloc.dart'; +import 'package:drawer/page/karyawan/widget/formkaryawan.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/page/sidebar/side_menu.dart'; +import 'package:intl/intl.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; + +class addKaryawan extends StatefulWidget { + final String? id; + final bool? isUpdate; + User? user; + + addKaryawan({this.id, this.isUpdate, this.user, super.key}); + + @override + State createState() => _addKaryawanState(); +} + +class _addKaryawanState extends State { + final MultiSelectController _controller = MultiSelectController(); + + String selectedRoleId = ''; + DateTime? selectedDate; + bool isLoading = false; + + final nama = TextEditingController(); + final username = TextEditingController(); + final nip = TextEditingController(); + final email = TextEditingController(); + final password = TextEditingController(); + final jk = TextEditingController(); + final tgl = TextEditingController(); + final notelp = TextEditingController(); + final alamat = TextEditingController(); + + void selectDate(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: selectedDate ?? DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null && pickedDate != selectedDate) { + selectedDate = pickedDate; + String tglnew = DateFormat('yyyy-MM-dd').format(pickedDate); + setState(() { + tgl.text = tglnew; + }); + } + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + if (widget.isUpdate == true) { + nama.text = widget.user!.name!; + username.text = widget.user!.username!; + nip.text = widget.user!.nip!; + email.text = widget.user!.email!; + jk.text = widget.user!.jenisKelamin!; + notelp.text = widget.user!.noTelp!; + alamat.text = widget.user!.alamat!; + tgl.text = DateFormat('yyyy-MM-dd').format(widget.user!.tanggalLahir!); + } + } + + void storeUser() async { + setState(() { + isLoading = true; + }); + try { + Map userData = { + 'role_id': selectedRoleId, + 'name': nama.text, + 'nip': nip.text, + 'email': email.text, + 'username': username.text, + 'password': password.text, + 'jenis_kelamin': jk.text, + 'tanggal_lahir': tgl.text, + 'no_telp': notelp.text, + 'alamat': alamat.text, + }; + + final userService = UserService(); + if (widget.isUpdate == true) { + await userService.updateUserById(widget.id ?? "", userData); + } else { + await userService.storeUser(userData); + } + + // Show success message + Fluttertoast.showToast( + msg: widget.isUpdate == true + ? "Update user successfully" + : "Store user successfully", + toastLength: Toast.LENGTH_LONG); + context.read().setSelectedItem('dashboard'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to save user: $e", toastLength: Toast.LENGTH_LONG); + } finally { + setState(() { + isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + drawer: SideMenu(), + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + SizedBox(height: defaultPadding), + customform(controller: nama, title: "Nama"), + customform(controller: nip, title: "Nip"), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Jabatan", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox( + height: 8, + ), + BlocProvider( + create: (context) => + RoleBloc(roleServices: RoleServices()) + ..add(LoadRole()), + child: BlocBuilder( + builder: (context, state) { + if (state is RoleLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is RoleLoaded) { + final List> + dropdownOptions = state.roles + .map((role) => ValueItem( + label: role.name, + value: role.id)) + .toList(); + return MultiSelectDropDown( + borderColor: Colors.white, + fieldBackgroundColor: bgColor, + dropdownBackgroundColor: secondaryColor, + optionsBackgroundColor: secondaryColor, + controller: _controller, + onOptionSelected: (options) { + setState(() { + selectedRoleId = + options[0].value.toString(); + print(selectedRoleId); + }); + debugPrint(options.toString()); + }, + options: dropdownOptions, + maxItems: 1, + disabledOptions: const [ + ValueItem(label: 'Option 1', value: '1') + ], + selectionType: SelectionType.single, + chipConfig: const ChipConfig( + wrapType: WrapType.wrap), + optionTextStyle: + const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ); + } else if (state is RoleError) { + return Center( + child: Text('Error: ${state.error}')); + } + return SizedBox(); + }, + ), + ), + const SizedBox( + height: 8, + ), + ], + ), + ), + customform(controller: email, title: "Email"), + customform(controller: username, title: "Username"), + customform(controller: password, title: "Password"), + customform(controller: jk, title: "Jenis Kelamin"), + customform( + onTap: () { + selectDate(context); + }, + isReadOnly: true, + controller: tgl, + title: "Tanggal Lahir"), + customform(controller: notelp, title: "No. Telp"), + customform(controller: alamat, title: "Alamat"), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + SizedBox(height: defaultPadding), + Center( + child: Container( + width: double.infinity, + child: ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: defaultPadding / + (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () { + storeUser(); + }, + icon: isLoading + ? CircularProgressIndicator( + color: Colors.white, + ) + : Icon(Icons.save), + label: isLoading + ? Text("Menyimpan...") + : Text("Simpan"), + ), + ), + ), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + // if (!Responsive.isMobile(context)) + // Expanded( + // flex: 2, + // child: Container( + // padding: EdgeInsets.all(defaultPadding), + // decoration: BoxDecoration( + // color: secondaryColor, + // borderRadius: + // const BorderRadius.all(Radius.circular(10)), + // ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // "Files", + // style: TextStyle( + // fontSize: 18, + // fontWeight: FontWeight.w500, + // ), + // ), + // SizedBox(height: defaultPadding), + // SizedBox(height: defaultPadding), + // Center( + // child: Container( + // width: double.infinity, + // child: ElevatedButton.icon( + // style: TextButton.styleFrom( + // padding: EdgeInsets.symmetric( + // horizontal: defaultPadding * 1.5, + // vertical: defaultPadding / + // (Responsive.isMobile(context) + // ? 2 + // : 1), + // ), + // ), + // onPressed: () { + // storeUser(); + // }, + // icon: isLoading + // ? CircularProgressIndicator( + // color: Colors.white, + // ) + // : Icon(Icons.save), + // label: isLoading + // ? Text("Menyimpan...") + // : Text("Simpan"), + // ), + // ), + // ), + // ], + // ), + // ), + // ), + ], + ), + ], + ), + )), + ); + } +} + +Container images(BuildContext context, VoidCallback onPressed) { + return Container( + margin: EdgeInsets.only(top: defaultPadding), + padding: EdgeInsets.all(defaultPadding), + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)), + borderRadius: const BorderRadius.all( + Radius.circular(defaultPadding), + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 100, + width: 100, + child: SvgPicture.asset("assets/icons/media.svg"), + ), + SizedBox( + width: defaultPadding), // Spacer horizontal antara gambar dan teks + Column( + crossAxisAlignment: + CrossAxisAlignment.start, // Mengatur teks agar berada di kiri + children: [ + Text( + "Foto Profil", + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + "Belum ada file dipilih", + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.white70), + ), + SizedBox( + height: 20, + ), + ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: onPressed, + icon: Icon(Icons.upload), + label: Text("Upload Foto"), + ), + ], + ), + ], + ), + ); +} diff --git a/dashboard_sim/lib/page/karyawan/detailKaryawan.dart b/dashboard_sim/lib/page/karyawan/detailKaryawan.dart new file mode 100644 index 0000000..841de41 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/detailKaryawan.dart @@ -0,0 +1,217 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/services/api/api_services.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:drawer/data/services/users/users_bloc.dart'; +import 'package:drawer/page/profil/profil.dart'; + +import 'package:drawer/page/sidebar/header.dart'; +import 'package:drawer/page/sidebar/side_menu.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class detailKaryawan extends StatelessWidget { + String? idUser; + detailKaryawan({this.idUser, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final bool isSmallScreen = MediaQuery.of(context).size.width < 600; + final Widget profileWidget = detailProfile(idUser ?? ""); + return Scaffold( + drawer: SideMenu(), + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Header(), + SizedBox(height: defaultPadding), + Container( + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.circular( + 20, + )), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + isSmallScreen + ? Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 400, + child: imageProfile( + id: idUser ?? "", + )), + profileWidget + ], + ) + : Container( + padding: const EdgeInsets.all(20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + child: imageProfile( + id: idUser ?? "", + ), + ), + const SizedBox( + width: 20, + ), + Center(child: profileWidget), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} + +class imageProfile extends StatelessWidget { + String id; + imageProfile({required this.id, super.key}); + + @override + Widget build(BuildContext context) { + final bool isSmallScreen = MediaQuery.of(context).size.width < 600; + + return BlocProvider( + create: (context) => + UsersBloc(userService: UserService())..add(GetUserById(userId: id)), + child: BlocBuilder( + builder: (context, state) { + if (state is UsersLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (state is UserByIdLoaded) { + final user = state.user; + return Column( + children: [ + Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(180), + color: bgColor, + ), + child: ClipOval( + child: Image.asset( + "assets/photos/user.png", + width: isSmallScreen ? 100 : 200, + height: isSmallScreen ? 100 : 200, + fit: BoxFit.cover, + ), + ), + ), + SizedBox( + height: 10, + ), + ElevatedButton.icon( + icon: const Icon(Icons.edit), + label: const Text("Edit"), + onPressed: () { + context.read().setSelectedItem( + 'add karyawan', + id: user.id.toString(), + isUpdate: true, + users: user); + }, + ), + ], + ); + } else if (state is UsersError) { + return Center( + child: Text('Failed to load user: ${state.error}'), + ); + } else { + return const Center( + child: Text('Unknown state'), + ); + } + }, + )); + } +} + +Container profileData(String title, String subtitle) { + return Container( + padding: const EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text(subtitle), + ], + ), + ); +} + +Widget detailProfile(String id) { + return BlocProvider( + create: (context) => + UsersBloc(userService: UserService())..add(GetUserById(userId: id)), + child: BlocBuilder( + builder: (context, state) { + if (state is UsersLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (state is UserByIdLoaded) { + final user = state.user; + return Container( + constraints: const BoxConstraints(maxWidth: 700), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + profileData("Nama", user.name!), + profileData("Nip", user.nip!), + profileData("Email", user.email!), + profileData("Username", user.username!), + profileData("Jenis Kelamin", user.jenisKelamin!), + profileData("Tanggal Lahir", + DateFormat('dddd MMMM yyyy').format(user.tanggalLahir!)), + profileData("No. Telepon", user.noTelp!), + profileData("Alamat", user.alamat!), + profileData("Role", user.role!.name), + ], + ), + ); + } else if (state is UsersError) { + return Center( + child: Text('Failed to load user: ${state.error}'), + ); + } else { + return const Center( + child: Text('Unknown state'), + ); + } + }, + )); +} diff --git a/dashboard_sim/lib/page/karyawan/editKaryawan.dart b/dashboard_sim/lib/page/karyawan/editKaryawan.dart new file mode 100644 index 0000000..9304604 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/editKaryawan.dart @@ -0,0 +1,15 @@ +import 'package:flutter/cupertino.dart'; + +class EditKaryawan extends StatefulWidget { + const EditKaryawan({super.key}); + + @override + State createState() => EditKaryawanState(); +} + +class EditKaryawanState extends State { + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/dashboard_sim/lib/page/karyawan/karyawan.dart b/dashboard_sim/lib/page/karyawan/karyawan.dart new file mode 100644 index 0000000..1a1dbc4 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/karyawan.dart @@ -0,0 +1,47 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/page/karyawan/widget/karyawan_files.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:flutter/material.dart'; + +class karyawan extends StatelessWidget { + const karyawan({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + karyawanfile(), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + // On Mobile means if the screen is less than 850 we don't want to show it + ], + ) + ], + ), + ), + ), + ); + } +} diff --git a/dashboard_sim/lib/page/karyawan/widget/custom_form_detail_karyawan.dart b/dashboard_sim/lib/page/karyawan/widget/custom_form_detail_karyawan.dart new file mode 100644 index 0000000..bd3a758 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/widget/custom_form_detail_karyawan.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class FormCustomKaryawan extends StatelessWidget { + const FormCustomKaryawan({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/dashboard_sim/lib/page/karyawan/widget/file_karyawan.dart b/dashboard_sim/lib/page/karyawan/widget/file_karyawan.dart new file mode 100644 index 0000000..0f31874 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/widget/file_karyawan.dart @@ -0,0 +1,58 @@ +import 'package:drawer/constants/responsive.dart'; +import 'package:flutter/material.dart'; +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/page/karyawan/widget/filecard.dart'; + +class fileKaryawan extends StatelessWidget { + const fileKaryawan({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Files", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: defaultPadding), + // fileCard( + // svgSrc: "assets/icons/media.svg", + // jabatan: "manager", + // ), + // fileCard( + // svgSrc: "assets/icons/media.svg", + // jabatan: "manager", + // ), + SizedBox(height: defaultPadding), + Center( + child: Container( + width: double.infinity, + child: ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () {}, + icon: Icon(Icons.save), + label: Text("Simpan"), + ), + ), + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/karyawan/widget/filecard.dart b/dashboard_sim/lib/page/karyawan/widget/filecard.dart new file mode 100644 index 0000000..7a7c4ed --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/widget/filecard.dart @@ -0,0 +1,114 @@ +import 'dart:io'; + +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:image_picker/image_picker.dart'; + +class fileCard extends StatefulWidget { + fileCard({ + super.key, + required this.svgSrc, + required this.jabatan, + required this.file, + }); + + final String svgSrc, jabatan; + File? file; + + @override + State createState() => _fileCardState(); +} + +class _fileCardState extends State { + // File? _image; + String? _imageName; + + Future getImageGalery() async { + final picker = ImagePicker(); + final imageFile = await picker.pickImage(source: ImageSource.gallery); + + setState(() { + if (imageFile != null) { + widget.file = File(imageFile.path); + } else { + print('No image selected.'); + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(top: defaultPadding), + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)), + borderRadius: const BorderRadius.all( + Radius.circular(defaultPadding), + ), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, // Mengatur teks agar berada di kiri + children: [ + SizedBox( + height: 100, + width: 100, + child: SvgPicture.asset(widget.svgSrc), + ), + SizedBox( + width: + defaultPadding), // Spacer horizontal antara gambar dan teks + Column( + crossAxisAlignment: + CrossAxisAlignment.start, // Mengatur teks agar berada di kiri + children: [ + Text( + "Foto Profil", + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + widget.file != null + ? Expanded( + child: Text( + widget.jabatan, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.white70), + ), + ) + : Text( + "Belum ada file dipilih", + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.white70), + ), + SizedBox( + height: 20, + ), + ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: getImageGalery, + // context.read().setSelectedItem('add karyawan'); + icon: Icon(Icons.upload), + label: Text("Upload Foto"), + ), + ], + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/karyawan/widget/formkaryawan.dart b/dashboard_sim/lib/page/karyawan/widget/formkaryawan.dart new file mode 100644 index 0000000..3c871bb --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/widget/formkaryawan.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; + +class customform extends StatefulWidget { + final String title; + final bool obscuretext; + final TextEditingController? controller; + final bool isReadOnly; + final bool isShowtitle; + final VoidCallback? onTap; + final TextInputType? keyboardType; + + const customform( + {Key? key, + required this.title, + this.obscuretext = false, + this.controller, + this.isReadOnly = false, + this.isShowtitle = true, + this.onTap, + this.keyboardType}) + : super(key: key); + + @override + State createState() => _customformState(); +} + +class _customformState extends State { + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.isShowtitle) + Text( + widget.title, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + if (widget.isShowtitle) + const SizedBox( + height: 8, + ), + TextFormField( + onTap: widget.onTap, + keyboardType: widget.keyboardType, + obscureText: widget.obscuretext, + controller: widget.controller, + readOnly: widget.isReadOnly, + decoration: InputDecoration( + hintText: !widget.isShowtitle ? widget.title : null, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(14), + ), + contentPadding: const EdgeInsets.all(12), + ), + ), + const SizedBox( + height: 8, + ), + ], + ); + } +} diff --git a/dashboard_sim/lib/page/karyawan/widget/karyawan_files.dart b/dashboard_sim/lib/page/karyawan/widget/karyawan_files.dart new file mode 100644 index 0000000..cb84db6 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/widget/karyawan_files.dart @@ -0,0 +1,228 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/user.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:drawer/data/services/users/users_bloc.dart'; +import 'package:drawer/models/data.dart'; +import 'package:drawer/page/karyawan/detailKaryawan.dart'; +import 'package:drawer/page/karyawan/widget/topjudul.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class karyawanfile extends StatefulWidget { + const karyawanfile({ + Key? key, + }) : super(key: key); + + @override + State createState() => _karyawanfileState(); +} + +class _karyawanfileState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + topjudulkaryawan(), + SizedBox( + width: double.infinity, + child: BlocProvider( + create: (context) => + UsersBloc(userService: UserService())..add(LoadUser()), + child: BlocBuilder( + builder: (context, state) { + if (state is UsersLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is UsersError) { + return Center(child: Text('Error: ${state.error}')); + } else if (state is UsersLoaded) { + final users = state.users; + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columnSpacing: defaultPadding, + columns: const [ + DataColumn(label: Text("No")), + DataColumn(label: Text("Name")), + DataColumn(label: Text("Position")), + DataColumn(label: Text("Birth")), + DataColumn(label: Text("No. Telp")), + DataColumn(label: Text("Email")), + DataColumn(label: Text("Gender")), + DataColumn(label: Text("Address")), + DataColumn(label: Text("Aksi")), + ], + rows: List.generate( + users.length, + (index) => karyawanFileDataRow( + context, users[index], index + 1), + ), + ), + ); + } + + return SizedBox(); + }, + ), + ), + ), + ], + ), + ); + } +} + +DataRow karyawanFileDataRow(BuildContext context, User user, int id) { + return DataRow( + cells: [ + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 50, + child: Text(id.toString()), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 100, + child: (Text(user.name!)), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 100, + child: Text(user.role!.name), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 130, + child: Text(DateFormat('dd MMMM yyyy').format(user.tanggalLahir!)), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 130, + child: Text(user.noTelp!), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 250, + child: Text(user.email!), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 100, + child: Text(user.jenisKelamin!), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail karyawan', id: user.id.toString()); + }, + child: Container( + width: 100, + child: Text(user.alamat!), + ), + ), + ), + DataCell( + IconButton( + color: Colors.red, + onPressed: () { + AwesomeDialog( + width: 500, + context: context, + animType: AnimType.scale, + title: "Warning", + btnCancelOnPress: () {}, + btnOkOnPress: () { + deleteData(user.id.toString(), context); + }, + desc: "Are you sure to delete the data?") + .show(); + }, + icon: Icon(Icons.remove_circle_outline_sharp)), + ), + ], + ); +} + +void deleteData(String id, BuildContext context) async { + try { + final userServices = UserService(); + await userServices.deleteUserById(id); + Fluttertoast.showToast( + msg: "Delete user successfully", toastLength: Toast.LENGTH_LONG); + context.read().setSelectedItem('dashboard'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to delete user: $e", toastLength: Toast.LENGTH_LONG); + } +} diff --git a/dashboard_sim/lib/page/karyawan/widget/topjudul.dart b/dashboard_sim/lib/page/karyawan/widget/topjudul.dart new file mode 100644 index 0000000..4daded8 --- /dev/null +++ b/dashboard_sim/lib/page/karyawan/widget/topjudul.dart @@ -0,0 +1,49 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/user.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class topjudulkaryawan extends StatelessWidget { + const topjudulkaryawan({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final Size _size = MediaQuery.of(context).size; + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Karyawan", + style: Theme.of(context).textTheme.titleMedium, + ), + ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () { + context.read().setSelectedItem( + 'add karyawan', + isUpdate: false, + id: "", + users: User()); + }, + icon: Icon(Icons.add), + label: Text("Add New"), + ), + ], + ), + SizedBox(height: defaultPadding), + ], + ); + } +} diff --git a/dashboard_sim/lib/page/login/login.dart b/dashboard_sim/lib/page/login/login.dart new file mode 100644 index 0000000..a062e3b --- /dev/null +++ b/dashboard_sim/lib/page/login/login.dart @@ -0,0 +1,213 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/data/services/auth/auth_bloc.dart'; +import 'package:drawer/data/services/auth/auth_event.dart'; +import 'package:drawer/data/services/auth/auth_state.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class Login extends StatelessWidget { + const Login({super.key}); + + @override + Widget build(BuildContext context) { + final bool isSmallScreen = MediaQuery.of(context).size.width < 600; + + return Scaffold( + body: Center( + child: isSmallScreen + ? Column( + mainAxisSize: MainAxisSize.min, + children: const [ + _Logo(), + _FormContent(), + ], + ) + : Container( + padding: const EdgeInsets.all(32.0), + constraints: const BoxConstraints(maxWidth: 800), + child: Row( + children: const [ + Expanded(child: _Logo()), + Expanded( + child: Center(child: _FormContent()), + ), + ], + ), + ), + ), + ); + } +} + +class _Logo extends StatelessWidget { + const _Logo({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final bool isSmallScreen = MediaQuery.of(context).size.width < 600; + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset( + "assets/photos/logo2.png", + width: isSmallScreen ? 100 : 200, + height: isSmallScreen ? 100 : 200, + fit: BoxFit.fill, + ), + // FlutterLogo(size: isSmallScreen ? 100 : 200), + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + "Welcome to Informatika Asia!", + textAlign: TextAlign.center, + style: isSmallScreen + ? Theme.of(context).textTheme.headlineSmall + : Theme.of(context) + .textTheme + .headlineMedium + ?.copyWith(color: Colors.white), + ), + ) + ], + ); + } +} + +class _FormContent extends StatefulWidget { + const _FormContent({Key? key}) : super(key: key); + + @override + State<_FormContent> createState() => __FormContentState(); +} + +class __FormContentState extends State<_FormContent> { + bool _isPasswordVisible = false; + bool _rememberMe = false; + + final email = TextEditingController(); + final password = TextEditingController(); + + final GlobalKey _formKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + if (state is AuthenticationSuccess) { + Navigator.pushReplacementNamed(context, '/dashboard'); + } + }, + child: Container( + constraints: const BoxConstraints(maxWidth: 300), + child: Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextFormField( + validator: (value) { + // add email validation + if (value == null || value.isEmpty) { + return 'Please enter some text'; + } + + bool emailValid = RegExp( + r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+") + .hasMatch(value); + if (!emailValid) { + return 'Please enter a valid email'; + } + + return null; + }, + controller: email, + decoration: const InputDecoration( + labelText: 'Email', + hintText: 'Enter your email', + prefixIcon: Icon(Icons.email_outlined), + border: OutlineInputBorder(), + ), + ), + _gap(), + TextFormField( + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter some text'; + } + + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + return null; + }, + obscureText: !_isPasswordVisible, + controller: password, + decoration: InputDecoration( + labelText: 'Password', + hintText: 'Enter your password', + prefixIcon: const Icon(Icons.lock_outline_rounded), + border: const OutlineInputBorder(), + suffixIcon: IconButton( + icon: Icon(_isPasswordVisible + ? Icons.visibility_off + : Icons.visibility), + onPressed: () { + setState(() { + _isPasswordVisible = !_isPasswordVisible; + }); + }, + )), + ), + _gap(), + CheckboxListTile( + value: _rememberMe, + onChanged: (value) { + if (value == null) return; + setState(() { + _rememberMe = value; + }); + }, + title: const Text('Remember me'), + controlAffinity: ListTileControlAffinity.leading, + dense: true, + contentPadding: const EdgeInsets.all(0), + ), + _gap(), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4)), + ), + child: const Padding( + padding: EdgeInsets.all(10.0), + child: Text( + 'Sign in', + style: + TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + ), + onPressed: () { + if (_formKey.currentState?.validate() ?? false) { + BlocProvider.of(context).add( + LoginButtonPressed( + email: email.text, + password: password.text, + ), + ); + } + }, + ), + ), + ], + ), + ), + ), + ); + } + + Widget _gap() => const SizedBox(height: 16); +} diff --git a/dashboard_sim/lib/page/profil/profil.dart b/dashboard_sim/lib/page/profil/profil.dart new file mode 100644 index 0000000..69f5fc3 --- /dev/null +++ b/dashboard_sim/lib/page/profil/profil.dart @@ -0,0 +1,270 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:drawer/page/sidebar/side_menu.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class profil extends StatelessWidget { + const profil({super.key}); + + @override + Widget build(BuildContext context) { + final bool isSmallScreen = MediaQuery.of(context).size.width < 600; + + return Scaffold( + drawer: SideMenu(), + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Header(), + SizedBox(height: defaultPadding), + Container( + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.circular( + 20, + )), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + isSmallScreen + ? Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container(width: 400, child: imageProfile()), + detailProfile(), + ], + ) + : Container( + padding: EdgeInsets.all(20), + // constraints: BoxConstraints(maxWidth: 600), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: const [ + imageProfile(), + SizedBox( + width: 20, + ), + Center(child: detailProfile()), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} + +class imageProfile extends StatelessWidget { + const imageProfile({super.key}); + + @override + Widget build(BuildContext context) { + final bool isSmallScreen = MediaQuery.of(context).size.width < 600; + + return Column( + children: [ + Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(180), + ), + color: bgColor), + child: Image.asset( + "assets/photos/logo2.png", + width: isSmallScreen ? 100 : 200, + height: isSmallScreen ? 100 : 200, + fit: BoxFit.fill, + ), + ), + SizedBox( + height: 10, + ), + ElevatedButton.icon( + icon: const Icon(Icons.edit), + label: const Text("Edit"), + onPressed: () { + context.read().setSelectedItem('add karyawan'); + }, + ), + ], + ); + } +} + +class detailProfile extends StatelessWidget { + const detailProfile({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + constraints: const BoxConstraints(maxWidth: 700), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Nama", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("Alexander Smith Oto Dinata"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "NIP", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("1223454636345"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Jabatan", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("Karyawan"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Email", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("AlexanderSmith@gmail.com"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Username", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("Alexander2230"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Jenis Kelamin", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("Laki-Laki"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tanggal Lahir", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("20-05-1990"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "No. Telepone", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text("09892749852"), + ], + ), + ), + Container( + padding: EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Alamat", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + Text( + "Ds. Cisadea Kec. Bogor Kab. Bogor Provinsi Jawa Barat ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + ], + ), + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/addProyek.dart b/dashboard_sim/lib/page/proyek/addProyek.dart new file mode 100644 index 0000000..f1439b6 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/addProyek.dart @@ -0,0 +1,329 @@ +import 'dart:io'; + +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:drawer/data/services/users/users_bloc.dart'; +import 'package:drawer/page/karyawan/widget/formkaryawan.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/file_proyek.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/filecard.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/formproyek.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:drawer/page/sidebar/side_menu.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:intl/intl.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; + +class addProyek extends StatefulWidget { + final String? id; + final bool? isUpdate; + Proyek? proyek; + addProyek({this.id, this.isUpdate, this.proyek, super.key}); + + @override + State createState() => _addProyekState(); +} + +class _addProyekState extends State { + List selectedUserId = []; + bool isLoading = false; + + void selectDate(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + setState(() { + String startText = DateFormat("yyyy-MM-dd").format(pickedDate); + start.text = startText; + }); + } + } + + void selectDate2(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + setState(() { + String finishText = DateFormat("yyyy-MM-dd").format(pickedDate); + finish.text = finishText; + }); + } + } + + String selectedManager = ''; + final MultiSelectController _controller = MultiSelectController(); + + final nama = TextEditingController(); + final detail = TextEditingController(); + final nilai = TextEditingController(); + final klien = TextEditingController(); + final start = TextEditingController(); + final finish = TextEditingController(); + + @override + void initState() { + super.initState(); + if (widget.isUpdate == true) { + nama.text = widget.proyek!.nama!; + detail.text = widget.proyek!.detail!; + selectedManager = widget.proyek!.manager!; + nilai.text = widget.proyek!.nilai!.toString(); + klien.text = widget.proyek!.klien!; + start.text = widget.proyek!.start!; + finish.text = widget.proyek!.finish!; + } + } + + void storeProyek() async { + setState(() { + isLoading = true; + }); + try { + Map userData = { + 'nama': nama.text, + 'detail': detail.text, + 'manager': selectedManager, + 'nilai': nilai.text, + 'start': start.text, + 'finish': finish.text, + 'klien': klien.text, + }; + + final proyekService = ProyekServices(); + if (widget.isUpdate == false) { + await proyekService.storeProyek(userData); + } else { + await proyekService.updateProyekById(widget.id ?? "", userData); + } + + Fluttertoast.showToast( + msg: widget.isUpdate == true + ? "Update proyek successfully" + : "Store proyek successfully", + toastLength: Toast.LENGTH_LONG); + context.read().setSelectedItem('dashboard'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to save proyek: $e", toastLength: Toast.LENGTH_LONG); + } finally { + setState(() { + isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + drawer: SideMenu(), + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + const SizedBox(height: defaultPadding), + customformProyek( + title: "Nama Proyek", + controller: nama, + ), + customformProyek( + title: "Klien", + controller: klien, + ), + customformProyek( + title: "Detail", + controller: detail, + ), + customformProyek( + title: "Nilai", + controller: nilai, + keyboardType: TextInputType.number, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Jabatan", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox( + height: 8, + ), + BlocProvider( + create: (context) => + UsersBloc(userService: UserService()) + ..add(LoadUserManager()), + child: BlocBuilder( + builder: (context, state) { + if (state is UsersLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is UsersLoaded) { + final List> + dropdownOptions = state.users + .map((user) => ValueItem( + label: user.name!, + value: user.name)) + .toList(); + return MultiSelectDropDown( + borderColor: Colors.white, + fieldBackgroundColor: bgColor, + dropdownBackgroundColor: secondaryColor, + optionsBackgroundColor: secondaryColor, + controller: _controller, + onOptionSelected: (options) { + setState(() { + selectedManager = + options[0].value.toString(); + print(selectedManager); + }); + debugPrint(options.toString()); + }, + options: dropdownOptions, + maxItems: 1, + disabledOptions: const [ + ValueItem(label: 'Option 1', value: '1') + ], + selectionType: SelectionType.single, + chipConfig: const ChipConfig( + wrapType: WrapType.wrap), + optionTextStyle: + const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ); + } else if (state is UsersError) { + return Center( + child: Text('Error: ${state.error}')); + } + return SizedBox(); + }, + ), + ), + const SizedBox( + height: 8, + ), + ], + ), + customform( + title: "Start", + controller: start, + isReadOnly: true, + onTap: () { + selectDate(context); + }, + ), + customform( + title: "Finish", + controller: finish, + isReadOnly: true, + onTap: () { + selectDate2(context); + }, + ), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + if (Responsive.isMobile(context)) fileproyek(), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + if (!Responsive.isMobile(context)) + Expanded( + flex: 2, + child: Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: + const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Files", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: defaultPadding), + fileCardProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + fileCardProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + SizedBox(height: defaultPadding), + Center( + child: Container( + width: double.infinity, + child: ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: defaultPadding / + (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () { + storeProyek(); + }, + icon: isLoading + ? CircularProgressIndicator( + color: Colors.white, + ) + : Icon(Icons.save), + label: isLoading + ? Text("Menyimpan...") + : Text("Simpan"), + ), + ), + ), + ], + ), + ), + ), + ], + ) + ], + ), + )), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/add_task_proyek.dart b/dashboard_sim/lib/page/proyek/add_task_proyek.dart new file mode 100644 index 0000000..489b8c9 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/add_task_proyek.dart @@ -0,0 +1,255 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/services/proyek/task/task_bloc.dart'; +import 'package:drawer/data/services/proyek/task/task_service.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:drawer/data/services/users/users_bloc.dart'; +import 'package:drawer/page/karyawan/widget/formkaryawan.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/formproyek.dart'; +import 'package:flutter/material.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:intl/intl.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; + +class add_task extends StatefulWidget { + String id; + bool? isUpdate; + String? idTask; + TaskProyek? taskProyek; + add_task( + {required this.id, + this.isUpdate, + this.idTask, + this.taskProyek, + super.key}); + + @override + State createState() => _add_taskState(); +} + +class _add_taskState extends State { + final MultiSelectController _controller = MultiSelectController(); + + List selectedUserId = []; + bool isLoading = false; + + final tugas = TextEditingController(); + final catatan = TextEditingController(); + final start = TextEditingController(); + final deadline = TextEditingController(); + final status = TextEditingController(); + final nilai = TextEditingController(); + + @override + void initState() { + // TODO: implement initState + super.initState(); + if (widget.isUpdate == true) { + tugas.text = widget.taskProyek!.tugas!; + catatan.text = widget.taskProyek!.catatan!; + start.text = widget.taskProyek!.start!; + deadline.text = widget.taskProyek!.deadline!; + status.text = widget.taskProyek!.status!; + nilai.text = widget.taskProyek!.nilai!.toString(); + } + } + + void selectDate(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + String tglnew = DateFormat('yyyy-MM-dd').format(pickedDate); + setState(() { + start.text = tglnew; + }); + } + } + + void selectDate2(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null) { + String tglnew = DateFormat('yyyy-MM-dd').format(pickedDate); + setState(() { + deadline.text = tglnew; + }); + } + } + + void saveTask() async { + setState(() { + isLoading = true; + }); + try { + Map userData = { + 'tugas': tugas.text, + 'catatan': catatan.text, + 'start': start.text, + 'deadline': deadline.text, + 'status': status.text, + 'nilai': nilai.text, + 'user_ids': selectedUserId, + 'proyek_id': widget.idTask, + }; + print(userData); + final taskServices = TaskService(); + if (widget.isUpdate == false) { + await taskServices.storeTask(userData); + } else { + await taskServices.updateTaskById(widget.id, userData); + } + + // Show success message + Fluttertoast.showToast( + msg: widget.isUpdate == true + ? "Update task successfully" + : "Store task successfully", + toastLength: Toast.LENGTH_LONG); + context.read().setSelectedItem('dashboard'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to save proyek: $e", toastLength: Toast.LENGTH_LONG); + } finally { + setState(() { + isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + scrollable: true, + title: const Text("Tambah Tugas"), + content: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + customformProyek( + title: "Tugas", + controller: tugas, + ), + customformProyek( + title: "Catatan", + controller: catatan, + ), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Team", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox( + height: 8, + ), + BlocProvider( + create: (context) => UsersBloc(userService: UserService()) + ..add(LoadUser()), + child: BlocBuilder( + builder: (context, state) { + if (state is UsersLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (state is UsersLoaded) { + final List< + ValueItem< + dynamic>> dropdownOptions = state.users + .map((user) => ValueItem( + label: + "Nama : ${user.name} - Role : ${user.role!.name}", + value: user.id)) + .toList(); + return MultiSelectDropDown( + borderColor: Colors.white, + fieldBackgroundColor: bgColor, + dropdownBackgroundColor: secondaryColor, + optionsBackgroundColor: secondaryColor, + controller: _controller, + onOptionSelected: (options) { + setState(() { + selectedUserId = options + .map((option) => option.value) + .toList(); + }); + debugPrint(selectedUserId.toString()); + debugPrint(options.toString()); + }, + options: dropdownOptions, + disabledOptions: const [ + ValueItem(label: 'Option 1', value: '1') + ], + selectionType: SelectionType.multi, + chipConfig: + const ChipConfig(wrapType: WrapType.wrap), + optionTextStyle: const TextStyle(fontSize: 16), + selectedOptionIcon: + const Icon(Icons.check_circle), + ); + } else if (state is UsersError) { + return Center(child: Text('Error: ${state.error}')); + } + return SizedBox(); + }, + ), + ), + const SizedBox( + height: 8, + ), + ], + ), + ), + customform( + title: "start", + controller: start, + onTap: () { + selectDate(context); + }, + ), + customform( + title: "Deadline", + controller: deadline, + onTap: () { + selectDate2(context); + }, + ), + customformProyek( + title: "Status", + controller: status, + ), + customformProyek( + title: "Nilai", + controller: nilai, + ), + ], + )), + actions: [ + ElevatedButton( + child: const Text("submit"), + onPressed: () { + saveTask(); + }, + ), + ], + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/chace b/dashboard_sim/lib/page/proyek/chace new file mode 100644 index 0000000..7cfb6a4 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/chace @@ -0,0 +1,375 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/data/services/users/user_services.dart'; +import 'package:drawer/data/services/users/users_bloc.dart'; +import 'package:drawer/page/karyawan/widget/formkaryawan.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/file_proyek.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/filecard.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/formproyek.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:intl/intl.dart'; +import 'package:multi_dropdown/multiselect_dropdown.dart'; + +class addProyek extends StatefulWidget { + final String? id; + final bool? isUpdate; + addProyek({this.id, this.isUpdate, super.key}); + + @override + State createState() => _addProyekState(); +} + +class _addProyekState extends State { + final MultiSelectController _controller = MultiSelectController(); + + DateTime? selectedDate; + DateTime? selectedDate2; + List selectedUserId = []; + bool isLoading = false; + + void selectDate(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: selectedDate ?? DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null && pickedDate != selectedDate) { + setState(() { + selectedDate = pickedDate; + }); + } + } + + void selectDate2(BuildContext context) async { + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: selectedDate2 ?? DateTime.now(), + firstDate: DateTime(1800), + lastDate: DateTime(2100), + ); + if (pickedDate != null && pickedDate != selectedDate2) { + selectedDate2 = pickedDate; + print(selectedDate2); + setState(() {}); + } + } + + @override + void initState() { + super.initState(); + if (widget.isUpdate == true) { + context.read().add(GetProyekById(userId: widget.id ?? "")); + } + } + + final nama = TextEditingController(); + final detail = TextEditingController(); + final manager = TextEditingController(); + final nilai = TextEditingController(); + final klien = TextEditingController(); + void storeProyek() async { + setState(() { + isLoading = true; + }); + try { + String start = DateFormat('yyyy-MM-dd').format(selectedDate!); + String finish = DateFormat('yyyy-MM-dd').format(selectedDate2!); + print(finish); + Map userData = { + 'nama': nama.text, + 'detail': detail.text, + 'manager': manager.text, + 'nilai': nilai.text, + 'start': start, + 'finish': finish, + 'klien': klien.text, + }; + + final proyekService = ProyekServices(); + if (widget.isUpdate == false) { + await proyekService.storeProyek(userData); + } else { + await proyekService.updateProyekById(widget.id ?? "", userData); + } + + Fluttertoast.showToast( + msg: widget.isUpdate == true + ? "Update proyek successfully" + : "Store proyek successfully", + toastLength: Toast.LENGTH_LONG); + // context.read().setSelectedItem('dashboard'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to save proyek: $e", toastLength: Toast.LENGTH_LONG); + } finally { + setState(() { + isLoading = false; + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: BlocConsumer( + listener: (context, state) { + if (state is ProyekStored) { + context.read().setSelectedItem('dashboard'); + } + }, + builder: (context, state) { + if (state is ProyekLoading) { + return Center(child: CircularProgressIndicator()); + } else if (state is ProyekByIdLoaded && widget.isUpdate == true) { + final proyek = state.proyek; + nama.text = proyek.nama ?? ""; + detail.text = proyek.detail ?? ""; + manager.text = proyek.manager ?? ""; + nilai.text = proyek.nilai.toString(); + selectedDate = DateTime.parse(proyek.start!); + selectedDate2 = DateTime.parse(proyek.finish!); + klien.text = proyek.klien ?? ""; + selectedUserId = + proyek.taskProyek!.map((task) => task.userId).toList(); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } + return SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + SizedBox(height: defaultPadding), + customformProyek( + title: "Nama Proyek", + controller: nama, + ), + customformProyek( + title: "Klien", + controller: klien, + ), + customformProyek( + title: "Detail", + controller: detail, + ), + customformProyek( + title: "Nilai", + controller: nilai, + ), + customformProyek( + title: "Manager", + controller: manager, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Start", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox( + height: 8, + ), + InkWell( + onTap: () { + showDatePicker( + context: context, + initialDate: selectedDate, + firstDate: DateTime(1800), + lastDate: DateTime(2300), + ).then( + (value) { + setState(() { + selectedDate = value; + }); + print("selectDate : $selectedDate"); + }, + ); + }, + child: Container( + height: 50, + padding: EdgeInsets.only(left: 8), + width: double.infinity, + decoration: BoxDecoration( + border: Border.all( + color: Colors.white, + width: 1, // Lebar border + ), + borderRadius: BorderRadius.circular( + 14), // Radius border + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + selectedDate != null + ? DateFormat('yyyy-MM-dd') + .format(selectedDate!) + : "Select Date", + style: TextStyle( + fontSize: 14, color: Colors.white), + ) + ], + ), + ), + ), + const SizedBox( + height: 8, + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Finish", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox( + height: 8, + ), + InkWell( + onTap: () { + selectDate2(context); + }, + child: Container( + height: 50, + padding: EdgeInsets.only(left: 8), + width: double.infinity, + decoration: BoxDecoration( + border: Border.all( + color: Colors.white, + width: 1, // Lebar border + ), + borderRadius: BorderRadius.circular( + 14), // Radius border + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + selectedDate2 != null + ? DateFormat('yyyy-MM-dd') + .format(selectedDate!) + : "Select Date", + style: TextStyle( + fontSize: 14, color: Colors.white), + ) + ], + ), + ), + ), + const SizedBox( + height: 8, + ), + ], + ), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + if (Responsive.isMobile(context)) fileproyek(), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + if (!Responsive.isMobile(context)) + Expanded( + flex: 2, + child: Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: + const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Files", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: defaultPadding), + fileCardProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + fileCardProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + SizedBox(height: defaultPadding), + Center( + child: Container( + width: double.infinity, + child: ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: defaultPadding / + (Responsive.isMobile(context) + ? 2 + : 1), + ), + ), + onPressed: () { + storeProyek(); + }, + icon: isLoading + ? CircularProgressIndicator( + color: Colors.white, + ) + : Icon(Icons.save), + label: isLoading + ? Text("Menyimpan...") + : Text("Simpan"), + ), + ), + ), + ], + ), + ), + ), + ], + ) + ], + ), + ); + }, + )), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/detailProyek.dart b/dashboard_sim/lib/page/proyek/detailProyek.dart new file mode 100644 index 0000000..cb670a0 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/detailProyek.dart @@ -0,0 +1,313 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:drawer/page/proyek/widget/widget%20detail%20proyek/filecarddetail.dart'; +import 'package:drawer/page/proyek/widget/widget%20detail%20proyek/tabel_task_proyek.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; + +class detailProyek extends StatelessWidget { + String? id; + detailProyek({this.id, super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + BlocProvider( + create: (context) => + ProyekBloc(proyekServices: ProyekServices()) + ..add(GetProyekById(userId: id ?? "")), + child: BlocBuilder( + builder: (context, state) { + if (state is ProyekLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (state is ProyekByIdLoaded) { + final proyek = state.proyek; + return Container( + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.circular( + 20, + )), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + proyek.nama ?? "", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 20, + ), + Text( + proyek.detail ?? "", + textAlign: TextAlign.justify, + ), + Wrap( + children: [ + Container( + padding: EdgeInsets.only( + right: defaultPadding, + top: defaultPadding, + bottom: defaultPadding), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Start :", + style: TextStyle( + fontWeight: + FontWeight.bold, + ), + ), + // Text(proyek.start.toString()), + Text(DateFormat( + 'EEEE, MMMM d, y') + .format(DateTime.parse( + proyek.start!))) + ], + ), + ), + Container( + padding: EdgeInsets.only( + right: defaultPadding, + top: defaultPadding, + bottom: defaultPadding), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Finish :", + style: TextStyle( + fontWeight: + FontWeight.bold, + ), + ), + Text(DateFormat( + 'EEEE, MMMM d, y') + .format(DateTime.parse( + proyek.finish!))) + ], + ), + ), + Container( + padding: EdgeInsets.only( + right: defaultPadding, + top: defaultPadding, + bottom: defaultPadding), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Klien :", + style: TextStyle( + fontWeight: + FontWeight.bold, + ), + ), + Text(proyek.klien ?? ""), + ], + ), + ), + ], + ), + Wrap( + children: [ + Text( + "Created by: ${proyek.user?.name ?? "Unknown"}", + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ], + ), + Wrap( + children: [ + Text( + "Team : ", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + proyek.taskProyek != null && + proyek + .taskProyek!.isNotEmpty + ? Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: proyek.taskProyek! + .map((task) { + return Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: task + .penerimaProyek! + .map((penerima) { + return Row( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + penerima.user + ?.name ?? + "No Name", + style: + const TextStyle( + fontWeight: + FontWeight + .bold, + ), + ), + Text( + " - ${task.tugas}" ?? + " - No Task", + ), + ], + ); + }).toList(), + ); + }).toList(), + ) + : const Text("No team members"), + ], + ) + ], + ), + ); + } else if (state is ProyekError) { + return Center( + child: Text( + 'Failed to load user: ${state.error}'), + ); + } else { + return const Center( + child: Text('Unknown state'), + ); + } + }, + )), + SizedBox( + height: 20, + ), + Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.circular( + 20, + )), + child: tabelTaskProyek( + id: id, + ), + ), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + if (Responsive.isMobile(context)) filedetailproyek(), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + if (!Responsive.isMobile(context)) + Expanded( + flex: 2, + child: filedetailproyek(), + ), + ], + ) + ], + ), + ), + ), + ); + } +} + +class filedetailproyek extends StatelessWidget { + const filedetailproyek({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Files", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: defaultPadding), + fileCardDetailProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + fileCardDetailProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + SizedBox(height: defaultPadding), + Center( + child: Container( + width: double.infinity, + child: ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () {}, + icon: Icon(Icons.save), + label: Text("Simpan"), + ), + ), + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/proyek.dart b/dashboard_sim/lib/page/proyek/proyek.dart new file mode 100644 index 0000000..6c90baf --- /dev/null +++ b/dashboard_sim/lib/page/proyek/proyek.dart @@ -0,0 +1,43 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/page/proyek/widget/tabel_file_proyek.dart'; +import 'package:drawer/page/sidebar/header.dart'; +import 'package:flutter/material.dart'; + +class proyek extends StatelessWidget { + const proyek({super.key}); + + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + primary: false, + padding: EdgeInsets.all(defaultPadding), + child: Column( + children: [ + Header(), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + children: [ + SizedBox(height: defaultPadding), + proyekfile(), + if (Responsive.isMobile(context)) + SizedBox(height: defaultPadding), + ], + ), + ), + if (!Responsive.isMobile(context)) + SizedBox(width: defaultPadding), + ], + ) + ], + ), + ), + ), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/widget/tabel_file_proyek.dart b/dashboard_sim/lib/page/proyek/widget/tabel_file_proyek.dart new file mode 100644 index 0000000..a82cfb0 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/tabel_file_proyek.dart @@ -0,0 +1,275 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/models/data.dart'; +import 'package:drawer/page/proyek/addProyek.dart'; +import 'package:drawer/page/proyek/widget/topjudulproyek.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class proyekfile extends StatelessWidget { + const proyekfile({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: BlocProvider( + create: (context) => + ProyekBloc(proyekServices: ProyekServices())..add(LoadProyek()), + child: BlocBuilder( + builder: (context, state) { + if (state is ProyekLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } else if (state is ProyekLoaded) { + final proyeks = state.proyeks; + return FutureBuilder>( + future: _buildDataRows(context, proyeks), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + topjudulproyek(), + SizedBox( + width: double.infinity, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: ScrollController(), + child: DataTable( + columnSpacing: defaultPadding, + columns: const [ + DataColumn( + label: Text("No"), + ), + DataColumn( + label: Text("Project Name"), + ), + DataColumn( + label: Text("Klien"), + ), + DataColumn( + label: Text("Manager"), + ), + DataColumn( + label: Text("Start"), + ), + DataColumn( + label: Text("Finished"), + ), + DataColumn( + label: Text("Nilai"), + ), + DataColumn( + label: Text("Aksi"), + ), + ], + rows: snapshot.data!, + ), + ), + ), + ], + ); + } + }, + ); + } + return SizedBox(); + }, + ), + ), + ); + } + + Future> _buildDataRows( + BuildContext context, List proyeks) async { + List dataRows = []; + for (int index = 0; index < proyeks.length; index++) { + DataRow dataRow = + await proyekFileDataRow(context, proyeks[index], index + 1); + dataRows.add(dataRow); + } + return dataRows; + } +} + +void deleteData(String id, BuildContext context) async { + try { + final proyekService = ProyekServices(); + await proyekService.deleteProyekById(id); + Fluttertoast.showToast( + msg: "Delete proyek successfully", toastLength: Toast.LENGTH_LONG); + context.read().setSelectedItem('dashboard'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to delete proyek: $e", toastLength: Toast.LENGTH_LONG); + } +} + +Future proyekFileDataRow( + BuildContext context, Proyek proyek, int id) async { + final prefs = await SharedPreferences.getInstance(); + final roleId = prefs.getInt('role_id') ?? 0; + return DataRow( + cells: [ + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 50, + child: Text(id.toString()), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 200, + child: Text(proyek.nama!), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 200, + child: Text(proyek.klien!), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 200, + child: Text(proyek.manager!), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 200, + child: Text(DateFormat('EEEE, MMMM d, y') + .format(DateTime.parse(proyek.start!))), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 200, + child: Text(DateFormat('EEEE, MMMM d, y') + .format(DateTime.parse(proyek.finish!))), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + context + .read() + .setSelectedItem('detail proyek', id: proyek.id.toString()); + }, + child: Container( + width: 100, + child: Text("${proyek.nilai}%"), + ), + ), + ), + roleId != 4 + ? DataCell( + Row( + children: [ + IconButton( + color: Colors.blue, + onPressed: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => addProyek( + // id: proyek.id.toString(), + // isUpdate: true, + // proyek: proyek), + // )); + context.read().setSelectedItem( + 'add proyek', + id: proyek.id.toString(), + isUpdate: true, + proyeks: proyek); + }, + icon: Icon(Icons.edit_note_outlined)), + IconButton( + color: Colors.red, + onPressed: () { + AwesomeDialog( + width: 500, + context: context, + animType: AnimType.scale, + title: "Warning", + btnCancelOnPress: () {}, + btnOkOnPress: () { + deleteData(proyek.id.toString(), context); + }, + desc: "Are you sure to delete the data?") + .show(); + }, + icon: Icon(Icons.remove_circle_outline_sharp)), + ], + ), + ) + : DataCell(Text('')) + ], + ); +} diff --git a/dashboard_sim/lib/page/proyek/widget/topjudulproyek.dart b/dashboard_sim/lib/page/proyek/widget/topjudulproyek.dart new file mode 100644 index 0000000..b69f342 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/topjudulproyek.dart @@ -0,0 +1,84 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/proyek.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class topjudulproyek extends StatelessWidget { + // Proyek? proyek; + topjudulproyek({ + Key? key, + // this.proyek, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final Size _size = MediaQuery.of(context).size; + return FutureBuilder( + future: _getRoleId(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return CircularProgressIndicator(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + final roleId = snapshot.data!; + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Proyek", + style: Theme.of(context).textTheme.titleMedium, + ), + if (roleId != 4) + ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: defaultPadding / + (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () { + context.read().setSelectedItem( + 'add proyek', + id: "", + isUpdate: false, + proyeks: Proyek( + id: 0, + userId: 0, + nama: "", + detail: "", + manager: "", + file: "", + start: "", + finish: "", + createdAt: "", + nilai: 0, + klien: "", + updatedAt: "", + taskProyek: [])); + }, + icon: Icon(Icons.add), + label: Text("Add New"), + ), + ], + ), + SizedBox(height: defaultPadding), + ], + ); + } + }, + ); + } + + Future _getRoleId() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getInt('role_id') ?? 0; + } +} diff --git a/dashboard_sim/lib/page/proyek/widget/widget add proyek/file_proyek.dart b/dashboard_sim/lib/page/proyek/widget/widget add proyek/file_proyek.dart new file mode 100644 index 0000000..4ece110 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/widget add proyek/file_proyek.dart @@ -0,0 +1,58 @@ +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/page/proyek/widget/widget%20add%20proyek/filecard.dart'; +import 'package:flutter/material.dart'; +import 'package:drawer/constants/constants.dart'; + +class fileproyek extends StatelessWidget { + const fileproyek({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Files", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: defaultPadding), + fileCardProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + fileCardProyek( + svgSrc: "assets/icons/media.svg", + jabatan: "manager", + ), + SizedBox(height: defaultPadding), + Center( + child: Container( + width: double.infinity, + child: ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () {}, + icon: Icon(Icons.save), + label: Text("Simpan"), + ), + ), + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/widget/widget add proyek/filecard.dart b/dashboard_sim/lib/page/proyek/widget/widget add proyek/filecard.dart new file mode 100644 index 0000000..6b61f49 --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/widget add proyek/filecard.dart @@ -0,0 +1,79 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class fileCardProyek extends StatelessWidget { + const fileCardProyek({ + Key? key, + required this.svgSrc, + required this.jabatan, + }) : super(key: key); + + final String svgSrc, jabatan; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(top: defaultPadding), + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)), + borderRadius: const BorderRadius.all( + Radius.circular(defaultPadding), + ), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, // Mengatur teks agar berada di kiri + children: [ + SizedBox( + height: 100, + width: 100, + child: SvgPicture.asset(svgSrc), + ), + SizedBox( + width: + defaultPadding), // Spacer horizontal antara gambar dan teks + Column( + crossAxisAlignment: + CrossAxisAlignment.start, // Mengatur teks agar berada di kiri + children: [ + Text( + "Foto Profil", + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + jabatan, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.white70), + ), + SizedBox( + height: 20, + ), + ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: + defaultPadding / (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () { + // context.read().setSelectedItem('add karyawan'); + }, + icon: Icon(Icons.upload), + label: Text("Upload Foto"), + ), + ], + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/widget/widget add proyek/formproyek.dart b/dashboard_sim/lib/page/proyek/widget/widget add proyek/formproyek.dart new file mode 100644 index 0000000..29fe17f --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/widget add proyek/formproyek.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +class customformProyek extends StatelessWidget { + final String title; + final bool obscuretext; + final TextEditingController? controller; + final bool isShowtitle; + final TextInputType? keyboardType; + + const customformProyek( + {Key? key, + required this.title, + this.obscuretext = false, + this.controller, + this.isShowtitle = true, + this.keyboardType}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (isShowtitle) + Text( + title, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + if (isShowtitle) + const SizedBox( + height: 8, + ), + TextFormField( + keyboardType: keyboardType, + obscureText: obscuretext, + controller: controller, + decoration: InputDecoration( + hintText: !isShowtitle ? title : null, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(14), + ), + contentPadding: const EdgeInsets.all(12), + ), + ), + const SizedBox( + height: 8, + ), + ], + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/widget/widget detail proyek/filecarddetail.dart b/dashboard_sim/lib/page/proyek/widget/widget detail proyek/filecarddetail.dart new file mode 100644 index 0000000..30c1a2b --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/widget detail proyek/filecarddetail.dart @@ -0,0 +1,57 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class fileCardDetailProyek extends StatelessWidget { + const fileCardDetailProyek({ + Key? key, + required this.svgSrc, + required this.jabatan, + }) : super(key: key); + + final String svgSrc, jabatan; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(top: defaultPadding), + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(width: 2, color: primaryColor.withOpacity(0.15)), + borderRadius: const BorderRadius.all( + Radius.circular(defaultPadding), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: 60, + width: 60, + child: SvgPicture.asset(svgSrc), + ), + SizedBox(width: defaultPadding), + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Foto Profil", + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + jabatan, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.white70), + ), + ], + ), + ], + ), + ); + } +} diff --git a/dashboard_sim/lib/page/proyek/widget/widget detail proyek/tabel_task_proyek.dart b/dashboard_sim/lib/page/proyek/widget/widget detail proyek/tabel_task_proyek.dart new file mode 100644 index 0000000..8ceb36b --- /dev/null +++ b/dashboard_sim/lib/page/proyek/widget/widget detail proyek/tabel_task_proyek.dart @@ -0,0 +1,357 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/data/model/penerima_proyek.dart'; +import 'package:drawer/data/model/task_proyek.dart'; +import 'package:drawer/data/services/proyek/proyek_bloc.dart'; +import 'package:drawer/data/services/proyek/proyek_service.dart'; +import 'package:drawer/data/services/proyek/task/task_service.dart'; +import 'package:drawer/models/data.dart'; +import 'package:drawer/page/proyek/add_task_proyek.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class tabelTaskProyek extends StatelessWidget { + String? id; + + tabelTaskProyek({ + this.id, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getRoleId(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return CircularProgressIndicator(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + final roleId = snapshot.data!; + return Container( + width: double.infinity, + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Data Pekerjaan", + style: Theme.of(context).textTheme.titleMedium, + ), + if (roleId != 4) + ElevatedButton.icon( + style: TextButton.styleFrom( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding * 1.5, + vertical: defaultPadding / + (Responsive.isMobile(context) ? 2 : 1), + ), + ), + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + idTask: id ?? "", + isUpdate: false, + taskProyek: TaskProyek(), + id: id ?? "", + ); + }, + ); + }, + icon: Icon(Icons.add_task), + label: Text("Tambah Tugas"), + ), + ], + ), + SizedBox(height: defaultPadding), + SizedBox( + width: double.infinity, + child: BlocProvider( + create: (context) => + ProyekBloc(proyekServices: ProyekServices()) + ..add(GetProyekById(userId: id ?? "")), + child: BlocBuilder( + builder: (context, state) { + if (state is ProyekLoading) { + return Center( + child: CircularProgressIndicator(), + ); + } else if (state is ProyekError) { + return Center(child: Text('Error: ${state.error}')); + } else if (state is ProyekByIdLoaded) { + final task = state.proyek.taskProyek; + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: ScrollController(), + child: DataTable( + columnSpacing: defaultPadding, + columns: const [ + DataColumn( + label: Text("Tugas"), + ), + DataColumn( + label: Text("Catatan"), + ), + DataColumn( + label: Text("Pekerja"), + ), + DataColumn( + label: Text("Start"), + ), + DataColumn( + label: Text("Deadline"), + ), + DataColumn( + label: Text("Status"), + ), + DataColumn( + label: Text("Nilai"), + ), + DataColumn( + label: Text("Aksi"), + ), + ], + // Rows + rows: List.generate( + task!.length, + (index) => recentTaskDataRow( + context, task[index], id ?? ""), + ), + ), + ); + } + return SizedBox(); + }, + )), + ), + ], + ), + ); + } + }, + ); + } + + Future _getRoleId() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getInt('role_id') ?? 0; + } +} + +DataRow recentTaskDataRow(BuildContext context, TaskProyek task, String id) { + return DataRow( + cells: [ + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + isUpdate: true, + idTask: id, + taskProyek: task, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.tugas ?? ""), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + isUpdate: true, + idTask: id, + taskProyek: task, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.catatan ?? ""), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + idTask: id, + taskProyek: task, + isUpdate: true, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.penerimaProyek != null + ? getPenerimaNames(task.penerimaProyek) + : ""), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + idTask: id, + taskProyek: task, + isUpdate: true, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.start ?? ""), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + idTask: id, + taskProyek: task, + isUpdate: true, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.deadline ?? ""), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + idTask: id, + taskProyek: task, + isUpdate: true, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.status ?? ""), + ), + ), + ), + DataCell( + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return add_task( + id: task.id.toString(), + idTask: id, + taskProyek: task, + isUpdate: true, + ); + }, + ); + }, + child: Container( + width: 200, + padding: EdgeInsets.symmetric(horizontal: 10), + child: Text(task.nilai == null ? "0%" : "${task.nilai}%"), + ), + ), + ), + DataCell( + SizedBox( + width: 100, + child: IconButton( + color: Colors.red, + onPressed: () { + AwesomeDialog( + width: 500, + context: context, + animType: AnimType.scale, + title: "Warning", + btnCancelOnPress: () {}, + btnOkOnPress: () { + deleteData(task.id.toString(), context); + }, + desc: "Are you sure to delete the data?") + .show(); + }, + icon: Icon(Icons.remove_circle_outline_sharp)), + ), + ), + ], + ); +} + +String getPenerimaNames(List? penerimaProyek) { + if (penerimaProyek == null || penerimaProyek.isEmpty) { + return ""; + } + return penerimaProyek.map((penerima) => penerima.user!.name).join(', '); +} + +void deleteData(String id, BuildContext context) async { + try { + final taskServices = TaskService(); + await taskServices.deleteTasksById(id); + Fluttertoast.showToast( + msg: "Delete proyek successfully", toastLength: Toast.LENGTH_LONG); + context.read().setSelectedItem('proyek'); + } catch (e) { + Fluttertoast.showToast( + msg: "Failed to delete proyek: $e", toastLength: Toast.LENGTH_LONG); + } +} diff --git a/dashboard_sim/lib/page/sidebar/header.dart b/dashboard_sim/lib/page/sidebar/header.dart new file mode 100644 index 0000000..e7c2d36 --- /dev/null +++ b/dashboard_sim/lib/page/sidebar/header.dart @@ -0,0 +1,202 @@ +import 'package:drawer/constants/constants.dart'; +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/page/login/login.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class Header extends StatelessWidget { + const Header({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final selectedItem = context.watch().selectedItem; + String pageTitle = ''; + + // Memperbarui nilai pageTitle sesuai dengan selectedItem + if (selectedItem == 'dashboard') { + pageTitle = 'Dashboard'; + } else if (selectedItem == 'karyawan') { + pageTitle = 'Karyawan'; + } else if (selectedItem == 'proyek') { + pageTitle = 'Proyek'; + } else if (selectedItem == 'add karyawan') { + pageTitle = 'Tambah Karyawan'; + } else if (selectedItem == 'add proyek') { + pageTitle = 'Tambah Proyek'; + } else if (selectedItem == 'Detail Karyawan') { + pageTitle = 'Detail Karyawan'; + } else if (selectedItem == 'detail proyek') { + pageTitle = 'Detail Proyek'; + } + + return Row( + children: [ + if (!Responsive.isDesktop(context)) + IconButton( + icon: Icon(Icons.menu), + onPressed: context.read().controlMenu, + ), + if (!Responsive.isMobile(context)) + Text( + pageTitle, + style: Theme.of(context).textTheme.titleLarge, + ), + if (!Responsive.isMobile(context)) + Spacer(flex: Responsive.isDesktop(context) ? 2 : 1), + Expanded(child: SearchField()), + ProfileCard() + ], + ); + } +} + +class ProfileCard extends StatelessWidget { + const ProfileCard({ + Key? key, + }) : super(key: key); + + Future _getName() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString('name') ?? 'Unknown User'; + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getName(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (snapshot.hasError) { + return const Center( + child: Text('Error loading name'), + ); + } else { + final name = snapshot.data ?? 'Unknown User'; + return InkWell( + onTap: () { + showMenu( + context: context, + position: RelativeRect.fromLTRB( + MediaQuery.of(context).size.width - 50, // right + 50, + 0, + 0), + items: [ + const PopupMenuItem( + value: 0, + child: Row( + children: [ + Icon( + Icons.logout, + color: Colors.white, + size: 20, + ), + SizedBox( + width: 10, + ), + Text( + "LogOut", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ], + )), + ]).then((value) { + if (value != null) { + if (value == 0) { + _logout(context); + } + } + }); + }, + child: Container( + margin: EdgeInsets.only(left: defaultPadding), + padding: EdgeInsets.symmetric( + horizontal: defaultPadding, + vertical: defaultPadding / 2, + ), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + border: Border.all(color: Colors.white10), + ), + child: Row( + children: [ + Image.asset( + "assets/images/profile_pic.png", + height: 38, + ), + if (!Responsive.isMobile(context)) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: defaultPadding / 2, + ), + child: Text(name), + ), + InkWell( + onTap: () {}, + child: const Icon(Icons.keyboard_arrow_down)), + ], + ), + ), + ); + } + }, + ); + } +} + +void _logout(BuildContext context) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.remove('token'); + await prefs.remove('role_id'); + await prefs.remove('name'); + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => Login(), + )); + Fluttertoast.showToast( + msg: "Berhasil logout", toastLength: Toast.LENGTH_LONG); +} + +class SearchField extends StatelessWidget { + const SearchField({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return TextField( + decoration: InputDecoration( + hintText: "Search", + fillColor: secondaryColor, + filled: true, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + suffixIcon: InkWell( + onTap: () {}, + child: Container( + padding: EdgeInsets.all(defaultPadding * 0.75), + margin: EdgeInsets.symmetric(horizontal: defaultPadding / 2), + decoration: BoxDecoration( + color: primaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: SvgPicture.asset("assets/icons/Search.svg"), + ), + ), + ), + ); + } +} diff --git a/dashboard_sim/lib/page/sidebar/main_screen.dart b/dashboard_sim/lib/page/sidebar/main_screen.dart new file mode 100644 index 0000000..5df9360 --- /dev/null +++ b/dashboard_sim/lib/page/sidebar/main_screen.dart @@ -0,0 +1,79 @@ +import 'package:drawer/constants/responsive.dart'; +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:drawer/page/dashboard/dashboard.dart'; +import 'package:drawer/page/karyawan/addKaryawan.dart'; +import 'package:drawer/page/karyawan/detailKaryawan.dart'; +import 'package:drawer/page/karyawan/detailKaryawan.dart'; +import 'package:drawer/page/karyawan/karyawan.dart'; +import 'package:drawer/page/proyek/addProyek.dart'; +import 'package:drawer/page/proyek/detailProyek.dart'; +import 'package:drawer/page/proyek/proyek.dart'; +import 'package:drawer/page/sidebar/side_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class MainScreen extends StatelessWidget { + const MainScreen({super.key}); + @override + Widget build(BuildContext context) { + final selectedItem = context.watch().selectedItem; + final selectedItemId = context.watch().selectedItemId; + final selectedItemUpdate = context.watch().isUpdateItem; + final selectedItemProyek = context.watch().proyek; + final selectedItemUser = context.watch().user; + final selectedItemTask = context.watch().task; + Widget? selectedPage; + + if (selectedItem == 'dashboard') { + selectedPage = const dashboard(); + } else if (selectedItem == 'proyek') { + selectedPage = const proyek(); + } else if (selectedItem == 'karyawan') { + selectedPage = const karyawan(); + } else if (selectedItem == 'add karyawan' && + selectedItemId != null && + selectedItemUpdate != null && + selectedItemUser != null) { + selectedPage = addKaryawan( + id: selectedItemId, + isUpdate: selectedItemUpdate, + user: selectedItemUser, + ); + } else if (selectedItem == 'add proyek' && + selectedItemId != null && + selectedItemUpdate != null && + selectedItemProyek != null) { + selectedPage = addProyek( + id: selectedItemId, + isUpdate: selectedItemUpdate, + proyek: selectedItemProyek, + ); + } else if (selectedItem == 'detail karyawan' && selectedItemId != null) { + selectedPage = detailKaryawan(idUser: selectedItemId); + } else if (selectedItem == 'detail proyek' && selectedItemId != null) { + selectedPage = detailProyek( + id: selectedItemId, + ); + } + + return Scaffold( + key: context.read().scaffoldKey, + drawer: SideMenu(), + body: SafeArea( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (Responsive.isDesktop(context)) + Expanded( + child: SideMenu(), + ), + Expanded( + flex: 5, + child: selectedPage ?? Container(), + ), + ], + ), + ), + ); + } +} diff --git a/dashboard_sim/lib/page/sidebar/side_menu.dart b/dashboard_sim/lib/page/sidebar/side_menu.dart new file mode 100644 index 0000000..a6967ba --- /dev/null +++ b/dashboard_sim/lib/page/sidebar/side_menu.dart @@ -0,0 +1,108 @@ +import 'package:drawer/controller/MenuAppController.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class SideMenu extends StatelessWidget { + const SideMenu({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getRoleId(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return CircularProgressIndicator(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + final roleId = snapshot.data ?? 0; + return Drawer( + child: ListView( + children: [ + DrawerHeader( + child: Image.asset("assets/photos/logo2.png"), + ), + DrawerListTile( + title: "Dashboard", + svgSrc: "assets/icons/menu_dashboard.svg", + press: () { + context + .read() + .setSelectedItem('dashboard'); + }, + ), + if (roleId != 4) + DrawerListTile( + title: "karyawan", + svgSrc: "assets/icons/menu_tran.svg", + press: () { + context + .read() + .setSelectedItem('karyawan'); + }, + ), + DrawerListTile( + title: "Proyek", + svgSrc: "assets/icons/menu_task.svg", + press: () { + context.read().setSelectedItem('proyek'); + }, + ), + DrawerListTile( + title: "Profile", + svgSrc: "assets/icons/menu_profile.svg", + press: () {}, + ), + DrawerListTile( + title: "Settings", + svgSrc: "assets/icons/menu_setting.svg", + press: () {}, + ), + ], + ), + ); + } + }, + ); + } + + Future _getRoleId() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getInt('role_id') ?? + 0; // Nilai default dapat disesuaikan sesuai kebutuhan + } +} + +class DrawerListTile extends StatelessWidget { + const DrawerListTile({ + Key? key, + // For selecting those three line once press "Command+D" + required this.title, + required this.svgSrc, + required this.press, + }) : super(key: key); + + final String title, svgSrc; + final VoidCallback press; + + @override + Widget build(BuildContext context) { + return ListTile( + onTap: press, + horizontalTitleGap: 0.0, + leading: SvgPicture.asset( + svgSrc, + colorFilter: ColorFilter.mode(Colors.white54, BlendMode.srcIn), + height: 16, + ), + title: Text( + title, + style: TextStyle(color: Colors.white54), + ), + ); + } +} diff --git a/dashboard_sim/linux/.gitignore b/dashboard_sim/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/dashboard_sim/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/dashboard_sim/linux/CMakeLists.txt b/dashboard_sim/linux/CMakeLists.txt new file mode 100644 index 0000000..bd8bb90 --- /dev/null +++ b/dashboard_sim/linux/CMakeLists.txt @@ -0,0 +1,145 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "drawer") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.drawer") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/dashboard_sim/linux/flutter/CMakeLists.txt b/dashboard_sim/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/dashboard_sim/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/dashboard_sim/linux/flutter/generated_plugin_registrant.cc b/dashboard_sim/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..5160f4d --- /dev/null +++ b/dashboard_sim/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,19 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) rive_common_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "RivePlugin"); + rive_plugin_register_with_registrar(rive_common_registrar); +} diff --git a/dashboard_sim/linux/flutter/generated_plugin_registrant.h b/dashboard_sim/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/dashboard_sim/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/dashboard_sim/linux/flutter/generated_plugins.cmake b/dashboard_sim/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..bd11bdc --- /dev/null +++ b/dashboard_sim/linux/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux + rive_common +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/dashboard_sim/linux/main.cc b/dashboard_sim/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/dashboard_sim/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/dashboard_sim/linux/my_application.cc b/dashboard_sim/linux/my_application.cc new file mode 100644 index 0000000..7c38123 --- /dev/null +++ b/dashboard_sim/linux/my_application.cc @@ -0,0 +1,124 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "drawer"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "drawer"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/dashboard_sim/linux/my_application.h b/dashboard_sim/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/dashboard_sim/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/dashboard_sim/macos/.gitignore b/dashboard_sim/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/dashboard_sim/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/dashboard_sim/macos/Flutter/Flutter-Debug.xcconfig b/dashboard_sim/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/dashboard_sim/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/dashboard_sim/macos/Flutter/Flutter-Release.xcconfig b/dashboard_sim/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/dashboard_sim/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/dashboard_sim/macos/Flutter/GeneratedPluginRegistrant.swift b/dashboard_sim/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..18ec264 --- /dev/null +++ b/dashboard_sim/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,18 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import file_selector_macos +import path_provider_foundation +import rive_common +import shared_preferences_foundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) +} diff --git a/dashboard_sim/macos/Runner.xcodeproj/project.pbxproj b/dashboard_sim/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e5dccd7 --- /dev/null +++ b/dashboard_sim/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* drawer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "drawer.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* drawer.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* drawer.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/drawer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/drawer"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/drawer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/drawer"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/drawer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/drawer"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/dashboard_sim/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dashboard_sim/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/dashboard_sim/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dashboard_sim/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/dashboard_sim/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..4f25897 --- /dev/null +++ b/dashboard_sim/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard_sim/macos/Runner.xcworkspace/contents.xcworkspacedata b/dashboard_sim/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/dashboard_sim/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/dashboard_sim/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dashboard_sim/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/dashboard_sim/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dashboard_sim/macos/Runner/AppDelegate.swift b/dashboard_sim/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/dashboard_sim/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..82b6f9d Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..13b35eb Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..0a3f5fa Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bdb5722 Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..f083318 Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..326c0e7 Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..2f1632c Binary files /dev/null and b/dashboard_sim/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/dashboard_sim/macos/Runner/Base.lproj/MainMenu.xib b/dashboard_sim/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/dashboard_sim/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard_sim/macos/Runner/Configs/AppInfo.xcconfig b/dashboard_sim/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..3cfc3d2 --- /dev/null +++ b/dashboard_sim/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = drawer + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.drawer + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. diff --git a/dashboard_sim/macos/Runner/Configs/Debug.xcconfig b/dashboard_sim/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/dashboard_sim/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/dashboard_sim/macos/Runner/Configs/Release.xcconfig b/dashboard_sim/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/dashboard_sim/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/dashboard_sim/macos/Runner/Configs/Warnings.xcconfig b/dashboard_sim/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/dashboard_sim/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/dashboard_sim/macos/Runner/DebugProfile.entitlements b/dashboard_sim/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/dashboard_sim/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/dashboard_sim/macos/Runner/Info.plist b/dashboard_sim/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/dashboard_sim/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/dashboard_sim/macos/Runner/MainFlutterWindow.swift b/dashboard_sim/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..3cc05eb --- /dev/null +++ b/dashboard_sim/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/dashboard_sim/macos/Runner/Release.entitlements b/dashboard_sim/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/dashboard_sim/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/dashboard_sim/macos/RunnerTests/RunnerTests.swift b/dashboard_sim/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..5418c9f --- /dev/null +++ b/dashboard_sim/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/dashboard_sim/pubspec.lock b/dashboard_sim/pubspec.lock new file mode 100644 index 0000000..d7164c1 --- /dev/null +++ b/dashboard_sim/pubspec.lock @@ -0,0 +1,714 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + awesome_dialog: + dependency: "direct main" + description: + name: awesome_dialog + sha256: "41c41ae4b30b5c7f26bb3d9f9c87010ed1cab0bb4d4ac0cc513e5799c37e9d82" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + bloc: + dependency: transitive + description: + name: bloc + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" + url: "https://pub.dev" + source: hosted + version: "8.1.4" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + url: "https://pub.dev" + source: hosted + version: "0.3.4+1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" + source: hosted + version: "1.0.6" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: d0f0d49112f2f4b192481c16d05b6418bd7820e021e265a3c22db98acf7ed7fb + url: "https://pub.dev" + source: hosted + version: "0.68.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2 + url: "https://pub.dev" + source: hosted + version: "8.1.5" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + url: "https://pub.dev" + source: hosted + version: "2.0.19" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "81b68579e23fcbcada2db3d50302813d2371664afe6165bc78148050ab94bf66" + url: "https://pub.dev" + source: hosted + version: "8.2.5" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 + url: "https://pub.dev" + source: hosted + version: "6.2.1" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + http: + dependency: "direct main" + description: + name: http + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "33974eca2e87e8b4e3727f1b94fa3abcb25afe80b6bc2c4d449a0e150aedf720" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "0f57fee1e8bfadf8cc41818bbcd7f72e53bb768a54d9496355d5e8a5681a19f1" + url: "https://pub.dev" + source: hosted + version: "0.8.12+1" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3" + url: "https://pub.dev" + source: hosted + version: "3.0.4" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "4824d8c7f6f89121ef0122ff79bb00b009607faecc8545b86bca9ab5ce1e95bf" + url: "https://pub.dev" + source: hosted + version: "0.8.11+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" + url: "https://pub.dev" + source: hosted + version: "2.10.0" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + meta: + dependency: transitive + description: + name: meta + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + mime: + dependency: transitive + description: + name: mime + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + multi_dropdown: + dependency: "direct main" + description: + name: multi_dropdown + sha256: b63ff339fcc875d667f8688c8ef62853545b580dd2b6fe78b73339783268afd8 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + provider: + dependency: "direct main" + description: + name: provider + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + url: "https://pub.dev" + source: hosted + version: "6.1.2" + random_string: + dependency: "direct main" + description: + name: random_string + sha256: "03b52435aae8cbdd1056cf91bfc5bf845e9706724dd35ae2e99fa14a1ef79d02" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + rive: + dependency: transitive + description: + name: rive + sha256: "255ab7892a77494458846cecee1376a017e64fd6b4130b51ec21424d12ffa6fe" + url: "https://pub.dev" + source: hosted + version: "0.13.4" + rive_common: + dependency: transitive + description: + name: rive_common + sha256: "3a0d95f529d52caef535d8ff32d75629ca37f7ab4707b13c83e9552a322557bc" + url: "https://pub.dev" + source: hosted + version: "0.4.8" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + url: "https://pub.dev" + source: hosted + version: "2.2.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" + url: "https://pub.dev" + source: hosted + version: "5.4.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" +sdks: + dart: ">=3.3.3 <4.0.0" + flutter: ">=3.19.2" diff --git a/dashboard_sim/pubspec.yaml b/dashboard_sim/pubspec.yaml new file mode 100644 index 0000000..6643f1f --- /dev/null +++ b/dashboard_sim/pubspec.yaml @@ -0,0 +1,88 @@ +name: drawer +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: ">=3.3.3 <4.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + awesome_dialog: ^3.2.1 + cupertino_icons: ^1.0.6 + fl_chart: ^0.68.0 + flutter: + sdk: flutter + flutter_bloc: ^8.1.5 + flutter_svg: ^2.0.10+1 + fluttertoast: ^8.2.5 + google_fonts: ^6.2.1 + http: ^1.2.1 + image_picker: ^1.1.1 + intl: ^0.19.0 + multi_dropdown: ^2.1.4 + provider: ^6.1.2 + random_string: ^2.3.1 + shared_preferences: ^2.2.3 + +dev_dependencies: + flutter_lints: ^3.0.0 + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec +# The following section is specific to Flutter packages. +flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/ + - assets/icons/ + - assets/photos/ + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/dashboard_sim/test/widget_test.dart b/dashboard_sim/test/widget_test.dart new file mode 100644 index 0000000..5bfc428 --- /dev/null +++ b/dashboard_sim/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:drawer/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/dashboard_sim/web/favicon.png b/dashboard_sim/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/dashboard_sim/web/favicon.png differ diff --git a/dashboard_sim/web/icons/Icon-192.png b/dashboard_sim/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/dashboard_sim/web/icons/Icon-192.png differ diff --git a/dashboard_sim/web/icons/Icon-512.png b/dashboard_sim/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/dashboard_sim/web/icons/Icon-512.png differ diff --git a/dashboard_sim/web/icons/Icon-maskable-192.png b/dashboard_sim/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/dashboard_sim/web/icons/Icon-maskable-192.png differ diff --git a/dashboard_sim/web/icons/Icon-maskable-512.png b/dashboard_sim/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/dashboard_sim/web/icons/Icon-maskable-512.png differ diff --git a/dashboard_sim/web/index.html b/dashboard_sim/web/index.html new file mode 100644 index 0000000..aa3d50f --- /dev/null +++ b/dashboard_sim/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + drawer + + + + + + + + + + diff --git a/dashboard_sim/web/manifest.json b/dashboard_sim/web/manifest.json new file mode 100644 index 0000000..e59bbd4 --- /dev/null +++ b/dashboard_sim/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "drawer", + "short_name": "drawer", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/dashboard_sim/windows/.gitignore b/dashboard_sim/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/dashboard_sim/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/dashboard_sim/windows/CMakeLists.txt b/dashboard_sim/windows/CMakeLists.txt new file mode 100644 index 0000000..e09eb96 --- /dev/null +++ b/dashboard_sim/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(drawer LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "drawer") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/dashboard_sim/windows/flutter/CMakeLists.txt b/dashboard_sim/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..903f489 --- /dev/null +++ b/dashboard_sim/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/dashboard_sim/windows/flutter/generated_plugin_registrant.cc b/dashboard_sim/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..e1d3db4 --- /dev/null +++ b/dashboard_sim/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,17 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); + RivePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RivePlugin")); +} diff --git a/dashboard_sim/windows/flutter/generated_plugin_registrant.h b/dashboard_sim/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/dashboard_sim/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/dashboard_sim/windows/flutter/generated_plugins.cmake b/dashboard_sim/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..ed99bc4 --- /dev/null +++ b/dashboard_sim/windows/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows + rive_common +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/dashboard_sim/windows/runner/CMakeLists.txt b/dashboard_sim/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/dashboard_sim/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/dashboard_sim/windows/runner/Runner.rc b/dashboard_sim/windows/runner/Runner.rc new file mode 100644 index 0000000..978f932 --- /dev/null +++ b/dashboard_sim/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "drawer" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "drawer" "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "drawer.exe" "\0" + VALUE "ProductName", "drawer" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/dashboard_sim/windows/runner/flutter_window.cpp b/dashboard_sim/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..955ee30 --- /dev/null +++ b/dashboard_sim/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/dashboard_sim/windows/runner/flutter_window.h b/dashboard_sim/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/dashboard_sim/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/dashboard_sim/windows/runner/main.cpp b/dashboard_sim/windows/runner/main.cpp new file mode 100644 index 0000000..a319752 --- /dev/null +++ b/dashboard_sim/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"drawer", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/dashboard_sim/windows/runner/resource.h b/dashboard_sim/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/dashboard_sim/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/dashboard_sim/windows/runner/resources/app_icon.ico b/dashboard_sim/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/dashboard_sim/windows/runner/resources/app_icon.ico differ diff --git a/dashboard_sim/windows/runner/runner.exe.manifest b/dashboard_sim/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..a42ea76 --- /dev/null +++ b/dashboard_sim/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/dashboard_sim/windows/runner/utils.cpp b/dashboard_sim/windows/runner/utils.cpp new file mode 100644 index 0000000..b2b0873 --- /dev/null +++ b/dashboard_sim/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length <= 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/dashboard_sim/windows/runner/utils.h b/dashboard_sim/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/dashboard_sim/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/dashboard_sim/windows/runner/win32_window.cpp b/dashboard_sim/windows/runner/win32_window.cpp new file mode 100644 index 0000000..60608d0 --- /dev/null +++ b/dashboard_sim/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/dashboard_sim/windows/runner/win32_window.h b/dashboard_sim/windows/runner/win32_window.h new file mode 100644 index 0000000..e901dde --- /dev/null +++ b/dashboard_sim/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/inforasia.sql b/inforasia.sql new file mode 100644 index 0000000..e6317aa --- /dev/null +++ b/inforasia.sql @@ -0,0 +1,467 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.1 +-- https://www.phpmyadmin.net/ +-- +-- Host: 127.0.0.1 +-- Waktu pembuatan: 23 Bulan Mei 2024 pada 15.25 +-- Versi server: 10.4.28-MariaDB +-- Versi PHP: 8.2.0 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `inforasia` +-- + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `failed_jobs` +-- + +CREATE TABLE `failed_jobs` ( + `id` bigint(20) UNSIGNED NOT NULL, + `uuid` varchar(255) NOT NULL, + `connection` text NOT NULL, + `queue` text NOT NULL, + `payload` longtext NOT NULL, + `exception` longtext NOT NULL, + `failed_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `migrations` +-- + +CREATE TABLE `migrations` ( + `id` int(10) UNSIGNED NOT NULL, + `migration` varchar(255) NOT NULL, + `batch` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `migrations` +-- + +INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES +(1, '2014_10_12_000000_create_users_table', 1), +(2, '2014_10_12_100000_create_password_reset_tokens_table', 1), +(3, '2019_08_19_000000_create_failed_jobs_table', 1), +(4, '2019_12_14_000001_create_personal_access_tokens_table', 1), +(5, '2024_05_09_181009_create_roles_table', 1), +(6, '2024_05_09_181043_create_proyeks_table', 1), +(7, '2024_05_09_181114_create_penerima_proyeks_table', 1), +(8, '2024_05_09_181139_create_task_proyeks_table', 1), +(9, '2024_05_09_181822_add_column_to_users_table', 1), +(10, '2024_05_09_181857_add_column_to_task_proyeks', 1), +(11, '2024_05_15_101454_remove_team_from_proyeks_table', 2), +(12, '2024_05_17_165255_add_foto_profile_users_table', 3); + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `password_reset_tokens` +-- + +CREATE TABLE `password_reset_tokens` ( + `email` varchar(255) NOT NULL, + `token` varchar(255) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `penerima_proyeks` +-- + +CREATE TABLE `penerima_proyeks` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `task_proyek_id` bigint(20) UNSIGNED NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `penerima_proyeks` +-- + +INSERT INTO `penerima_proyeks` (`id`, `user_id`, `task_proyek_id`, `created_at`, `updated_at`) VALUES +(28, 3, 33, '2024-05-23 06:07:14', '2024-05-23 06:07:14'); + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `personal_access_tokens` +-- + +CREATE TABLE `personal_access_tokens` ( + `id` bigint(20) UNSIGNED NOT NULL, + `tokenable_type` varchar(255) NOT NULL, + `tokenable_id` bigint(20) UNSIGNED NOT NULL, + `name` varchar(255) NOT NULL, + `token` varchar(64) NOT NULL, + `abilities` text DEFAULT NULL, + `last_used_at` timestamp NULL DEFAULT NULL, + `expires_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `personal_access_tokens` +-- + +INSERT INTO `personal_access_tokens` (`id`, `tokenable_type`, `tokenable_id`, `name`, `token`, `abilities`, `last_used_at`, `expires_at`, `created_at`, `updated_at`) VALUES +(1, 'App\\Models\\User', 2, 'user login', '72ecd4e42f97b2a55eda53bc1bdc44e3e5c2333af9ab294ef597fb6f15fb2483', '[\"*\"]', NULL, NULL, '2024-05-09 12:57:34', '2024-05-09 12:57:34'), +(2, 'App\\Models\\User', 2, 'user login', '0efa6e6ca4067f0b628fc81c2f2668c4a3780df5c09b40ad4937fc28f37d58a2', '[\"*\"]', '2024-05-09 13:01:00', NULL, '2024-05-09 12:58:42', '2024-05-09 13:01:00'), +(5, 'App\\Models\\User', 2, 'user login', 'b579a63ff8c2d02af16e323bbc43466676ac06927f6508771060d751bc60eef4', '[\"*\"]', '2024-05-19 08:05:33', NULL, '2024-05-10 07:45:08', '2024-05-19 08:05:33'), +(6, 'App\\Models\\User', 2, 'user login', 'df9185fcbdc36ce01763ed03b2b7d9d307090ec4869779ebe875871ce5fd7a2a', '[\"*\"]', NULL, NULL, '2024-05-10 11:17:15', '2024-05-10 11:17:15'), +(7, 'App\\Models\\User', 2, 'user login', 'c48131156794ef1f63f4cf5596c66bcef3252df6c2678ae1408a5fb320c356e0', '[\"*\"]', NULL, NULL, '2024-05-10 11:28:22', '2024-05-10 11:28:22'), +(8, 'App\\Models\\User', 2, 'user login', '6697cb6590b32134243852fe4a3740dd136814083e1679a8d3354c064de7cc76', '[\"*\"]', NULL, NULL, '2024-05-10 11:46:11', '2024-05-10 11:46:11'), +(9, 'App\\Models\\User', 3, 'user login', 'd6d8046d6950f6276c86b696e4b6dba764bdde0bf469092633798db1537f61e4', '[\"*\"]', '2024-05-11 08:07:06', NULL, '2024-05-11 08:06:52', '2024-05-11 08:07:06'), +(10, 'App\\Models\\User', 3, 'auth', '719705e7d6cc75234a7649f02ed3ae3c6a9ef8df01dbe78699bdeae074b239c3', '[\"*\"]', NULL, NULL, '2024-05-15 10:01:23', '2024-05-15 10:01:23'), +(11, 'App\\Models\\User', 2, 'auth', '6dff5d163f42d53f7c4de0d5ed5d0fba2c8f344c2b41c20251b6aa2cdcc41d8a', '[\"*\"]', '2024-05-15 11:24:46', NULL, '2024-05-15 11:24:15', '2024-05-15 11:24:46'), +(12, 'App\\Models\\User', 2, 'auth', '6517497e11b6e158fedf0f9544d4c4c45e7827c9e9f7c9b43da25586317787d5', '[\"*\"]', '2024-05-17 07:36:45', NULL, '2024-05-17 07:26:35', '2024-05-17 07:36:45'), +(13, 'App\\Models\\User', 2, 'auth', '218657205ef7529b3dba482c920b4ba852a43d78a5e8609240773a7054af24bf', '[\"*\"]', '2024-05-17 07:41:27', NULL, '2024-05-17 07:37:39', '2024-05-17 07:41:27'), +(14, 'App\\Models\\User', 2, 'auth', 'df4d831c1aae698e023f8b14be2945d262250326dc3068e4d02ee04e8e4e3420', '[\"*\"]', '2024-05-17 07:44:48', NULL, '2024-05-17 07:41:32', '2024-05-17 07:44:48'), +(15, 'App\\Models\\User', 2, 'auth', '3bb12105a78fac3b224435d82069f0decc718e512167fc0a2ab675c7da005e5d', '[\"*\"]', '2024-05-17 07:45:29', NULL, '2024-05-17 07:44:53', '2024-05-17 07:45:29'), +(16, 'App\\Models\\User', 3, 'auth', '1468e0b6699bc68c4ddb64a413e6986fb382bc455337e5d8ea18c978a4f7bf2a', '[\"*\"]', '2024-05-17 08:29:53', NULL, '2024-05-17 07:45:42', '2024-05-17 08:29:53'), +(17, 'App\\Models\\User', 3, 'auth', '23443f97b5f2ce3e06164d8fa8c67903a81e9a9e53746385e5b012e0b8dfe053', '[\"*\"]', NULL, NULL, '2024-05-18 02:25:13', '2024-05-18 02:25:13'), +(18, 'App\\Models\\User', 3, 'auth', '86fd2711c5ced755d12e2deaaa14e517dff35f53eb21d4abec1da5fe552ba34c', '[\"*\"]', NULL, NULL, '2024-05-18 17:20:23', '2024-05-18 17:20:23'), +(19, 'App\\Models\\User', 3, 'auth', '93548e5720fb90ec62ea69a81bf81832076cff5f49c475d1524cd46f7e093298', '[\"*\"]', NULL, NULL, '2024-05-18 18:36:56', '2024-05-18 18:36:56'), +(20, 'App\\Models\\User', 3, 'auth', 'da62a08dd0ecfa8dab1ccd45109b71b56cbee40debad850d79f78bb83095ba22', '[\"*\"]', NULL, NULL, '2024-05-18 18:43:45', '2024-05-18 18:43:45'), +(21, 'App\\Models\\User', 3, 'auth', '1e2c5674bfd38c67d459d2a166a07767cd8a2ac3d0864ec2b4f9b010e4ac51c1', '[\"*\"]', NULL, NULL, '2024-05-18 18:50:55', '2024-05-18 18:50:55'), +(22, 'App\\Models\\User', 3, 'auth', '55c402d33a6d569940484185b4b7f8a60593b9f4c6380ef2ca51c0e0e677b1e4', '[\"*\"]', NULL, NULL, '2024-05-19 08:03:32', '2024-05-19 08:03:32'), +(23, 'App\\Models\\User', 3, 'auth', 'fb322a90e1358faae9633a07448b0a955450cd93c854c0500790d90df0cbbd90', '[\"*\"]', NULL, NULL, '2024-05-19 08:21:30', '2024-05-19 08:21:30'), +(24, 'App\\Models\\User', 3, 'auth', '14d78a19bad4b052a549c933eef2168d94bb7d164238fca959a602782f94a102', '[\"*\"]', NULL, NULL, '2024-05-19 08:41:44', '2024-05-19 08:41:44'), +(25, 'App\\Models\\User', 3, 'auth', 'a3f4188d547ca07d1f819a4809c54cf0ae5ff0b59994c18bb93440716be1952f', '[\"*\"]', NULL, NULL, '2024-05-19 08:43:56', '2024-05-19 08:43:56'), +(26, 'App\\Models\\User', 3, 'auth', 'b972738a26f7973a38da6fcf5fd0477d1cbffc150a9cd7ee0734d16712509f23', '[\"*\"]', NULL, NULL, '2024-05-19 08:47:47', '2024-05-19 08:47:47'), +(27, 'App\\Models\\User', 3, 'auth', 'fe9d34d98aceda12200f8cd4eff101264da73c02fd77d4f93f9787d887c07a91', '[\"*\"]', NULL, NULL, '2024-05-19 08:52:39', '2024-05-19 08:52:39'), +(28, 'App\\Models\\User', 3, 'auth', '4b25e8d7a2492cf8c55aafbf23d464376fbf64d9e1823b31d0eee6f8c6e63e58', '[\"*\"]', NULL, NULL, '2024-05-19 08:55:43', '2024-05-19 08:55:43'), +(29, 'App\\Models\\User', 3, 'auth', '87abb2c6843c0851126f2bbcc0fb30073cd9188d5ef3c640be5fb73545a45fa7', '[\"*\"]', NULL, NULL, '2024-05-19 08:58:00', '2024-05-19 08:58:00'), +(30, 'App\\Models\\User', 3, 'auth', '9ad651bb87a811da6362c85e165cc5bf5c692ca72582bd17d015fe904ebfc158', '[\"*\"]', NULL, NULL, '2024-05-19 09:00:38', '2024-05-19 09:00:38'), +(31, 'App\\Models\\User', 3, 'auth', '842be64ea406553da515f0f38c54bbe6ffa58a990ffdcd28816a31acbd8b7012', '[\"*\"]', NULL, NULL, '2024-05-19 09:22:01', '2024-05-19 09:22:01'), +(32, 'App\\Models\\User', 3, 'auth', 'ad6a3b536934252bf29c2bcc51ab431d9a4e1d7722a08f703be5663c753a265d', '[\"*\"]', NULL, NULL, '2024-05-19 09:24:33', '2024-05-19 09:24:33'), +(33, 'App\\Models\\User', 3, 'auth', '8b96cd97d02d5809fe9cf71834e3522c6f6425f225727257c698d158f0e0fb80', '[\"*\"]', '2024-05-19 10:20:32', NULL, '2024-05-19 09:25:28', '2024-05-19 10:20:32'), +(34, 'App\\Models\\User', 3, 'auth', '2d005f67ec2d125d81e6668b4d4ec5badcc94c7838a2066fbefe4804a4def8bb', '[\"*\"]', NULL, NULL, '2024-05-19 09:27:51', '2024-05-19 09:27:51'), +(35, 'App\\Models\\User', 3, 'auth', '6b95e1342b47f8ba84caf86d89320cfc3984e26198a24ebefa1f7ee7f0fc4834', '[\"*\"]', NULL, NULL, '2024-05-19 09:29:33', '2024-05-19 09:29:33'), +(36, 'App\\Models\\User', 3, 'auth', '48478c1e430964cc5827227a669e7566d8d07bcf6da69661297d235f327ace17', '[\"*\"]', NULL, NULL, '2024-05-19 09:31:10', '2024-05-19 09:31:10'), +(37, 'App\\Models\\User', 3, 'auth', '192a4a45346b521f1cf709a2d50df642ca9b42d8e6ff008df2759d0d90a2dfdd', '[\"*\"]', NULL, NULL, '2024-05-19 09:37:21', '2024-05-19 09:37:21'), +(38, 'App\\Models\\User', 3, 'auth', '9c1c3d0da25171063dedbf2d7721285651544bb70989aa8aa815523776940278', '[\"*\"]', NULL, NULL, '2024-05-19 09:38:55', '2024-05-19 09:38:55'), +(39, 'App\\Models\\User', 3, 'auth', '087bff8e24096177b3e7fe17984a5ea46a8669e28e1345205a9fdfd573b2d7c8', '[\"*\"]', '2024-05-19 09:40:55', NULL, '2024-05-19 09:40:52', '2024-05-19 09:40:55'), +(40, 'App\\Models\\User', 3, 'auth', '3ba55f3a78516a5564658cd981ba7a9802397466adec92698e3b5f7e57db63d8', '[\"*\"]', '2024-05-19 09:50:05', NULL, '2024-05-19 09:50:02', '2024-05-19 09:50:05'), +(41, 'App\\Models\\User', 3, 'auth', '26b367611067dfd7b572b75a6becdc2339f60d66b1a92bfce1c25e78c31d0f03', '[\"*\"]', '2024-05-19 09:52:46', NULL, '2024-05-19 09:52:42', '2024-05-19 09:52:46'), +(42, 'App\\Models\\User', 3, 'auth', '2e6e927ca268d8589ad5833486bd550c17eb7ea5161d79bdec860d9766925492', '[\"*\"]', '2024-05-19 09:55:26', NULL, '2024-05-19 09:55:23', '2024-05-19 09:55:26'), +(43, 'App\\Models\\User', 3, 'auth', 'afa4b91a70c2e4222c64f39b5b446aaa385ab279efe74de888b235c6d1b4c701', '[\"*\"]', '2024-05-19 09:56:50', NULL, '2024-05-19 09:56:47', '2024-05-19 09:56:50'), +(44, 'App\\Models\\User', 3, 'auth', '2f8a0ffa06a8c3f62e7779a592aa1369dc9fa49c9bfca6acf0f5313e25a25525', '[\"*\"]', '2024-05-19 10:00:16', NULL, '2024-05-19 10:00:07', '2024-05-19 10:00:16'), +(45, 'App\\Models\\User', 3, 'auth', '69ba38d2957e45a2adcdd66a38ec89687ef57515d208483aea7b85e22252854b', '[\"*\"]', '2024-05-19 10:04:38', NULL, '2024-05-19 10:04:33', '2024-05-19 10:04:38'), +(46, 'App\\Models\\User', 3, 'auth', 'f32c37205cf9f75637d0201aaef6f4c7e934037d691f6bb5c1cb9372861552cf', '[\"*\"]', '2024-05-19 10:29:58', NULL, '2024-05-19 10:05:38', '2024-05-19 10:29:58'), +(47, 'App\\Models\\User', 3, 'auth', 'b3de41ee5fec1824025e3a2f2958b6ae9e540f95090e0200728d5f6f0670d38a', '[\"*\"]', '2024-05-19 16:30:34', NULL, '2024-05-19 15:58:04', '2024-05-19 16:30:34'), +(48, 'App\\Models\\User', 3, 'auth', 'ce4a86f6bee9368c6f1c45c0de80f2f32cdf6c91709241a62a64454bc4ed3861', '[\"*\"]', '2024-05-20 04:58:45', NULL, '2024-05-20 04:58:26', '2024-05-20 04:58:45'), +(49, 'App\\Models\\User', 3, 'auth', 'a9adc47fca496e691271aa48bc0a8ded44267ee604a6e689ce621b19e29a3902', '[\"*\"]', '2024-05-20 05:20:28', NULL, '2024-05-20 05:13:39', '2024-05-20 05:20:28'), +(50, 'App\\Models\\User', 3, 'auth', '99ba3b3815b5cb838c8e329403f56112e46f1428e52b72f7ac3d0858d47cabbe', '[\"*\"]', '2024-05-22 11:35:58', NULL, '2024-05-20 11:43:22', '2024-05-22 11:35:58'), +(51, 'App\\Models\\User', 3, 'auth', 'f74ef88fb5e4d4bee402bb5ba2afe738c82f6d52f578cf29fd3746d7ac0fa52d', '[\"*\"]', '2024-05-20 12:28:04', NULL, '2024-05-20 12:20:41', '2024-05-20 12:28:04'), +(52, 'App\\Models\\User', 3, 'auth', 'd1c72d62cdca876e4cd88d87b9a0b8a51b20a96b6a7aab41707dc4f300bfca8e', '[\"*\"]', NULL, NULL, '2024-05-20 13:30:25', '2024-05-20 13:30:25'), +(53, 'App\\Models\\User', 3, 'auth', '3366f9f73816be09fb1f024f5ee1f5dcb39421c0aad379ecaff39b5e7867c193', '[\"*\"]', '2024-05-20 14:36:46', NULL, '2024-05-20 13:30:26', '2024-05-20 14:36:46'), +(54, 'App\\Models\\User', 3, 'auth', 'b8af36ecc139e6988adc64e05d5b3e80b294a118f664bc2d358c0cc6e43ff188', '[\"*\"]', '2024-05-20 20:41:48', NULL, '2024-05-20 15:29:39', '2024-05-20 20:41:48'), +(55, 'App\\Models\\User', 3, 'auth', 'a6669e7bbaeddf5543f9b2f6cfbc88ae8a30dc880428458b3f4095c9be452be2', '[\"*\"]', '2024-05-20 22:12:27', NULL, '2024-05-20 20:50:38', '2024-05-20 22:12:27'), +(56, 'App\\Models\\User', 3, 'auth', '7d9e2e7db9c39398a96251878f5414a122fd7f06fc12fcb9924be017f63a6fbb', '[\"*\"]', '2024-05-21 02:05:54', NULL, '2024-05-21 02:05:19', '2024-05-21 02:05:54'), +(57, 'App\\Models\\User', 3, 'auth', '24fab303260c9aaa4d5cb3e7c9a17c87db36378ab686cdd5cc79aa2cf4c62128', '[\"*\"]', '2024-05-21 03:58:44', NULL, '2024-05-21 02:38:33', '2024-05-21 03:58:44'), +(58, 'App\\Models\\User', 3, 'auth', 'e952090105d603e2c6a22db24ef1b968705737d9f7369870984dc2a69a6da647', '[\"*\"]', '2024-05-21 15:12:58', NULL, '2024-05-21 09:28:08', '2024-05-21 15:12:58'), +(59, 'App\\Models\\User', 3, 'auth', 'a762147461a9778c62d742817b71cd66b7a15fb1f974e83468429237c9379a8e', '[\"*\"]', '2024-05-21 10:29:05', NULL, '2024-05-21 09:56:52', '2024-05-21 10:29:05'), +(60, 'App\\Models\\User', 3, 'auth', '3ad8b2c878ce2a5448974ebe874dbf69546d707262abd415a42758614ad3c66c', '[\"*\"]', '2024-05-22 11:27:44', NULL, '2024-05-21 11:04:56', '2024-05-22 11:27:44'), +(61, 'App\\Models\\User', 3, 'auth', 'e3e430f813c87c11e919354d38ba40e7ff4071851f70262881afbbabc2bf9def', '[\"*\"]', '2024-05-21 19:09:59', NULL, '2024-05-21 15:31:17', '2024-05-21 19:09:59'), +(62, 'App\\Models\\User', 3, 'auth', '5fe082dc91c6ad30eaa87255e0ff928c43994ebb12e51d01c95c3cc03bb6dfc0', '[\"*\"]', '2024-05-22 07:13:33', NULL, '2024-05-22 07:11:21', '2024-05-22 07:13:33'), +(63, 'App\\Models\\User', 3, 'auth', 'b231996b223c165e3822e618fdb4387546a03e63faf0aca9abdfa81dcfef2622', '[\"*\"]', '2024-05-22 09:24:31', NULL, '2024-05-22 09:20:53', '2024-05-22 09:24:31'), +(64, 'App\\Models\\User', 5, 'auth', '28d63a5d6bc5b953c3cf1c1584dc8f88aa6dcdeb934df78d2911bfa705333a2b', '[\"*\"]', '2024-05-22 13:57:03', NULL, '2024-05-22 09:25:48', '2024-05-22 13:57:03'), +(65, 'App\\Models\\User', 3, 'auth', '415df883472103f2cb4c22dbcc7a3e1306da8519aba8f7016d450239a23e8df4', '[\"*\"]', NULL, NULL, '2024-05-22 09:52:21', '2024-05-22 09:52:21'), +(66, 'App\\Models\\User', 3, 'auth', 'f4290ee74b40b279946985e3f6503a4631afc0e441a862e28ab93f2ce739eaff', '[\"*\"]', NULL, NULL, '2024-05-22 09:52:28', '2024-05-22 09:52:28'), +(67, 'App\\Models\\User', 3, 'auth', '55204cc91305254ae4d09eeb23c554e3a55eb383d4206fb2f4d753aaef10ca1b', '[\"*\"]', '2024-05-22 10:25:27', NULL, '2024-05-22 09:52:32', '2024-05-22 10:25:27'), +(68, 'App\\Models\\User', 3, 'auth', '8f41dd0ed6f50babc9794597cce482010266c57eb0e8bf31104a1ab1cd2ac887', '[\"*\"]', '2024-05-22 12:55:17', NULL, '2024-05-22 11:04:11', '2024-05-22 12:55:17'), +(69, 'App\\Models\\User', 3, 'auth', '4cba9fa945afdf3af43e4d3542ace4837ba51b0f3e75a2e6202c4a7de23f1e14', '[\"*\"]', '2024-05-22 13:29:40', NULL, '2024-05-22 12:58:19', '2024-05-22 13:29:40'), +(70, 'App\\Models\\User', 12, 'auth', '78d30fc0005d8b9256d19d384bd1a205b494759059699b2ec07436367ca8ffee', '[\"*\"]', '2024-05-22 14:00:01', NULL, '2024-05-22 13:33:02', '2024-05-22 14:00:01'), +(71, 'App\\Models\\User', 3, 'auth', '2710eed7ec22df366be3539814abb9f7a28860cccd3cc7d0cf6d569e66e01347', '[\"*\"]', '2024-05-22 18:58:13', NULL, '2024-05-22 17:51:55', '2024-05-22 18:58:13'), +(72, 'App\\Models\\User', 3, 'auth', 'ab1d44c19d72054702c7e7e32fcf5ecc2123af3851053c00debe48a487da1723', '[\"*\"]', '2024-05-22 20:15:35', NULL, '2024-05-22 19:43:03', '2024-05-22 20:15:35'), +(73, 'App\\Models\\User', 3, 'auth', '3ca2375e4866cc172ecc89029816e726318dbffe5268759eb1a392657fedc576', '[\"*\"]', '2024-05-22 22:30:23', NULL, '2024-05-22 21:13:39', '2024-05-22 22:30:23'), +(74, 'App\\Models\\User', 3, 'auth', '2ed8d64d68f6b7a332d4e283da2d520c584acccdf6298592ada25a914722ab09', '[\"*\"]', '2024-05-23 06:10:46', NULL, '2024-05-23 05:56:52', '2024-05-23 06:10:46'); + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `proyeks` +-- + +CREATE TABLE `proyeks` ( + `id` bigint(20) UNSIGNED NOT NULL, + `user_id` bigint(20) UNSIGNED NOT NULL, + `nama` varchar(255) NOT NULL, + `detail` longtext NOT NULL, + `manager` varchar(255) NOT NULL, + `file` varchar(255) DEFAULT NULL, + `start` date NOT NULL, + `finish` date NOT NULL, + `nilai` int(11) NOT NULL, + `klien` varchar(225) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `proyeks` +-- + +INSERT INTO `proyeks` (`id`, `user_id`, `nama`, `detail`, `manager`, `file`, `start`, `finish`, `nilai`, `klien`, `created_at`, `updated_at`) VALUES +(10, 3, 'Webisite', 'asdads', 'asc', NULL, '2024-05-30', '2024-05-31', 70, 'asd', '2024-05-22 11:37:42', '2024-05-23 06:01:20'), +(11, 3, 'asdas', 'asd', 'das', NULL, '2024-05-23', '2024-05-31', 12, 'asd', '2024-05-22 21:16:06', '2024-05-22 21:16:06'), +(12, 3, 'asd', 'asd', 'asd', NULL, '2024-05-23', '2024-05-31', 20, 'asd', '2024-05-23 06:00:14', '2024-05-23 06:00:14'); + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `roles` +-- + +CREATE TABLE `roles` ( + `id` bigint(20) UNSIGNED NOT NULL, + `name` varchar(255) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `roles` +-- + +INSERT INTO `roles` (`id`, `name`, `created_at`, `updated_at`) VALUES +(1, 'direktur', '2024-05-09 11:40:08', '2024-05-09 11:40:08'), +(2, 'admin', '2024-05-09 11:40:16', '2024-05-09 11:40:16'), +(3, 'manager', '2024-05-09 11:40:21', '2024-05-09 11:40:21'), +(4, 'karyawan', '2024-05-09 11:40:26', '2024-05-09 11:40:26'); + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `task_proyeks` +-- + +CREATE TABLE `task_proyeks` ( + `id` bigint(20) UNSIGNED NOT NULL, + `proyek_id` bigint(20) UNSIGNED NOT NULL, + `tugas` varchar(255) DEFAULT NULL, + `catatan` longtext DEFAULT NULL, + `start` date DEFAULT NULL, + `deadline` date DEFAULT NULL, + `status` varchar(255) DEFAULT NULL, + `nilai` int(11) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `task_proyeks` +-- + +INSERT INTO `task_proyeks` (`id`, `proyek_id`, `tugas`, `catatan`, `start`, `deadline`, `status`, `nilai`, `created_at`, `updated_at`) VALUES +(33, 10, 'asd', 'asd', '2024-05-23', '2024-05-30', 'asd', 12, '2024-05-23 06:07:14', '2024-05-23 06:07:14'); + +-- -------------------------------------------------------- + +-- +-- Struktur dari tabel `users` +-- + +CREATE TABLE `users` ( + `id` bigint(20) UNSIGNED NOT NULL, + `name` varchar(255) NOT NULL, + `nip` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, + `email_verified_at` timestamp NULL DEFAULT NULL, + `username` varchar(255) NOT NULL, + `password` varchar(255) NOT NULL, + `jenis_kelamin` varchar(255) NOT NULL, + `tanggal_lahir` date NOT NULL, + `no_telp` varchar(255) NOT NULL, + `alamat` varchar(255) NOT NULL, + `remember_token` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT NULL, + `role_id` bigint(20) UNSIGNED DEFAULT NULL, + `foto_profile` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data untuk tabel `users` +-- + +INSERT INTO `users` (`id`, `name`, `nip`, `email`, `email_verified_at`, `username`, `password`, `jenis_kelamin`, `tanggal_lahir`, `no_telp`, `alamat`, `remember_token`, `created_at`, `updated_at`, `role_id`, `foto_profile`) VALUES +(3, 'daru', '1234567890', 'daru@gmail.com', '2024-05-23 05:59:40', 'daru', '$2y$12$1YV2PLsdwmEsq8qRotv3D.RV6bmYYrty4duisSMSe4bFTv1qrryXK', 'laki-laki', '2024-05-29', '087896754564', 'jakarta bogor ajs', '43', '2024-05-10 08:44:29', '2024-05-23 05:59:40', 1, '1716238421.jpg'), +(5, 'fawaid', '38838383', 'fawaidbengbe@gmail.com', '2024-05-20 20:58:37', 'gagaga', '$2y$12$rq94WXkt8nWHH4zPQ16chexk78DiyqyAxC0t1QSfLT3IKyTZZ8aKu', 'laki laki', '2003-12-12', '071332499295', 'jember', '12', '2024-05-20 13:53:42', '2024-05-20 13:53:42', 4, '1716238421.jpg'), +(11, 'hadi', '1234567890', 'hadi@gmail.com', '2024-05-22 11:35:58', 'hadi', '$2y$12$rqC3Plb.0Xv7/fBOlMlgmu4HBQwIWZh4AeugjMrvVJJFmH0XiAfr.', 'laki-laki', '2003-04-09', '087896754564', 'jakarta bogor', '86', '2024-05-22 11:33:28', '2024-05-22 11:35:58', 4, NULL), +(12, 'Hahaha', '123345', 'fwdac@gmail.com', '2024-05-22 20:31:25', 'fawad', '$2y$10$0dO8M42Nh1WaFwEcgSPjruiN1yebVKp10mIn0d1IUxSOzaW4a4QhG', 'l', '2024-05-23', '08123213123', 'jember', 'asdaasdsdaasdasasdasdasdasd', '2024-05-22 20:33:57', '2024-05-22 20:34:03', 4, NULL), +(14, 'Fawaidac', '123', 'fwdacdh@gmail.com', '2024-05-23 05:58:21', 'asd', '$2y$12$N2sG.3Vb8eBOqSnNZIaeAub3YUoAOx0KxA6GnX2xUISmyZCsw4zOq', 'laki laki', '2024-05-23', '081332443999', 'jember', '57', '2024-05-23 05:58:21', '2024-05-23 05:58:21', 1, NULL); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indeks untuk tabel `failed_jobs` +-- +ALTER TABLE `failed_jobs` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`); + +-- +-- Indeks untuk tabel `migrations` +-- +ALTER TABLE `migrations` + ADD PRIMARY KEY (`id`); + +-- +-- Indeks untuk tabel `password_reset_tokens` +-- +ALTER TABLE `password_reset_tokens` + ADD PRIMARY KEY (`email`); + +-- +-- Indeks untuk tabel `penerima_proyeks` +-- +ALTER TABLE `penerima_proyeks` + ADD PRIMARY KEY (`id`), + ADD KEY `penerima_proyeks_user_id_foreign` (`user_id`), + ADD KEY `penerima_proyeks_proyek_id_foreign` (`task_proyek_id`); + +-- +-- Indeks untuk tabel `personal_access_tokens` +-- +ALTER TABLE `personal_access_tokens` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `personal_access_tokens_token_unique` (`token`), + ADD KEY `personal_access_tokens_tokenable_type_tokenable_id_index` (`tokenable_type`,`tokenable_id`); + +-- +-- Indeks untuk tabel `proyeks` +-- +ALTER TABLE `proyeks` + ADD PRIMARY KEY (`id`), + ADD KEY `proyeks_user_id_foreign` (`user_id`); + +-- +-- Indeks untuk tabel `roles` +-- +ALTER TABLE `roles` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `roles_name_unique` (`name`); + +-- +-- Indeks untuk tabel `task_proyeks` +-- +ALTER TABLE `task_proyeks` + ADD PRIMARY KEY (`id`), + ADD KEY `task_proyeks_proyek_id_foreign` (`proyek_id`); + +-- +-- Indeks untuk tabel `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `users_email_unique` (`email`), + ADD KEY `users_role_id_foreign` (`role_id`); + +-- +-- AUTO_INCREMENT untuk tabel yang dibuang +-- + +-- +-- AUTO_INCREMENT untuk tabel `failed_jobs` +-- +ALTER TABLE `failed_jobs` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT untuk tabel `migrations` +-- +ALTER TABLE `migrations` + MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13; + +-- +-- AUTO_INCREMENT untuk tabel `penerima_proyeks` +-- +ALTER TABLE `penerima_proyeks` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=31; + +-- +-- AUTO_INCREMENT untuk tabel `personal_access_tokens` +-- +ALTER TABLE `personal_access_tokens` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=75; + +-- +-- AUTO_INCREMENT untuk tabel `proyeks` +-- +ALTER TABLE `proyeks` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13; + +-- +-- AUTO_INCREMENT untuk tabel `roles` +-- +ALTER TABLE `roles` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- AUTO_INCREMENT untuk tabel `task_proyeks` +-- +ALTER TABLE `task_proyeks` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=34; + +-- +-- AUTO_INCREMENT untuk tabel `users` +-- +ALTER TABLE `users` + MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15; + +-- +-- Ketidakleluasaan untuk tabel pelimpahan (Dumped Tables) +-- + +-- +-- Ketidakleluasaan untuk tabel `penerima_proyeks` +-- +ALTER TABLE `penerima_proyeks` + ADD CONSTRAINT `penerima_proyeks_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + ADD CONSTRAINT `task_proyeks_penerimaproyek_id_foreign` FOREIGN KEY (`task_proyek_id`) REFERENCES `task_proyeks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- +-- Ketidakleluasaan untuk tabel `proyeks` +-- +ALTER TABLE `proyeks` + ADD CONSTRAINT `proyeks_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); + +-- +-- Ketidakleluasaan untuk tabel `task_proyeks` +-- +ALTER TABLE `task_proyeks` + ADD CONSTRAINT `proyek` FOREIGN KEY (`proyek_id`) REFERENCES `proyeks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- +-- Ketidakleluasaan untuk tabel `users` +-- +ALTER TABLE `users` + ADD CONSTRAINT `users_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`); +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;