├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── .php-cs-fixer.dist.php ├── LICENSE ├── README.md ├── app ├── Console │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Filament │ ├── Pages │ │ ├── Dashboard.php │ │ └── MyProfile.php │ ├── Resources │ │ ├── ProblemCategoryResource.php │ │ ├── ProblemCategoryResource │ │ │ ├── Pages │ │ │ │ ├── CreateProblemCategory.php │ │ │ │ ├── EditProblemCategory.php │ │ │ │ ├── ListProblemCategories.php │ │ │ │ └── ViewProblemCategory.php │ │ │ └── RelationManagers │ │ │ │ └── TicketsRelationManager.php │ │ ├── TicketResource.php │ │ ├── TicketResource │ │ │ ├── Pages │ │ │ │ ├── CreateTicket.php │ │ │ │ ├── EditTicket.php │ │ │ │ ├── ListTickets.php │ │ │ │ └── ViewTicket.php │ │ │ └── RelationManagers │ │ │ │ └── CommentsRelationManager.php │ │ ├── TicketStatusResource.php │ │ ├── TicketStatusResource │ │ │ ├── Pages │ │ │ │ ├── CreateTicketStatus.php │ │ │ │ ├── EditTicketStatus.php │ │ │ │ ├── ListTicketStatuses.php │ │ │ │ └── ViewTicketStatus.php │ │ │ └── RelationManagers │ │ │ │ └── TicketsRelationManager.php │ │ ├── UnitResource.php │ │ ├── UnitResource │ │ │ ├── Pages │ │ │ │ ├── CreateUnit.php │ │ │ │ ├── EditUnit.php │ │ │ │ ├── ListUnits.php │ │ │ │ └── ViewUnit.php │ │ │ └── RelationManagers │ │ │ │ ├── ProblemCategoriesRelationManager.php │ │ │ │ └── UsersRelationManager.php │ │ ├── UserResource.php │ │ └── UserResource │ │ │ ├── Pages │ │ │ ├── CreateUser.php │ │ │ ├── EditUser.php │ │ │ ├── ListUsers.php │ │ │ └── ViewUser.php │ │ │ └── RelationManagers │ │ │ ├── RolesRelationManager.php │ │ │ └── TicketsRelationManager.php │ └── Widgets │ │ └── TicketStatusesChart.php ├── Http │ ├── Controllers │ │ ├── Auth │ │ │ └── SocialiteController.php │ │ └── Controller.php │ ├── Kernel.php │ └── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ ├── ValidateSignature.php │ │ └── VerifyCsrfToken.php ├── Models │ ├── Comment.php │ ├── Priority.php │ ├── ProblemCategory.php │ ├── Role.php │ ├── SocialiteUser.php │ ├── Ticket.php │ ├── TicketStatus.php │ ├── Unit.php │ └── User.php ├── Policies │ ├── CommentPolicy.php │ ├── PermissionPolicy.php │ ├── PriorityPolicy.php │ ├── ProblemCategoryPolicy.php │ ├── RolePolicy.php │ ├── TicketPolicy.php │ ├── TicketStatusPolicy.php │ ├── UnitPolicy.php │ └── UserPolicy.php └── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filament-authentication.php ├── filament-breezy.php ├── filament-language-switch.php ├── filament-socialite.php ├── filament-spatie-roles-permissions.php ├── filament.php ├── filesystems.php ├── hashing.php ├── laravel-to-uml.php ├── logging.php ├── mail.php ├── models.php ├── overlook.php ├── permission.php ├── queue.php ├── sanctum.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_reset_tokens_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ ├── 2023_06_06_082020_create_comments_table.php │ ├── 2023_06_06_082020_create_priorities_table.php │ ├── 2023_06_06_082020_create_problem_categories_table.php │ ├── 2023_06_06_082020_create_ticket_statuses_table.php │ ├── 2023_06_06_082020_create_tickets_table.php │ ├── 2023_06_06_082020_create_units_table.php │ ├── 2023_06_06_082020_update_users_table.php │ ├── 2023_06_06_082023_add_foreign_keys_to_comments_table.php │ ├── 2023_06_06_082023_add_foreign_keys_to_problem_categories_table.php │ ├── 2023_06_06_082023_add_foreign_keys_to_tickets_table.php │ ├── 2023_06_06_082023_add_foreign_keys_to_users_table.php │ ├── 2023_06_07_070117_create_permission_tables.php │ ├── 2023_06_13_041702_create_notifications_table.php │ ├── 2023_06_14_043122_add_attachment_to_comments_table.php │ ├── 2023_06_14_070356_create_socialite_users_table.php │ └── 2023_06_14_070958_update_users_table_add_nullable_to_password.php └── seeders │ ├── DatabaseSeeder.php │ ├── PermissionSeeder.php │ ├── PrioritySeeder.php │ ├── ProblemCategoryMigration.php │ ├── RoleSeeder.php │ ├── TicketSeeder.php │ ├── TicketStatusSeeder.php │ ├── UnitSeeder.php │ └── UserSeeder.php ├── lang ├── en.json ├── id.json └── vendor │ └── filament-authentication │ ├── en │ └── filament-authentication.php │ ├── pt_BR │ └── filament-authentication.php │ └── vi │ └── filament-authentication.php ├── package-lock.json ├── package.json ├── phpstan.neon.dist ├── phpunit.xml ├── public ├── .htaccess ├── favicon.ico ├── index.php ├── lamp.png └── robots.txt ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ └── bootstrap.js └── views │ ├── landing.blade.php │ └── vendor │ ├── filament-apex-charts │ ├── .gitkeep │ └── widgets │ │ ├── apex-chart-widget.blade.php │ │ └── components │ │ ├── chart.blade.php │ │ ├── filter-form.blade.php │ │ └── header.blade.php │ ├── filament-authentication │ ├── components │ │ └── banner.blade.php │ ├── filament │ │ └── pages │ │ │ └── profile.blade.php │ └── impersonating-banner.blade.php │ └── filament-breezy │ ├── .gitkeep │ ├── components │ ├── auth-card.blade.php │ ├── grid-section.blade.php │ └── sections │ │ ├── 2fa.blade.php │ │ ├── passwords.blade.php │ │ ├── personal-info.blade.php │ │ └── sanctum.blade.php │ ├── filament │ └── pages │ │ └── my-profile.blade.php │ ├── livewire │ └── breezy-sanctum-tokens.blade.php │ ├── login.blade.php │ ├── register.blade.php │ ├── reset-password.blade.php │ ├── two-factor.blade.php │ └── verify.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── screenshot ├── create-ticket.png ├── database-design.png ├── super-admin.png └── uml.png ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── debugbar │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── CreatesApplication.php ├── Feature │ └── ExampleTest.php ├── TestCase.php └── Unit │ └── ExampleTest.php └── vite.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_DESCRIPTION= 3 | APP_ENV=local 4 | APP_KEY= 5 | APP_DEBUG=true 6 | APP_URL=http://localhost 7 | 8 | LOG_CHANNEL=stack 9 | LOG_DEPRECATIONS_CHANNEL=null 10 | LOG_LEVEL=debug 11 | 12 | DB_CONNECTION=mysql 13 | DB_HOST=127.0.0.1 14 | DB_PORT=3306 15 | DB_DATABASE=laravel 16 | DB_USERNAME=root 17 | DB_PASSWORD= 18 | 19 | BROADCAST_DRIVER=log 20 | CACHE_DRIVER=file 21 | FILESYSTEM_DISK=local 22 | QUEUE_CONNECTION=sync 23 | SESSION_DRIVER=file 24 | SESSION_LIFETIME=120 25 | 26 | MEMCACHED_HOST=127.0.0.1 27 | 28 | REDIS_HOST=127.0.0.1 29 | REDIS_PASSWORD=null 30 | REDIS_PORT=6379 31 | 32 | MAIL_MAILER=smtp 33 | MAIL_HOST=mailpit 34 | MAIL_PORT=1025 35 | MAIL_USERNAME=null 36 | MAIL_PASSWORD=null 37 | MAIL_ENCRYPTION=null 38 | MAIL_FROM_ADDRESS="hello@example.com" 39 | MAIL_FROM_NAME="${APP_NAME}" 40 | 41 | AWS_ACCESS_KEY_ID= 42 | AWS_SECRET_ACCESS_KEY= 43 | AWS_DEFAULT_REGION=us-east-1 44 | AWS_BUCKET= 45 | AWS_USE_PATH_STYLE_ENDPOINT=false 46 | 47 | PUSHER_APP_ID= 48 | PUSHER_APP_KEY= 49 | PUSHER_APP_SECRET= 50 | PUSHER_HOST= 51 | PUSHER_PORT=443 52 | PUSHER_SCHEME=https 53 | PUSHER_APP_CLUSTER=mt1 54 | 55 | VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 56 | VITE_PUSHER_HOST="${PUSHER_HOST}" 57 | VITE_PUSHER_PORT="${PUSHER_PORT}" 58 | VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" 59 | VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 60 | 61 | 62 | GOOGLE_CLIENT_ID= 63 | GOOGLE_CLIENT_SECRET= 64 | GOOGLE_CLIENT_REDIRECT= 65 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.blade.php diff=html 4 | *.css diff=css 5 | *.html diff=html 6 | *.md diff=markdown 7 | *.php diff=php 8 | 9 | /.github export-ignore 10 | CHANGELOG.md export-ignore 11 | .styleci.yml export-ignore 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/hot 5 | /public/storage 6 | /storage/*.key 7 | /vendor 8 | .env 9 | .env.backup 10 | .env.production 11 | .phpunit.result.cache 12 | Homestead.json 13 | Homestead.yaml 14 | auth.json 15 | npm-debug.log 16 | yarn-error.log 17 | /.fleet 18 | /.idea 19 | /.vscode 20 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | exclude([ 5 | 'app/Providers', 6 | 'bootstrap', 7 | 'config', 8 | 'lang', 9 | 'public', 10 | 'storage', 11 | ]) 12 | ->in(__DIR__); 13 | 14 | $rules = [ 15 | // Rules based on PhpCsFixer rule set with added or modified rules below. 16 | '@PhpCsFixer' => true, 17 | // List Notation 18 | 'list_syntax' => [ 19 | 'syntax' => 'short', 20 | ], 21 | // Basic 22 | 'curly_braces_position' => true, 23 | // Class Notation 24 | 'ordered_class_elements' => [ 25 | 'order' => [ 26 | 'use_trait', 'case', 27 | 'constant_public', 'constant_protected', 'constant_private', 28 | 'property_public_readonly', 'property_protected_readonly', 'property_private_readonly', 29 | 'property_public', 'property_protected', 'property_private', 30 | 'property_public_static', 'property_protected_static', 'property_private_static', 31 | 'method_public_abstract', 'method_protected_abstract', 'method_private_abstract', 32 | 'method_public_abstract_static', 'method_protected_abstract_static', 'method_private_abstract_static', 33 | 'construct', 'destruct', 'magic', 'phpunit', 34 | 'method_public', 'method_protected', 'method_private', 35 | 'method_public_static', 'method_protected_static', 'method_private_static', 36 | ], 37 | ], 38 | 'ordered_interfaces' => true, 39 | 'self_static_accessor' => true, 40 | 'single_trait_insert_per_statement' => false, 41 | // Control Structure 42 | 'control_structure_continuation_position' => [ 43 | 'position' => 'same_line', 44 | ], 45 | 'no_alternative_syntax' => [ 46 | 'fix_non_monolithic_code' => false, 47 | ], 48 | 'trailing_comma_in_multiline' => [ 49 | 'elements' => ['arguments', 'arrays', 'match', 'parameters'], 50 | ], 51 | 'yoda_style' => false, 52 | // Function Notation 53 | 'method_argument_space' => [ 54 | 'on_multiline' => 'ignore', 55 | ], 56 | 'nullable_type_declaration_for_default_null_value' => false, 57 | // Operator 58 | 'not_operator_with_space' => true, 59 | // PHP Tag 60 | 'echo_tag_syntax' => [ 61 | 'format' => 'short', 62 | ], 63 | // PHPUnit 64 | 'php_unit_internal_class' => false, 65 | 'php_unit_method_casing' => [ 66 | 'case' => 'snake_case', 67 | ], 68 | 'php_unit_test_class_requires_covers' => true, 69 | // PHPDoc 70 | 'phpdoc_add_missing_param_annotation' => false, 71 | 'phpdoc_align' => [ 72 | 'align' => 'left', 73 | ], 74 | 'phpdoc_no_alias_tag' => [ 75 | 'replacements' => [ 76 | 'type' => 'var', 77 | 'link' => 'see', 78 | ], 79 | ], 80 | 'phpdoc_no_empty_return' => false, 81 | 'phpdoc_order' => [ 82 | 'order' => ['property', 'property-write', 'property-read', 'method', 'param', 'return', 'throws'], 83 | ], 84 | // String Notation 85 | 'explicit_string_variable' => false, 86 | // Whitespace 87 | 'blank_line_between_import_groups' => false, 88 | ]; 89 | 90 | return (new PhpCsFixer\Config()) 91 | ->setRules($rules) 92 | ->setCacheFile('.php-cs-fixer.cache') 93 | ->setIndent(' ') 94 | ->setLineEnding("\n") 95 | ->setFinder($finder); 96 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ruswandi, S.T. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Helpdesk Laravel 3 | 4 | The Helpdesk Laravel repository is a project aimed at providing a web-based helpdesk system using the [**Laravel Framewrok v10**](https://laravel.com) and [**Filament v2**](https://github.com/filamentphp). Helpdesk is a system that allows users to submit questions, request assistance, or report issues related to a company's products or services. 5 | 6 | In this repository, you will find the complete source code implemented using Laravel, a popular and powerful PHP framework. This project is designed to assist web developers in building and managing helpdesk systems with ease. 7 | 8 | The key features of Laravel Helpdesk include: 9 | 1. Ticket Submission: Users can submit new tickets containing their questions, assistance requests, or issue reports. 10 | 2. Ticket Management: Admins can view, assign, or close tickets submitted by users. 11 | 3. Ticket Prioritization: Users can prioritize their tickets to emphasize the level of urgency. 12 | 4. History and Tracking: The system records all activities and conversations within tickets, allowing for easy tracking and auditing. 13 | 14 | This Laravel Helpdesk repository will provide a solid foundation for building a customizable and extensible helpdesk system according to your specific needs. By utilizing Laravel as the main framework, this project offers user-friendliness, flexibility, and good performance. 15 | 16 | Feel free to explore this repository and start building a robust and responsive helpdesk application using Laravel Helpdesk! 17 | 18 |
19 | 20 | ## Database Design 21 | 22 | 23 |
24 | 25 | ## Unified Modeling Language (UML) 26 | 27 |
28 | 29 | ## Requirements 30 | * PHP 8.1 or higher 31 | * Database (eg: MySQL, PostgreSQL, SQLite) 32 | * Web Server (eg: Apache, Nginx, IIS) 33 | 34 |
35 | 36 | 37 | ## Installation 38 | 39 | * Install [Composer](https://getcomposer.org/download) 40 | * Clone the repository: `git clone https://github.com/ruswan/laravel_helpdesk.git` 41 | * Install PHP dependencies: `composer install` 42 | * Setup configuration: `cp .env.example .env` 43 | * Generate application key: `php artisan key:generate` 44 | * Create a database and update your configuration. 45 | * Run database migration: `php artisan migrate` 46 | * Run database seeder: `php artisan db:seed` 47 | * Create a symlink to the storage: `php artisan storage:link` 48 | * Run the dev server: `php artisan serve` 49 | 50 |
51 | 52 | ## Dummy Account 53 | ### Super Admin 54 | > - Email: superadmin@example.com 55 | > - Password: password 56 | ### Admin Unit 57 | > - Email: adminunit@example.com 58 | > - Password: password 59 | ### Staff Unit 60 | > - Email: staffunit@example.com 61 | > - Password: password 62 | ### General User 63 | > - Email: user@example.com 64 | > - Password: password 65 | 66 | ## Super Admin Preview 67 | 68 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 16 | } 17 | 18 | /** 19 | * Register the commands for the application. 20 | */ 21 | protected function commands(): void 22 | { 23 | $this->load(__DIR__.'/Commands'); 24 | 25 | require base_path('routes/console.php'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected $dontFlash = [ 16 | 'current_password', 17 | 'password', 18 | 'password_confirmation', 19 | ]; 20 | 21 | /** 22 | * Register the exception handling callbacks for the application. 23 | */ 24 | public function register(): void 25 | { 26 | $this->reportable(function (Throwable $e) { 27 | // 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Filament/Pages/Dashboard.php: -------------------------------------------------------------------------------- 1 | required() 19 | ->label(__('filament-breezy::default.fields.name')), 20 | ]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Filament/Resources/ProblemCategoryResource.php: -------------------------------------------------------------------------------- 1 | schema([ 29 | Forms\Components\Select::make('unit_id') 30 | ->label(__('Work Unit')) 31 | ->options(Unit::all() 32 | ->pluck('name', 'id')) 33 | ->searchable() 34 | ->required(), 35 | Forms\Components\TextInput::make('name') 36 | ->translateLabel() 37 | ->required() 38 | ->maxLength(255), 39 | ]); 40 | } 41 | 42 | public static function table(Table $table): Table 43 | { 44 | return $table 45 | ->columns([ 46 | Tables\Columns\TextColumn::make('name') 47 | ->translateLabel() 48 | ->searchable(), 49 | Tables\Columns\TextColumn::make('unit.name') 50 | ->searchable() 51 | ->label(__('Work Unit')), 52 | ]) 53 | ->filters([ 54 | Tables\Filters\TrashedFilter::make(), 55 | ]) 56 | ->actions([ 57 | Tables\Actions\ViewAction::make(), 58 | Tables\Actions\EditAction::make(), 59 | ]) 60 | ->bulkActions([ 61 | Tables\Actions\DeleteBulkAction::make(), 62 | Tables\Actions\ForceDeleteBulkAction::make(), 63 | Tables\Actions\RestoreBulkAction::make(), 64 | ]); 65 | } 66 | 67 | public static function getRelations(): array 68 | { 69 | return [ 70 | TicketsRelationManager::class, 71 | ]; 72 | } 73 | 74 | public static function getPages(): array 75 | { 76 | return [ 77 | 'index' => Pages\ListProblemCategories::route('/'), 78 | 'create' => Pages\CreateProblemCategory::route('/create'), 79 | 'view' => Pages\ViewProblemCategory::route('/{record}'), 80 | 'edit' => Pages\EditProblemCategory::route('/{record}/edit'), 81 | ]; 82 | } 83 | 84 | public static function getEloquentQuery(): Builder 85 | { 86 | return parent::getEloquentQuery() 87 | ->withoutGlobalScopes([ 88 | SoftDeletingScope::class, 89 | ])->where(function ($query) { 90 | if (auth()->user()->hasRole('Admin Unit')) { 91 | $query->where('problem_categories.unit_id', auth()->user()->unit_id); 92 | } 93 | }); 94 | } 95 | 96 | public static function getPluralModelLabel(): string 97 | { 98 | return __('Problem Category'); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/Filament/Resources/ProblemCategoryResource/Pages/CreateProblemCategory.php: -------------------------------------------------------------------------------- 1 | schema([ 21 | Forms\Components\TextInput::make('title') 22 | ->required() 23 | ->maxLength(255), 24 | ]); 25 | } 26 | 27 | public static function table(Table $table): Table 28 | { 29 | return $table 30 | ->columns([ 31 | Tables\Columns\TextColumn::make('title') 32 | ->translateLabel(), 33 | Tables\Columns\TextColumn::make('owner.name') 34 | ->translateLabel(), 35 | Tables\Columns\TextColumn::make('responsible.name') 36 | ->translateLabel(), 37 | Tables\Columns\TextColumn::make('ticket_status.name') 38 | ->label(__("Ticket Status")), 39 | ]) 40 | ->filters([]) 41 | ->headerActions([]) 42 | ->actions([]) 43 | ->bulkActions([]); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Filament/Resources/TicketResource/Pages/CreateTicket.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $data['ticket_statuses_id'] = 1; 19 | 20 | return $data; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Filament/Resources/TicketResource/Pages/EditTicket.php: -------------------------------------------------------------------------------- 1 | schema([ 28 | Forms\Components\TextInput::make('name') 29 | ->translateLabel() 30 | ->required() 31 | ->maxLength(255), 32 | ]); 33 | } 34 | 35 | public static function table(Table $table): Table 36 | { 37 | return $table 38 | ->columns([ 39 | Tables\Columns\TextColumn::make('id') 40 | ->label('#'), 41 | 42 | Tables\Columns\TextColumn::make('name') 43 | ->translateLabel() 44 | ->searchable(), 45 | 46 | Tables\Columns\TextColumn::make('tickets_count') 47 | ->counts('tickets') 48 | ->label(__('Tickets Count')) 49 | ->sortable(), 50 | ]) 51 | ->filters([]) 52 | ->actions([]) 53 | ->bulkActions([]); 54 | } 55 | 56 | public static function getRelations(): array 57 | { 58 | return [ 59 | TicketsRelationManager::class, 60 | ]; 61 | } 62 | 63 | public static function getPages(): array 64 | { 65 | return [ 66 | 'index' => Pages\ListTicketStatuses::route('/'), 67 | 'create' => Pages\CreateTicketStatus::route('/create'), 68 | 'view' => Pages\ViewTicketStatus::route('/{record}'), 69 | 'edit' => Pages\EditTicketStatus::route('/{record}/edit'), 70 | ]; 71 | } 72 | 73 | public static function getEloquentQuery(): Builder 74 | { 75 | return parent::getEloquentQuery() 76 | ->withoutGlobalScopes([ 77 | SoftDeletingScope::class, 78 | ]); 79 | } 80 | 81 | public static function getPluralModelLabel(): string 82 | { 83 | return __('Ticket Statuses '); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/Filament/Resources/TicketStatusResource/Pages/CreateTicketStatus.php: -------------------------------------------------------------------------------- 1 | columns([ 22 | Tables\Columns\TextColumn::make('title') 23 | ->translateLabel() 24 | ->searchable(), 25 | Tables\Columns\TextColumn::make('created_at') 26 | ->dateTime() 27 | ->translateLabel() 28 | ->sortable() 29 | ->toggleable(), 30 | Tables\Columns\TextColumn::make('problemCategory.name') 31 | ->searchable() 32 | ->label(__('Problem Category')) 33 | ->toggleable(), 34 | Tables\Columns\TextColumn::make('ticketStatus.name') 35 | ->label('Status') 36 | ->sortable(), 37 | ]) 38 | ->filters([]) 39 | ->headerActions([]) 40 | ->actions([ 41 | Tables\Actions\ViewAction::make() 42 | ->url(fn (Ticket $record): string => route('filament.resources.tickets.view', $record)), 43 | ]) 44 | ->bulkActions([]); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/Filament/Resources/UnitResource.php: -------------------------------------------------------------------------------- 1 | schema([ 29 | Forms\Components\TextInput::make('name') 30 | ->required() 31 | ->maxLength(255), 32 | ]) 33 | ; 34 | } 35 | 36 | public static function table(Table $table): Table 37 | { 38 | return $table 39 | ->columns([ 40 | Tables\Columns\TextColumn::make('name'), 41 | ]) 42 | ->filters([ 43 | Tables\Filters\TrashedFilter::make(), 44 | ]) 45 | ->actions([ 46 | Tables\Actions\ViewAction::make(), 47 | Tables\Actions\EditAction::make(), 48 | ]) 49 | ->bulkActions([ 50 | Tables\Actions\DeleteBulkAction::make(), 51 | Tables\Actions\ForceDeleteBulkAction::make(), 52 | Tables\Actions\RestoreBulkAction::make(), 53 | ]) 54 | ; 55 | } 56 | 57 | public static function getRelations(): array 58 | { 59 | return [ 60 | ProblemCategoriesRelationManager::class, 61 | UsersRelationManager::class, 62 | ]; 63 | } 64 | 65 | public static function getPages(): array 66 | { 67 | return [ 68 | 'index' => Pages\ListUnits::route('/'), 69 | 'create' => Pages\CreateUnit::route('/create'), 70 | 'view' => Pages\ViewUnit::route('/{record}'), 71 | 'edit' => Pages\EditUnit::route('/{record}/edit'), 72 | ]; 73 | } 74 | 75 | public static function getEloquentQuery(): Builder 76 | { 77 | return parent::getEloquentQuery() 78 | ->withoutGlobalScopes([ 79 | SoftDeletingScope::class, 80 | ]) 81 | ; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/Filament/Resources/UnitResource/Pages/CreateUnit.php: -------------------------------------------------------------------------------- 1 | schema([ 21 | Forms\Components\TextInput::make('name') 22 | ->required() 23 | ->maxLength(255), 24 | ]) 25 | ; 26 | } 27 | 28 | public static function table(Table $table): Table 29 | { 30 | return $table 31 | ->columns([ 32 | Tables\Columns\TextColumn::make('name'), 33 | ]) 34 | ->filters([ 35 | ]) 36 | ->headerActions([ 37 | Tables\Actions\CreateAction::make(), 38 | ]) 39 | ->actions([ 40 | Tables\Actions\EditAction::make(), 41 | Tables\Actions\DeleteAction::make(), 42 | ]) 43 | ->bulkActions([ 44 | Tables\Actions\DeleteBulkAction::make(), 45 | ]) 46 | ; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Filament/Resources/UnitResource/RelationManagers/UsersRelationManager.php: -------------------------------------------------------------------------------- 1 | schema([ 21 | Forms\Components\TextInput::make('name') 22 | ->required() 23 | ->maxLength(255), 24 | ]) 25 | ; 26 | } 27 | 28 | public static function table(Table $table): Table 29 | { 30 | return $table 31 | ->columns([ 32 | Tables\Columns\TextColumn::make('name'), 33 | Tables\Columns\TagsColumn::make('roles.name'), 34 | ]) 35 | ->filters([ 36 | ]) 37 | ->headerActions([ 38 | Tables\Actions\AttachAction::make(), 39 | ]) 40 | ->actions([ 41 | Tables\Actions\DetachAction::make(), 42 | ]) 43 | ->bulkActions([ 44 | Tables\Actions\DetachBulkAction::make(), 45 | ]) 46 | ; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Filament/Resources/UserResource.php: -------------------------------------------------------------------------------- 1 | schema([ 31 | Forms\Components\Select::make('unit_id') 32 | ->options(Unit::all() 33 | ->pluck('name', 'id')) 34 | ->searchable(), 35 | Forms\Components\TextInput::make('name') 36 | ->required() 37 | ->maxLength(255), 38 | Forms\Components\TextInput::make('email') 39 | ->email() 40 | ->required() 41 | ->maxLength(255), 42 | Forms\Components\DateTimePicker::make('email_verified_at'), 43 | Forms\Components\TextInput::make('password') 44 | ->password() 45 | ->required() 46 | ->maxLength(255), 47 | Forms\Components\TextInput::make('identity') 48 | ->maxLength(255), 49 | Forms\Components\TextInput::make('phone') 50 | ->tel() 51 | ->maxLength(255), 52 | Forms\Components\Toggle::make('is_active') 53 | ->required(), 54 | ]) 55 | ; 56 | } 57 | 58 | public static function table(Table $table): Table 59 | { 60 | return $table 61 | ->columns([ 62 | Tables\Columns\TextColumn::make('name'), 63 | Tables\Columns\TextColumn::make('email'), 64 | Tables\Columns\TagsColumn::make('roles.name'), 65 | Tables\Columns\IconColumn::make('is_active') 66 | ->boolean(), 67 | ]) 68 | ->filters([ 69 | Tables\Filters\TrashedFilter::make(), 70 | ]) 71 | ->actions([ 72 | Impersonate::make() 73 | ->redirectTo(route('filament.pages.dashboard')), 74 | Tables\Actions\ViewAction::make(), 75 | Tables\Actions\EditAction::make(), 76 | ]) 77 | ->bulkActions([ 78 | Tables\Actions\DeleteBulkAction::make(), 79 | Tables\Actions\ForceDeleteBulkAction::make(), 80 | Tables\Actions\RestoreBulkAction::make(), 81 | ]) 82 | ; 83 | } 84 | 85 | public static function getRelations(): array 86 | { 87 | return [ 88 | RolesRelationManager::class, 89 | TicketsRelationManager::class, 90 | ]; 91 | } 92 | 93 | public static function getPages(): array 94 | { 95 | return [ 96 | 'index' => Pages\ListUsers::route('/'), 97 | 'create' => Pages\CreateUser::route('/create'), 98 | 'view' => Pages\ViewUser::route('/{record}'), 99 | 'edit' => Pages\EditUser::route('/{record}/edit'), 100 | ]; 101 | } 102 | 103 | public static function getEloquentQuery(): Builder 104 | { 105 | return parent::getEloquentQuery() 106 | ->withoutGlobalScopes([ 107 | SoftDeletingScope::class, 108 | ]) 109 | ; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/Filament/Resources/UserResource/Pages/CreateUser.php: -------------------------------------------------------------------------------- 1 | record($this->getRecord()) 20 | ->redirectTo(route('filament.pages.dashboard')), 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Filament/Resources/UserResource/RelationManagers/RolesRelationManager.php: -------------------------------------------------------------------------------- 1 | schema([ 21 | Forms\Components\TextInput::make('name') 22 | ->required() 23 | ->maxLength(255), 24 | ]) 25 | ; 26 | } 27 | 28 | public static function table(Table $table): Table 29 | { 30 | return $table 31 | ->columns([ 32 | Tables\Columns\TextColumn::make('name'), 33 | ]) 34 | ->filters([ 35 | ]) 36 | ->headerActions([ 37 | Tables\Actions\AttachAction::make(), 38 | ]) 39 | ->actions([ 40 | Tables\Actions\DetachAction::make(), 41 | ]) 42 | ->bulkActions([ 43 | Tables\Actions\DetachBulkAction::make(), 44 | ]) 45 | ; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/Filament/Resources/UserResource/RelationManagers/TicketsRelationManager.php: -------------------------------------------------------------------------------- 1 | schema([ 22 | Forms\Components\TextInput::make('title') 23 | ->required() 24 | ->maxLength(255), 25 | ]) 26 | ; 27 | } 28 | 29 | public static function table(Table $table): Table 30 | { 31 | return $table 32 | ->columns([ 33 | Tables\Columns\TextColumn::make('title') 34 | ->translateLabel() 35 | ->searchable(), 36 | Tables\Columns\TextColumn::make('created_at') 37 | ->dateTime() 38 | ->translateLabel() 39 | ->sortable() 40 | ->toggleable(), 41 | Tables\Columns\TextColumn::make('problemCategory.name') 42 | ->searchable() 43 | ->translateLabel() 44 | ->toggleable(), 45 | Tables\Columns\TextColumn::make('ticketStatus.name') 46 | ->sortable(), 47 | ]) 48 | ->filters([ 49 | ]) 50 | ->headerActions([ 51 | ]) 52 | ->actions([ 53 | Tables\Actions\ViewAction::make() 54 | ->url(fn (Ticket $record): string => route('filament.resources.tickets.view', $record)), 55 | ]) 56 | ->bulkActions([ 57 | ]) 58 | ; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/Filament/Widgets/TicketStatusesChart.php: -------------------------------------------------------------------------------- 1 | withCount(['tickets'])->get(); 33 | return [ 34 | 'chart' => [ 35 | 'type' => 'pie', 36 | 'height' => 300, 37 | ], 38 | 'series' => $ticketStatuses->pluck('tickets_count')->toArray(), 39 | 'labels' => $ticketStatuses->pluck('name')->toArray(), 40 | 'legend' => [ 41 | 'labels' => [ 42 | 'colors' => '#9ca3af', 43 | 'fontWeight' => 600, 44 | ], 45 | ], 46 | ]; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/SocialiteController.php: -------------------------------------------------------------------------------- 1 | redirect(); 16 | } 17 | 18 | public function handleProvideCallback($provider) 19 | { 20 | try { 21 | $user = Socialite::driver($provider)->user(); 22 | } catch (\Exception $e) { 23 | return redirect()->back(); 24 | } 25 | // find or create user and send params user get from socialite and provider 26 | $authUser = $this->findOrCreateUser($user, $provider); 27 | 28 | // login user 29 | Auth()->login($authUser, true); 30 | 31 | // setelah login redirect ke dashboard 32 | return redirect()->route('filament.pages.dashboard'); 33 | } 34 | 35 | public function findOrCreateUser($socialUser, $provider) 36 | { 37 | // Get Social Account 38 | $socialAccount = SocialiteUser::where('provider_id', $socialUser->id) 39 | ->where('provider', $provider) 40 | ->first(); 41 | 42 | // If it already exists. 43 | if ($socialAccount) { 44 | // return user 45 | return $socialAccount->user; 46 | // If there isn't yet. 47 | } 48 | 49 | $user = User::where('email', $socialUser->getEmail())->first(); 50 | 51 | // If there are no users. 52 | if (!$user) { 53 | // Create a new user 54 | $user = User::create([ 55 | 'name' => $socialUser->getName(), 56 | 'email' => $socialUser->getEmail(), 57 | 'email_verified_at' => Carbon::now()->timestamp, 58 | ]); 59 | } 60 | 61 | // Buat a new socialite user 62 | $user->socialiteUsers()->create([ 63 | 'provider_id' => $socialUser->getId(), 64 | 'provider' => $provider, 65 | ]); 66 | 67 | // return user 68 | return $user; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | protected $middleware = [ 17 | // \App\Http\Middleware\TrustHosts::class, 18 | \App\Http\Middleware\TrustProxies::class, 19 | \Illuminate\Http\Middleware\HandleCors::class, 20 | \App\Http\Middleware\PreventRequestsDuringMaintenance::class, 21 | \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 22 | \App\Http\Middleware\TrimStrings::class, 23 | \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, 24 | ]; 25 | 26 | /** 27 | * The application's route middleware groups. 28 | * 29 | * @var array> 30 | */ 31 | protected $middlewareGroups = [ 32 | 'web' => [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 37 | \App\Http\Middleware\VerifyCsrfToken::class, 38 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 39 | ], 40 | 41 | 'api' => [ 42 | // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 43 | \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', 44 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 45 | ], 46 | ]; 47 | 48 | /** 49 | * The application's middleware aliases. 50 | * 51 | * Aliases may be used instead of class names to conveniently assign middleware to routes and groups. 52 | * 53 | * @var array 54 | */ 55 | protected $middlewareAliases = [ 56 | 'auth' => \App\Http\Middleware\Authenticate::class, 57 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 58 | 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, 59 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 60 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 61 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 62 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 63 | 'signed' => \App\Http\Middleware\ValidateSignature::class, 64 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 65 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 66 | ]; 67 | } 68 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson() ? null : route('filament.auth.login'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventRequestsDuringMaintenance.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 24 | return redirect(RouteServiceProvider::HOME); 25 | } 26 | } 27 | 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'current_password', 16 | 'password', 17 | 'password_confirmation', 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustHosts.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function hosts(): array 15 | { 16 | return [ 17 | $this->allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | |string|null 14 | */ 15 | protected $proxies; 16 | 17 | /** 18 | * The headers that should be used to detect proxies. 19 | * 20 | * @var int 21 | */ 22 | protected $headers = 23 | Request::HEADER_X_FORWARDED_FOR | 24 | Request::HEADER_X_FORWARDED_HOST | 25 | Request::HEADER_X_FORWARDED_PORT | 26 | Request::HEADER_X_FORWARDED_PROTO | 27 | Request::HEADER_X_FORWARDED_AWS_ELB; 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Middleware/ValidateSignature.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 'fbclid', 16 | // 'utm_campaign', 17 | // 'utm_content', 18 | // 'utm_medium', 19 | // 'utm_source', 20 | // 'utm_term', 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Models/Comment.php: -------------------------------------------------------------------------------- 1 | 'int', 33 | 'user_id' => 'int', 34 | ]; 35 | 36 | protected $fillable = [ 37 | 'tiket_id', 38 | 'user_id', 39 | 'comment', 40 | 'attachments', 41 | ]; 42 | 43 | public function user() 44 | { 45 | return $this->belongsTo(User::class); 46 | } 47 | 48 | public function ticket() 49 | { 50 | return $this->belongsTo(Ticket::class, 'tiket_id'); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/Models/Priority.php: -------------------------------------------------------------------------------- 1 | hasMany(Ticket::class); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Models/ProblemCategory.php: -------------------------------------------------------------------------------- 1 | 'int', 31 | ]; 32 | 33 | protected $fillable = [ 34 | 'unit_id', 35 | 'name', 36 | ]; 37 | 38 | public function unit() 39 | { 40 | return $this->belongsTo(Unit::class); 41 | } 42 | 43 | public function tickets() 44 | { 45 | return $this->hasMany(Ticket::class); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/Models/Role.php: -------------------------------------------------------------------------------- 1 | belongsTo(User::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Models/Ticket.php: -------------------------------------------------------------------------------- 1 | 'int', 45 | 'unit_id' => 'int', 46 | 'owner_id' => 'int', 47 | 'problem_category_id' => 'int', 48 | 'ticket_statuses_id' => 'int', 49 | 'responsible_id' => 'int', 50 | 'approved_at' => 'datetime', 51 | 'solved_at' => 'datetime', 52 | ]; 53 | 54 | protected $fillable = [ 55 | 'priority_id', 56 | 'unit_id', 57 | 'owner_id', 58 | 'problem_category_id', 59 | 'title', 60 | 'description', 61 | 'ticket_statuses_id', 62 | 'responsible_id', 63 | 'approved_at', 64 | 'solved_at', 65 | ]; 66 | 67 | /** 68 | * Get the priority that owns the Ticket. 69 | * 70 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 71 | */ 72 | public function priority() 73 | { 74 | return $this->belongsTo(Priority::class); 75 | } 76 | 77 | /** 78 | * Get the unit that owns the Ticket. 79 | * 80 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 81 | */ 82 | public function unit() 83 | { 84 | return $this->belongsTo(Unit::class); 85 | } 86 | 87 | /** 88 | * Get the owner that owns the Ticket. 89 | * 90 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 91 | */ 92 | public function owner() 93 | { 94 | return $this->belongsTo(User::class, 'owner_id'); 95 | } 96 | 97 | /** 98 | * Get the responsible that owns the Ticket. 99 | * 100 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 101 | */ 102 | public function responsible() 103 | { 104 | return $this->belongsTo(User::class, 'responsible_id'); 105 | } 106 | 107 | /** 108 | * Get the problemCategory that owns the Ticket. 109 | * 110 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 111 | */ 112 | public function problemCategory() 113 | { 114 | return $this->belongsTo(ProblemCategory::class); 115 | } 116 | 117 | /** 118 | * Get the ticketStatus that owns the Ticket. 119 | * 120 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 121 | */ 122 | public function ticketStatus() 123 | { 124 | return $this->belongsTo(TicketStatus::class, 'ticket_statuses_id'); 125 | } 126 | 127 | /** 128 | * Get all of the comments for the Ticket. 129 | * 130 | * @return \Illuminate\Database\Eloquent\Relations\HasMany 131 | */ 132 | public function comments() 133 | { 134 | return $this->hasMany(Comment::class, 'tiket_id'); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /app/Models/TicketStatus.php: -------------------------------------------------------------------------------- 1 | hasMany(Ticket::class, 'ticket_statuses_id'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Models/Unit.php: -------------------------------------------------------------------------------- 1 | hasMany(ProblemCategory::class); 41 | } 42 | 43 | /** 44 | * Get all of the tickets for the Unit 45 | * 46 | * @return \Illuminate\Database\Eloquent\Relations\HasMany 47 | */ 48 | public function tickets() 49 | { 50 | return $this->hasMany(Ticket::class); 51 | } 52 | 53 | /** 54 | * Get all of the users for the Unit 55 | * 56 | * @return \Illuminate\Database\Eloquent\Relations\HasMany 57 | */ 58 | public function users() 59 | { 60 | return $this->hasMany(User::class); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/Policies/CommentPolicy.php: -------------------------------------------------------------------------------- 1 | can('delete Comment'); 48 | } 49 | 50 | /** 51 | * Determine whether the user can restore the model. 52 | */ 53 | public function restore(User $user, Comment $comment): bool 54 | { 55 | return $user->can('restore Comment'); 56 | } 57 | 58 | /** 59 | * Determine whether the user can permanently delete the model. 60 | */ 61 | public function forceDelete(User $user, Comment $comment): bool 62 | { 63 | return $user->can('force-delete Comment'); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/Policies/PermissionPolicy.php: -------------------------------------------------------------------------------- 1 | can('view-any Permission'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, Permission $Permission): bool 23 | { 24 | return $user->can('view Permission'); 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $user->can('create Permission'); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, Permission $Permission): bool 39 | { 40 | return $user->can('update Permission'); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, Permission $Permission): bool 47 | { 48 | return $user->can('delete Permission'); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, Permission $Permission): bool 55 | { 56 | return $user->can('restore Permission'); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, Permission $Permission): bool 63 | { 64 | return $user->can('force-delete Permission'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Policies/PriorityPolicy.php: -------------------------------------------------------------------------------- 1 | can('view-any Priority'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, Priority $priority): bool 23 | { 24 | return $user->can('view Priority'); 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $user->can('create Priority'); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, Priority $priority): bool 39 | { 40 | return $user->can('update Priority'); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, Priority $priority): bool 47 | { 48 | return $user->can('delete Priority'); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, Priority $priority): bool 55 | { 56 | return $user->can('restore Priority'); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, Priority $priority): bool 63 | { 64 | return $user->can('force-delete Priority'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Policies/ProblemCategoryPolicy.php: -------------------------------------------------------------------------------- 1 | hasRole('Admin Unit'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, ProblemCategory $problemcategory): bool 23 | { 24 | return $user->unit_id == $problemcategory->unit_id; 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $this->viewAny($user); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, ProblemCategory $problemcategory): bool 39 | { 40 | return $this->view($user, $problemcategory); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, ProblemCategory $problemcategory): bool 47 | { 48 | return $this->view($user, $problemcategory); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, ProblemCategory $problemcategory): bool 55 | { 56 | return $this->view($user, $problemcategory); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, ProblemCategory $problemcategory): bool 63 | { 64 | return $this->view($user, $problemcategory); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Policies/RolePolicy.php: -------------------------------------------------------------------------------- 1 | can('view-any Role'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, Role $Role): bool 23 | { 24 | return $user->can('view Role'); 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $user->can('create Role'); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, Role $Role): bool 39 | { 40 | return $user->can('update Role'); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, Role $Role): bool 47 | { 48 | return $user->can('delete Role'); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, Role $Role): bool 55 | { 56 | return $user->can('restore Role'); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, Role $Role): bool 63 | { 64 | return $user->can('force-delete Role'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Policies/TicketPolicy.php: -------------------------------------------------------------------------------- 1 | hasRole('Admin Unit')) { 27 | return $user->id == $ticket->owner_id || $ticket->unit_id == $user->unit_id; 28 | } 29 | 30 | // The staff unit can view tickets that have been assigned to them. 31 | if ($user->hasRole('Staff Unit')) { 32 | return $user->id == $ticket->owner_id || $ticket->responsible_id == $user->id; 33 | } 34 | 35 | // The user can view their own ticket 36 | return $user->id == $ticket->owner_id; 37 | } 38 | 39 | /** 40 | * Determine whether the user can create models. 41 | */ 42 | public function create(User $user): bool 43 | { 44 | return true; 45 | } 46 | 47 | /** 48 | * Determine whether the user can update the model. 49 | */ 50 | public function update(User $user, Ticket $ticket): bool 51 | { 52 | return $this->view($user, $ticket); 53 | } 54 | 55 | /** 56 | * Determine whether the user can delete the model. 57 | */ 58 | public function delete(User $user, Ticket $ticket): bool 59 | { 60 | if ($ticket->ticket_statuses_id != TicketStatus::OPEN) { 61 | return false; 62 | } 63 | 64 | return $user->id == $ticket->owner_id; 65 | } 66 | 67 | /** 68 | * Determine whether the user can restore the model. 69 | */ 70 | public function restore(User $user, Ticket $ticket): bool 71 | { 72 | return $user->id == $ticket->owner_id; 73 | } 74 | 75 | /** 76 | * Determine whether the user can permanently delete the model. 77 | */ 78 | public function forceDelete(User $user, Ticket $ticket): bool 79 | { 80 | return $user->id == $ticket->owner_id; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/Policies/TicketStatusPolicy.php: -------------------------------------------------------------------------------- 1 | can('view-any TicketStatus'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, TicketStatus $ticketstatus): bool 23 | { 24 | return $user->can('view TicketStatus'); 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $user->can('create TicketStatus'); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, TicketStatus $ticketstatus): bool 39 | { 40 | return $user->can('update TicketStatus'); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, TicketStatus $ticketstatus): bool 47 | { 48 | return $user->can('delete TicketStatus'); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, TicketStatus $ticketstatus): bool 55 | { 56 | return $user->can('restore TicketStatus'); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, TicketStatus $ticketstatus): bool 63 | { 64 | return $user->can('force-delete TicketStatus'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Policies/UnitPolicy.php: -------------------------------------------------------------------------------- 1 | can('view-any Unit'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, Unit $unit): bool 23 | { 24 | return $user->can('view Unit'); 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $user->can('create Unit'); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, Unit $unit): bool 39 | { 40 | return $user->can('update Unit'); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, Unit $unit): bool 47 | { 48 | return $user->can('delete Unit'); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, Unit $unit): bool 55 | { 56 | return $user->can('restore Unit'); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, Unit $unit): bool 63 | { 64 | return $user->can('force-delete Unit'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Policies/UserPolicy.php: -------------------------------------------------------------------------------- 1 | can('view-any User'); 17 | } 18 | 19 | /** 20 | * Determine whether the user can view the model. 21 | */ 22 | public function view(User $user, User $model): bool 23 | { 24 | return $user->can('view User'); 25 | } 26 | 27 | /** 28 | * Determine whether the user can create models. 29 | */ 30 | public function create(User $user): bool 31 | { 32 | return $user->can('create User'); 33 | } 34 | 35 | /** 36 | * Determine whether the user can update the model. 37 | */ 38 | public function update(User $user, User $model): bool 39 | { 40 | return $user->can('update User'); 41 | } 42 | 43 | /** 44 | * Determine whether the user can delete the model. 45 | */ 46 | public function delete(User $user, User $model): bool 47 | { 48 | return $user->can('delete User'); 49 | } 50 | 51 | /** 52 | * Determine whether the user can restore the model. 53 | */ 54 | public function restore(User $user, User $model): bool 55 | { 56 | return $user->can('restore User'); 57 | } 58 | 59 | /** 60 | * Determine whether the user can permanently delete the model. 61 | */ 62 | public function forceDelete(User $user, User $model): bool 63 | { 64 | return $user->can('force-delete User'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | protected $policies = [ 23 | Role::class => RolePolicy::class, 24 | Permission::class => PermissionPolicy::class, 25 | ]; 26 | 27 | /** 28 | * Register any authentication / authorization services. 29 | */ 30 | public function boot(): void 31 | { 32 | Gate::before(function (User $user, string $ability) { 33 | return $user->isSuperAdmin() ? true : null; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | > 16 | */ 17 | protected $listen = [ 18 | Registered::class => [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | */ 26 | public function boot(): void 27 | { 28 | // 29 | } 30 | 31 | /** 32 | * Determine if events and listeners should be automatically discovered. 33 | */ 34 | public function shouldDiscoverEvents(): bool 35 | { 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | by($request->user()?->id ?: $request->ip()); 29 | }); 30 | 31 | $this->routes(function () { 32 | Route::middleware('api') 33 | ->prefix('api') 34 | ->group(base_path('routes/api.php')); 35 | 36 | Route::middleware('web') 37 | ->group(base_path('routes/web.php')); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": [ 6 | "framework", 7 | "laravel" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^8.1", 12 | "althinect/filament-spatie-roles-permissions": "^1.2", 13 | "awcodes/overlook": "^1.2", 14 | "bezhansalleh/filament-language-switch": "^1.0", 15 | "dutchcodingcompany/filament-socialite": "^0.2.5", 16 | "filament/filament": "^2.0", 17 | "guzzlehttp/guzzle": "^7.2", 18 | "jeffgreco13/filament-breezy": "^1.5", 19 | "laravel/framework": "^10.10", 20 | "laravel/sanctum": "^3.2", 21 | "laravel/tinker": "^2.8", 22 | "leandrocfe/filament-apex-charts": "^2.0", 23 | "owenvoke/blade-fontawesome": "^2.3", 24 | "stechstudio/filament-impersonate": "^2.18" 25 | }, 26 | "require-dev": { 27 | "andyabih/laravel-to-uml": "^1.0", 28 | "barryvdh/laravel-debugbar": "^3.8", 29 | "doctrine/dbal": "^3.6", 30 | "fakerphp/faker": "^1.9.1", 31 | "friendsofphp/php-cs-fixer": "^3.17", 32 | "kitloong/laravel-migrations-generator": "^6.10", 33 | "laravel/pint": "^1.0", 34 | "laravel/sail": "^1.18", 35 | "mockery/mockery": "^1.4.4", 36 | "nunomaduro/collision": "^7.0", 37 | "nunomaduro/larastan": "^2.0", 38 | "phpunit/phpunit": "^10.1", 39 | "reliese/laravel": "^1.2", 40 | "spatie/laravel-ignition": "^2.0" 41 | }, 42 | "autoload": { 43 | "psr-4": { 44 | "App\\": "app/", 45 | "Database\\Factories\\": "database/factories/", 46 | "Database\\Seeders\\": "database/seeders/" 47 | } 48 | }, 49 | "autoload-dev": { 50 | "psr-4": { 51 | "Tests\\": "tests/" 52 | } 53 | }, 54 | "scripts": { 55 | "post-autoload-dump": [ 56 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 57 | "@php artisan package:discover --ansi" 58 | ], 59 | "post-update-cmd": [ 60 | "@php artisan vendor:publish --tag=laravel-assets --ansi --force" 61 | ], 62 | "post-root-package-install": [ 63 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 64 | ], 65 | "post-create-project-cmd": [ 66 | "@php artisan key:generate --ansi" 67 | ] 68 | }, 69 | "extra": { 70 | "laravel": { 71 | "dont-discover": [] 72 | } 73 | }, 74 | "config": { 75 | "optimize-autoloader": true, 76 | "preferred-install": "dist", 77 | "sort-packages": true, 78 | "allow-plugins": { 79 | "pestphp/pest-plugin": true, 80 | "php-http/discovery": true 81 | } 82 | }, 83 | "minimum-stability": "stable", 84 | "prefer-stable": true, 85 | "sniff": [ 86 | "./vendor/bin/php-cs-fixer fix -vvv --dry-run --show-progress=dots" 87 | ], 88 | "lint": [ 89 | "./vendor/bin/php-cs-fixer fix -vvv --show-progress=dots" 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com', 41 | 'port' => env('PUSHER_PORT', 443), 42 | 'scheme' => env('PUSHER_SCHEME', 'https'), 43 | 'encrypted' => true, 44 | 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', 45 | ], 46 | 'client_options' => [ 47 | // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html 48 | ], 49 | ], 50 | 51 | 'ably' => [ 52 | 'driver' => 'ably', 53 | 'key' => env('ABLY_KEY'), 54 | ], 55 | 56 | 'redis' => [ 57 | 'driver' => 'redis', 58 | 'connection' => 'default', 59 | ], 60 | 61 | 'log' => [ 62 | 'driver' => 'log', 63 | ], 64 | 65 | 'null' => [ 66 | 'driver' => 'null', 67 | ], 68 | 69 | ], 70 | 71 | ]; 72 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | | Supported drivers: "apc", "array", "database", "file", 30 | | "memcached", "redis", "dynamodb", "octane", "null" 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'apc' => [ 37 | 'driver' => 'apc', 38 | ], 39 | 40 | 'array' => [ 41 | 'driver' => 'array', 42 | 'serialize' => false, 43 | ], 44 | 45 | 'database' => [ 46 | 'driver' => 'database', 47 | 'table' => 'cache', 48 | 'connection' => null, 49 | 'lock_connection' => null, 50 | ], 51 | 52 | 'file' => [ 53 | 'driver' => 'file', 54 | 'path' => storage_path('framework/cache/data'), 55 | 'lock_path' => storage_path('framework/cache/data'), 56 | ], 57 | 58 | 'memcached' => [ 59 | 'driver' => 'memcached', 60 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 61 | 'sasl' => [ 62 | env('MEMCACHED_USERNAME'), 63 | env('MEMCACHED_PASSWORD'), 64 | ], 65 | 'options' => [ 66 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 67 | ], 68 | 'servers' => [ 69 | [ 70 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 71 | 'port' => env('MEMCACHED_PORT', 11211), 72 | 'weight' => 100, 73 | ], 74 | ], 75 | ], 76 | 77 | 'redis' => [ 78 | 'driver' => 'redis', 79 | 'connection' => 'cache', 80 | 'lock_connection' => 'default', 81 | ], 82 | 83 | 'dynamodb' => [ 84 | 'driver' => 'dynamodb', 85 | 'key' => env('AWS_ACCESS_KEY_ID'), 86 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 87 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 88 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 89 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 90 | ], 91 | 92 | 'octane' => [ 93 | 'driver' => 'octane', 94 | ], 95 | 96 | ], 97 | 98 | /* 99 | |-------------------------------------------------------------------------- 100 | | Cache Key Prefix 101 | |-------------------------------------------------------------------------- 102 | | 103 | | When utilizing the APC, database, memcached, Redis, or DynamoDB cache 104 | | stores there might be other applications using the same cache. For 105 | | that reason, you may prefix every cache key to avoid collisions. 106 | | 107 | */ 108 | 109 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), 110 | 111 | ]; 112 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*', 'sanctum/csrf-cookie'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /config/filament-authentication.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'User' => \App\Models\User::class, 6 | 'Role' => \Spatie\Permission\Models\Role::class, 7 | 'Permission' => \Spatie\Permission\Models\Permission::class, 8 | ], 9 | 'resources' => [ 10 | 'UserResource' => \Phpsa\FilamentAuthentication\Resources\UserResource::class, 11 | 'RoleResource' => \Phpsa\FilamentAuthentication\Resources\RoleResource::class, 12 | 'PermissionResource' => \Phpsa\FilamentAuthentication\Resources\PermissionResource::class, 13 | ], 14 | 'pages' => [ 15 | 'Profile' => \Phpsa\FilamentAuthentication\Pages\Profile::class 16 | ], 17 | 'Widgets' => [ 18 | 'LatestUsers' => [ 19 | 'enabled' => true, 20 | 'limit' => 5, 21 | 'sort' => 0, 22 | 'paginate' => false 23 | ], 24 | ], 25 | 'preload_roles' => true, 26 | 'impersonate' => [ 27 | 'enabled' => true, 28 | 'guard' => 'web', 29 | 'redirect' => '/' 30 | ] 31 | ]; 32 | -------------------------------------------------------------------------------- /config/filament-socialite.php: -------------------------------------------------------------------------------- 1 | [], 9 | 10 | // Allow registration through socials 11 | 'registration' => true, 12 | 13 | // Specify the providers that should be visible on the login. 14 | // These should match the socialite providers you have setup in your services.php config. 15 | // Uses blade UI icons, for example: https://github.com/owenvoke/blade-fontawesome 16 | 'providers' => [ 17 | 'google' => [ 18 | 'label' => 'Google', 19 | 'icon' => 'fab-google', 20 | ], 21 | // 'github' => [ 22 | // 'label' => 'GitHub', 23 | // 'icon' => 'fab-github', 24 | // ], 25 | ], 26 | 27 | 'user_model' => \App\Models\User::class, 28 | 29 | // Specify the default redirect route for successful logins 30 | 'login_redirect_route' => 'filament.pages.dashboard', 31 | 32 | // Specify the route name for the socialite login page 33 | 'login_page_route' => 'filament.auth.login', 34 | ]; 35 | -------------------------------------------------------------------------------- /config/filament-spatie-roles-permissions.php: -------------------------------------------------------------------------------- 1 | false, 6 | 7 | 'preload_permissions' => false, 8 | 9 | 'navigation_section_group' => 'filament-spatie-roles-permissions::filament-spatie.section.roles_and_permissions', // Default uses language constant 10 | 11 | 'team_model' => \App\Models\Team::class, 12 | 13 | /* 14 | * Set to false to remove from navigation 15 | */ 16 | 'should_register_on_navigation' => [ 17 | 'permissions' => false, 18 | 'roles' => false 19 | ], 20 | 21 | 'generator' => [ 22 | 23 | 'guard_names' => [ 24 | 'web', 25 | //'api' 26 | ], 27 | 28 | 'permission_affixes' => [ 29 | 30 | /* 31 | * Permissions Aligned with Policies. 32 | * DO NOT change the keys unless the genericPolicy.stub is published and altered accordingly 33 | */ 34 | 'viewAnyPermission' => 'view-any', 35 | 'viewPermission' => 'view', 36 | 'createPermission' => 'create', 37 | 'updatePermission' => 'update', 38 | 'deletePermission' => 'delete', 39 | 'restorePermission' => 'restore', 40 | 'forceDeletePermission' => 'force-delete', 41 | 42 | /* 43 | * Additional Resource Permissions 44 | */ 45 | 'replicate', 46 | 'reorder', 47 | ], 48 | 49 | /* 50 | * returns the "name" for the permission. 51 | * 52 | * $permission which is an iteration of [permission_affixes] , 53 | * $model The model to which the $permission will be concatenated 54 | * 55 | * Eg: 'permission_name' => 'return $permissionAffix . ' ' . Str::kebab($modelName), 56 | * 57 | * Note: If you are changing the "permission_name" , It's recommended to run with --clean to avoid duplications 58 | */ 59 | 'permission_name' => 'return $permissionAffix . \' \' . $modelName;', 60 | 61 | /* 62 | * Permissions will be generated for the models associated with the respective Filament Resources 63 | */ 64 | 'discover_models_through_filament_resources' => false, 65 | 66 | /* 67 | * Include directories which consists of models. 68 | */ 69 | 'model_directories' => [ 70 | app_path('Models') 71 | //app_path('Domains/Forum') 72 | ], 73 | 74 | /* 75 | * Define custom_models in snake-case 76 | */ 77 | 'custom_models' => [ 78 | // 79 | ], 80 | 81 | /* 82 | * Define excluded_models in snake-case 83 | */ 84 | 'excluded_models' => [ 85 | // 86 | ], 87 | 88 | 'excluded_policy_models' => [ 89 | \App\Models\User::class 90 | ], 91 | 92 | /* 93 | * Define any other permission here 94 | */ 95 | 'custom_permissions' => [ 96 | //'view-log' 97 | ], 98 | 99 | 100 | 'user_model' => \App\Models\User::class, 101 | 102 | 'policies_namespace' => 'App\Policies' 103 | ], 104 | ]; 105 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DISK', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Filesystem Disks 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure as many filesystem "disks" as you wish, and you 24 | | may even configure multiple disks of the same driver. Defaults have 25 | | been set up for each driver as an example of the required values. 26 | | 27 | | Supported Drivers: "local", "ftp", "sftp", "s3" 28 | | 29 | */ 30 | 31 | 'disks' => [ 32 | 33 | 'local' => [ 34 | 'driver' => 'local', 35 | 'root' => storage_path('app'), 36 | 'throw' => false, 37 | ], 38 | 39 | 'public' => [ 40 | 'driver' => 'local', 41 | 'root' => storage_path('app/public'), 42 | 'url' => env('APP_URL').'/storage', 43 | 'visibility' => 'public', 44 | 'throw' => false, 45 | ], 46 | 47 | 's3' => [ 48 | 'driver' => 's3', 49 | 'key' => env('AWS_ACCESS_KEY_ID'), 50 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 51 | 'region' => env('AWS_DEFAULT_REGION'), 52 | 'bucket' => env('AWS_BUCKET'), 53 | 'url' => env('AWS_URL'), 54 | 'endpoint' => env('AWS_ENDPOINT'), 55 | 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 56 | 'throw' => false, 57 | ], 58 | 59 | ], 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Symbolic Links 64 | |-------------------------------------------------------------------------- 65 | | 66 | | Here you may configure the symbolic links that will be created when the 67 | | `storage:link` Artisan command is executed. The array keys should be 68 | | the locations of the links and the values should be their targets. 69 | | 70 | */ 71 | 72 | 'links' => [ 73 | public_path('storage') => storage_path('app/public'), 74 | ], 75 | 76 | ]; 77 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 65536, 48 | 'threads' => 1, 49 | 'time' => 4, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /config/overlook.php: -------------------------------------------------------------------------------- 1 | [ 5 | // App\Filament\Resources\Blog\AuthorResource::class, 6 | ], 7 | 'excludes' => [ 8 | Althinect\FilamentSpatieRolesPermissions\Resources\PermissionResource::class, 9 | Althinect\FilamentSpatieRolesPermissions\Resources\RoleResource::class, 10 | ], 11 | 'should_convert_count' => true, 12 | 'enable_convert_tooltip' => true, 13 | ]; 14 | -------------------------------------------------------------------------------- /config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'sync'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection information for each server that 24 | | is used by your application. A default configuration has been added 25 | | for each back-end shipped with Laravel. You are free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | 'after_commit' => false, 43 | ], 44 | 45 | 'beanstalkd' => [ 46 | 'driver' => 'beanstalkd', 47 | 'host' => 'localhost', 48 | 'queue' => 'default', 49 | 'retry_after' => 90, 50 | 'block_for' => 0, 51 | 'after_commit' => false, 52 | ], 53 | 54 | 'sqs' => [ 55 | 'driver' => 'sqs', 56 | 'key' => env('AWS_ACCESS_KEY_ID'), 57 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 58 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 59 | 'queue' => env('SQS_QUEUE', 'default'), 60 | 'suffix' => env('SQS_SUFFIX'), 61 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 62 | 'after_commit' => false, 63 | ], 64 | 65 | 'redis' => [ 66 | 'driver' => 'redis', 67 | 'connection' => 'default', 68 | 'queue' => env('REDIS_QUEUE', 'default'), 69 | 'retry_after' => 90, 70 | 'block_for' => null, 71 | 'after_commit' => false, 72 | ], 73 | 74 | ], 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Job Batching 79 | |-------------------------------------------------------------------------- 80 | | 81 | | The following options configure the database and table that store job 82 | | batching information. These options can be updated to any database 83 | | connection and table which has been defined by your application. 84 | | 85 | */ 86 | 87 | 'batching' => [ 88 | 'database' => env('DB_CONNECTION', 'mysql'), 89 | 'table' => 'job_batches', 90 | ], 91 | 92 | /* 93 | |-------------------------------------------------------------------------- 94 | | Failed Queue Jobs 95 | |-------------------------------------------------------------------------- 96 | | 97 | | These options configure the behavior of failed queue job logging so you 98 | | can control which database and table are used to store the jobs that 99 | | have failed. You may change them to any database / table you wish. 100 | | 101 | */ 102 | 103 | 'failed' => [ 104 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 105 | 'database' => env('DB_CONNECTION', 'mysql'), 106 | 'table' => 'failed_jobs', 107 | ], 108 | 109 | ]; 110 | -------------------------------------------------------------------------------- /config/sanctum.php: -------------------------------------------------------------------------------- 1 | explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( 19 | '%s%s', 20 | 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', 21 | Sanctum::currentApplicationUrlWithPort() 22 | ))), 23 | 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | Sanctum Guards 27 | |-------------------------------------------------------------------------- 28 | | 29 | | This array contains the authentication guards that will be checked when 30 | | Sanctum is trying to authenticate a request. If none of these guards 31 | | are able to authenticate the request, Sanctum will use the bearer 32 | | token that's present on an incoming request for authentication. 33 | | 34 | */ 35 | 36 | 'guard' => ['web'], 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Expiration Minutes 41 | |-------------------------------------------------------------------------- 42 | | 43 | | This value controls the number of minutes until an issued token will be 44 | | considered expired. If this value is null, personal access tokens do 45 | | not expire. This won't tweak the lifetime of first-party sessions. 46 | | 47 | */ 48 | 49 | 'expiration' => null, 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | Sanctum Middleware 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When authenticating your first-party SPA with Sanctum you may need to 57 | | customize some of the middleware Sanctum uses while processing the 58 | | request. You may change the middleware listed below as required. 59 | | 60 | */ 61 | 62 | 'middleware' => [ 63 | 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, 64 | 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, 65 | ], 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | 'scheme' => 'https', 22 | ], 23 | 24 | 'postmark' => [ 25 | 'token' => env('POSTMARK_TOKEN'), 26 | ], 27 | 28 | 'ses' => [ 29 | 'key' => env('AWS_ACCESS_KEY_ID'), 30 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 31 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 32 | ], 33 | 34 | 'google' => [ 35 | 'client_id' => env('GOOGLE_CLIENT_ID'), 36 | 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 37 | 'redirect' => env('GOOGLE_CLIENT_REDIRECT'), 38 | ], 39 | ]; 40 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class UserFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => fake()->name(), 22 | 'email' => fake()->unique()->safeEmail(), 23 | 'email_verified_at' => now(), 24 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 25 | 'remember_token' => Str::random(10), 26 | ]; 27 | } 28 | 29 | /** 30 | * Indicate that the model's email address should be unverified. 31 | */ 32 | public function unverified(): static 33 | { 34 | return $this->state(fn (array $attributes) => [ 35 | 'email_verified_at' => null, 36 | ]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 15 | $table->string('name'); 16 | $table->string('email')->unique(); 17 | $table->timestamp('email_verified_at')->nullable(); 18 | $table->string('password'); 19 | $table->rememberToken(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down(): void 28 | { 29 | Schema::dropIfExists('users'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php: -------------------------------------------------------------------------------- 1 | string('email')->primary(); 15 | $table->string('token'); 16 | $table->timestamp('created_at')->nullable(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down(): void 24 | { 25 | Schema::dropIfExists('password_reset_tokens'); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 15 | $table->string('uuid')->unique(); 16 | $table->text('connection'); 17 | $table->text('queue'); 18 | $table->longText('payload'); 19 | $table->longText('exception'); 20 | $table->timestamp('failed_at')->useCurrent(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down(): void 28 | { 29 | Schema::dropIfExists('failed_jobs'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php: -------------------------------------------------------------------------------- 1 | id(); 15 | $table->morphs('tokenable'); 16 | $table->string('name'); 17 | $table->string('token', 64)->unique(); 18 | $table->text('abilities')->nullable(); 19 | $table->timestamp('last_used_at')->nullable(); 20 | $table->timestamp('expires_at')->nullable(); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('personal_access_tokens'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_create_comments_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->unsignedBigInteger('tiket_id')->index('tiket_id'); 18 | $table->unsignedBigInteger('user_id')->index('user_id'); 19 | $table->text('comment'); 20 | $table->timestamps(); 21 | $table->softDeletes(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('comments'); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_create_priorities_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->string('name'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | * 24 | * @return void 25 | */ 26 | public function down() 27 | { 28 | Schema::dropIfExists('priorities'); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_create_problem_categories_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->unsignedBigInteger('unit_id')->index('unit_id'); 18 | $table->string('name'); 19 | $table->timestamps(); 20 | $table->softDeletes(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('problem_categories'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_create_ticket_statuses_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->string('name'); 18 | $table->timestamps(); 19 | $table->softDeletes(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('ticket_statuses'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_create_tickets_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->unsignedBigInteger('priority_id')->index('priority_id'); 18 | $table->unsignedBigInteger('unit_id')->index('unit_id'); 19 | $table->unsignedBigInteger('owner_id')->index('owner_id'); 20 | $table->unsignedBigInteger('problem_category_id')->index('problem_category_id'); 21 | $table->string('title'); 22 | $table->text('description'); 23 | $table->unsignedBigInteger('ticket_statuses_id')->index('ticket_statuses_id'); 24 | $table->unsignedBigInteger('responsible_id')->nullable()->index('responsible_id'); 25 | $table->timestamps(); 26 | $table->timestamp('approved_at')->nullable(); 27 | $table->timestamp('solved_at')->nullable(); 28 | $table->softDeletes(); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('tickets'); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_create_units_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->string('name'); 18 | $table->timestamps(); 19 | $table->softDeletes(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('units'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082020_update_users_table.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('unit_id')->nullable()->index('unit_id'); 17 | $table->string('identity')->nullable(); 18 | $table->string('phone')->nullable(); 19 | $table->boolean('is_active')->default(true); 20 | $table->softDeletes(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::table('users', function (Blueprint $table) { 32 | $table->dropColumn([ 33 | 'unit_id', 34 | 'identity', 35 | 'phone', 36 | 'is_active', 37 | 'deleted_at', 38 | ]); 39 | }); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082023_add_foreign_keys_to_comments_table.php: -------------------------------------------------------------------------------- 1 | foreign(['user_id'], 'comments_ibfk_2')->references(['id'])->on('users')->onUpdate('NO ACTION'); 17 | $table->foreign(['tiket_id'], 'comments_ibfk_3')->references(['id'])->on('tickets')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 18 | $table->foreign(['user_id'], 'comments_ibfk_4')->references(['id'])->on('users')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::table('comments', function (Blueprint $table) { 30 | $table->dropForeign('comments_ibfk_2'); 31 | $table->dropForeign('comments_ibfk_3'); 32 | $table->dropForeign('comments_ibfk_4'); 33 | }); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082023_add_foreign_keys_to_problem_categories_table.php: -------------------------------------------------------------------------------- 1 | foreign(['unit_id'], 'problem_categories_ibfk_1')->references(['id'])->on('units')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('problem_categories', function (Blueprint $table) { 28 | $table->dropForeign('problem_categories_ibfk_1'); 29 | }); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082023_add_foreign_keys_to_tickets_table.php: -------------------------------------------------------------------------------- 1 | foreign(['priority_id'], 'tickets_ibfk_1')->references(['id'])->on('priorities')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 17 | $table->foreign(['unit_id'], 'tickets_ibfk_2')->references(['id'])->on('units')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 18 | $table->foreign(['owner_id'], 'tickets_ibfk_3')->references(['id'])->on('users')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 19 | $table->foreign(['problem_category_id'], 'tickets_ibfk_4')->references(['id'])->on('problem_categories')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 20 | $table->foreign(['responsible_id'], 'tickets_ibfk_5')->references(['id'])->on('users')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 21 | $table->foreign(['ticket_statuses_id'], 'tickets_ibfk_6')->references(['id'])->on('ticket_statuses')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::table('tickets', function (Blueprint $table) { 33 | $table->dropForeign('tickets_ibfk_1'); 34 | $table->dropForeign('tickets_ibfk_2'); 35 | $table->dropForeign('tickets_ibfk_3'); 36 | $table->dropForeign('tickets_ibfk_4'); 37 | $table->dropForeign('tickets_ibfk_5'); 38 | $table->dropForeign('tickets_ibfk_6'); 39 | }); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /database/migrations/2023_06_06_082023_add_foreign_keys_to_users_table.php: -------------------------------------------------------------------------------- 1 | foreign(['unit_id'], 'users_ibfk_1')->references(['id'])->on('units')->onUpdate('NO ACTION')->onDelete('NO ACTION'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('users', function (Blueprint $table) { 28 | $table->dropForeign('users_ibfk_1'); 29 | }); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/2023_06_13_041702_create_notifications_table.php: -------------------------------------------------------------------------------- 1 | uuid('id')->primary(); 16 | $table->string('type'); 17 | $table->morphs('notifiable'); 18 | $table->text('data'); 19 | $table->timestamp('read_at')->nullable(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down(): void 28 | { 29 | Schema::dropIfExists('notifications'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/2023_06_14_043122_add_attachment_to_comments_table.php: -------------------------------------------------------------------------------- 1 | string('attachments')->after('comment')->nullable(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('comments', function (Blueprint $table) { 25 | $table->dropColumn('attachments'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2023_06_14_070356_create_socialite_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | 14 | $table->foreignIdFor(FilamentSocialite::getUserModelClass(), 'user_id'); 15 | $table->string('provider'); 16 | $table->string('provider_id'); 17 | 18 | $table->timestamps(); 19 | 20 | $table->unique([ 21 | 'provider', 22 | 'provider_id', 23 | ]); 24 | }); 25 | } 26 | 27 | public function down() 28 | { 29 | Schema::dropIfExists('socialite_users'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /database/migrations/2023_06_14_070958_update_users_table_add_nullable_to_password.php: -------------------------------------------------------------------------------- 1 | string('password')->nullable()->change(); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('password', function (Blueprint $table) { 25 | // 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call([ 16 | PermissionSeeder::class, 17 | RoleSeeder::class, 18 | UnitSeeder::class, 19 | UserSeeder::class, 20 | PrioritySeeder::class, 21 | TicketStatusSeeder::class, 22 | ProblemCategoryMigration::class, 23 | TicketSeeder::class, 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/seeders/PermissionSeeder.php: -------------------------------------------------------------------------------- 1 | Priority::CRITICAL, 'name' => 'Critical/Urgent']); 16 | Priority::create(['id' => Priority::HIGHT, 'name' => 'High']); 17 | Priority::create(['id' => Priority::MEDIUM, 'name' => 'Medium']); 18 | Priority::create(['id' => Priority::LOW, 'name' => 'Low']); 19 | Priority::create(['id' => Priority::ENHANCEMENT, 'name' => 'Enhancement/Feature Request']); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/seeders/ProblemCategoryMigration.php: -------------------------------------------------------------------------------- 1 | 1, 18 | 'name' => 'Problem One at Sales Department', 19 | ], 20 | [ 21 | 'unit_id' => 1, 22 | 'name' => 'Problem Two at Sales Department', 23 | ], 24 | [ 25 | 'unit_id' => 2, 26 | 'name' => 'Problem One at Technical Support', 27 | ], 28 | [ 29 | 'unit_id' => 3, 30 | 'name' => 'Problem One at Billing Support', 31 | ], 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/seeders/RoleSeeder.php: -------------------------------------------------------------------------------- 1 | 'Super Admin', 17 | 'guard_name' => 'web', 18 | ]); 19 | 20 | Role::create([ 21 | 'name' => 'Admin Unit', 22 | 'guard_name' => 'web', 23 | ]); 24 | 25 | Role::create([ 26 | 'name' => 'Staff Unit', 27 | 'guard_name' => 'web', 28 | ]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/seeders/TicketSeeder.php: -------------------------------------------------------------------------------- 1 | 1, 17 | 'unit_id' => 1, 18 | 'owner_id' => 1, 19 | 'problem_category_id' => 1, 20 | 'title' => 'This is a sample ticket', 21 | 'description' => 'This is a descriptions', 22 | 'ticket_statuses_id' => '1', 23 | ]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/seeders/TicketStatusSeeder.php: -------------------------------------------------------------------------------- 1 | TicketStatus::OPEN, 'name' => 'Open'], 17 | ['id' => TicketStatus::ASSIGNED, 'name' => 'Assigned'], 18 | ['id' => TicketStatus::IN_PROGRESS, 'name' => 'In Progress'], 19 | ['id' => TicketStatus::ON_HOLD, 'name' => 'On Hold'], 20 | ['id' => TicketStatus::ESCALATED, 'name' => 'Escalated'], 21 | ['id' => TicketStatus::PENDING_CUSTOMER_RESPONSE, 'name' => 'Pending Customer Response'], 22 | ['id' => TicketStatus::RESOLVED, 'name' => 'Resolved'], 23 | ['id' => TicketStatus::CLOSED, 'name' => 'Closed'], 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/seeders/UnitSeeder.php: -------------------------------------------------------------------------------- 1 | 'Sales Department'], 17 | ['name' => 'Technical Support'], 18 | ['name' => 'Billing Support'], 19 | ]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/seeders/UserSeeder.php: -------------------------------------------------------------------------------- 1 | create([ 17 | 'name' => 'Super Admin', 18 | 'email' => 'superadmin@example.com', 19 | ]); 20 | $superAdmin->syncRoles('Super Admin'); 21 | 22 | // 2. create a admin unit 23 | $adminUnit = User::factory()->create([ 24 | 'name' => 'Admin Unit', 25 | 'email' => 'adminunit@example.com', 26 | 'unit_id' => 1, 27 | ]); 28 | $adminUnit->syncRoles('Admin Unit'); 29 | 30 | // 3. create a staff unit 31 | $staffUnit = User::factory()->create([ 32 | 'name' => 'Staff Unit', 33 | 'email' => 'staffunit@example.com', 34 | 'unit_id' => 1, 35 | ]); 36 | $staffUnit->syncRoles('Staff Unit'); 37 | 38 | // 4. create a user 39 | $staffUnit = User::factory()->create([ 40 | 'name' => 'User', 41 | 'email' => 'user@example.com', 42 | ]); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "Ticket": "Tiket", 3 | "Tickets": "Tikets", 4 | "Name": "Name", 5 | "Title": "Title", 6 | "Work Unit": "Work Unit", 7 | "Problem Category": "Problem Category", 8 | "Description": "Description", 9 | "Priority": "Priority", 10 | "Created at": "Created at", 11 | "Updated at": "Updated at", 12 | "Approved at": "Approved at", 13 | "Solved at": "Solved at", 14 | "Status": "Status", 15 | "Ticket Status": "Ticket Status", 16 | "Responsible": "Responsible", 17 | "Tickets Count": "Tickets Count", 18 | "Ticket Statuses ": "Ticket Statuses", 19 | "Owner": "Owner", 20 | "Login": "Login", 21 | "Why Use Helpdesk?": "Why Use Helpdesk?", 22 | "Reasons": "Helpdesks provide efficient support, centralize communication, streamline workflows, offer self-service options, monitor performance, and enhance the customer experience." 23 | } 24 | -------------------------------------------------------------------------------- /lang/id.json: -------------------------------------------------------------------------------- 1 | { 2 | "Ticket": "Ticket", 3 | "Tickets": "Tiket", 4 | "Name": "Nama", 5 | "Title": "Judul", 6 | "Work Unit": "Unit Kerja", 7 | "Problem Category": "Kategori Masalah", 8 | "Description": "Deskripsi", 9 | "Priority": "Prioritas", 10 | "Created at": "Dibuat pada", 11 | "Updated at": "Diperbarui pada", 12 | "Approved at": "Diterima pada", 13 | "Solved at": "Diselesaikan pada", 14 | "Status": "Status", 15 | "Ticket Status": "Status Tiket", 16 | "Responsible": "Penanggungjawab", 17 | "Tickets Count": "Jumlah Tiket", 18 | "Ticket Statuses ": "Status Tiket", 19 | "Owner": "Pemilik", 20 | "Login": "Masuk", 21 | "Why Use Helpdesk?": "Kenapa Menggunakan Helpdesk?", 22 | "Reasons": "Helpdesk menyediakan dukungan yang efisien, menggabungkan komunikasi, menyederhanakan alur kerja, menyediakan opsi self-service, memantau kinerja, dan meningkatkan pengalaman pelanggan." 23 | } 24 | -------------------------------------------------------------------------------- /lang/vendor/filament-authentication/en/filament-authentication.php: -------------------------------------------------------------------------------- 1 | 'Authentication', 6 | 'section.users' => 'Users', 7 | 'section.user' => 'User', 8 | 9 | 10 | /* 11 | |-------------------------------------------------------------------------- 12 | | Fields 13 | |-------------------------------------------------------------------------- 14 | */ 15 | 'field.id' => 'ID', 16 | 'field.user.name' => 'Name', 17 | 'field.user.email' => 'Email', 18 | 'field.user.roles' => 'Roles', 19 | 'field.user.verified_at' => 'Verified', 20 | 'field.user.created_at' => 'Joined', 21 | 'field.user.password' => 'Password', 22 | 'field.user.confirm_password' => 'Confirm Password', 23 | 24 | 'field.guard_name' => 'Guard Name', 25 | 'field.name' => 'Name', 26 | 'field.permissions' => 'Permissions', 27 | 'field.roles' => 'Roles', 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Labels 32 | |-------------------------------------------------------------------------- 33 | */ 34 | 35 | 'section.permission' => 'Permission', 36 | 'section.permissions' => 'Permissions', 37 | 'section.role' => 'Role', 38 | 'section.roles' => 'Roles', 39 | 'section.roles_and_permissions' => 'Roles and Permissions', 40 | 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Filters 45 | |-------------------------------------------------------------------------- 46 | */ 47 | 'filter.verified' => 'Email Verified', 48 | 49 | 'button.impersonate' => "Impersonate User", 50 | 'text.impersonating' => 'Impersonating User: ', 51 | 'text.impersonating.end' => ' - End Impersonation ', 52 | ]; 53 | -------------------------------------------------------------------------------- /lang/vendor/filament-authentication/pt_BR/filament-authentication.php: -------------------------------------------------------------------------------- 1 | 'Autenticação', 6 | 'section.users' => 'Usuários', 7 | 'section.user' => 'Usuário', 8 | 9 | 10 | /* 11 | |-------------------------------------------------------------------------- 12 | | Fields 13 | |-------------------------------------------------------------------------- 14 | */ 15 | 'field.id' => 'ID', 16 | 'field.user.name' => 'Nome', 17 | 'field.user.email' => 'E-mail', 18 | 'field.user.roles' => 'Função', 19 | 'field.user.verified_at' => 'Verificado em', 20 | 'field.user.created_at' => 'Criado em', 21 | 'field.user.password' => 'Senha', 22 | 'field.user.confirm_password' => 'Confimação da Senha', 23 | 24 | 'field.guard_name' => 'Nome do Guarda', 25 | 'field.name' => 'Nome', 26 | 'field.permissions' => 'Permissões', 27 | 'field.roles' => 'Funções', 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Labels 32 | |-------------------------------------------------------------------------- 33 | */ 34 | 35 | 'section.permission' => 'Permissão', 36 | 'section.permissions' => 'Permissões', 37 | 'section.role' => 'Função', 38 | 'section.roles' => 'Funções', 39 | 'section.roles_and_permissions' => 'Funções e Permissões', 40 | 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Filters 45 | |-------------------------------------------------------------------------- 46 | */ 47 | 'filter.verified' => 'E-mail Verificado', 48 | 49 | 'button.impersonate' => "Personificar Usuário", 50 | 'text.impersonating' => 'Personificando o Usuário: ', 51 | 'text.impersonating.end' => ' - Encerrar Perssonificação ', 52 | ]; 53 | -------------------------------------------------------------------------------- /lang/vendor/filament-authentication/vi/filament-authentication.php: -------------------------------------------------------------------------------- 1 | 'Xác thực', 6 | 'section.users' => 'Người dùng', 7 | 'section.user' => 'Người dùng', 8 | 9 | 10 | /* 11 | |-------------------------------------------------------------------------- 12 | | Fields 13 | |-------------------------------------------------------------------------- 14 | */ 15 | 'field.id' => 'ID', 16 | 'field.user.name' => 'Họ tên', 17 | 'field.user.email' => 'Email', 18 | 'field.user.roles' => 'Vai trò', 19 | 'field.user.verified_at' => 'Đã xác thực', 20 | 'field.user.created_at' => 'Tham gia lúc', 21 | 'field.user.password' => 'Mật khẩu', 22 | 'field.user.confirm_password' => 'Mật khẩu xác nhận', 23 | 24 | 'field.guard_name' => 'Tên guard', 25 | 'field.name' => 'Tên', 26 | 'field.permissions' => 'Quyền', 27 | 'field.roles' => 'Vai trò', 28 | 29 | /* 30 | |-------------------------------------------------------------------------- 31 | | Labels 32 | |-------------------------------------------------------------------------- 33 | */ 34 | 35 | 'section.permission' => 'Quyền', 36 | 'section.permissions' => 'Quyền', 37 | 'section.role' => 'Vai trò', 38 | 'section.roles' => 'Vai trò', 39 | 'section.roles_and_permissions' => 'Vai trò và Quyền', 40 | 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Filters 45 | |-------------------------------------------------------------------------- 46 | */ 47 | 'filter.verified' => 'Đã xác thực email', 48 | 49 | 'button.impersonate' => "Người dùng mạo danh", 50 | 'text.impersonating' => 'Mạo danh người dùng: ', 51 | 'text.impersonating.end' => ' - Kết thúc Mạo danh ', 52 | ]; 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "type": "module", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build" 7 | }, 8 | "devDependencies": { 9 | "axios": "^1.1.2", 10 | "laravel-vite-plugin": "^0.7.5", 11 | "vite": "^4.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | includes: 2 | - ./vendor/nunomaduro/larastan/extension.neon 3 | 4 | parameters: 5 | 6 | paths: 7 | - app/ 8 | 9 | # Level 9 is the highest level 10 | level: 5 11 | 12 | ignoreErrors: 13 | # - '#PHPDoc tag @var#' 14 | - '#^Access to an undefined property Livewire\\Component\:\:\$ownerRecord\.#' 15 | # 16 | # excludePaths: 17 | # - ./*/*/FileToBeExcluded.php 18 | # 19 | # checkMissingIterableValueType: false 20 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/Unit 10 | 11 | 12 | ./tests/Feature 13 | 14 | 15 | 16 | 17 | ./app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruswan/helpdesk-laravel/1f2edae666d308927d9076f34146905cb101fa88/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = $kernel->handle( 52 | $request = Request::capture() 53 | )->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /public/lamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruswan/helpdesk-laravel/1f2edae666d308927d9076f34146905cb101fa88/public/lamp.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | import './bootstrap'; 2 | -------------------------------------------------------------------------------- /resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * We'll load the axios HTTP library which allows us to easily issue requests 3 | * to our Laravel back-end. This library automatically handles sending the 4 | * CSRF token as a header based on the value of the "XSRF" token cookie. 5 | */ 6 | 7 | import axios from 'axios'; 8 | window.axios = axios; 9 | 10 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 11 | 12 | /** 13 | * Echo exposes an expressive API for subscribing to channels and listening 14 | * for events that are broadcast by Laravel. Echo and event broadcasting 15 | * allows your team to easily build robust real-time web applications. 16 | */ 17 | 18 | // import Echo from 'laravel-echo'; 19 | 20 | // import Pusher from 'pusher-js'; 21 | // window.Pusher = Pusher; 22 | 23 | // window.Echo = new Echo({ 24 | // broadcaster: 'pusher', 25 | // key: import.meta.env.VITE_PUSHER_APP_KEY, 26 | // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1', 27 | // wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`, 28 | // wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, 29 | // wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, 30 | // forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https', 31 | // enabledTransports: ['ws', 'wss'], 32 | // }); 33 | -------------------------------------------------------------------------------- /resources/views/landing.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ config('app.name') }} 9 | 10 | @vite(['resources/css/app.css']) 11 | 12 | 13 | 14 |
15 | 29 |
30 | 31 |
32 |
33 |
34 |

