├── public ├── favicon.ico ├── robots.txt ├── fonts │ ├── unicons.eot │ ├── unicons.ttf │ ├── unicons.woff │ ├── Nunito-Bold.eot │ ├── Nunito-Bold.ttf │ ├── summernote.eot │ ├── summernote.ttf │ ├── summernote.woff │ ├── unicons.woff2 │ ├── Nunito-Bold.woff │ ├── Nunito-Light.ttf │ ├── Nunito-Light.woff │ ├── dripicons-v2.eot │ ├── dripicons-v2.ttf │ ├── dripicons-v2.woff │ ├── summernote.woff2 │ ├── Nunito-Light.woff2 │ ├── Nunito-Regular.eot │ ├── Nunito-Regular.ttf │ ├── Nunito-Regular.woff │ ├── Nunito-SemiBold.eot │ ├── Nunito-SemiBold.ttf │ ├── Nunito-SemiBold.woff │ ├── materialdesignicons-webfont.eot │ ├── materialdesignicons-webfont.ttf │ ├── materialdesignicons-webfont.woff │ └── materialdesignicons-webfont.woff2 ├── locations │ ├── data │ │ ├── .DS_Store │ │ └── DNO.json │ └── index.json ├── vendor │ └── telescope │ │ ├── favicon.ico │ │ └── mix-manifest.json ├── css │ └── style.css ├── flag │ └── vn.svg ├── .htaccess ├── js │ └── helper.js ├── web.config └── index.php ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ └── bootstrap.js ├── lang │ ├── en │ │ ├── auth.php │ │ ├── frontpage.php │ │ ├── pagination.php │ │ └── passwords.php │ └── vi │ │ └── frontpage.php └── views │ ├── layout_frontpage │ ├── header.blade.php │ ├── master.blade.php │ ├── navbar.blade.php │ └── posts.blade.php │ ├── layout │ ├── footer.blade.php │ ├── sidebar.blade.php │ └── master.blade.php │ ├── applicant │ ├── index.blade.php │ └── show.blade.php │ └── components │ └── post.blade.php ├── database ├── migrations │ ├── .gitkeep │ ├── 2022_05_31_140704_alter_slug_column_unique_in_post_table.php │ ├── 2022_05_24_143350_alter_column_remotable_nullable_in_posts_table.php │ ├── 2022_05_24_150915_alter_column_company_id_nullable_in_posts_table.php │ ├── 2022_07_14_134246_alter_column_role_in_users_table.php │ ├── 2022_04_23_134846_create_configs_table.php │ ├── 2022_04_23_135809_create_languages_table.php │ ├── 2022_06_09_144625_alter_remotable_and_is_partime_column_in_posts_table.php │ ├── 2022_07_01_132827_alter_column_city_in_posts_table.php │ ├── 2022_07_07_134651_alter_add_column_is_public_to_configs_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2022_06_07_132234_alter_add_column_remember_token_to_users_table.php │ ├── 2022_04_23_142610_create_files_table.php │ ├── 2022_07_01_132637_alter_columns_address2_and_district_and_city_in_companies_table.php │ ├── 2022_04_23_142303_create_object_language_table.php │ ├── 2022_08_16_132834_alter_add_column_levels_to_posts_table.php │ ├── 2022_04_23_142757_create_reports_table.php │ ├── 2014_04_02_193005_create_translations_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2022_05_03_132228_alter_add_is_pinned_column_to_post_table.php │ ├── 2022_06_21_150030_alter_column_type_in_object_language_table.php │ ├── 2022_07_07_141642_alter_columns_salary_in_posts_table.php │ ├── 2022_08_16_141125_alter_columns_foreign_key_on_delete.php │ ├── 2022_05_05_142215_alter_columns_nullable_in_user_table.php │ ├── 2022_04_23_135222_create_companies_table.php │ ├── 2022_05_14_133243_alter_add_deleted_at_column_to_some_table.php │ ├── 2022_04_23_135934_create_users_table.php │ ├── 2022_04_23_140743_create_posts_table.php │ └── 2022_05_24_141814_alter_multiple_columns_nullable.php ├── .gitignore ├── seeders │ ├── FileSeeder.php │ ├── PostSeeder.php │ ├── CompanySeeder.php │ ├── ConfigSeeder.php │ ├── LanguageSeeder.php │ ├── ReportSeeder.php │ ├── DatabaseSeeder.php │ └── UserSeeder.php └── factories │ ├── FileFactory.php │ ├── PostFactory.php │ ├── ConfigFactory.php │ ├── ReportFactory.php │ ├── LanguageFactory.php │ ├── CompanyFactory.php │ └── UserFactory.php ├── bootstrap ├── cache │ └── .gitignore └── app.php ├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore ├── debugbar │ └── .gitignore ├── framework │ ├── testing │ │ └── .gitignore │ ├── views │ │ └── .gitignore │ ├── cache │ │ ├── data │ │ │ └── .gitignore │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── .gitignore └── clockwork │ └── .gitignore ├── .gitattributes ├── app ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ ├── TestController.php │ │ ├── ResponseTrait.php │ │ ├── SystemConfigController.php │ │ ├── LanguageController.php │ │ ├── CompanyController.php │ │ ├── PostController.php │ │ ├── Admin │ │ │ ├── UserController.php │ │ │ └── PostController.php │ │ ├── Applicant │ │ │ └── HomePageController.php │ │ └── AuthController.php │ ├── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── VerifyCsrfToken.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── AdminMiddleware.php │ │ ├── TrustProxies.php │ │ ├── Localization.php │ │ └── RedirectIfAuthenticated.php │ ├── Requests │ │ ├── Post │ │ │ ├── GenerateSlugRequest.php │ │ │ ├── CheckSlugRequest.php │ │ │ └── StoreRequest.php │ │ ├── Auth │ │ │ └── RegisteringRequest.php │ │ ├── Applicant │ │ │ └── HomePage │ │ │ │ └── IndexRequest.php │ │ └── Company │ │ │ └── StoreRequest.php │ └── Kernel.php ├── Enums │ ├── ObjectLanguageTypeEnum.php │ ├── FileTypeEnum.php │ ├── SystemCacheKeyEnum.php │ ├── PostLevelEnum.php │ ├── CompanyCountryEnum.php │ ├── UserRoleEnum.php │ ├── PostStatusEnum.php │ ├── PostCurrencySalaryEnum.php │ └── PostRemotableEnum.php ├── Models │ ├── Report.php │ ├── Language.php │ ├── ObjectLanguage.php │ ├── File.php │ ├── Company.php │ ├── Config.php │ └── User.php ├── Providers │ ├── BroadcastServiceProvider.php │ ├── AuthServiceProvider.php │ ├── AppServiceProvider.php │ ├── EventServiceProvider.php │ ├── RouteServiceProvider.php │ └── TelescopeServiceProvider.php ├── View │ └── Components │ │ └── Post.php ├── Exceptions │ └── Handler.php ├── Console │ └── Kernel.php ├── functions.php └── Policies │ ├── UserPolicy.php │ ├── FilePolicy.php │ ├── PostPolicy.php │ ├── ConfigPolicy.php │ ├── ReportPolicy.php │ ├── CompanyPolicy.php │ └── LanguagePolicy.php ├── .idea ├── vcs.xml ├── .gitignore ├── modules.xml └── phpunit.xml ├── tests ├── TestCase.php ├── Unit │ └── ExampleTest.php ├── Feature │ └── ExampleTest.php └── CreatesApplication.php ├── .gitignore ├── .styleci.yml ├── routes ├── applicant.php ├── channels.php ├── console.php ├── api.php ├── web.php └── admin.php ├── .editorconfig ├── webpack.mix.js ├── server.php ├── config ├── cors.php ├── view.php ├── services.php ├── translation-manager.php ├── hashing.php ├── broadcasting.php ├── filesystems.php ├── queue.php ├── logging.php ├── cache.php └── mail.php ├── .env.example ├── package.json ├── phpunit.xml ├── artisan ├── README.md └── composer.json /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/css/app.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | require('./bootstrap'); 2 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | *.sqlite-journal 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/debugbar/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/clockwork/.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | *.json.gz 3 | index 4 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /public/fonts/unicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/unicons.eot -------------------------------------------------------------------------------- /public/fonts/unicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/unicons.ttf -------------------------------------------------------------------------------- /public/fonts/unicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/unicons.woff -------------------------------------------------------------------------------- /public/fonts/Nunito-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Bold.eot -------------------------------------------------------------------------------- /public/fonts/Nunito-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Bold.ttf -------------------------------------------------------------------------------- /public/fonts/summernote.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/summernote.eot -------------------------------------------------------------------------------- /public/fonts/summernote.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/summernote.ttf -------------------------------------------------------------------------------- /public/fonts/summernote.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/summernote.woff -------------------------------------------------------------------------------- /public/fonts/unicons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/unicons.woff2 -------------------------------------------------------------------------------- /public/fonts/Nunito-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Bold.woff -------------------------------------------------------------------------------- /public/fonts/Nunito-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Light.ttf -------------------------------------------------------------------------------- /public/fonts/Nunito-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Light.woff -------------------------------------------------------------------------------- /public/fonts/dripicons-v2.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/dripicons-v2.eot -------------------------------------------------------------------------------- /public/fonts/dripicons-v2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/dripicons-v2.ttf -------------------------------------------------------------------------------- /public/fonts/dripicons-v2.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/dripicons-v2.woff -------------------------------------------------------------------------------- /public/fonts/summernote.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/summernote.woff2 -------------------------------------------------------------------------------- /public/fonts/Nunito-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Light.woff2 -------------------------------------------------------------------------------- /public/fonts/Nunito-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Regular.eot -------------------------------------------------------------------------------- /public/fonts/Nunito-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Regular.ttf -------------------------------------------------------------------------------- /public/fonts/Nunito-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-Regular.woff -------------------------------------------------------------------------------- /public/fonts/Nunito-SemiBold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-SemiBold.eot -------------------------------------------------------------------------------- /public/fonts/Nunito-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-SemiBold.ttf -------------------------------------------------------------------------------- /public/fonts/Nunito-SemiBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/Nunito-SemiBold.woff -------------------------------------------------------------------------------- /public/locations/data/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/locations/data/.DS_Store -------------------------------------------------------------------------------- /public/vendor/telescope/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/vendor/telescope/favicon.ico -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | .notification-list .noti-icon::before { 2 | line-height: 70px; 3 | } 4 | 5 | .navbar-custom{ 6 | max-height: 70px; 7 | } 8 | -------------------------------------------------------------------------------- /public/fonts/materialdesignicons-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/materialdesignicons-webfont.eot -------------------------------------------------------------------------------- /public/fonts/materialdesignicons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/materialdesignicons-webfont.ttf -------------------------------------------------------------------------------- /public/fonts/materialdesignicons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/materialdesignicons-webfont.woff -------------------------------------------------------------------------------- /public/fonts/materialdesignicons-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/J2TeamNNL/web_moi_gioi_viec_lam/HEAD/public/fonts/materialdesignicons-webfont.woff2 -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 5 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 6 | ); 7 | -------------------------------------------------------------------------------- /app/Enums/ObjectLanguageTypeEnum.php: -------------------------------------------------------------------------------- 1 | name('index'); 7 | Route::get('/{post}', [HomePageController::class, 'show'])->name('show'); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /database/seeders/FileSeeder.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /app/Models/Language.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Enums/PostLevelEnum.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 12 | return route('login'); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Enums/CompanyCountryEnum.php: -------------------------------------------------------------------------------- 1 | 'Find what you need', 5 | 'location' => 'Location', 6 | 'from_salary' => 'From', 7 | 'to_salary' => 'Up to', 8 | 'applicant' => 'Applicant', 9 | 'hr' => 'HR', 10 | 'not_available' => 'Not Available', 11 | 'remote_only' => 'Remote Only', 12 | 'office_only' => 'Office Only', 13 | 'hybrid' => 'Hybrid', 14 | 'all' => 'All', 15 | ); 16 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 'Tìm thứ bạn cần', 5 | 'location' => 'Địa điểm', 6 | 'from_salary' => 'Trên', 7 | 'to_salary' => 'Tới', 8 | 'applicant' => 'Ứng viên', 9 | 'hr' => 'Nhà tuyển dụng', 10 | 'not_available' => 'Đang Đóng', 11 | 'remote_only' => 'Chỉ làm từ xa', 12 | 'office_only' => 'Chỉ làm tại văn phòng', 13 | 'hybrid' => 'Làm việc linh hoạt', 14 | 'all' => 'Tất cả', 15 | ); 16 | -------------------------------------------------------------------------------- /database/factories/LanguageFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->word(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 18 | 19 | $response->assertStatus(200); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustHosts.php: -------------------------------------------------------------------------------- 1 | allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventRequestsDuringMaintenance.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Enums/UserRoleEnum.php: -------------------------------------------------------------------------------- 1 | self::APPLICANT, 18 | 'hr' => self::HR, 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | route('login'); 17 | } 18 | 19 | return $next($request); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 19 | Company::factory(10)->create(); 20 | $this->call(UserSeeder::class); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /public/flag/vn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/Http/Requests/Post/GenerateSlugRequest.php: -------------------------------------------------------------------------------- 1 | check(); 12 | } 13 | 14 | public function rules(): array 15 | { 16 | return [ 17 | 'title' => [ 18 | 'required', 19 | 'string', 20 | 'filled', 21 | ] 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | user_id = user()->id; 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Models/Company.php: -------------------------------------------------------------------------------- 1 | hasMany(Post::class); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/View/Components/Post.php: -------------------------------------------------------------------------------- 1 | post = $post; 16 | $this->languages = implode(', ', $post->languages->pluck('name')->toArray()); 17 | $this->company = $post->company; 18 | } 19 | 20 | public function render() 21 | { 22 | return view('components.post'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /database/migrations/2022_05_31_140704_alter_slug_column_unique_in_post_table.php: -------------------------------------------------------------------------------- 1 | unique('slug'); 14 | }); 15 | } 16 | } 17 | 18 | public function down() 19 | { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel applications. By default, we are compiling the CSS 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/js/app.js', 'public/js') 15 | .postCss('resources/css/app.css', 'public/css', [ 16 | // 17 | ]); 18 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /app/Http/Requests/Post/CheckSlugRequest.php: -------------------------------------------------------------------------------- 1 | check(); 14 | } 15 | 16 | public function rules(): array 17 | { 18 | return [ 19 | 'slug' => [ 20 | 'required', 21 | 'string', 22 | 'filled', 23 | Rule::unique(Post::class), 24 | ] 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/migrations/2022_05_24_143350_alter_column_remotable_nullable_in_posts_table.php: -------------------------------------------------------------------------------- 1 | string('remotable')->nullable()->change(); 14 | }); 15 | } 16 | } 17 | 18 | public function down() 19 | { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/views/layout_frontpage/header.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Http/Controllers/TestController.php: -------------------------------------------------------------------------------- 1 | get('locale'); 14 | if (empty($locale)) { 15 | $locale = $request->cookie('locale'); 16 | } 17 | if (!in_array($locale, config('app.locales'))) { 18 | $locale = config('app.fallback_locale'); 19 | } 20 | 21 | app()->setLocale($locale); 22 | 23 | return $next($request); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/migrations/2022_05_24_150915_alter_column_company_id_nullable_in_posts_table.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('company_id')->nullable()->change(); 14 | }); 15 | } 16 | } 17 | 18 | public function down() 19 | { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/migrations/2022_07_14_134246_alter_column_role_in_users_table.php: -------------------------------------------------------------------------------- 1 | integer('role')->default(UserRoleEnum::APPLICANT)->change(); 15 | }); 16 | } 17 | } 18 | 19 | public function down() 20 | { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/Http/Controllers/ResponseTrait.php: -------------------------------------------------------------------------------- 1 | json([ 12 | 'success' => true, 13 | 'data' => $data, 14 | 'message' => $message 15 | ]); 16 | } 17 | 18 | public function errorResponse($message = '', $status = 400): JsonResponse 19 | { 20 | return response()->json([ 21 | 'success' => false, 22 | 'data' => [], 23 | 'message' => $message 24 | ], $status); 25 | } 26 | } -------------------------------------------------------------------------------- /app/Http/Controllers/SystemConfigController.php: -------------------------------------------------------------------------------- 1 | remember('configs', 24 * 60 * 60, function () { 14 | $arr = []; 15 | $arr['currencies'] = PostCurrencySalaryEnum::asArray(); 16 | $arr['countries'] = CompanyCountryEnum::asArray(); 17 | $arr['languages'] = Language::query()->get(); 18 | 19 | return $arr; 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'vi_VN', 20 | self::USD => 'en_US', 21 | self::EUR => 'en_UK', 22 | self::JPY => 'ja_JP', 23 | self::KRW => 'ko_KR', 24 | self::CNY => 'cn_CN', 25 | ]; 26 | 27 | return $locales[$key]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | name('posts'); 9 | Route::get('/posts/slug', [PostController::class, 'checkSlug'])->name('posts.slug.check'); 10 | Route::post('/posts/slug', [PostController::class, 'generateSlug'])->name('posts.slug.generate'); 11 | Route::get('/companies/check/{companyName?}', [CompanyController::class, 'check'])->name('companies.check'); 12 | Route::get('/companies', [CompanyController::class, 'index'])->name('companies'); 13 | Route::get('/languages', [LanguageController::class, 'index'])->name('languages'); 14 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_134846_create_configs_table.php: -------------------------------------------------------------------------------- 1 | string('key'); 18 | $table->text('value'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::dropIfExists('configs'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_135809_create_languages_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::dropIfExists('languages'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2022_06_09_144625_alter_remotable_and_is_partime_column_in_posts_table.php: -------------------------------------------------------------------------------- 1 | boolean('is_partime')->default(0)->change(); 13 | $table->integer('remotable')->change(); 14 | }); 15 | Schema::table('posts', function (Blueprint $table) { 16 | $table->renameColumn('is_partime', 'can_parttime'); 17 | }); 18 | } 19 | 20 | public function down() 21 | { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Requests/Auth/RegisteringRequest.php: -------------------------------------------------------------------------------- 1 | [ 20 | 'required', 21 | 'string', 22 | 'min:0', 23 | 'max:255', 24 | ], 25 | 'role' => [ 26 | 'required', 27 | Rule::in(UserRoleEnum::getRolesForRegister()), 28 | ], 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2022_07_01_132827_alter_column_city_in_posts_table.php: -------------------------------------------------------------------------------- 1 | string('city')->nullable()->change(); 19 | }); 20 | } 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Enums/PostRemotableEnum.php: -------------------------------------------------------------------------------- 1 | $val) { 20 | $index = strtolower($key); 21 | $arr[$index] = $val; 22 | } 23 | 24 | return $arr; 25 | } 26 | 27 | public static function getArrWithoutAll(): array 28 | { 29 | $array = self::asArray(); 30 | array_shift($array); 31 | 32 | return $array; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/views/layout/footer.blade.php: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | // 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have emailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 25 | return redirect(RouteServiceProvider::HOME); 26 | } 27 | } 28 | 29 | return $next($request); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2022_07_07_134651_alter_add_column_is_public_to_configs_table.php: -------------------------------------------------------------------------------- 1 | boolean('is_public')->default(0); 14 | }); 15 | } 16 | } 17 | 18 | public function down() 19 | { 20 | if (Schema::hasColumn('configs', 'is_public')) { 21 | Schema::table('configs', function (Blueprint $table) { 22 | $table->dropColumn('is_public'); 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Requests/Applicant/HomePage/IndexRequest.php: -------------------------------------------------------------------------------- 1 | [ 20 | 'array', 21 | ], 22 | 'min_salary' => [ 23 | 'integer', 24 | ], 25 | 'max_salary' => [ 26 | 'integer', 27 | ], 28 | 'remotable' => [ 29 | 'nullable', 30 | Rule::in(PostRemotableEnum::asArray()), 31 | ], 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2022_06_07_132234_alter_add_column_remember_token_to_users_table.php: -------------------------------------------------------------------------------- 1 | string('remember_token')->nullable(); 14 | }); 15 | } 16 | } 17 | 18 | public function down() 19 | { 20 | if (Schema::hasColumn('users', 'remember_token')) { 21 | Schema::table('users', function (Blueprint $table) { 22 | $table->dropColumn('remember_token'); 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/factories/CompanyFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->company, 18 | 'address' => $this->faker->streetAddress, 19 | 'address2' => $this->faker->buildingNumber, 20 | 'district' => $this->faker->city, 21 | 'city' => $this->faker->city, 22 | 'country' => 'Vietnam', 23 | 'zipcode' => $this->faker->postcode, 24 | 'phone' => $this->faker->phoneNumber, 25 | 'email' => $this->faker->email, 26 | 'logo' => $this->faker->imageUrl(), 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_142610_create_files_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->foreignId('user_id')->constrained(); 19 | $table->foreignId('post_id')->nullable()->constrained(); 20 | $table->string('link'); 21 | $table->integer('type'); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('files'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2022_07_01_132637_alter_columns_address2_and_district_and_city_in_companies_table.php: -------------------------------------------------------------------------------- 1 | dropColumn('address2'); 14 | } 15 | if (Schema::hasColumn('companies', 'district')) { 16 | $table->dropColumn('district'); 17 | } 18 | if (Schema::hasColumn('companies', 'city')) { 19 | $table->dropColumn('city'); 20 | } 21 | }); 22 | } 23 | 24 | public function down() 25 | { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Controllers/LanguageController.php: -------------------------------------------------------------------------------- 1 | model = Language::query(); 19 | } 20 | 21 | public function index(Request $request): JsonResponse 22 | { 23 | $configs = SystemConfigController::getAndCache(); 24 | $data = $configs['languages']->filter(function ($each) use ($request) { 25 | if ($request->has('q')) { 26 | return Str::contains(strtolower($each['name']), $request->get('q')); 27 | } 28 | 29 | return true; 30 | }); 31 | 32 | return $this->successResponse($data); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_142303_create_object_language_table.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('object_id'); 18 | $table->foreignId('language_id')->constrained(); 19 | $table->primary(['object_id', 'language_id']); 20 | $table->integer('type'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('object_language'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2022_08_16_132834_alter_add_column_levels_to_posts_table.php: -------------------------------------------------------------------------------- 1 | string('levels') 14 | ->comment('array of levels') 15 | ->nullable() 16 | ->after('job_title'); 17 | }); 18 | } 19 | } 20 | 21 | public function down() 22 | { 23 | if (Schema::hasColumn('posts', 'levels')) { 24 | Schema::table('posts', function (Blueprint $table) { 25 | $table->dropColumn('levels'); 26 | }); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_142757_create_reports_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->foreignId('user_id')->constrained(); 19 | $table->unsignedBigInteger('reported_id'); 20 | $table->integer('type'); 21 | $table->integer('status'); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('reports'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*'], 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 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | 9 | DB_CONNECTION=mysql 10 | DB_HOST=127.0.0.1 11 | DB_PORT=3306 12 | DB_DATABASE=laravel 13 | DB_USERNAME=root 14 | DB_PASSWORD= 15 | 16 | BROADCAST_DRIVER=log 17 | CACHE_DRIVER=file 18 | QUEUE_CONNECTION=sync 19 | SESSION_DRIVER=file 20 | SESSION_LIFETIME=120 21 | 22 | REDIS_HOST=127.0.0.1 23 | REDIS_PASSWORD=null 24 | REDIS_PORT=6379 25 | 26 | MAIL_MAILER=smtp 27 | MAIL_HOST=smtp.mailtrap.io 28 | MAIL_PORT=2525 29 | MAIL_USERNAME=null 30 | MAIL_PASSWORD=null 31 | MAIL_ENCRYPTION=null 32 | MAIL_FROM_ADDRESS=null 33 | MAIL_FROM_NAME="${APP_NAME}" 34 | 35 | AWS_ACCESS_KEY_ID= 36 | AWS_SECRET_ACCESS_KEY= 37 | AWS_DEFAULT_REGION=us-east-1 38 | AWS_BUCKET= 39 | 40 | PUSHER_APP_ID= 41 | PUSHER_APP_KEY= 42 | PUSHER_APP_SECRET= 43 | PUSHER_APP_CLUSTER=mt1 44 | 45 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 46 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 47 | -------------------------------------------------------------------------------- /database/migrations/2014_04_02_193005_create_translations_table.php: -------------------------------------------------------------------------------- 1 | collation = 'utf8mb4_bin'; 18 | $table->bigIncrements('id'); 19 | $table->integer('status')->default(0); 20 | $table->string('locale'); 21 | $table->string('group'); 22 | $table->text('key'); 23 | $table->text('value')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('ltm_translations'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load the axios HTTP library which allows us to easily issue requests 5 | * to our Laravel back-end. This library automatically handles sending the 6 | * CSRF token as a header based on the value of the "XSRF" token cookie. 7 | */ 8 | 9 | window.axios = require('axios'); 10 | 11 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 12 | 13 | /** 14 | * Echo exposes an expressive API for subscribing to channels and listening 15 | * for events that are broadcast by Laravel. Echo and event broadcasting 16 | * allows your team to easily build robust real-time web applications. 17 | */ 18 | 19 | // import Echo from 'laravel-echo'; 20 | 21 | // window.Pusher = require('pusher-js'); 22 | 23 | // window.Echo = new Echo({ 24 | // broadcaster: 'pusher', 25 | // key: process.env.MIX_PUSHER_APP_KEY, 26 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 27 | // forceTLS: true 28 | // }); 29 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 28 | } 29 | 30 | /** 31 | * Register the commands for the application. 32 | * 33 | * @return void 34 | */ 35 | protected function commands() 36 | { 37 | $this->load(__DIR__.'/Commands'); 38 | 39 | require base_path('routes/console.php'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('uuid')->unique(); 19 | $table->text('connection'); 20 | $table->text('queue'); 21 | $table->longText('payload'); 22 | $table->longText('exception'); 23 | $table->timestamp('failed_at')->useCurrent(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('failed_jobs'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.19", 14 | "cross-env": "^7.0", 15 | "laravel-mix": "^5.0.1", 16 | "lodash": "^4.17.19", 17 | "resolve-url-loader": "^3.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /database/migrations/2022_05_03_132228_alter_add_is_pinned_column_to_post_table.php: -------------------------------------------------------------------------------- 1 | boolean('is_pinned')->default(false)->after('status'); 19 | }); 20 | } 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | if (Schema::hasColumn('posts', 'is_pinned')) { 31 | Schema::table('posts', function (Blueprint $table) { 32 | $table->dropColumn('is_pinned'); 33 | }); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2022_06_21_150030_alter_column_type_in_object_language_table.php: -------------------------------------------------------------------------------- 1 | string('type')->change(); 19 | } 20 | }); 21 | Schema::table('object_language', function (Blueprint $table) { 22 | if (Schema::hasColumn('object_language', 'type')) { 23 | $table->renameColumn('type','object_type'); 24 | } 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2022_07_07_141642_alter_columns_salary_in_posts_table.php: -------------------------------------------------------------------------------- 1 | float('min_salary')->change(); 19 | } 20 | if (Schema::hasColumn('posts', 'max_salary')) { 21 | $table->float('max_salary')->change(); 22 | } 23 | if (Schema::hasColumn('posts', 'currency_salary')) { 24 | $table->integer('currency_salary')->change(); 25 | } 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2022_08_16_141125_alter_columns_foreign_key_on_delete.php: -------------------------------------------------------------------------------- 1 | getDoctrineSchemaManager(); 12 | $indexesFiles = $sm->listTableIndexes('files'); 13 | Schema::table('files', function (Blueprint $table) use($indexesFiles) { 14 | if(array_key_exists('files_post_id_foreign', $indexesFiles)) { 15 | $table->dropForeign('files_post_id_foreign'); 16 | $table->foreign('post_id', 'files_post_id_foreign') 17 | ->references('id') 18 | ->on('posts') 19 | ->onDelete('cascade'); 20 | } 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | // 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /public/js/helper.js: -------------------------------------------------------------------------------- 1 | function convertDateToDateTime(date) { 2 | let m = new Date(date); 3 | return ("0" + m.getUTCDate()).slice(-2) + "/" + 4 | ("0" + (m.getUTCMonth() + 1)).slice(-2) + "/" + 5 | m.getUTCFullYear() + " " + 6 | ("0" + m.getUTCHours()).slice(-2) + ":" + 7 | ("0" + m.getUTCMinutes()).slice(-2); 8 | } 9 | 10 | function renderPagination(links) { 11 | links.forEach(function (each) { 12 | $('#pagination').append($('
  • ').attr('class', `page-item ${each.active ? 'active' : ''}`) 13 | .append(`${each.label}`)); 14 | }) 15 | } 16 | 17 | function notifySuccess(message = '') { 18 | $.toast({ 19 | heading: 'Success', 20 | text: message, 21 | showHideTransition: 'slide', 22 | position: 'bottom-right', 23 | icon: 'success' 24 | }); 25 | } 26 | 27 | function notifyError(message = '') { 28 | $.toast({ 29 | heading: 'Error', 30 | text: message, 31 | showHideTransition: 'slide', 32 | position: 'bottom-right', 33 | icon: 'error' 34 | }); 35 | } -------------------------------------------------------------------------------- /database/migrations/2022_05_05_142215_alter_columns_nullable_in_user_table.php: -------------------------------------------------------------------------------- 1 | string('password')->nullable()->change(); 19 | } 20 | if (Schema::hasColumn('users', 'city')) { 21 | $table->string('city')->nullable()->change(); 22 | } 23 | if (Schema::hasColumn('users', 'company_id')) { 24 | $table->unsignedBigInteger('company_id')->nullable()->change(); 25 | } 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_135222_create_companies_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name')->unique(); 19 | $table->string('address'); 20 | $table->string('address2'); 21 | $table->string('district'); 22 | $table->string('city'); 23 | $table->string('country'); 24 | $table->string('zipcode'); 25 | $table->string('phone'); 26 | $table->string('email'); 27 | $table->string('logo'); 28 | }); 29 | } 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::dropIfExists('companies'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/Models/Config.php: -------------------------------------------------------------------------------- 1 | remember( 16 | SystemCacheKeyEnum::CONFIGS . $isPublic, 17 | 86400 * 30, 18 | function () use ($isPublic) { 19 | $data = self::query() 20 | ->where('is_public', $isPublic) 21 | ->get(); 22 | $arr = []; 23 | 24 | foreach ($data as $each) { 25 | $arr[$each->key] = $each->value; 26 | } 27 | 28 | return $arr; 29 | } 30 | ); 31 | } 32 | 33 | public static function getByKey($key) 34 | { 35 | return cache()->remember( 36 | SystemCacheKeyEnum::CONFIGS . $key, 37 | 86400 * 30, 38 | function () use ($key) { 39 | return self::query() 40 | ->where('key', $key) 41 | ->value('value'); 42 | } 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /database/migrations/2022_05_14_133243_alter_add_deleted_at_column_to_some_table.php: -------------------------------------------------------------------------------- 1 | timestamp('deleted_at')->nullable(); 19 | }); 20 | } 21 | if (!Schema::hasColumn('companies', 'deleted_at')) { 22 | Schema::table('companies', function (Blueprint $table) { 23 | $table->timestamp('deleted_at')->nullable(); 24 | }); 25 | } 26 | if (!Schema::hasColumn('files', 'deleted_at')) { 27 | Schema::table('files', function (Blueprint $table) { 28 | $table->timestamp('deleted_at')->nullable(); 29 | }); 30 | } 31 | } 32 | 33 | /** 34 | * Reverse the migrations. 35 | * 36 | * @return void 37 | */ 38 | public function down() 39 | { 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | name('login'); 11 | Route::get('/register', [AuthController::class, 'register'])->name('register'); 12 | Route::post('/register', [AuthController::class, 'registering'])->name('registering'); 13 | Route::get('/auth/redirect/{provider}', function ($provider) { 14 | return Socialite::driver($provider)->redirect(); 15 | })->name('auth.redirect'); 16 | Route::get('/auth/callback/{provider}', [AuthController::class, 'callback'])->name('auth.callback'); 17 | Route::get('/logout', [AuthController::class, 'logout'])->name('logout'); 18 | 19 | 20 | Route::get('/', function () { 21 | return view('layout.master'); 22 | })->name('welcome'); 23 | 24 | Route::get('/language/{locale}', function ($locale) { 25 | if (!in_array($locale, config('app.locales'))) { 26 | $locale = config('app.fallback_locale'); 27 | } 28 | 29 | session()->put('locale', $locale); 30 | 31 | 32 | return redirect()->back()->withCookie(cookie('locale', $locale, 60 * 24 * 30)); 33 | })->name('language'); 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /routes/admin.php: -------------------------------------------------------------------------------- 1 | name('welcome'); 11 | 12 | Route::group([ 13 | 'as' => 'users.', 14 | 'prefix' => 'users', 15 | ], static function () { 16 | Route::get('/', [UserController::class, 'index'])->name('index'); 17 | Route::get('/{user}', [UserController::class, 'show'])->name('show'); 18 | Route::delete('/{user}', [UserController::class, 'destroy'])->name('destroy'); 19 | }); 20 | Route::group([ 21 | 'as' => 'posts.', 22 | 'prefix' => 'posts', 23 | ], static function () { 24 | Route::get('/', [PostController::class, 'index'])->name('index'); 25 | Route::get('/create', [PostController::class, 'create'])->name('create'); 26 | Route::post('/store', [PostController::class, 'store'])->name('store'); 27 | Route::post('/import-csv', [PostController::class, 'importCsv'])->name('import_csv'); 28 | }); 29 | 30 | Route::group([ 31 | 'as' => 'companies.', 32 | 'prefix' => 'companies', 33 | ], static function () { 34 | Route::post('/store', [CompanyController::class, 'store'])->name('store'); 35 | }); 36 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_135934_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name'); 19 | $table->string('avatar')->nullable(); 20 | $table->string('email'); 21 | $table->string('password'); 22 | $table->string('phone')->nullable(); 23 | $table->string('link')->nullable(); 24 | $table->integer('role')->default(1); 25 | $table->text('bio')->nullable(); 26 | $table->string('position')->nullable(); 27 | $table->boolean('gender')->default(false); 28 | $table->string('city'); 29 | $table->foreignId('company_id')->constrained(); 30 | $table->timestamps(); 31 | }); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::dropIfExists('users'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->firstName . ' ' . $this->faker->lastName, 29 | 'avatar' => $this->faker->imageUrl(), 30 | 'email' => $this->faker->email, 31 | 'password' => $this->faker->password, 32 | 'phone' => $this->faker->phoneNumber, 33 | 'link' => null, 34 | 'role' => $this->faker->randomElement(UserRoleEnum::getValues()), 35 | 'bio' => $this->faker->boolean ? $this->faker->word : null, 36 | 'position' => $this->faker->jobTitle, 37 | 'gender' => $this->faker->boolean, 38 | 'city' => $this->faker->city, 39 | 'company_id' => Company::query()->inRandomOrder()->value('id'), 40 | ]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /database/seeders/UserSeeder.php: -------------------------------------------------------------------------------- 1 | pluck('id')->toArray(); 22 | 23 | for($i = 1; $i <= 100000; $i++){ 24 | $arr[] = [ 25 | 'name' => $faker->firstName . ' ' . $faker->lastName, 26 | 'avatar' => $faker->imageUrl(), 27 | 'email' => $faker->email, 28 | 'password' => $faker->password, 29 | 'phone' => $faker->phoneNumber, 30 | 'link' => null, 31 | 'role' => $faker->randomElement(UserRoleEnum::getValues()), 32 | 'bio' => $faker->boolean ? $faker->word : null, 33 | 'position' => $faker->jobTitle, 34 | 'gender' => $faker->boolean, 35 | 'city' => $faker->city, 36 | 'company_id' => $companies[array_rand($companies)], 37 | ]; 38 | if($i % 1000 === 0){ 39 | User::insert($arr); 40 | $arr = []; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | ], 22 | 23 | 'postmark' => [ 24 | 'token' => env('POSTMARK_TOKEN'), 25 | ], 26 | 27 | 'ses' => [ 28 | 'key' => env('AWS_ACCESS_KEY_ID'), 29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 | ], 32 | 33 | 'github' => [ 34 | 'client_id' => env('GITHUB_CLIENT_ID'), 35 | 'client_secret' => env('GITHUB_CLIENT_SECRET'), 36 | 'redirect' => env('CALLBACK_URI') . '/github', 37 | ], 38 | 39 | 'gitlab' => [ 40 | 'client_id' => env('GITLAB_CLIENT_ID'), 41 | 'client_secret' => env('GITLAB_CLIENT_SECRET'), 42 | 'redirect' => env('CALLBACK_URI') . '/gitlab', 43 | ], 44 | 45 | ]; 46 | -------------------------------------------------------------------------------- /database/migrations/2022_04_23_140743_create_posts_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->foreignId('user_id')->constrained(); 19 | $table->foreignId('company_id')->constrained(); 20 | $table->string('job_title'); 21 | $table->string('district'); 22 | $table->string('city'); 23 | $table->integer('remote'); 24 | $table->boolean('is_partime'); 25 | $table->integer('min_salary'); 26 | $table->integer('max_salary'); 27 | $table->integer('currency_salary')->default(1); 28 | $table->text('requirement')->nullable(); 29 | $table->date('start_date')->nullable(); 30 | $table->date('end_date')->nullable(); 31 | $table->integer('number_applicants')->nullable(); 32 | $table->integer('status')->default(0); 33 | $table->string('slug'); 34 | $table->timestamps(); 35 | $table->softDeletes(); 36 | }); 37 | } 38 | 39 | /** 40 | * Reverse the migrations. 41 | * 42 | * @return void 43 | */ 44 | public function down() 45 | { 46 | Schema::dropIfExists('posts'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Http/Controllers/CompanyController.php: -------------------------------------------------------------------------------- 1 | model = Company::query(); 20 | } 21 | 22 | public function index(Request $request): JsonResponse 23 | { 24 | $data = $this->model 25 | ->where('name', 'like', '%' . $request->get('q') . '%') 26 | ->get(); 27 | 28 | return $this->successResponse($data); 29 | } 30 | 31 | public function check($companyName): JsonResponse 32 | { 33 | $check = $this->model 34 | ->where('name', $companyName) 35 | ->exists(); 36 | 37 | return $this->successResponse($check); 38 | } 39 | 40 | public function store(StoreRequest $request): JsonResponse 41 | { 42 | try { 43 | $arr = $request->validated(); 44 | $arr['logo'] = optional($request->file('logo'))->store('company_logo'); 45 | 46 | Company::create($arr); 47 | 48 | return $this->successResponse(); 49 | } catch (Throwable $e) { 50 | $message = ''; 51 | if ($e->getCode() === '23000') { 52 | $message = 'Duplicate company name'; 53 | } 54 | 55 | return $this->errorResponse($message); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/Http/Controllers/PostController.php: -------------------------------------------------------------------------------- 1 | model = Post::query(); 23 | } 24 | 25 | public function index(): JsonResponse 26 | { 27 | $data = $this->model 28 | ->latest() 29 | ->paginate(); 30 | foreach ($data as $each) { 31 | $each->currency_salary = $each->currency_salary_code; 32 | $each->status = $each->status_name; 33 | } 34 | 35 | $arr['data'] = $data->getCollection(); 36 | $arr['pagination'] = $data->linkCollection(); 37 | 38 | return $this->successResponse($arr); 39 | } 40 | 41 | public function generateSlug(GenerateSlugRequest $request): JsonResponse 42 | { 43 | try { 44 | $title = $request->get('title'); 45 | $slug = SlugService::createSlug(Post::class, 'slug', $title); 46 | 47 | return $this->successResponse($slug); 48 | } catch (Throwable $e) { 49 | return $this->errorResponse(); 50 | } 51 | } 52 | 53 | public function checkSlug(CheckSlugRequest $request): JsonResponse 54 | { 55 | return $this->successResponse(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /config/translation-manager.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'prefix' => 'translations', 15 | // 'middleware' => 'auth', 16 | ], 17 | 18 | /** 19 | * Enable deletion of translations 20 | * 21 | * @type boolean 22 | */ 23 | 'delete_enabled' => true, 24 | 25 | /** 26 | * Exclude specific groups from Laravel Translation Manager. 27 | * This is useful if, for example, you want to avoid editing the official Laravel language files. 28 | * 29 | * @type array 30 | * 31 | * array( 32 | * 'pagination', 33 | * 'reminders', 34 | * 'validation', 35 | * ) 36 | */ 37 | 'exclude_groups' => [], 38 | 39 | /** 40 | * Exclude specific languages from Laravel Translation Manager. 41 | * 42 | * @type array 43 | * 44 | * array( 45 | * 'fr', 46 | * 'de', 47 | * ) 48 | */ 49 | 'exclude_langs' => [], 50 | 51 | /** 52 | * Export translations with keys output alphabetically. 53 | */ 54 | 'sort_keys' => false, 55 | 56 | 'trans_functions' => [ 57 | 'trans', 58 | 'trans_choice', 59 | 'Lang::get', 60 | 'Lang::choice', 61 | 'Lang::trans', 62 | 'Lang::transChoice', 63 | '@lang', 64 | '@choice', 65 | '__', 66 | '$trans.get', 67 | ], 68 | 69 | ]; 70 | -------------------------------------------------------------------------------- /app/Http/Requests/Company/StoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 14 | } 15 | 16 | public function rules(): array 17 | { 18 | return [ 19 | 'name' => [ 20 | 'required', 21 | 'filled', 22 | 'string', 23 | 'min:0', 24 | ], 25 | 'country' => [ 26 | 'required', 27 | 'string', 28 | Rule::in(CompanyCountryEnum::getKeys()), 29 | ], 30 | 'city' => [ 31 | 'required', 32 | 'string', 33 | ], 34 | 'distinct' => [ 35 | 'nullable', 36 | 'string', 37 | ], 38 | 'address' => [ 39 | 'nullable', 40 | 'string', 41 | ], 42 | 'address2' => [ 43 | 'nullable', 44 | 'string', 45 | ], 46 | 'zipcode' => [ 47 | 'nullable', 48 | 'string', 49 | ], 50 | 'phone' => [ 51 | 'nullable', 52 | 'string', 53 | ], 54 | 'email' => [ 55 | 'nullable', 56 | 'string', 57 | ], 58 | 'logo' => [ 59 | 'nullable', 60 | 'file', 61 | 'image', 62 | 'max:5000', 63 | ], 64 | ]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /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' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 'useTLS' => true, 41 | ], 42 | ], 43 | 44 | 'redis' => [ 45 | 'driver' => 'redis', 46 | 'connection' => 'default', 47 | ], 48 | 49 | 'log' => [ 50 | 'driver' => 'log', 51 | ], 52 | 53 | 'null' => [ 54 | 'driver' => 'null', 55 | ], 56 | 57 | ], 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = tap($kernel->handle( 52 | $request = Request::capture() 53 | ))->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /resources/views/applicant/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layout_frontpage.master') 2 | @section('content') 3 |

    4 | {{ __('frontpage.title') }} 5 |

    6 |
    7 | @include('layout_frontpage.sidebar') 8 | 9 |
    10 |
    11 | @foreach($posts as $post) 12 | 13 | @endforeach 14 |
    15 |
      16 | {{ $posts->appends(request()->all())->links() }} 17 |
    18 |
    19 |
    20 | @endsection 21 | @push('js') 22 | 23 | 54 | @endpush -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | configureRateLimiting(); 31 | 32 | $this->routes(function () { 33 | Route::middleware('web') 34 | ->group(base_path('routes/web.php')); 35 | 36 | Route::prefix('api') 37 | ->middleware('api') 38 | ->name('api.') 39 | ->group(base_path('routes/api.php')); 40 | 41 | Route::prefix('admin') 42 | ->middleware('admin') 43 | ->name('admin.') 44 | ->group(base_path('routes/admin.php')); 45 | 46 | Route::prefix('applicant') 47 | // ->middleware(AdminMiddleware::class) 48 | ->name('applicant.') 49 | ->group(base_path('routes/applicant.php')); 50 | }); 51 | } 52 | 53 | /** 54 | * Configure the rate limiters for the application. 55 | * 56 | * @return void 57 | */ 58 | protected function configureRateLimiting() 59 | { 60 | RateLimiter::for('api', function (Request $request) { 61 | return Limit::perMinute(60); 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Trang web môi giới việc làm 2 | ## _Dự án vì cộng đồng_ 3 | [![Sơ đồ thực thể](https://app.diagrams.net/images/favicon-32x32.png)](https://drive.google.com/file/d/1CIiWkZ25f-Pu1gYtNiLrdV2dG-IGLmrI/view?usp=sharing) 4 | [![Cơ sở dữ liệu](https://i.ibb.co/S7KTZxP/google-sheets-1.png)](https://docs.google.com/spreadsheets/d/1k0TEgq5_6LldRxVwSTqpFD4Nd6u8_f6bzy8TnV7oOPo/edit?usp=sharing) 5 | 6 | ### Đối tượng sử dụng 7 | - Quản trị viên 8 | - Nhà tuyển dụng 9 | - Ứng viên 10 | 11 | ### Chức năng từng đối tượng 12 | A. Quản trị viên 13 | - Quản lý trang thông tin: banner, giới thiệu,… 14 | - Quản lý người dùng 15 | - Quản lý file: JD, CV 16 | - Quản lý bài đăng công việc 17 | - Quản lý báo cáo 18 | 19 | B. Nhà tuyển dụng 20 | - Quản lý bài tuyển dụng 21 | - Tìm kiếm CV 22 | - Chỉnh sửa thông tin cá nhân (thuộc công ty nào, thông tin liên hệ) 23 | 24 | C. Ứng viên 25 | - Tìm kiếm công việc (công ty, vị trí, mức lương, địa điểm, ngôn ngữ, trình độ, yêu cầu bằng cấp - chứng chỉ, số lượng) 26 | - Đăng CV 27 | - Xem danh sách công việc (có thể ghim và còn lại sắp xếp ngẫu nhiên) 28 | - Báo cáo vi phạm: công ty, cá nhân (lừa đảo, spam, không liên hệ được, thông tin bài tuyển dụng sai) 29 | 30 | ### Phân tích chức năng 31 | 32 | - Đăng bài tuyển dụng 33 | 34 | | Các tác nhân | Nhà tuyển dụng | 35 | | ------ | ------ | 36 | | Mô tả | Đăng bài tuyển dụng | 37 | | Kích hoạt | Người dùng ấn vào nút “Đăng bài tuyển dụng” trên thanh menu | 38 | | Đầu vào | Tên công ty
    Tên công việc
    Địa điểm: thành phố - quận (select2 - load về local)
    Remote | Local? (checkbox)
    Có cho part time không? (radio)
    Mức lương (slidebar)
    Ngôn ngữ (multiple select2)
    Yêu cầu thêm (textarea)
    Thời gian
    Số lượng
    File JD | 39 | | Trình tự xử lý | | 40 | | Đầu ra | Đúng: Hiển thị trang người dùng và thông báo thành công
    Sai: Hiển thị trang đăng nhập và thông báo thất bại | 41 | | Lưu ý | Kiểm tra ô nhập không được để trống bằng JavaScript | 42 | 43 | 44 | ## License 45 | 46 | MIT 47 | 48 | **Free Software, Hell Yeah!** 49 | -------------------------------------------------------------------------------- /app/Providers/TelescopeServiceProvider.php: -------------------------------------------------------------------------------- 1 | hideSensitiveRequestDetails(); 22 | 23 | Telescope::filter(function (IncomingEntry $entry) { 24 | if ($this->app->environment('local')) { 25 | return true; 26 | } 27 | 28 | return $entry->isReportableException() || 29 | $entry->isFailedRequest() || 30 | $entry->isFailedJob() || 31 | $entry->isScheduledTask() || 32 | $entry->hasMonitoredTag(); 33 | }); 34 | } 35 | 36 | /** 37 | * Prevent sensitive request details from being logged by Telescope. 38 | * 39 | * @return void 40 | */ 41 | protected function hideSensitiveRequestDetails() 42 | { 43 | if ($this->app->environment('local')) { 44 | return; 45 | } 46 | 47 | Telescope::hideRequestParameters(['_token']); 48 | 49 | Telescope::hideRequestHeaders([ 50 | 'cookie', 51 | 'x-csrf-token', 52 | 'x-xsrf-token', 53 | ]); 54 | } 55 | 56 | /** 57 | * Register the Telescope gate. 58 | * 59 | * This gate determines who can access Telescope in non-local environments. 60 | * 61 | * @return void 62 | */ 63 | protected function gate() 64 | { 65 | Gate::define('viewTelescope', function ($user) { 66 | return in_array($user->email, [ 67 | // 68 | ]); 69 | }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /resources/views/layout_frontpage/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ $title ?? config('app.name', 'Laravel') }} 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | @include('layout_frontpage.navbar') 23 | @include('layout_frontpage.header') 24 | 25 |
    26 | 27 |
    28 |
    29 | @yield('content') 30 |
    31 |
    32 | 33 |
    34 | 35 | 36 | @include('layout_frontpage.footer') 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | @stack('js') 48 | 49 | 50 | -------------------------------------------------------------------------------- /resources/views/layout_frontpage/navbar.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/functions.php: -------------------------------------------------------------------------------- 1 | user(); 18 | } 19 | } 20 | 21 | if (!function_exists('isSuperAdmin')) { 22 | function isSuperAdmin(): bool 23 | { 24 | return user() && user()->role === UserRoleEnum::SUPER_ADMIN; 25 | } 26 | } 27 | 28 | if (!function_exists('isAdmin')) { 29 | function isAdmin(): bool 30 | { 31 | return user() && user()->role === UserRoleEnum::ADMIN; 32 | } 33 | } 34 | 35 | if (!function_exists('get_currency_symbol')) { 36 | function get_currency_symbol($string) 37 | { 38 | $symbol = ''; 39 | $length = mb_strlen($string, 'utf-8'); 40 | for ($i = 0; $i < $length; $i++) { 41 | $char = mb_substr($string, $i, 1, 'utf-8'); 42 | if (!ctype_digit($char) && !ctype_punct($char)) { 43 | $symbol .= $char; 44 | } 45 | } 46 | return $symbol; 47 | } 48 | } 49 | 50 | if (!function_exists('getAndCachePostCities')) { 51 | function getAndCachePostCities(): array 52 | { 53 | return cache()->remember( 54 | SystemCacheKeyEnum::POST_CITIES, 55 | 86400 * 30, 56 | function () { 57 | $cities = Post::query() 58 | ->pluck('city'); 59 | $arrCity = []; 60 | foreach ($cities as $city) { 61 | if (empty($city)) { 62 | continue; 63 | } 64 | $arr = explode(', ', $city); 65 | foreach ($arr as $item) { 66 | if (empty($item)) { 67 | continue; 68 | } 69 | if (in_array($item, $arrCity)) { 70 | continue; 71 | } 72 | $arrCity[] = $item; 73 | } 74 | } 75 | 76 | return $arrCity; 77 | } 78 | ); 79 | } 80 | } -------------------------------------------------------------------------------- /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": "^7.4|^8.0", 12 | "ext-intl": "*", 13 | "barryvdh/laravel-translation-manager": "^0.6.3", 14 | "bensampo/laravel-enum": "^4.2", 15 | "cviebrock/eloquent-sluggable": "^8.0", 16 | "doctrine/dbal": "^3.3", 17 | "fideloper/proxy": "^4.2", 18 | "fruitcake/laravel-cors": "^2.0", 19 | "guzzlehttp/guzzle": "^7.0.1", 20 | "itsgoingd/clockwork": "^5.1", 21 | "laravel/framework": "^8.0", 22 | "laravel/socialite": "^5.5", 23 | "laravel/telescope": "^4.9", 24 | "laravel/tinker": "^2.0", 25 | "maatwebsite/excel": "^3.1" 26 | }, 27 | "require-dev": { 28 | "barryvdh/laravel-debugbar": "^3.6", 29 | "barryvdh/laravel-ide-helper": "^2.12", 30 | "facade/ignition": "^2.3.6", 31 | "fzaninotto/faker": "^1.9.1", 32 | "mockery/mockery": "^1.3.1", 33 | "nunomaduro/collision": "^5.0", 34 | "phpunit/phpunit": "^9.3" 35 | }, 36 | "config": { 37 | "optimize-autoloader": true, 38 | "preferred-install": "dist", 39 | "sort-packages": true 40 | }, 41 | "extra": { 42 | "laravel": { 43 | "dont-discover": [] 44 | } 45 | }, 46 | "autoload": { 47 | "psr-4": { 48 | "App\\": "app/", 49 | "Database\\Factories\\": "database/factories/", 50 | "Database\\Seeders\\": "database/seeders/" 51 | }, 52 | "files": [ 53 | "app/functions.php" 54 | ] 55 | }, 56 | "autoload-dev": { 57 | "psr-4": { 58 | "Tests\\": "tests/" 59 | } 60 | }, 61 | "minimum-stability": "dev", 62 | "prefer-stable": true, 63 | "scripts": { 64 | "post-autoload-dump": [ 65 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 66 | "@php artisan package:discover --ansi" 67 | ], 68 | "post-root-package-install": [ 69 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 70 | ], 71 | "post-create-project-cmd": [ 72 | "@php artisan key:generate --ansi" 73 | ] 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/Policies/UserPolicy.php: -------------------------------------------------------------------------------- 1 | model = User::query(); 20 | $this->table = (new User())->getTable(); 21 | 22 | View::share('title', ucwords($this->table)); 23 | View::share('table', $this->table); 24 | } 25 | 26 | public function index(Request $request) 27 | { 28 | $selectedRole = $request->get('role'); 29 | $selectedCity = $request->get('city'); 30 | $selectedCompany = $request->get('company'); 31 | 32 | $query = $this->model->clone() 33 | ->with('company:id,name') 34 | ->latest(); 35 | if (!is_null($selectedRole)) { 36 | $query->where('role', $selectedRole); 37 | } 38 | if (!is_null($selectedCity)) { 39 | $query->where('city', $selectedCity); 40 | } 41 | if (!is_null($selectedCompany)) { 42 | $query->whereHas('company', function ($q) use ($selectedCompany) { 43 | return $q->where('id', $selectedCompany); 44 | }); 45 | } 46 | $data = $query->paginate(1) 47 | ->appends($request->all()); 48 | 49 | $roles = UserRoleEnum::asArray(); 50 | 51 | $companies = Company::query() 52 | ->get([ 53 | 'id', 54 | 'name', 55 | ]); 56 | 57 | $cities = $this->model->clone() 58 | ->distinct() 59 | ->limit(10) 60 | ->whereNotNull('city') 61 | ->pluck('city'); 62 | 63 | return view("admin.$this->table.index", [ 64 | 'data' => $data, 65 | 'roles' => $roles, 66 | 'cities' => $cities, 67 | 'companies' => $companies, 68 | 'selectedRole' => $selectedRole, 69 | 'selectedCity' => $selectedCity, 70 | 'selectedCompany' => $selectedCompany, 71 | ]); 72 | } 73 | 74 | public function destroy($userId) 75 | { 76 | User::destroy($userId); 77 | 78 | return redirect()->back(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /database/migrations/2022_05_24_141814_alter_multiple_columns_nullable.php: -------------------------------------------------------------------------------- 1 | string('district')->nullable()->change(); 14 | } 15 | if (Schema::hasColumn('posts', 'remote')) { 16 | $table->renameColumn('remote', 'remotable'); 17 | } 18 | if (Schema::hasColumn('posts', 'is_partime')) { 19 | $table->string('is_partime')->nullable()->change(); 20 | } 21 | if (Schema::hasColumn('posts', 'min_salary')) { 22 | $table->string('min_salary')->nullable()->change(); 23 | } 24 | if (Schema::hasColumn('posts', 'max_salary')) { 25 | $table->string('max_salary')->nullable()->change(); 26 | } 27 | if (Schema::hasColumn('posts', 'currency_salary')) { 28 | $table->string('currency_salary')->nullable()->change(); 29 | } 30 | }); 31 | Schema::table('companies', static function (Blueprint $table) { 32 | if (Schema::hasColumn('companies', 'address')) { 33 | $table->string('address')->nullable()->change(); 34 | } 35 | if (Schema::hasColumn('companies', 'address2')) { 36 | $table->string('address2')->nullable()->change(); 37 | } 38 | if (Schema::hasColumn('companies', 'district')) { 39 | $table->string('district')->nullable()->change(); 40 | } 41 | if (Schema::hasColumn('companies', 'zipcode')) { 42 | $table->string('zipcode')->nullable()->change(); 43 | } 44 | if (Schema::hasColumn('companies', 'phone')) { 45 | $table->string('phone')->nullable()->change(); 46 | } 47 | if (Schema::hasColumn('companies', 'email')) { 48 | $table->string('email')->nullable()->change(); 49 | } 50 | if (Schema::hasColumn('companies', 'logo')) { 51 | $table->string('logo')->nullable()->change(); 52 | } 53 | }); 54 | } 55 | 56 | public function down() 57 | { 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/Policies/ConfigPolicy.php: -------------------------------------------------------------------------------- 1 | get('cities', []); 16 | $configs = Config::getAndCache(0); 17 | $minSalary = $request->get('min_salary', $configs['filter_min_salary']); 18 | $maxSalary = $request->get('max_salary', $configs['filter_max_salary']); 19 | $remotable = $request->get('remotable'); 20 | $searchCanParttime = $request->boolean('can_parttime'); 21 | 22 | $filters = []; 23 | if (!empty($searchCities)) { 24 | $filters['cities'] = $searchCities; 25 | } 26 | if ($request->has('min_salary')) { 27 | $filters['min_salary'] = $minSalary; 28 | } 29 | if ($request->has('max_salary')) { 30 | $filters['max_salary'] = $maxSalary; 31 | } 32 | if (!empty($remotable)) { 33 | $filters['remotable'] = $remotable; 34 | } 35 | if ($searchCanParttime) { 36 | $filters['can_parttime'] = $searchCanParttime; 37 | } 38 | 39 | $posts = Post::query() 40 | ->indexHomePage($filters) 41 | ->paginate(); 42 | 43 | $arrCity = getAndCachePostCities(); 44 | $filtersPostRemotable = PostRemotableEnum::getArrWithLowerKey(); 45 | 46 | return view('applicant.index', [ 47 | 'posts' => $posts, 48 | 'arrCity' => $arrCity, 49 | 'searchCities' => $searchCities, 50 | 'minSalary' => $minSalary, 51 | 'maxSalary' => $maxSalary, 52 | 'configs' => $configs, 53 | 'filtersPostRemotable' => $filtersPostRemotable, 54 | 'remotable' => $remotable, 55 | 'searchCanParttime' => $searchCanParttime, 56 | ]); 57 | } 58 | 59 | public function show($postId) 60 | { 61 | $post = Post::query() 62 | ->with('file') 63 | ->approved() 64 | ->findOrFail($postId); 65 | 66 | $title = $post->job_title; 67 | 68 | return view('applicant.show', [ 69 | 'post' => $post, 70 | 'title' => $title, 71 | ]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /resources/views/layout/sidebar.blade.php: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 12 | 13 | 14 | 22 | 23 |
    24 |
    25 |
    26 |
    27 |
    28 |
    29 |
    30 |
    31 |
    32 | 33 | 34 | 54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |
    61 |
    62 | 63 |
    -------------------------------------------------------------------------------- /app/Http/Kernel.php: -------------------------------------------------------------------------------- 1 | [ 36 | \App\Http\Middleware\EncryptCookies::class, 37 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 38 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 39 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 40 | \App\Http\Middleware\VerifyCsrfToken::class, 41 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 42 | ], 43 | 44 | 'api' => [ 45 | 'throttle:api', 46 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 47 | ], 48 | ]; 49 | 50 | /** 51 | * The application's route middleware. 52 | * 53 | * These middleware may be assigned to groups or used individually. 54 | * 55 | * @var array 56 | */ 57 | protected $routeMiddleware = [ 58 | 'auth' => \App\Http\Middleware\Authenticate::class, 59 | 'admin' => \App\Http\Middleware\AdminMiddleware::class, 60 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 61 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 62 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 63 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 64 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 65 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 66 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 67 | ]; 68 | } 69 | -------------------------------------------------------------------------------- /app/Http/Controllers/AuthController.php: -------------------------------------------------------------------------------- 1 | $roles, 27 | ]); 28 | } 29 | 30 | public function callback($provider): RedirectResponse 31 | { 32 | $data = Socialite::driver($provider)->user(); 33 | 34 | $user = User::query() 35 | ->where('email', $data->getEmail()) 36 | ->first(); 37 | $checkExist = true; 38 | 39 | if (is_null($user)) { 40 | $user = new User(); 41 | $user->email = $data->getEmail(); 42 | $user->role = UserRoleEnum::APPLICANT; 43 | $checkExist = false; 44 | } 45 | 46 | $user->name = $data->getName(); 47 | $user->avatar = $data->getAvatar(); 48 | 49 | auth()->login($user, true); 50 | 51 | if ($checkExist) { 52 | $role = getRoleByKey($user->role); 53 | 54 | return redirect()->route("$role.welcome"); 55 | } 56 | 57 | return redirect()->route('register'); 58 | } 59 | 60 | public function registering(RegisteringRequest $request): RedirectResponse 61 | { 62 | $password = Hash::make($request->get('password')); 63 | $role = $request->get('role'); 64 | 65 | if (auth()->check()) { 66 | User::where('id', auth()->user()->id) 67 | ->update([ 68 | 'password' => $password, 69 | 'role' => $role, 70 | ]); 71 | } else { 72 | $user = User::create([ 73 | 'name' => $request->name, 74 | 'email' => $request->email, 75 | 'password' => $password, 76 | 'role' => $role, 77 | ]); 78 | 79 | Auth::login($user); 80 | } 81 | 82 | $role = getRoleByKey($role); 83 | 84 | return redirect()->route("$role.welcome"); 85 | } 86 | 87 | public function logout(Request $request): RedirectResponse 88 | { 89 | Auth::logout(); 90 | 91 | $request->session()->invalidate(); 92 | 93 | return redirect()->route('login'); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /resources/views/layout/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ $title ?? '' }} - {{ config('app.name') }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | @stack('css') 16 | 17 | 18 | 21 | 22 |
    23 | 24 | @include('layout.sidebar') 25 | 26 | 27 | 28 | 29 | 30 | 31 |
    32 |
    33 | 34 | @include('layout.topbar') 35 | 36 | 37 | 38 |
    39 |
    40 |
    41 |
    42 |

    {{ $title ?? '' }}

    43 |
    44 |
    45 |
    46 | @yield('content') 47 |
    48 | 49 | 50 |
    51 | 52 | 53 | 54 | @include('layout.footer') 55 | 56 | 57 |
    58 | 59 | 60 | 61 | 62 | 63 |
    64 | 65 | 66 | 67 | 68 | 69 | 70 | @stack('js') 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /resources/views/components/post.blade.php: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | @if($post->is_pinned) 6 | 8 | 9 | 10 | 11 | @endif 12 |
    13 |
    14 | 15 | {{ $post->job_title }} 16 | 17 |
    18 |

    19 | {{ $languages }} 20 |

    21 |

    22 | {{ $post->location }} 23 |

    24 | 38 |
    39 | @if($post->is_not_available) 40 | 41 | 42 | {{ __('frontpage.not_available') }} 43 | 44 | @endif 45 |
    46 |
    47 |
    48 |
    49 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "sftp", "s3" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'url' => env('APP_URL').'/storage', 55 | 'visibility' => 'public', 56 | ], 57 | 58 | 's3' => [ 59 | 'driver' => 's3', 60 | 'key' => env('AWS_ACCESS_KEY_ID'), 61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 62 | 'region' => env('AWS_DEFAULT_REGION'), 63 | 'bucket' => env('AWS_BUCKET'), 64 | 'url' => env('AWS_URL'), 65 | 'endpoint' => env('AWS_ENDPOINT'), 66 | ], 67 | 68 | ], 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Symbolic Links 73 | |-------------------------------------------------------------------------- 74 | | 75 | | Here you may configure the symbolic links that will be created when the 76 | | `storage:link` Artisan command is executed. The array keys should be 77 | | the locations of the links and the values should be their targets. 78 | | 79 | */ 80 | 81 | 'links' => [ 82 | public_path('storage') => storage_path('app/public'), 83 | ], 84 | 85 | ]; 86 | -------------------------------------------------------------------------------- /app/Http/Requests/Post/StoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 16 | } 17 | 18 | public function rules(): array 19 | { 20 | $rules = [ 21 | 'company' => [ 22 | 'string', 23 | 'nullable', 24 | ], 25 | 'languages' => [ 26 | 'required', 27 | 'array', 28 | 'filled', 29 | ], 30 | 'city' => [ 31 | 'required', 32 | 'filled', 33 | 'string', 34 | ], 35 | 'district' => [ 36 | 'nullable', 37 | 'string', 38 | ], 39 | 'currency_salary' => [ 40 | 'required', 41 | 'numeric', 42 | Rule::in(PostCurrencySalaryEnum::getValues()), 43 | ], 44 | 'number_applicants' => [ 45 | 'nullable', 46 | 'numeric', 47 | 'min:1', 48 | ], 49 | 'remotable' => [ 50 | 'required', 51 | Rule::in(PostRemotableEnum::getArrWithoutAll()), 52 | ], 53 | 'is_parttime' => [ 54 | 'nullable', 55 | ], 56 | 'start_date' => [ 57 | 'nullable', 58 | 'date', 59 | 'before:end_date', 60 | ], 61 | 'end_date' => [ 62 | 'nullable', 63 | 'date', 64 | 'after:start_date', 65 | ], 66 | 'job_title' => [ 67 | 'required', 68 | 'string', 69 | 'filled', 70 | 'min:3', 71 | 'max:255', 72 | ], 73 | 'slug' => [ 74 | 'required', 75 | 'string', 76 | 'filled', 77 | 'min:3', 78 | 'max:255', 79 | Rule::unique(Post::class), 80 | ], 81 | ]; 82 | 83 | $rules['min_salary'] = [ 84 | 'nullable', 85 | 'numeric', 86 | ]; 87 | if (!empty($this->max_salary)) { 88 | $rules['min_salary'][] = 'lt:max_salary'; 89 | } 90 | 91 | $rules['max_salary'] = [ 92 | 'nullable', 93 | 'numeric', 94 | ]; 95 | if (!empty($this->min_salary)) { 96 | $rules['max_salary'][] = 'gt:min_salary'; 97 | } 98 | 99 | return $rules; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /resources/views/layout_frontpage/posts.blade.php: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 |
    6 |
    7 | Manual Rotating Card 8 |
    9 |

    10 | "This card is doing a full rotation, click on the rotate button" 11 |

    12 |

    13 | Don't be scared of the truth because we need to restart the human foundation in truth And I love you like Kanye loves Kanye I love Rick Owens’ bed design but the back is... 14 |

    15 | 20 |
    21 |
    22 | 23 |
    24 |
    25 |
    26 |
    27 | Do more... 28 |
    29 |

    30 | You can read this article or share it with your friends and family on different networks... 31 |

    32 | 46 |
    47 | 50 | 51 |
    52 |
    53 | 54 |
    55 |
    56 |
    -------------------------------------------------------------------------------- /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 | ], 43 | 44 | 'beanstalkd' => [ 45 | 'driver' => 'beanstalkd', 46 | 'host' => 'localhost', 47 | 'queue' => 'default', 48 | 'retry_after' => 90, 49 | 'block_for' => 0, 50 | ], 51 | 52 | 'sqs' => [ 53 | 'driver' => 'sqs', 54 | 'key' => env('AWS_ACCESS_KEY_ID'), 55 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 56 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 57 | 'queue' => env('SQS_QUEUE', 'your-queue-name'), 58 | 'suffix' => env('SQS_SUFFIX'), 59 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 60 | ], 61 | 62 | 'redis' => [ 63 | 'driver' => 'redis', 64 | 'connection' => 'default', 65 | 'queue' => env('REDIS_QUEUE', 'default'), 66 | 'retry_after' => 90, 67 | 'block_for' => null, 68 | ], 69 | 70 | ], 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Failed Queue Jobs 75 | |-------------------------------------------------------------------------- 76 | | 77 | | These options configure the behavior of failed queue job logging so you 78 | | can control which database and table are used to store the jobs that 79 | | have failed. You may change them to any database / table you wish. 80 | | 81 | */ 82 | 83 | 'failed' => [ 84 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 85 | 'database' => env('DB_CONNECTION', 'mysql'), 86 | 'table' => 'failed_jobs', 87 | ], 88 | 89 | ]; 90 | -------------------------------------------------------------------------------- /public/locations/index.json: -------------------------------------------------------------------------------- 1 | {"Hồ Chí Minh":{"code":"SG","file_path":"./data/SG.json"},"Hà Nội":{"code":"HN","file_path":"./data/HN.json"},"Đà Nẵng":{"code":"DDN","file_path":"./data/DDN.json"},"Bình Dương":{"code":"BD","file_path":"./data/BD.json"},"Sóc Trăng":{"code":"ST","file_path":"./data/ST.json"},"Kon Tum":{"code":"KT","file_path":"./data/KT.json"},"Quảng Bình":{"code":"QB","file_path":"./data/QB.json"},"Quảng Trị":{"code":"QT","file_path":"./data/QT.json"},"Trà Vinh":{"code":"TV","file_path":"./data/TV.json"},"Hậu Giang":{"code":"HGI","file_path":"./data/HGI.json"},"Sơn La":{"code":"SL","file_path":"./data/SL.json"},"Bạc Liêu":{"code":"BL","file_path":"./data/BL.json"},"Yên Bái":{"code":"YB","file_path":"./data/YB.json"},"Tuyên Quang":{"code":"TQ","file_path":"./data/TQ.json"},"Điện Biên":{"code":"DDB","file_path":"./data/DDB.json"},"Lai Châu":{"code":"LCH","file_path":"./data/LCH.json"},"Lạng Sơn":{"code":"LS","file_path":"./data/LS.json"},"Hà Giang":{"code":"HG","file_path":"./data/HG.json"},"Bắc Kạn":{"code":"BK","file_path":"./data/BK.json"},"Cao Bằng":{"code":"CB","file_path":"./data/CB.json"},"Bắc Giang":{"code":"BG","file_path":"./data/BG.json"},"Hòa Bình":{"code":"HB","file_path":"./data/HB.json"},"An Giang":{"code":"AG","file_path":"./data/AG.json"},"Vĩnh Phúc":{"code":"VP","file_path":"./data/VP.json"},"Tây Ninh":{"code":"TNI","file_path":"./data/TNI.json"},"Thái Nguyên":{"code":"TN","file_path":"./data/TN.json"},"Lào Cai":{"code":"LCA","file_path":"./data/LCA.json"},"Nam Định":{"code":"NDD","file_path":"./data/NDD.json"},"Quảng Ngãi":{"code":"QNG","file_path":"./data/QNG.json"},"Bến Tre":{"code":"BTR","file_path":"./data/BTR.json"},"Đắk Nông":{"code":"DNO","file_path":"./data/DNO.json"},"Cà Mau":{"code":"CM","file_path":"./data/CM.json"},"Vĩnh Long":{"code":"VL","file_path":"./data/VL.json"},"Ninh Bình":{"code":"NB","file_path":"./data/NB.json"},"Phú Thọ":{"code":"PT","file_path":"./data/PT.json"},"Ninh Thuận":{"code":"NT","file_path":"./data/NT.json"},"Phú Yên":{"code":"PY","file_path":"./data/PY.json"},"Hà Nam":{"code":"HNA","file_path":"./data/HNA.json"},"Hà Tĩnh":{"code":"HT","file_path":"./data/HT.json"},"Đồng Tháp":{"code":"DDT","file_path":"./data/DDT.json"},"Đồng Nai":{"code":"DNA","file_path":"./data/DNA.json"},"Khánh Hòa":{"code":"KH","file_path":"./data/KH.json"},"Hải Phòng":{"code":"HP","file_path":"./data/HP.json"},"Long An":{"code":"LA","file_path":"./data/LA.json"},"Quảng Nam":{"code":"QNA","file_path":"./data/QNA.json"},"Bà Rịa Vũng Tàu":{"code":"VT","file_path":"./data/VT.json"},"Đắk Lắk":{"code":"DDL","file_path":"./data/DDL.json"},"Cần Thơ":{"code":"CT","file_path":"./data/CT.json"},"Bình Thuận ":{"code":"BTH","file_path":"./data/BTH.json"},"Lâm Đồng":{"code":"LDD","file_path":"./data/LDD.json"},"Thừa Thiên Huế":{"code":"TTH","file_path":"./data/TTH.json"},"Kiên Giang":{"code":"KG","file_path":"./data/KG.json"},"Bắc Ninh":{"code":"BN","file_path":"./data/BN.json"},"Quảng Ninh":{"code":"QNI","file_path":"./data/QNI.json"},"Thanh Hóa":{"code":"TH","file_path":"./data/TH.json"},"Nghệ An":{"code":"NA","file_path":"./data/NA.json"},"Hải Dương":{"code":"HD","file_path":"./data/HD.json"},"Gia Lai":{"code":"GL","file_path":"./data/GL.json"},"Bình Phước":{"code":"BP","file_path":"./data/BP.json"},"Hưng Yên":{"code":"HY","file_path":"./data/HY.json"},"Bình Định":{"code":"BDD","file_path":"./data/BDD.json"},"Tiền Giang":{"code":"TG","file_path":"./data/TG.json"},"Thái Bình":{"code":"TB","file_path":"./data/TB.json"}} -------------------------------------------------------------------------------- /config/logging.php: -------------------------------------------------------------------------------- 1 | env('LOG_CHANNEL', 'stack'), 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Log Channels 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Here you may configure the log channels for your application. Out of 28 | | the box, Laravel uses the Monolog PHP logging library. This gives 29 | | you a variety of powerful log handlers / formatters to utilize. 30 | | 31 | | Available Drivers: "single", "daily", "slack", "syslog", 32 | | "errorlog", "monolog", 33 | | "custom", "stack" 34 | | 35 | */ 36 | 37 | 'channels' => [ 38 | 'stack' => [ 39 | 'driver' => 'stack', 40 | 'channels' => ['single'], 41 | 'ignore_exceptions' => false, 42 | ], 43 | 44 | 'single' => [ 45 | 'driver' => 'single', 46 | 'path' => storage_path('logs/laravel.log'), 47 | 'level' => 'debug', 48 | ], 49 | 50 | 'daily' => [ 51 | 'driver' => 'daily', 52 | 'path' => storage_path('logs/laravel.log'), 53 | 'level' => 'debug', 54 | 'days' => 14, 55 | ], 56 | 57 | 'slack' => [ 58 | 'driver' => 'slack', 59 | 'url' => env('LOG_SLACK_WEBHOOK_URL'), 60 | 'username' => 'Laravel Log', 61 | 'emoji' => ':boom:', 62 | 'level' => 'critical', 63 | ], 64 | 65 | 'papertrail' => [ 66 | 'driver' => 'monolog', 67 | 'level' => 'debug', 68 | 'handler' => SyslogUdpHandler::class, 69 | 'handler_with' => [ 70 | 'host' => env('PAPERTRAIL_URL'), 71 | 'port' => env('PAPERTRAIL_PORT'), 72 | ], 73 | ], 74 | 75 | 'stderr' => [ 76 | 'driver' => 'monolog', 77 | 'handler' => StreamHandler::class, 78 | 'formatter' => env('LOG_STDERR_FORMATTER'), 79 | 'with' => [ 80 | 'stream' => 'php://stderr', 81 | ], 82 | ], 83 | 84 | 'syslog' => [ 85 | 'driver' => 'syslog', 86 | 'level' => 'debug', 87 | ], 88 | 89 | 'errorlog' => [ 90 | 'driver' => 'errorlog', 91 | 'level' => 'debug', 92 | ], 93 | 94 | 'null' => [ 95 | 'driver' => 'monolog', 96 | 'handler' => NullHandler::class, 97 | ], 98 | 99 | 'emergency' => [ 100 | 'path' => storage_path('logs/laravel.log'), 101 | ], 102 | ], 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Cache Stores 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Here you may define all of the cache "stores" for your application as 29 | | well as their drivers. You may even define multiple stores for the 30 | | same cache driver to group types of items stored in your caches. 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 | ], 50 | 51 | 'file' => [ 52 | 'driver' => 'file', 53 | 'path' => storage_path('framework/cache/data'), 54 | ], 55 | 56 | 'memcached' => [ 57 | 'driver' => 'memcached', 58 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 59 | 'sasl' => [ 60 | env('MEMCACHED_USERNAME'), 61 | env('MEMCACHED_PASSWORD'), 62 | ], 63 | 'options' => [ 64 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 65 | ], 66 | 'servers' => [ 67 | [ 68 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 69 | 'port' => env('MEMCACHED_PORT', 11211), 70 | 'weight' => 100, 71 | ], 72 | ], 73 | ], 74 | 75 | 'redis' => [ 76 | 'driver' => 'redis', 77 | 'connection' => 'cache', 78 | ], 79 | 80 | 'dynamodb' => [ 81 | 'driver' => 'dynamodb', 82 | 'key' => env('AWS_ACCESS_KEY_ID'), 83 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 84 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 85 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 86 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 87 | ], 88 | 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Cache Key Prefix 94 | |-------------------------------------------------------------------------- 95 | | 96 | | When utilizing a RAM based store such as APC or Memcached, there might 97 | | be other applications utilizing the same cache. So, we'll specify a 98 | | value to get prefixed to all our keys so we can avoid collisions. 99 | | 100 | */ 101 | 102 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'), 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /resources/views/applicant/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layout_frontpage.master') 2 | @section('content') 3 |
    4 |
    5 | 6 |
    7 |
    8 |
    9 |
      10 |
    • 11 | {{ $post->remotable_name }} 12 |
    • 13 |
    • 14 | 15 | @if($post->can_parttime) 16 | check 17 | @else 18 | close 19 | @endif 20 | 21 | Part time 22 |
    • 23 | @isset($post->number_applicants) 24 |
    • 25 | close 26 | Private Messages 27 |
    • 28 | @endisset 29 |
    30 | 31 | Get Started 32 | 33 |
    34 |
    35 |
    36 |
    37 |
    38 |

    39 | {{ $post->job_title }} 40 |

    41 |

    42 | {{ $post->salary }} 43 |

    44 |

    45 | Location: {{ $post->location }} 46 | - 47 | 48 | {{ $post->company->name }} 49 | 50 |

    51 | @isset($post->requirement) 52 |
    53 |
    54 |
    55 | 64 |
    65 |
    66 |

    {{ $post->requirement }}

    67 |
    68 |
    69 |
    70 |
    71 |
    72 | @endisset 73 | 74 | @isset($post->file) 75 | 81 | @endisset 82 |
    83 |
    84 | @endsection -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/PostController.php: -------------------------------------------------------------------------------- 1 | model = Post::query(); 35 | $this->table = (new Post())->getTable(); 36 | 37 | View::share('title', ucwords($this->table)); 38 | View::share('table', $this->table); 39 | } 40 | 41 | public function index() 42 | { 43 | $levels = PostLevelEnum::asArray(); 44 | 45 | return view('admin.posts.index', [ 46 | 'levels' => $levels, 47 | ]); 48 | } 49 | 50 | public function create() 51 | { 52 | $configs = SystemConfigController::getAndCache(); 53 | $remotables = PostRemotableEnum::getArrWithoutAll(); 54 | 55 | return view('admin.posts.create', [ 56 | 'currencies' => $configs['currencies'], 57 | 'countries' => $configs['countries'], 58 | 'remotables' => $remotables, 59 | ]); 60 | } 61 | 62 | public function importCsv(Request $request): JsonResponse 63 | { 64 | try { 65 | $levels = $request->input('levels'); 66 | $file = $request->file('file'); 67 | 68 | Excel::import(new PostImport($levels), $file); 69 | 70 | return $this->successResponse(); 71 | } catch (Throwable $e) { 72 | return $this->errorResponse(); 73 | } 74 | } 75 | 76 | public function store(StoreRequest $request) 77 | { 78 | DB::beginTransaction(); 79 | try { 80 | $arr = $request->validated(); 81 | 82 | $companyName = $request->get('company'); 83 | 84 | if (!empty($companyName)) { 85 | $arr['company_id'] = Company::firstOrCreate(['name' => $companyName])->id; 86 | } 87 | if ($request->has('remotable')) { 88 | $arr['remotable'] = $request->get('remotable'); 89 | } 90 | if ($request->has('can_parttime')) { 91 | $arr['can_parttime'] = 1; 92 | } 93 | 94 | $post = Post::create($arr); 95 | $languages = $request->get('languages'); 96 | 97 | foreach ($languages as $language) { 98 | $language = Language::firstOrCreate(['name' => $language]); 99 | ObjectLanguage::create([ 100 | 'object_id' => $post->id, 101 | 'language_id' => $language->id, 102 | 'object_type' => Post::class, 103 | ]); 104 | } 105 | 106 | DB::commit(); 107 | return $this->successResponse(); 108 | } catch (Throwable $e) { 109 | DB::rollBack(); 110 | return $this->errorResponse($e->getMessage()); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | load('company'); 72 | $str = $model->company->name; 73 | $ret = ''; 74 | foreach (explode(' ', $str) as $word) { 75 | $ret .= strtoupper($word); 76 | } 77 | $model->name = $model->id . "-" . $ret; 78 | $model->saveQuietly(); 79 | }); 80 | } 81 | 82 | public function company(): BelongsTo 83 | { 84 | return $this->belongsTo(Company::class); 85 | } 86 | 87 | public function getRoleNameAttribute() 88 | { 89 | return UserRoleEnum::getKeys($this->role)[0]; 90 | } 91 | 92 | public function getGenderNameAttribute() 93 | { 94 | return ($this->gender == 0) ? 'Male' : 'Female'; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /public/locations/data/DNO.json: -------------------------------------------------------------------------------- 1 | {"code":"DNO","name":"Đắk Nông","district":[{"name":"Cư Jút","pre":"Huyện","ward":[{"name":"Cư KNia","pre":"Xã"},{"name":"Đăk Đrông","pre":"Xã"},{"name":"Đăk Wil","pre":"Xã"},{"name":"Ea Pô","pre":"Xã"},{"name":"Ea T'ling","pre":"Thị trấn"},{"name":"Nam Dong","pre":"Xã"},{"name":"Tâm Thắng","pre":"Xã"},{"name":"Trúc Sơn","pre":"Xã"}],"street":["14","Bà Triệu","Hùng Vương","Kim Đồng","Lê Hồng Phong","Liên Tỉnh 5","Nguyễn Tất Thành","Nguyễn Thị Minh Khai","Nguyễn Văn Linh","Phạm Văn Đồng","Quang Trung","Quốc lộ 14","Trần Hưng Đạo","Ybih Aleo"]},{"name":"Dăk GLong","pre":"Huyện","ward":[{"name":"Đắk Ha","pre":"Xã"},{"name":"Đắk PLao","pre":"Xã"},{"name":"Đắk R'Măng","pre":"Xã"},{"name":"Đắk Som","pre":"Xã"},{"name":"Quảng Hòa","pre":"Xã"},{"name":"Quảng Khê","pre":"Thị trấn"},{"name":"Quảng Sơn","pre":"Thị trấn"}],"street":["Bon R'Bút","Quốc lộ 28","Quốc Lộ 28B","Tỉnh Lộ 684","Tỉnh lộ 693"]},{"name":"Dăk Mil","pre":"Huyện","ward":[{"name":"Đắk Gằn","pre":"Xã"},{"name":"Đắk Lao","pre":"Xã"},{"name":"Đắk Mil","pre":"Thị trấn"},{"name":"Đắk N'Drót","pre":"Xã"},{"name":"Đắk R'La","pre":"Xã"},{"name":"Đắk Sắk","pre":"Xã"},{"name":"Đức Mạnh","pre":"Xã"},{"name":"Đức Minh","pre":"Xã"},{"name":"Long Sơn","pre":"Xã"},{"name":"Thuận An","pre":"Xã"}],"street":["14","Đức Tân","Hoàng Diệu","Hùng Vương","Lê Duẩn","Nguyễn Chí Thanh","Nguyễn Trãi","Nơ Trang Gưh","Phan Bội Châu","Quang Trung","Quốc lộ 14","Trần Hưng Đạo"]},{"name":"Dăk R'Lấp","pre":"Huyện","ward":[{"name":"Đắk Ru","pre":"Xã"},{"name":"Đắk Sin","pre":"Xã"},{"name":"Đắk Wer","pre":"Xã"},{"name":"Đạo Nghĩa","pre":"Xã"},{"name":"Hưng Bình","pre":"Xã"},{"name":"Kiến Đức","pre":"Thị trấn"},{"name":"Kiến Thành","pre":"Xã"},{"name":"Nghĩa Thắng","pre":"Xã"},{"name":"Nhân Cơ","pre":"Xã"},{"name":"Nhân Đạo","pre":"Xã"},{"name":"Quảng Tín","pre":"Xã"}],"street":["14","Nguyễn Tất Thành","Quốc lộ 14","Tỉnh Lộ 681","Trần Hưng Đạo"]},{"name":"Dăk Song","pre":"Huyện","ward":[{"name":"Đắk Hoà","pre":"Xã"},{"name":"Đắk Môl","pre":"Xã"},{"name":"Đắk N'Drung","pre":"Xã"},{"name":"Đức An","pre":"Thị trấn"},{"name":"Nam Bình","pre":"Xã"},{"name":"Nâm N'Jang","pre":"Xã"},{"name":"Thuận Hà","pre":"Xã"},{"name":"Thuận Hạnh","pre":"Xã"},{"name":"Trường Xuân","pre":"Xã"}],"street":["Đăk Rung","Quốc lộ 14","Quốc lộ 14C","Tỉnh lộ 4"]},{"name":"Gia Nghĩa","pre":"Thị xã","ward":[{"name":"Đắk Nia","pre":"Xã"},{"name":"Đắk R’Moan","pre":"Xã"},{"name":"Nghĩa Đức","pre":"Phường"},{"name":"Nghĩa Phú","pre":"Phường"},{"name":"Nghĩa Tân","pre":"Phường"},{"name":"Nghĩa Thành","pre":"Phường"},{"name":"Nghĩa Trung","pre":"Phường"},{"name":"Quảng Thành","pre":"Xã"}],"street":["23/3","3/2","An Dương Vương","Bà Triệu","Chu Văn An","D4","Đào Duy Từ","Điện Biên Phủ","Đinh Tiên Hoàng","Hàm Nghi","Hồ Chí Minh","Hùng Vương","Huỳnh Thúc Kháng","Kim Đồng","Lê Duẩn","Lê Hồng Phong","Lê Lai","Lê Lợi","Lê Thánh Tông","Lý Thường Kiệt","Lý Tự Trọng","Mạc Thị Bưởi","N1","N3","Ngô Mây","Ngô Tất Tố","Nguyễn Đức Cảnh","Nguyễn Hữu Thọ","Nguyễn Trãi","Nguyễn Trung Trực","Nguyễn Văn Trỗi","Nhân Cơ","Nơ Trang Long","Phạm Ngọc Thạch","Phan Đình Phùng","Quang Trung","Quốc lộ 14","Quốc lộ 28","Tôn Đức Thắng","Trần Đại Nghĩa","Trần Phú","Vành Đai","Võ Thị Sáu","Vũ Anh Ba","Yniê"]},{"name":"Krông Nô","pre":"Huyện","ward":[{"name":"Buôn Choah","pre":"Xã"},{"name":"Đăk Drô","pre":"Xã"},{"name":"Đăk Mâm","pre":"Thị trấn"},{"name":"Đăk Nang","pre":"Xã"},{"name":"Đăk Sôr","pre":"Xã"},{"name":"Đức Xuyên","pre":"Xã"},{"name":"Nam Đà","pre":"Xã"},{"name":"Nâm N'Đir","pre":"Xã"},{"name":"Nâm Nung","pre":"Xã"},{"name":"Nam Xuân","pre":"Xã"},{"name":"Quảng Phú","pre":"Xã"},{"name":"Tân Thành","pre":"Xã"}],"street":["Hùng Vương","Quốc lộ 28","Tỉnh lộ 4"]},{"name":"Tuy Đức","pre":"Huyện","ward":[{"name":"Đắk Búk So","pre":"Thị trấn"},{"name":"Đắk Ngo","pre":"Xã"},{"name":"Đắk R'Tíh","pre":"Xã"},{"name":"Quảng Tâm","pre":"Xã"},{"name":"Quảng Tân","pre":"Xã"},{"name":"Quảng Trực","pre":"Xã"}],"street":["Quốc lộ 14C"]}]} -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'smtp'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Mailer Configurations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure all of the mailers used by your application plus 24 | | their respective settings. Several examples have been configured for 25 | | you and you are free to add your own as your application requires. 26 | | 27 | | Laravel supports a variety of mail "transport" drivers to be used while 28 | | sending an e-mail. You will specify which one you are using for your 29 | | mailers below. You are free to add additional mailers as required. 30 | | 31 | | Supported: "smtp", "sendmail", "mailgun", "ses", 32 | | "postmark", "log", "array" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 40 | 'port' => env('MAIL_PORT', 587), 41 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 42 | 'username' => env('MAIL_USERNAME'), 43 | 'password' => env('MAIL_PASSWORD'), 44 | 'timeout' => null, 45 | 'auth_mode' => null, 46 | ], 47 | 48 | 'ses' => [ 49 | 'transport' => 'ses', 50 | ], 51 | 52 | 'mailgun' => [ 53 | 'transport' => 'mailgun', 54 | ], 55 | 56 | 'postmark' => [ 57 | 'transport' => 'postmark', 58 | ], 59 | 60 | 'sendmail' => [ 61 | 'transport' => 'sendmail', 62 | 'path' => '/usr/sbin/sendmail -bs', 63 | ], 64 | 65 | 'log' => [ 66 | 'transport' => 'log', 67 | 'channel' => env('MAIL_LOG_CHANNEL'), 68 | ], 69 | 70 | 'array' => [ 71 | 'transport' => 'array', 72 | ], 73 | ], 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Global "From" Address 78 | |-------------------------------------------------------------------------- 79 | | 80 | | You may wish for all e-mails sent by your application to be sent from 81 | | the same address. Here, you may specify a name and address that is 82 | | used globally for all e-mails that are sent by your application. 83 | | 84 | */ 85 | 86 | 'from' => [ 87 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 88 | 'name' => env('MAIL_FROM_NAME', 'Example'), 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Markdown Mail Settings 94 | |-------------------------------------------------------------------------- 95 | | 96 | | If you are using Markdown based email rendering, you may configure your 97 | | theme and component paths here, allowing you to customize the design 98 | | of the emails. Or, you may simply stick with the Laravel defaults! 99 | | 100 | */ 101 | 102 | 'markdown' => [ 103 | 'theme' => 'default', 104 | 105 | 'paths' => [ 106 | resource_path('views/vendor/mail'), 107 | ], 108 | ], 109 | 110 | ]; 111 | --------------------------------------------------------------------------------