Compare commits

..

22 Commits

Author SHA1 Message Date
91e7943546 employee module 2024-04-11 16:37:12 +05:45
b5c603ceec employee crud 2024-04-10 15:15:24 +05:45
d92366b1f4 employee setup 2024-04-10 11:40:07 +05:45
c019fcb02d work on user role module 2024-04-09 18:00:26 +05:45
4eace5b650 Merge branch 'main' of http://bibgit.com/dharmaraj/New-OMIS into omis_dharma 2024-04-07 17:59:16 +05:45
09222c8a3a working on omis setup 2024-04-07 17:59:05 +05:45
6b6696ded4 employee module 2024-04-07 17:39:18 +05:45
4f34db3381 spatie form packages 2024-04-07 13:43:06 +05:45
cfd2147536 leave user employee module setup 2024-04-07 13:13:58 +05:45
da9f493572 Merge branch 'omis_dharma' of ssh://bibgit.com:22022/dharmaraj/New-OMIS 2024-04-07 10:29:00 +05:45
8a9cb39352 employee module fix 2024-04-05 17:56:16 +05:45
dbe6632313 Merge branch 'omis_ranjan' of http://bibgit.com/dharmaraj/New-OMIS into omis_dharma 2024-04-05 11:19:23 +05:45
58d8ee8080 nepalidatepicker added 2024-04-05 11:18:06 +05:45
c792d0a7e0 master crud setup 2024-04-05 11:07:15 +05:45
7d7f7223f6 Merge branch 'main' of http://bibgit.com/dharmaraj/New-OMIS into omis_dharma 2024-04-05 10:57:24 +05:45
73b666affc leave module issue fixes 2024-04-05 10:18:35 +05:45
f4718d7d55 remove leave module 2024-04-05 10:16:48 +05:45
3324d7e3ae Merge branch 'omis_leave' of ssh://bibgit.com:22022/dharmaraj/New-OMIS 2024-04-05 10:15:59 +05:45
d36571ba7a validation added 2024-04-05 10:14:34 +05:45
6717db6f4a Merge branch 'main' of ssh://bibgit.com:22022/dharmaraj/New-OMIS 2024-04-05 10:03:38 +05:45
f7b7d80b87 issues 2024-04-05 10:02:17 +05:45
89d7a82f03 updated 2024-04-04 18:04:56 +05:45
308 changed files with 21375 additions and 573 deletions

18
.htaccess Normal file
View File

@ -0,0 +1,18 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ ^$1 [N]
RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
RewriteRule ^(.*)$ public/$1
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ server.php
</IfModule>

View File

@ -0,0 +1,67 @@
<?php
namespace Modules\Attendance\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class AttendanceController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('attendance::index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('attendance::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
//
}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('attendance::show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('attendance::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
}

View File

View File

@ -0,0 +1,114 @@
<?php
namespace Modules\Attendance\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AttendanceServiceProvider extends ServiceProvider
{
protected string $moduleName = 'Attendance';
protected string $moduleNameLower = 'attendance';
/**
* Boot the application events.
*/
public function boot(): void
{
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->app->register(RouteServiceProvider::class);
}
/**
* Register commands in the format of Command::class
*/
protected function registerCommands(): void
{
// $this->commands([]);
}
/**
* Register command Schedules.
*/
protected function registerCommandSchedules(): void
{
// $this->app->booted(function () {
// $schedule = $this->app->make(Schedule::class);
// $schedule->command('inspire')->hourly();
// });
}
/**
* Register translations.
*/
public function registerTranslations(): void
{
$langPath = resource_path('lang/modules/'.$this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
}
}
/**
* Register config.
*/
protected function registerConfig(): void
{
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config');
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
}
/**
* Register views.
*/
public function registerViews(): void
{
$viewPath = resource_path('views/modules/'.$this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'resources/views');
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
$componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.ltrim(config('modules.paths.generator.component-class.path'), config('modules.paths.app_folder','')));
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path.'/modules/'.$this->moduleNameLower)) {
$paths[] = $path.'/modules/'.$this->moduleNameLower;
}
}
return $paths;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Modules\Attendance\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*/
public function boot(): void
{
parent::boot();
}
/**
* Define the routes for the application.
*/
public function map(): void
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*/
protected function mapWebRoutes(): void
{
Route::middleware('web')->group(module_path('Attendance', '/routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*/
protected function mapApiRoutes(): void
{
Route::middleware('api')->prefix('api')->name('api.')->group(module_path('Attendance', '/routes/api.php'));
}
}

View File

@ -0,0 +1,30 @@
{
"name": "nwidart/attendance",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\Attendance\\": "app/",
"Modules\\Attendance\\Database\\Factories\\": "database/factories/",
"Modules\\Attendance\\Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Modules\\Attendance\\Tests\\": "tests/"
}
}
}

View File

View File

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

View File

@ -0,0 +1,16 @@
<?php
namespace Modules\Attendance\database\seeders;
use Illuminate\Database\Seeder;
class AttendanceDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

View File

@ -0,0 +1,11 @@
{
"name": "Attendance",
"alias": "attendance",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\Attendance\\Providers\\AttendanceServiceProvider"
],
"files": []
}

View File

@ -0,0 +1,15 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.69.5",
"postcss": "^8.3.7",
"vite": "^4.0.0"
}
}

View File

@ -0,0 +1,7 @@
@extends('attendance::layouts.master')
@section('content')
<h1>Hello World</h1>
<p>Module: {!! config('attendance.name') !!}</p>
@endsection

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Attendance Module - {{ config('app.name', 'Laravel') }}</title>
<meta name="description" content="{{ $description ?? '' }}">
<meta name="keywords" content="{{ $keywords ?? '' }}">
<meta name="author" content="{{ $author ?? '' }}">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
{{-- Vite CSS --}}
{{-- {{ module_vite('build-attendance', 'resources/assets/sass/app.scss') }} --}}
</head>
<body>
@yield('content')
{{-- Vite JS --}}
{{-- {{ module_vite('build-attendance', 'resources/assets/js/app.js') }} --}}
</body>

View File

View File

@ -0,0 +1,19 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Attendance\Http\Controllers\AttendanceController;
/*
*--------------------------------------------------------------------------
* API Routes
*--------------------------------------------------------------------------
*
* Here is where you can register API routes for your application. These
* routes are loaded by the RouteServiceProvider within a group which
* is assigned the "api" middleware group. Enjoy building your API!
*
*/
Route::middleware(['auth:sanctum'])->prefix('v1')->group(function () {
Route::apiResource('attendance', AttendanceController::class)->names('attendance');
});