35 | {{ config('app.name') }}

36 |

37 | {{ env('APP_DESCRIPTION', 'This is descriptions') }}

38 | 40 | {{ __('Login') }} 41 | 42 |
43 | 46 |
47 |
48 | 49 | 50 |
51 |
52 |
53 |

{{ __('Why Use Helpdesk?') }}

54 |

{{ __('Reasons') }}

55 |
56 |
57 |
58 | 59 | 60 |
61 |
62 |
63 |
64 | © {{ date('Y') }} {{ config('app.name') }}. All Rights 66 | Reserved. 67 | 68 |
69 |
70 |
71 |
72 |
73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-apex-charts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruswan/helpdesk-laravel/1f2edae666d308927d9076f34146905cb101fa88/resources/views/vendor/filament-apex-charts/.gitkeep -------------------------------------------------------------------------------- /resources/views/vendor/filament-apex-charts/widgets/apex-chart-widget.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $heading = $this->getHeading(); 3 | $subheading = $this->getSubheading(); 4 | $filters = $this->getFilters(); 5 | $indicatorsCount = $this->getIndicatorsCount(); 6 | $darkMode = $this->getDarkMode(); 7 | $width = 'xs'; 8 | $pollingInterval = $this->getPollingInterval(); 9 | $chartId = $this->getChartId(); 10 | $chartOptions = $this->getOptions(); 11 | $filterFormAccessible = $this->getFilterFormAccessible(); 12 | $loadingIndicator = $this->getLoadingIndicator(); 13 | $contentHeight = $this->getContentHeight(); 14 | $deferLoading = $this->getDeferLoading(); 15 | $footer = $this->getFooter(); 16 | $readyToLoad = $this->readyToLoad; 17 | @endphp 18 | 19 | 21 | 22 | 24 | 25 | {{ $this->form }} 26 | 27 | 28 | 29 | 31 | 32 | @if ($footer) 33 |
34 | {!! $footer !!} 35 |
36 | @endif 37 | 38 |
39 | 40 |
41 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-apex-charts/widgets/components/chart.blade.php: -------------------------------------------------------------------------------- 1 | @props(['chartId', 'chartOptions', 'contentHeight', 'pollingInterval', 'loadingIndicator', 'deferLoading', 'readyToLoad', 'darkMode']) 2 | 3 |
5 | @if ($readyToLoad) 6 |
7 | 8 |
9 |
10 | 11 |
{ 18 | this.chart.updateOptions(options, false, true, true); 19 | }); 20 | 21 | this.options.theme = { mode: this.theme }; 22 | this.options.chart.background = 'inherit'; 23 | 24 | this.chart = new ApexCharts($refs.{{ $chartId }}, this.options); 25 | this.chart.render(); 26 | } 27 | }" 28 | @dark-mode-toggled.window="chart.updateOptions( { theme: { mode: {{ $darkMode ? '$event.detail' : "'light'" }} } } )" 29 | x-init="$watch('dropdownOpen', value => $wire.dropdownOpen = value)"> 30 |
31 | 32 |
33 | @else 34 |
35 | @if ($loadingIndicator) 36 | {!! $loadingIndicator !!} 37 | @else 38 | 39 | @endif 40 |
41 | @endif 42 |
43 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-apex-charts/widgets/components/filter-form.blade.php: -------------------------------------------------------------------------------- 1 | @props(['indicatorsCount', 'width']) 2 |
3 | 4 | 5 |
6 | 7 |
config( 10 | 'filament.dark_mode'), 11 | ]) 12 | style="{{ match ($width) { 13 | 'xs' => 'width: 20rem;', 14 | 'sm' => 'width: 24rem;', 15 | 'md' => 'width: 28rem;', 16 | 'lg' => 'width: 32rem;', 17 | 'xl' => 'width: 36rem;', 18 | '2xl' => 'width: 42rem;', 19 | '3xl' => 'width: 48rem;', 20 | '4xl' => 'width: 56rem;', 21 | '5xl' => 'width: 64rem;', 22 | '6xl' => 'width: 72rem;', 23 | '7xl' => 'width: 80rem;', 24 | default => 'width: 20rem;', 25 | } }}"> 26 |
27 | 28 | {{ $slot }} 29 | 30 |
31 | 32 | {{ __('filament-support::actions/modal.actions.submit.label') }} 33 | 34 | 36 | {{ __('tables::table.filters.buttons.reset.label') }} 37 | 38 |
39 |
40 | 41 |
42 |
43 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-apex-charts/widgets/components/header.blade.php: -------------------------------------------------------------------------------- 1 | @props(['heading', 'subheading', 'filters', 'indicatorsCount', 'width', 'filterFormAccessible']) 2 |
3 | @if ($heading || $subheading || $filters || $filterFormAccessible) 4 |
5 | 6 |
7 | @if ($heading) 8 | 9 | {!! $heading !!} 10 | 11 | @endif 12 | 13 | @if ($subheading) 14 |
15 | {!! $subheading !!} 16 |
17 | @endif 18 |
19 | 20 |
21 | @if ($filters) 22 | 33 | @endif 34 |
35 | 36 | @if ($filterFormAccessible) 37 |
38 | 39 | 40 | {{ $filterForm }} 41 | 42 | 43 |
44 | @endif 45 | 46 |
47 | @endif 48 |
49 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-authentication/components/banner.blade.php: -------------------------------------------------------------------------------- 1 | @if(app('impersonate')->isImpersonating()) 2 | 13 | @php 14 | $impersonating = Filament\Facades\Filament::getUserName(auth()->user()); 15 | @endphp 16 |
20 |
21 | {{ __('filament-authentication::filament-authentication.text.impersonating') }} {{ $impersonating }} 22 | {{ __('filament-authentication::filament-authentication.text.impersonating.end') }} 23 |
24 | 25 |
26 | @endIf 27 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-authentication/filament/pages/profile.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | {{ $this->form }} 4 | 5 |
6 | 7 | {{ __('filament::resources/pages/edit-record.form.actions.save.label') }} 8 | 9 | 10 | 11 | 12 | {{__('filament::resources/pages/edit-record.form.actions.cancel.label')}} 13 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-authentication/impersonating-banner.blade.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruswan/helpdesk-laravel/1f2edae666d308927d9076f34146905cb101fa88/resources/views/vendor/filament-breezy/.gitkeep -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/components/auth-card.blade.php: -------------------------------------------------------------------------------- 1 | @props(['action']) 2 |
config('filament.dark_mode'), 5 | ])> 6 | 7 |
9 |
config('filament.dark_mode'), 12 | ])> 13 | {{ $slot }} 14 |
15 | 16 | {{ $this->modal }} 17 | 18 |
19 | 20 | @livewire('notifications') 21 | 22 |
23 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/components/grid-section.blade.php: -------------------------------------------------------------------------------- 1 | @props(['title','description']) 2 |
class(["grid grid-cols-2 gap-6 filament-breezy-grid-section"])}}> 3 | 4 |
5 |
6 |

config('filament.dark_mode')])>{{$title}}

7 | 8 |

config('filament.dark_mode')])> 9 | {{$description}} 10 |

11 |
12 |
13 | 14 | {{$slot}} 15 | 16 |
17 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/components/sections/2fa.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ __('filament-breezy::default.profile.2fa.title') }} 5 | 6 | 7 | 8 | {{ __('filament-breezy::default.profile.2fa.description') }} 9 | 10 | 11 | 12 | 13 | @if($this->user->has_enabled_two_factor) 14 | 15 | @if ($this->user->has_confirmed_two_factor) 16 |

{{ __('filament-breezy::default.profile.2fa.enabled.title') }}

17 | {{ __('filament-breezy::default.profile.2fa.enabled.description') ?? __('filament-breezy::default.profile.2fa.enabled.store_codes') }} 18 | @else 19 |

{{ __('filament-breezy::default.profile.2fa.finish_enabling.title') }}

20 | {{ __('filament-breezy::default.profile.2fa.finish_enabling.description') }} 21 | @endif 22 | 23 |
24 | {!! $this->twoFactorQrCode() !!} 25 |

{{ __('filament-breezy::default.profile.2fa.setup_key') }} {{ decrypt($this->user->two_factor_secret) }}

26 |
27 | 28 | @if ($this->showing_two_factor_recovery_codes) 29 |
30 |