View File

@ -0,0 +1,19 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Attendance\Http\Controllers\AttendanceController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::group([], function () {
Route::resource('attendance', AttendanceController::class)->names('attendance');
});

View File

@ -0,0 +1,26 @@
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
build: {
outDir: '../../public/build-attendance',
emptyOutDir: true,
manifest: true,
},
plugins: [
laravel({
publicDirectory: '../../public',
buildDirectory: 'build-attendance',
input: [
__dirname + '/resources/assets/sass/app.scss',
__dirname + '/resources/assets/js/app.js'
],
refresh: true,
}),
],
});
//export const paths = [
// 'Modules/Attendance/resources/assets/sass/app.scss',
// 'Modules/Attendance/resources/assets/js/app.js',
//];

View File

@ -0,0 +1,156 @@
<?php
namespace Modules\Employee\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Role;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Modules\Employee\Repositories\EmployeeInterface;
use Modules\User\Repositories\UserInterface;
class EmployeeController extends Controller
{
private $employeeRepository;
private $userRepository;
public function __construct(EmployeeInterface $employeeRepository, UserInterface $userRepository)
{
$this->employeeRepository = $employeeRepository;
$this->userRepository = $userRepository;
}
/**
* Display a listing of the resource.
*/
public function index()
{
$data['employees'] = $this->employeeRepository->findAll();
$data['roleLists'] = Role::pluck('name', 'id');
// dd($data['employees']->toArray());
return view('employee::index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Employee';
$data['departmentList'] = [];
$data['designationList'] = [];
$data['genderList'] = [];
$data['nationalityList'] = [];
return view('employee::create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$inputData = $request->all();
try {
if ($request->hasFile('profile_pic')) {
$fileName = time() . '_' . $request->profile_pic->getClientOriginalName();
$filePath = $request->file('profile_pic')->storeAs('uploads', $fileName, 'public');
$inputData['profile_picture'] = time() . '_' . $request->profile_pic->getClientOriginalName();
}
$this->employeeRepository->create($inputData);
toastr()->success('Employee Created Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('employee.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['employee'] = $this->employeeRepository->getEmployeeById($id);
return view('employee::show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Employee';
$data['employee'] = $this->employeeRepository->getEmployeeById($id);
return view('employee::edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
$inputData = $request->except(['_method', '_token']);
try {
if ($request->hasFile('profile_pic')) {
$fileName = time() . '_' . $request->profile_pic->getClientOriginalName();
$filePath = $request->file('profile_pic')->storeAs('uploads', $fileName, 'public');
$inputData['profile_picture'] = time() . '_' . $request->profile_pic->getClientOriginalName();
}
$this->employeeRepository->update($id, $inputData);
toastr()->success('Employee Created Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('employee.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$employeeModel = $this->employeeRepository->getEmployeeById($id);
$employeeModel->user->roles()->detach();
$employeeModel->user->delete();
$employeeModel->delete();
toastr()->success('Employee Delete Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('employee.index');
}
public function assignRole(Request $request)
{
try {
$employeeModel = $this->employeeRepository->getEmployeeByEmail($request->email);
$inputData = [
'name' => $employeeModel->first_name . ' ' . $employeeModel->last_name,
'email' => $request->email,
'password' => Hash::make('password'),
'email_verified_at' => Carbon::now(),
];
$userModel = $this->userRepository->create($inputData, [$request->role_id]);
$employeeModel->users_id = $userModel->id;
$employeeModel->save();
toastr()->success('Role Assigned Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('employee.index');
}
}

View File

View File

@ -0,0 +1,24 @@
<?php
namespace Modules\Employee\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
protected $table = 'tbl_employees';
protected $primaryKey = 'id';
protected $guarded = [];
protected $appends = (['full_name']);
protected function getFullNameAttribute()
{
return $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
}
public function user()
{
return $this->belongsTo(User::class, 'users_id');
}
}

View File

View File

@ -0,0 +1,117 @@
<?php
namespace Modules\Employee\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Modules\Employee\Repositories\EmployeeInterface;
use Modules\Employee\Repositories\EmployeeRepository;
class EmployeeServiceProvider extends ServiceProvider
{
protected string $moduleName = 'Employee';
protected string $moduleNameLower = 'employee';
/**
* Boot the application events.
*/
public function boot(): void
{
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->app->bind(EmployeeInterface::class, EmployeeRepository::class);
$this->app->register(RouteServiceProvider::class);
}
/**
* Register commands in the format of Command::class
*/
protected function registerCommands(): void
{
// $this->commands([]);
}
/**
* Register command Schedules.
*/
protected function registerCommandSchedules(): void
{
// $this->app->booted(function () {
// $schedule = $this->app->make(Schedule::class);
// $schedule->command('inspire')->hourly();
// });
}
/**
* Register translations.
*/
public function registerTranslations(): void
{
$langPath = resource_path('lang/modules/' . $this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
}
}
/**
* Register config.
*/
protected function registerConfig(): void
{
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower . '.php')], 'config');
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
}
/**
* Register views.
*/
public function registerViews(): void
{
$viewPath = resource_path('views/modules/' . $this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'resources/views');
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower . '-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
$componentNamespace = str_replace('/', '\\', config('modules.namespace') . '\\' . $this->moduleName . '\\' . ltrim(config('modules.paths.generator.component-class.path'), config('modules.paths.app_folder', '')));
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
$paths[] = $path . '/modules/' . $this->moduleNameLower;
}
}
return $paths;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Modules\Employee\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*/
public function boot(): void
{
parent::boot();
}
/**
* Define the routes for the application.
*/
public function map(): void
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*/
protected function mapWebRoutes(): void
{
Route::middleware('web')->group(module_path('Employee', '/routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*/
protected function mapApiRoutes(): void
{
Route::middleware('api')->prefix('api')->name('api.')->group(module_path('Employee', '/routes/api.php'));
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace Modules\Employee\Repositories;
interface EmployeeInterface
{
public function findAll();
public function getEmployeeById($employeeId);
public function getEmployeeByEmail($email);
public function delete($employeeId);
public function create($EmployeeDetails);
public function update($employeeId, array $newDetails);
public function pluck();
}

View File

@ -0,0 +1,58 @@
<?php
namespace Modules\Employee\Repositories;
use Modules\Employee\Models\Employee;
class EmployeeRepository implements EmployeeInterface
{
public function findAll()
{
return Employee::paginate(20);
}
public function getEmployeeById($employeeId)
{
return Employee::findOrFail($employeeId);
}
public function getEmployeeByEmail($email)
{
return Employee::where('email', $email)->first();
}
public function delete($employeeId)
{
Employee::destroy($employeeId);
}
public function create($employeeDetails)
{
return Employee::create($employeeDetails);
}
public function update($employeeId, array $newDetails)
{
return Employee::whereId($employeeId)->update($newDetails);
}
public function pluck()
{
return Employee::pluck('first_name', 'id');
}
// public function uploadImage($file)
// {
// if ($req->file()) {
// $fileName = time() . '_' . $req->file->getClientOriginalName();
// $filePath = $req->file('file')->storeAs('uploads', $fileName, 'public');
// $fileModel->name = time() . '_' . $req->file->getClientOriginalName();
// $fileModel->file_path = '/storage/' . $filePath;
// $fileModel->save();
// return back()
// ->with('success', 'File has been uploaded.')
// ->with('file', $fileName);
// }
// }
}

View File

@ -0,0 +1,30 @@
{
"name": "nwidart/employee",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\Employee\\": "app/",
"Modules\\Employee\\Database\\Factories\\": "database/factories/",
"Modules\\Employee\\Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Modules\\Employee\\Tests\\": "tests/"
}
}
}

View File

View File

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

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('tbl_employees', function (Blueprint $table) {
$table->id();
$table->string('first_name')->nullable();
$table->string('middle_name')->nullable();
$table->string('last_name')->nullable();
$table->string('email')->nullable();
$table->date('nepali_dob')->nullable();
$table->date('dob')->nullable();
$table->string('signature')->nullable();
$table->string('father_name')->nullable();
$table->string('contact')->nullable();
$table->string('profile_picture')->nullable();
$table->unsignedBigInteger('genders_id')->nullable();
$table->unsignedBigInteger('nationalities_id')->nullable();
$table->unsignedBigInteger('users_id')->nullable();
$table->integer('is_user_assigned')->nullable()->default(10);
$table->unsignedBigInteger('organization_id')->nullable();
$table->unsignedBigInteger('department_id')->nullable();
$table->unsignedBigInteger('designation_id')->nullable();
$table->text('permanent_address')->nullable();
$table->text('temporary_address')->nullable();
$table->string('status')->nullable()->default(11);
$table->string('remarks')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('employees');
}
};

View File

@ -0,0 +1,16 @@
<?php
namespace Modules\Employee\database\seeders;
use Illuminate\Database\Seeder;
class EmployeeDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

View File

@ -0,0 +1,11 @@
{
"name": "Employee",
"alias": "employee",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\Employee\\Providers\\EmployeeServiceProvider"
],
"files": []
}

View File

@ -0,0 +1,15 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.69.5",
"postcss": "^8.3.7",
"vite": "^4.0.0"
}
}

View File

@ -0,0 +1,23 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
@include('layouts.partials.breadcrumb', ['title' => $title])
<!-- end page title -->
{{ html()->form('POST')->route('employee.store')->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data'])->open() }}
@include('employee::partials.action')
{{ html()->form()->close() }}
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,23 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
@include('layouts.partials.breadcrumb', ['title' => $title])
<!-- end page title -->
{{ html()->modelForm($employee, 'PUT')->route('employee.update', $employee->id)->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data'])->open() }}
@include('employee::partials.action')
{{ html()->closeModelForm() }}
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,215 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
@include('layouts.partials.breadcrumb', ['title' => 'Employee'])
<!-- end page title -->
<div class="card">
<div class="card-body">
<div class="row g-2">
<div class="col-sm-4">
<div class="search-box">
<input type="text" class="form-control" id="searchMemberList" placeholder="Search for name...">
<i class="ri-search-line search-icon"></i>
</div>
</div>
<!--end col-->
<div class="col-sm-auto ms-auto">
<div class="list-grid-nav hstack gap-1">
<a class="btn btn-success" href="{{ route('employee.create') }}"><i
class="ri-add-fill me-1 align-bottom"></i> Create Employee</a>
</div>
</div>
<!--end col-->
</div>
<!--end row-->
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div>
<div id="teamlist">
<div class="team-list row grid-view-filter" id="team-member-list">
@forelse ($employees as $employee)
<div class="col">
<div class="card team-box ribbon-box mb-lg-0 material-shadow border shadow-none">
<div class="team-cover"> <img src="assets/images/small/img-9.jpg" alt="" class="img-fluid">
</div>
<div class="card-body p-4">
@if ($employee->user)
<div class="ribbon-two ribbon-two-success">
<span>{{ optional($employee->user)->getRoleNames()->first() }}</span>
</div>
@endif
<div class="row align-items-center team-row">
<div class="col team-settings">
<div class="row">
<div class="col">
</div>
<div class="col dropdown text-end"> <a href="javascript:void(0);" data-bs-toggle="dropdown"
aria-expanded="false" class=""> <i class="ri-more-fill fs-17"></i> </a>
<ul class="dropdown-menu dropdown-menu-end" style="">
<li><a class="dropdown-item remove-item-btn" href="javascript:void(0);"
data-link="{{ route('employee.destroy', $employee->id) }}"
data-id="{{ $employee->id }}"><i
class="ri-delete-bin-5-line text-muted me-2 align-bottom"></i>Delete</a></li>
</ul>
</div>
</div>
</div>
<div class="col-lg-4 col">
<div class="team-profile-img">
<div class="avatar-lg img-thumbnail rounded-circle flex-shrink-0"><img
src="{{ asset('app/public/uploads/' . $employee->profile_picture) }}" alt=""
class="member-img img-fluid d-block rounded-circle"></div>
<div class="team-content"> <a class="member-name"
href="{{ route('employee.show', $employee->id) }}">
<h5 class="fs-16 mb-1">{{ $employee->first_name }}</h5>
</a>
<p class="text-muted member-designation mb-0">Bibhuti</p>
</div>
</div>
</div>
{{-- <div class="col-lg-4 col">
<div class="row text-muted text-center">
<div class="col-6 border-end border-end-dashed">
<h5 class="projects-num mb-1">225</h5>
<p class="text-muted mb-0">Projects</p>
</div>
<div class="col-6">
<h5 class="tasks-num mb-1">197</h5>
<p class="text-muted mb-0">Tasks</p>
</div>
</div>
</div> --}}
<div class="col-lg-2 col">
<ul class="list-inline mb-0 text-center">
<li class="list-inline-item avatar-xs">
<a href="{{ route('employee.edit', $employee->id) }}"
class="avatar-title bg-info-subtle text-info fs-15 rounded">
<i class="ri-edit-line"></i>
</a>
</li>
<li class="list-inline-item avatar-xs">
<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#assignRoleModal"
data-email="{{ $employee->email }}"
class="avatar-title bg-primary-subtle text-primary fs-15 rounded">
<i class="ri-user-add-line"></i>
</a>
</li>
<li class="list-inline-item avatar-xs">
<a href="javascript:void(0);" data-bs-toggle="modal" data-bs-target="#changePasswordModal"
class="avatar-title bg-danger-subtle text-danger fs-15 rounded">
<i class="ri-lock-unlock-line"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
@endforeach
<div class="d-flex justify-content-end align-self-end">
<div class="mt-2 p-2">
{{ $employees->links() }}
</div>
</div>
</div>
</div>
</div>
</div><!-- end col -->
</div>
<!--end row-->
</div><!-- container-fluid -->
</div>
<div class="modal fade" id="assignRoleModal" tabindex="-1" aria-labelledby="assignRoleLabel" aria-modal="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header model-primary">
<h5 class="modal-title" id="exampleModalgridLabel">Assign Role</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{{ html()->form('POST')->route('employee.assignRole')->class(['needs-validation'])->attributes(['novalidate'])->open() }}
<div class="row gy-2">
<div class="col-lg-12">
{{ html()->label('Email')->class('form-label') }}
{{ html()->email('email')->class('form-control email-field')->placeholder('Enter Email')->isReadonly(true)->required() }}
</div>
<div class="col-lg-12">
{{ html()->label('Role')->class('form-label') }}
{{ html()->select('role_id', $roleLists)->class('form-select')->placeholder('Select Role')->required() }}
</div>
</div>
<div class="mt-4 text-end">
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
{{ html()->form()->close() }}
</div>
</div>
</div>
</div>
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordLabel"
aria-modal="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header model-primary">
<h5 class="modal-title" id="exampleModalgridLabel">Change Password</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="{{ route('leave.store') }}" class="needs-validation" novalidate method="post">
<div class="row gy-2">
<div class="col-lg-12">
{{ html()->label('New Password')->class('form-label') }}
{{ html()->text('password')->class('form-control')->placeholder('Enter New Password')->required() }}
</div>
<div class="col-lg-12">
{{ html()->label('Confirm New Password')->class('form-label') }}
{{ html()->text('confirm_password')->class('form-control')->placeholder('Enter Confirm New Password')->required() }}
</div>
</div>
<div class="mt-4 text-end">
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@push('js')
<script>
$(document).ready(function() {
$('#assignRoleModal').on('shown.bs.modal', function(e) {
// do something...
var email = $(e.relatedTarget).data('email');
$('.email-field').val(email)
console.log(email);
})
})
</script>
@endpush

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Employee Module - {{ config('app.name', 'Laravel') }}</title>
<meta name="description" content="{{ $description ?? '' }}">
<meta name="keywords" content="{{ $keywords ?? '' }}">
<meta name="author" content="{{ $author ?? '' }}">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
{{-- Vite CSS --}}
{{-- {{ module_vite('build-employee', 'resources/assets/sass/app.scss') }} --}}
</head>
<body>
@yield('content')
{{-- Vite JS --}}
{{-- {{ module_vite('build-employee', 'resources/assets/js/app.js') }} --}}
</body>

View File

@ -0,0 +1,124 @@
<div class="row">
<div class="col-lg-12">
<div class="card">
{{-- <div class="card-header card-primary">
<h4 class="card-title mb-0">Personal Details</h4>
</div> --}}
<div class="card-body">
<div class="row gy-1">
<p class="text-primary">Personal Details</p>
<hr>
<div class="col-md-4">
{{ html()->label('First name')->class('form-label') }}
{{ html()->text('first_name')->class('form-control')->placeholder('Enter First Name')->required() }}
</div>
<div class="col-md-4">
{{ html()->label('Middle name')->class('form-label') }}
{{ html()->text('middle_name')->class('form-control')->placeholder('Enter Middle Name') }}
</div>
<div class="col-md-4">
{{ html()->label('Last name')->class('form-label') }}
{{ html()->text('last_name')->class('form-control')->placeholder('Enter Last Name')->required() }}
{{ html()->div('Please enter last name')->class('invalid-feedback') }}
</div>
<div class="col-md-4">
{{ html()->label('Gender')->class('form-label') }}
{{ html()->select('genders_id', [1 => 'male', 2 => 'female'])->class('form-select')->placeholder('Select Gender') }}
</div>
<div class="col-md-4">
{{ html()->label('Date of Birth')->class('form-label') }}
{{ html()->date('dob')->class('form-control')->placeholder('Choose Date of Birth')->required() }}
{{ html()->div('Please choose dob')->class('invalid-feedback') }}
</div>
<div class="col-md-4">
{{ html()->label('Nationality')->class('form-label') }}
{{ html()->select('nationalities_id', [1 => 'Nepal', 2 => 'Other'])->class('form-control')->placeholder('Select Nationality') }}
</div>
<div class="col-md-4">
{{ html()->label('Email')->class('form-label') }}
{{ html()->email('email')->class('form-control')->placeholder('Enter Email')->required() }}
{{ html()->div('Please enter email')->class('invalid-feedback') }}
</div>
<div class="col-md-4">
{{ html()->label('Phone Number')->class('form-label') }}
{{ html()->text('contact')->class('form-control')->placeholder('Enter Phone Number') }}
</div>
<div class="col-md-4">
{{ html()->label('Upload Profile Pic')->class('form-label') }}
{{ html()->file('profile_pic')->class('form-control') }}
</div>
</div>
<div class="row gy-1 mt-1">
<p class="text-primary">Address Details</p>
<hr>
{{-- <div class="col-md-4">
{{ html()->label('Municipality')->class('form-label') }}
{{ html()->select('municipality_id', [])->class('form-select')->placeholder('Select Municipality') }}
</div>
<div class="col-md-4">
{{ html()->label('Ward')->class('form-label') }}
{{ html()->text('ward')->class('form-control')->placeholder('Enter Ward no') }}
</div> --}}
<div class="col-md-4">
{{ html()->label('Permanent Address')->class('form-label') }}
{{ html()->text('permanent_address')->class('form-control')->placeholder('Enter Permanent Address') }}
</div>
<div class="col-md-4">
{{ html()->label('Temporary Address')->class('form-label') }}
{{ html()->text('temporary_address')->class('form-control')->placeholder('Enter Temporary Address') }}
</div>
</div>
<div class="row gy-1 mt-1">
<p class="text-primary">Organization Details</p>
<hr>
<div class="col-md-4">
{{ html()->label('Department')->class('form-label') }}
{{ html()->select('department_id', ['Nepal'])->class('form-select')->placeholder('Select Department') }}
</div>
<div class="col-md-4">
{{ html()->label('Designation')->class('form-label') }}
{{ html()->select('designation_id', ['Nepal'])->class('form-select')->placeholder('Select Designation') }}
</div>
{{-- <div class="col-md-4">
{{ html()->label('Join Date')->class('form-label') }}
{{ html()->date('join_date')->class('form-control')->placeholder('Choose Join Date') }}
</div> --}}
<div class="col-md-8">
{{ html()->label('Remarks')->class('form-label') }}
{{ html()->textarea('remarks')->class('form-control')->placeholder('Enter Remarks') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mb-4 text-end">
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
</div>
</div>

View File

@ -0,0 +1,128 @@
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header card-primary">
<h4 class="card-title mb-0">Personal Details</h4>
</div>
<div class="card-body row gy-4">
<div class="col-md-4">
{{ html()->label('First name')->class('form-label') }}
{{ html()->text('first_name')->class('form-control')->placeholder('Enter First Name')->required() }}
</div>
<div class="col-md-4">
{{ html()->label('Middle name')->class('form-label') }}
{{ html()->text('middle_name')->class('form-control')->placeholder('Enter Middle Name') }}
</div>
<div class="col-md-4">
{{ html()->label('Last name')->class('form-label') }}
{{ html()->text('last_name')->class('form-control')->placeholder('Enter Last Name')->required() }}
{{ html()->div('Please enter last name')->class('invalid-feedback') }}
</div>
<div class="col-md-4">
{{ html()->label('Gender')->class('form-label') }}
{{ html()->select('gender', ['male', 'female'])->class('form-select')->placeholder('Select Gender') }}
</div>
<div class="col-md-4">
{{ html()->label('Date of Birth')->class('form-label') }}
{{ html()->date('dob')->class('form-control')->placeholder('Choose Date of Birth')->required() }}
{{ html()->div('Please choose dob')->class('invalid-feedback') }}
</div>
<div class="col-md-4">
{{ html()->label('Nationality')->class('form-label') }}
{{ html()->select('nationality', ['Nepal', 'Other'])->class('form-control')->placeholder('Select Nationality') }}
</div>
<div class="col-md-4">
{{ html()->label('Email')->class('form-label') }}
{{ html()->email('email')->class('form-control')->placeholder('Enter Email')->required() }}
{{ html()->div('Please enter email')->class('invalid-feedback') }}
</div>
<div class="col-md-4">
{{ html()->label('Phone Number')->class('form-label') }}
{{ html()->text('phone')->class('form-control')->placeholder('Enter Phone Number') }}
</div>
<div class="col-md-4">
{{ html()->label('Upload Profile Pic')->class('form-label') }}
{{ html()->file('profile_pic')->class('form-control') }}
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="card">
<div class="card-header card-primary">
<h5 class="card-title mb-0">Address Detail</h5>
</div>
<div class="card-body row gy-2">
<div class="col-md-4">
{{ html()->label('Municipality')->class('form-label') }}
{{ html()->select('municipality_id', [])->class('form-select')->placeholder('Select Municipality') }}
</div>
<div class="col-md-4">
{{ html()->label('Ward')->class('form-label') }}
{{ html()->text('ward')->class('form-control')->placeholder('Enter Ward no') }}
</div>
<div class="col-md-4">
{{ html()->label('Permanent Address')->class('form-label') }}
{{ html()->text('perm_address')->class('form-control')->placeholder('Enter Permanent Address') }}
</div>
<div class="col-md-4">
{{ html()->label('Temporary Address')->class('form-label') }}
{{ html()->text('temp_address')->class('form-control')->placeholder('Enter Temporary Address') }}
</div>
</div>
</div>
<div class="card">
<div class="card-header card-primary">
<h5 class="card-title mb-0">Organization Detail</h5>
</div>
<div class="card-body row gy-2">
<div class="col-md-4">
{{ html()->label('Department')->class('form-label') }}
{{ html()->select('department_id', ['Nepal'])->class('form-select')->placeholder('Select Department') }}
</div>
<div class="col-md-4">
{{ html()->label('Designation')->class('form-label') }}
{{ html()->select('designation_id', ['Nepal'])->class('form-select')->placeholder('Select Designation') }}
</div>
<div class="col-md-4">
{{ html()->label('Join Date')->class('form-label') }}
{{ html()->date('join_date')->class('form-control')->placeholder('Choose Join Date') }}
</div>
<div class="col-md-8">
{{ html()->label('Remarks')->class('form-label') }}
{{ html()->textarea('remark')->class('form-control')->placeholder('Enter Remarks') }}
</div>
</div>
</div>
<!-- end card -->
<div class="mb-4 text-end">
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,19 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Employee\Http\Controllers\EmployeeController;
/*
*--------------------------------------------------------------------------
* API Routes
*--------------------------------------------------------------------------
*
* Here is where you can register API routes for your application. These
* routes are loaded by the RouteServiceProvider within a group which
* is assigned the "api" middleware group. Enjoy building your API!
*
*/
Route::middleware(['auth:sanctum'])->prefix('v1')->group(function () {
Route::apiResource('employee', EmployeeController::class)->names('employee');
});

View File

@ -0,0 +1,25 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Employee\Http\Controllers\EmployeeController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::group(['middleware' => 'auth'], function () {
Route::post('assignRole', [EmployeeController::class, 'assignRole'])->name('employee.assignRole');
Route::resource('employee', EmployeeController::class)->names('employee');
Route::group(['prefix' => 'employee'], function () {
});
});

View File

@ -0,0 +1,26 @@
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
build: {
outDir: '../../public/build-employee',
emptyOutDir: true,
manifest: true,
},
plugins: [
laravel({
publicDirectory: '../../public',
buildDirectory: 'build-employee',
input: [
__dirname + '/resources/assets/sass/app.scss',
__dirname + '/resources/assets/js/app.js'
],
refresh: true,
}),
],
});
//export const paths = [
// 'Modules/Employee/resources/assets/sass/app.scss',
// 'Modules/Employee/resources/assets/js/app.js',
//];

View File

@ -5,15 +5,25 @@ namespace Modules\Leave\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\Employee\Repositories\EmployeeInterface;
use Modules\Leave\Repositories\LeaveInterface;
use Yoeunes\Toastr\Facades\Toastr;
class LeaveController extends Controller
{
private LeaveInterface $leaveRepository;
private $leaveRepository;
private $employeeRepository;
public function __construct(LeaveInterface $leaveRepository)
public function __construct(LeaveInterface $leaveRepository, EmployeeInterface $employeeRepository)
{
$this->leaveRepository = $leaveRepository;
$this->employeeRepository = $employeeRepository;
$this->middleware('role_or_permission:access leaves|create leaves|edit leaves|delete leaves', ['only' => ['index', 'show']]);
$this->middleware('role_or_permission:create leaves', ['only' => ['create', 'store']]);
$this->middleware('role_or_permission:edit leaves', ['only' => ['edit', 'update']]);
$this->middleware('role_or_permission:delete leaves', ['only' => ['destroy']]);
}
/**
@ -22,8 +32,9 @@ class LeaveController extends Controller
public function index()
{
$data['leaves'] = $this->leaveRepository->findAll();
// dd($data['leaves']);
return view('leave::index');
$data['employeeList'] = $this->employeeRepository->pluck();
return view('leave::index', $data);
}
/**
@ -32,6 +43,7 @@ class LeaveController extends Controller
public function create()
{
$data['title'] = 'Create Leave';
$data['employeeList'] = $this->employeeRepository->pluck();
return view('leave::create', $data);
}
@ -63,7 +75,11 @@ class LeaveController extends Controller
*/
public function edit($id)
{
return view('leave::edit');
$data['title'] = 'Edit Leave';
$data['leave'] = $this->leaveRepository->getLeaveById($id);
return view('leave::edit', $data);
}
/**
@ -71,7 +87,16 @@ class LeaveController extends Controller
*/
public function update(Request $request, $id): RedirectResponse
{
//
$inputData = $request->all();
try {
$this->leaveRepository->update($id, $inputData);
toastr()->success('Leave Updated Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('leave.index');
}
/**
@ -79,6 +104,8 @@ class LeaveController extends Controller
*/
public function destroy($id)
{
//
$this->leaveRepository->delete($id);
toastr()->success('Leave Deleted Succesfully');
}
}

View File

@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
class Leave extends Model
{
protected $table = 'leaves';
protected $primaryKey = 'leave_id';
protected $guarded = [];
}

View File

@ -28,7 +28,7 @@ class LeaveRepository implements LeaveInterface
public function update($leaveId, array $newDetails)
{
return Leave::whereId($leaveId)->update($newDetails);
return Leave::where('leave_id',$leaveId)->update($newDetails);
}
}

View File

@ -4,21 +4,7 @@
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">{{ $title }}</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);">Dashboards</a></li>
<li class="breadcrumb-item active">{{ $title }}</li>
</ol>
</div>
</div>
</div>
</div>
@include('layouts.partials.breadcrumb', ['title' => $title])
<!-- end page title -->
<div class="row">
<div class="col-lg-8">
@ -38,3 +24,7 @@
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,47 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">{{ $title }}</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);">Dashboards</a></li>
<li class="breadcrumb-item active">{{ $title }}</li>
</ol>
</div>
</div>
</div>
</div>
<!-- end page title -->
<div class="row">
<div class="col-lg-8">
<div class="card">
<div class="card-body">
{{ html()->modelForm($leave, 'PUT')->route('leave.update', $leave->id)->class(['needs-validation'])->attributes(['novalidate'])->open() }}
@include('leave::partials.action')
{{ html()->closeModelForm() }}
</div>
</div>
</div>
</div>
<!--end row-->
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -56,243 +56,53 @@
<div class="card-body">
<div class="table-responsive">
<table id="buttons-datatables" class="display table-bordered table" style="width:100%">
<table id="buttons-datatables" class="display table-sm table-bordered table" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
<th>S.N</th>
<th>Employee Name</th>
<th>Start Date</th>
<th>End Date</th>
<th>Created At</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@forelse ($leaves as $key => $leave)
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>Garrett Winters</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>63</td>
<td>2011/07/25</td>
<td>$170,750</td>
</tr>
<tr>
<td>Ashton Cox</td>
<td>Junior Technical Author</td>
<td>San Francisco</td>
<td>66</td>
<td>2009/01/12</td>
<td>$86,000</td>
</tr>
<tr>
<td>Cedric Kelly</td>
<td>Senior Javascript Developer</td>
<td>Edinburgh</td>
<td>22</td>
<td>2012/03/29</td>
<td>$433,060</td>
</tr>
<tr>
<td>Airi Satou</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>33</td>
<td>2008/11/28</td>
<td>$162,700</td>
</tr>
<tr>
<td>Brielle Williamson</td>
<td>Integration Specialist</td>
<td>New York</td>
<td>61</td>
<td>2012/12/02</td>
<td>$372,000</td>
</tr>
<tr>
<td>Herrod Chandler</td>
<td>Sales Assistant</td>
<td>San Francisco</td>
<td>59</td>
<td>2012/08/06</td>
<td>$137,500</td>
</tr>
<tr>
<td>Rhona Davidson</td>
<td>Integration Specialist</td>
<td>Tokyo</td>
<td>55</td>
<td>2010/10/14</td>
<td>$327,900</td>
</tr>
<tr>
<td>Colleen Hurst</td>
<td>Javascript Developer</td>
<td>San Francisco</td>
<td>39</td>
<td>2009/09/15</td>
<td>$205,500</td>
</tr>
<tr>
<td>Sonya Frost</td>
<td>Software Engineer</td>
<td>Edinburgh</td>
<td>23</td>
<td>2008/12/13</td>
<td>$103,600</td>
</tr>
<tr>
<td>Jena Gaines</td>
<td>Office Manager</td>
<td>London</td>
<td>30</td>
<td>2008/12/19</td>
<td>$90,560</td>
</tr>
<tr>
<td>Quinn Flynn</td>
<td>Support Lead</td>
<td>Edinburgh</td>
<td>22</td>
<td>2013/03/03</td>
<td>$342,000</td>
</tr>
<tr>
<td>Charde Marshall</td>
<td>Regional Director</td>
<td>San Francisco</td>
<td>36</td>
<td>2008/10/16</td>
<td>$470,600</td>
</tr>
<tr>
<td>Haley Kennedy</td>
<td>Senior Marketing Designer</td>
<td>London</td>
<td>43</td>
<td>2012/12/18</td>
<td>$313,500</td>
</tr>
<tr>
<td>Tatyana Fitzpatrick</td>
<td>Regional Director</td>
<td>London</td>
<td>19</td>
<td>2010/03/17</td>
<td>$385,750</td>
</tr>
<tr>
<td>Michael Silva</td>
<td>Marketing Designer</td>
<td>London</td>
<td>66</td>
<td>2012/11/27</td>
<td>$198,500</td>
</tr>
<tr>
<td>Paul Byrd</td>
<td>Chief Financial Officer (CFO)</td>
<td>New York</td>
<td>64</td>
<td>2010/06/09</td>
<td>$725,000</td>
</tr>
<tr>
<td>Gloria Little</td>
<td>Systems Administrator</td>
<td>New York</td>
<td>59</td>
<td>2009/04/10</td>
<td>$237,500</td>
</tr>
<tr>
<td>Bradley Greer</td>
<td>Software Engineer</td>
<td>London</td>
<td>41</td>
<td>2012/10/13</td>
<td>$132,000</td>
</tr>
<tr>
<td>Dai Rios</td>
<td>Personnel Lead</td>
<td>Edinburgh</td>
<td>35</td>
<td>2012/09/26</td>
<td>$217,500</td>
</tr>
<tr>
<td>Jenette Caldwell</td>
<td>Development Lead</td>
<td>New York</td>
<td>30</td>
<td>2011/09/03</td>
<td>$345,000</td>
</tr>
<tr>
<td>Yuri Berry</td>
<td>Chief Marketing Officer (CMO)</td>
<td>New York</td>
<td>40</td>
<td>2009/06/25</td>
<td>$675,000</td>
</tr>
<tr>
<td>Caesar Vance</td>
<td>Pre-Sales Support</td>
<td>New York</td>
<td>21</td>
<td>2011/12/12</td>
<td>$106,450</td>
</tr>
<tr>
<td>Doris Wilder</td>
<td>Sales Assistant</td>
<td>Sydney</td>
<td>23</td>
<td>2010/09/20</td>
<td>$85,600</td>
</tr>
<td>{{ $key + 1 }}</td>
<td>{{ $leave->employee_id }}</td>
<td>{{ $leave->start_date }}</td>
<td>{{ $leave->end_date }}</td>
<td>{{ $leave->created_at }}</td>
<td>
<div class="hstack flex-wrap gap-3">
<a href="javascript:void(0);" class="link-info fs-15 view-item-btn" data-bs-toggle="modal"
data-bs-target="#viewModal">
<i class="ri-eye-line"></i>
</a>
<a href="{{ route('leave.edit', $leave->leave_id) }}"
class="link-success fs-15 edit-item-btn"><i class="ri-edit-2-line"></i></a>
<tr>
<td>Gavin Cortez</td>
<td>Team Leader</td>
<td>San Francisco</td>
<td>22</td>
<td>2008/10/26</td>
<td>$235,500</td>
</tr>
<tr>
<td>Martena Mccray</td>
<td>Post-Sales support</td>
<td>Edinburgh</td>
<td>46</td>
<td>2011/03/09</td>
<td>$324,050</td>
</tr>
<tr>
<td>Unity Butler</td>
<td>Marketing Designer</td>
<td>San Francisco</td>
<td>47</td>
<td>2009/12/09</td>
<td>$85,675</td>
<a href="javascript:void(0);" data-link="{{ route('leave.destroy', $leave->leave_id) }}"
data-id="{{ $leave->leave_id }}" class="link-danger fs-15 remove-item-btn"><i
class="ri-delete-bin-line"></i></a>
</div>
</td>
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div><!--end row-->
</div>
<!--end row-->
</div>
</div>
<!-- container-fluid -->
</div>
@include('leave::partials.view')
@endsection

View File

@ -1,28 +1,23 @@
<div class="mb-3">
<label for="employeeName" class="form-label">Employee Name</label>
<input type="text" class="form-control" id="employeeName" placeholder="Enter employee name" name="employeeName" required>
<div class="invalid-feedback">
Please enter employee name.
</div>
<label for="employee_id" class="form-label">Employee Name</label>
{{ html()->select('employee_id', $employeeList)->class('form-select')->placeholder('Select Employee') }}
</div>
<div class="mb-3">
<label for="employeeUrl" class="form-label">Employee Department URL</label>
<input type="url" class="form-control" id="employeeUrl" placeholder="Enter emploree url" name="employeeUrl">
<label for="start_date" class="form-label">Start Leave Date</label>
<input type="date" class="form-control" id="start_date" name="start_date"
value="{{ old('start_date', $leave->start_date ?? '') }}">
</div>
<div class="mb-3">
<label for="StartleaveDate" class="form-label">Start Leave Date</label>
<input type="date" class="form-control" id="StartleaveDate" name="start_date">
</div>
<div class="mb-3">
<label for="EndleaveDate" class="form-label">End Leave Date</label>
<input type="date" class="form-control" id="EndleaveDate" name="end_date">
</div>
<div class="mb-3">
<label for="VertimeassageInput" class="form-label">Message</label>
<textarea class="form-control" id="VertimeassageInput" rows="3" placeholder="Enter your message" name="remark"></textarea>
<label for="end_date" class="form-label">End Leave Date</label>
<input type="date" class="form-control" id="end_date" name="end_date"
value="{{ old('end_date', $leave->end_date ?? '') }}">
</div>
<div class="text-end">
<button type="submit" class="btn btn-primary">Add Leave</button>
<button type="submit" class="btn btn-primary">{{ isset($leave) ? 'Update' : 'Add Leave' }}</button>
</div>
@push('js')

View File

@ -0,0 +1,16 @@
<div class="modal fade" id="viewModal" tabindex="-1" aria-labelledby="viewModalLabel" aria-modal="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalgridLabel">View Leave</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="{{ route('leave.store') }}" class="needs-validation" novalidate method="post">
@csrf
@include('leave::partials.action')
</form>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,93 @@
<?php
namespace Modules\User\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Modules\User\Repositories\RoleRepository;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RoleController extends Controller
{
private $roleRepository;
public function __construct(RoleRepository $roleRepository){
$this->roleRepository = $roleRepository;
}
/**
* Display a listing of the resource.
*/
public function index()
{
$data['roles'] = $this->roleRepository->findAll();
$data['editable'] = false;
return view('user::role.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['permissions'] = Permission::get();
$data['title'] = "Create Role";
return view('user::role.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate(['name' => 'required']);
$role = $this->roleRepository->create($request->all());
$role->syncPermissions($request->permissions);
toastr()->success('New role has been created!');
return redirect()->route('role.index');
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Role $role)
{
$data['permissions'] = Permission::get();
$data['role'] = $role;
$data['title'] = "Edit Role";
return view('user::role.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Role $role)
{
$role->update(['name' => $request->name]);
$role->syncPermissions($request->permissions);
toastr()->success('Role has been updated!');
return redirect()->route('role.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Role $role)
{
$role->delete();
toastr()->success('Role has been deleted!');
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace Modules\User\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\User\Repositories\UserRepository;
class UserController extends Controller
{
/**
* Display a listing of the resource.
*/
protected $userRepository;
public function __construct(UserRepository $userRepository){
$this->userRepository = $userRepository;
}
public function index()
{
$data['editable'] = false;
$data['users'] = $this->userRepository->findAll();
return view('user::user.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = "Create User";
return view('user::user.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$validatedData = $request->validate([
'name' => 'required|min:5',
'email' => 'required',
'password' => 'required',
]);
$user = $this->userRepository->create($validatedData, $request->role);
toastr()->success('User has been created!');
return redirect()->route('user.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['user'] = $this->userRepository->getUserById($id);
return view('user::user.show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = "Edit User";
$data['user'] = $this->userRepository->getUserById($id);
return view('user::user.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
}

View File

View File

View File

View File

@ -0,0 +1,49 @@
<?php
namespace Modules\User\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*/
public function boot(): void
{
parent::boot();
}
/**
* Define the routes for the application.
*/
public function map(): void
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*/
protected function mapWebRoutes(): void
{
Route::middleware('web')->group(module_path('User', '/routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*/
protected function mapApiRoutes(): void
{
Route::middleware('api')->prefix('api')->name('api.')->group(module_path('User', '/routes/api.php'));
}
}

View File

@ -0,0 +1,120 @@
<?php
namespace Modules\User\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Modules\User\Repositories\RoleInterface;
use Modules\User\Repositories\RoleRepository;
use Modules\User\Repositories\UserInterface;
use Modules\User\Repositories\UserRepository;
class UserServiceProvider extends ServiceProvider
{
protected string $moduleName = 'User';
protected string $moduleNameLower = 'user';
/**
* Boot the application events.
*/
public function boot(): void
{
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->app->bind(UserInterface::class, UserRepository::class);
$this->app->bind(RoleInterface::class, RoleRepository::class);
$this->app->register(RouteServiceProvider::class);
}
/**
* Register commands in the format of Command::class
*/
protected function registerCommands(): void
{
// $this->commands([]);
}
/**
* Register command Schedules.
*/
protected function registerCommandSchedules(): void
{
// $this->app->booted(function () {
// $schedule = $this->app->make(Schedule::class);
// $schedule->command('inspire')->hourly();
// });
}
/**
* Register translations.
*/
public function registerTranslations(): void
{
$langPath = resource_path('lang/modules/'.$this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
}
}
/**
* Register config.
*/
protected function registerConfig(): void
{
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config');
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
}
/**
* Register views.
*/
public function registerViews(): void
{
$viewPath = resource_path('views/modules/'.$this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'resources/views');
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
$componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.ltrim(config('modules.paths.generator.component-class.path'), config('modules.paths.app_folder','')));
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path.'/modules/'.$this->moduleNameLower)) {
$paths[] = $path.'/modules/'.$this->moduleNameLower;
}
}
return $paths;
}
}

View File

View File

@ -0,0 +1,12 @@
<?php
namespace Modules\User\Repositories;
interface RoleInterface
{
public function findAll();
public function getRoleById($roleId);
public function delete($roleId);
public function create(array $RoleDetails);
public function update($roleId, array $newDetails);
}

View File

@ -0,0 +1,34 @@
<?php
namespace Modules\User\Repositories;
use App\Models\Role;
class RoleRepository implements RoleInterface
{
public function findAll()
{
return Role::get();
}
public function getRoleById($roleId)
{
return Role::findOrFail($roleId);
}
public function delete($roleId)
{
Role::destroy($roleId);
}
public function create(array $roleDetails)
{
return Role::create($roleDetails);
}
public function update($roleId, array $newDetails)
{
return Role::whereId($roleId)->update($newDetails);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Modules\User\Repositories;
interface UserInterface
{
public function findAll();
public function getUserById($userId);
public function delete($userId);
public function create(array $UserDetails, array $role);
public function update($userId, array $newDetails);
}

View File

@ -0,0 +1,36 @@
<?php
namespace Modules\User\Repositories;
use App\Models\User;
class UserRepository implements UserInterface
{
public function findAll()
{
return User::get();
}
public function getUserById($userId)
{
return User::findOrFail($userId);
}
public function delete($userId)
{
User::destroy($userId);
}
public function create(array $userDetails, array $role)
{
$user = User::create($userDetails);
$user->roles()->attach($role);
return $user;
}
public function update($userId, array $newDetails)
{
return User::whereId($userId)->update($newDetails);
}
}

View File

@ -0,0 +1,30 @@
{
"name": "nwidart/user",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\User\\": "app/",
"Modules\\User\\Database\\Factories\\": "database/factories/",
"Modules\\User\\Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Modules\\User\\Tests\\": "tests/"
}
}
}

View File

View File

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

View File

View File

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

View File

View File

@ -0,0 +1,16 @@
<?php
namespace Modules\User\database\seeders;
use Illuminate\Database\Seeder;
class UserDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

11
Modules/User/module.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "User",
"alias": "user",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\User\\Providers\\UserServiceProvider"
],
"files": []
}

15
Modules/User/package.json Normal file
View File

@ -0,0 +1,15 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.69.5",
"postcss": "^8.3.7",
"vite": "^4.0.0"
}
}

View File

View File

View File

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