{{ __('filament-breezy::default.profile.2fa.enabled.store_codes') }}

31 |
32 | @foreach (json_decode(decrypt($this->user->two_factor_recovery_codes), true) as $code) 33 | {{ $code }} 34 | @endforeach 35 |
36 | {{$this->getCachedAction('regenerate2fa')}} 37 | 38 | @endif 39 | 40 | @else 41 | 42 |

{{ __('filament-breezy::default.profile.2fa.not_enabled.title') }}

43 | {{ __('filament-breezy::default.profile.2fa.not_enabled.description') }} 44 | 45 | @endif 46 | 47 | @if($this->user->has_enabled_two_factor && $this->user->has_confirmed_two_factor) 48 |
49 | 50 | {{$this->showing_two_factor_recovery_codes ? __('filament-breezy::default.profile.2fa.enabled.hide_codes') :__('filament-breezy::default.profile.2fa.enabled.show_codes')}} 51 | 52 | {{$this->getCachedAction('disable2fa')}} 53 |
54 | @elseif($this->user->has_enabled_two_factor) 55 |
56 |
57 |
{{$this->confirmTwoFactorForm}}
58 |
59 | 60 | {{ __('filament-breezy::default.profile.2fa.actions.confirm_finish') }} 61 | 62 | 63 | 64 | {{ __('filament-breezy::default.profile.2fa.actions.cancel_setup') }} 65 | 66 |
67 |
68 |
69 | @else 70 |
71 | {{$this->getCachedAction('enable2fa')}} 72 |
73 | @endif 74 |
75 |
76 | 77 |
78 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/components/sections/passwords.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ __('filament-breezy::default.profile.password.heading') }} 5 | 6 | 7 | 8 | {{ __('filament-breezy::default.profile.password.subheading') }} 9 | 10 | 11 |
12 | 13 | 14 | {{ $this->updatePasswordForm }} 15 | 16 | 17 |
18 | 19 | {{ __('filament-breezy::default.profile.password.submit.label') }} 20 | 21 |
22 |
23 |
24 |
25 | 26 |
27 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/components/sections/personal-info.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ __('filament-breezy::default.profile.personal_info.heading') }} 5 | 6 | 7 | 8 | {{ __('filament-breezy::default.profile.personal_info.subheading') }} 9 | 10 | 11 |
12 | 13 | 14 | {{ $this->updateProfileForm }} 15 | 16 | 17 |
18 | 19 | {{ __('filament-breezy::default.profile.personal_info.submit.label') }} 20 | 21 |
22 |
23 |
24 |
25 | 26 |
27 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/components/sections/sanctum.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ __('filament-breezy::default.profile.sanctum.title') }} 5 | 6 | 7 | 8 | {{ __('filament-breezy::default.profile.sanctum.description') }} 9 | 10 | 11 |
12 | 13 |
14 | 15 | 16 | @if($plain_text_token) 17 | config('filament.dark_mode')]) name="plain_text_token" value="{{$plain_text_token}}" /> 18 | @endif 19 | 20 | {{$this->createApiTokenForm}} 21 | 22 |
23 | 24 | {{ __('filament-breezy::default.profile.sanctum.create.submit.label') }} 25 | 26 |
27 |
28 |
29 | 30 | 31 | 32 | @livewire(\JeffGreco13\FilamentBreezy\Http\Livewire\BreezySanctumTokens::class) 33 | 34 |
35 |
36 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/filament/pages/my-profile.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @if(config('filament-breezy.enable_2fa')) 10 | 11 | 12 | 13 | @endif 14 | 15 | @if(config('filament-breezy.enable_sanctum')) 16 | 17 | 18 | 19 | 20 | 21 | {{ __('filament-breezy::default.profile.sanctum.title') }} 22 | 23 | 24 | 25 | {{ __('filament-breezy::default.profile.sanctum.description') }} 26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 | @if($plain_text_token) 34 | config('filament.dark_mode')]) name="plain_text_token" value="{{$plain_text_token}}" /> 35 | @endif 36 | 37 | {{$this->createApiTokenForm}} 38 | 39 |
40 | 41 | {{ __('filament-breezy::default.profile.sanctum.create.submit.label') }} 42 | 43 |
44 |
45 |
46 | 47 | 48 | 49 | @livewire(\JeffGreco13\FilamentBreezy\Http\Livewire\BreezySanctumTokens::class) 50 | 51 |
52 |
53 | @endif 54 | 55 |
56 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/livewire/breezy-sanctum-tokens.blade.php: -------------------------------------------------------------------------------- 1 |
2 | {{$this->table}} 3 |
4 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/login.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 |
8 |

9 | {{ __('filament::login.heading') }} 10 |

11 | @if (config('filament-breezy.enable_registration')) 12 |

13 | {{ __('filament-breezy::default.or') }} 14 | 15 | {{ strtolower(__('filament-breezy::default.registration.heading')) }} 16 | 17 |

18 | @endif 19 |
20 | 21 | {{ $this->form }} 22 | 23 | 24 | {{ __('filament::login.buttons.submit.label') }} 25 | 26 | 27 | 28 | 29 | 33 |
34 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/register.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 |

8 | {{ __('filament-breezy::default.registration.heading') }} 9 |

10 |

11 | {{ __('filament-breezy::default.or') }} 12 | 13 | {{ strtolower(__('filament::login.heading')) }} 14 | 15 |

16 |
17 | 18 | {{ $this->form }} 19 | 20 | 21 | {{ __('filament-breezy::default.registration.submit.label') }} 22 | 23 |
24 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/reset-password.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 |

8 | {{ __('filament-breezy::default.reset_password.heading') }} 9 |

10 |

11 | {{ __('filament-breezy::default.or') }} 12 | 13 | {{ strtolower(__('filament::login.heading')) }} 14 | 15 |

16 |
17 | 18 | @unless($hasBeenSent) 19 | {{ $this->form }} 20 | 21 | 22 | {{ __('filament-breezy::default.reset_password.submit.label') }} 23 | 24 | @else 25 | {{ __('filament-breezy::default.reset_password.notification_success') }} 26 | @endunless 27 |
28 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/two-factor.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | 8 |
9 |

10 | {{ $this->usingRecoveryCode ? __('filament-breezy::default.two_factor.recovery.heading') : __('filament-breezy::default.two_factor.heading') }} 11 |

12 |

13 | {{ $this->usingRecoveryCode ? __('filament-breezy::default.two_factor.recovery.description') : __('filament-breezy::default.two_factor.description') }} 14 | {{ __('filament-breezy::default.two_factor.back_to_login_link') }} 15 | 16 |

17 |
18 | 19 | {{ $this->twoFactorForm }} 20 | 21 | 22 | {{ __('filament::login.buttons.submit.label') }} 23 | 24 | 25 |
26 | {{ $this->usingRecoveryCode ? '' : __('filament-breezy::default.two_factor.recovery_code_text') }} 27 | {{$this->usingRecoveryCode ? __('filament-breezy::default.cancel') : __('filament-breezy::default.two_factor.recovery_code_link') }} 28 |
29 | 30 |
31 | -------------------------------------------------------------------------------- /resources/views/vendor/filament-breezy/verify.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 |

8 | {{ __('filament-breezy::default.verification.heading') }} 9 |

10 |
11 | {{ __('filament-breezy::default.verification.before_proceeding') }} 12 | @unless($hasBeenSent) 13 | {{ __('filament-breezy::default.verification.not_receive') }} 14 | 15 | 16 | {{ __('filament-breezy::default.verification.request_another') }} 17 | 18 | 19 | @else 20 | {{ __('filament-breezy::default.verification.notification_success') }} 21 | @endunless 22 |
23 |
24 | 25 | {{ $this->form }} 26 | 27 | 28 | {{ __('filament-breezy::default.verification.submit.label') }} 29 | 30 |
31 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 18 | return $request->user(); 19 | }); 20 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 18 | 19 | return $app; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 16 | 17 | $response->assertStatus(200); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | withoutVite(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/ExampleTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import laravel from 'laravel-vite-plugin'; 3 | 4 | export default defineConfig({ 5 | plugins: [ 6 | laravel({ 7 | input: ['resources/css/app.css', 'resources/js/app.js'], 8 | refresh: true, 9 | }), 10 | ], 11 | }); 12 | --------------------------------------------------------------------------------