first commit

This commit is contained in:
Sampanna Rimal
2024-08-27 17:48:06 +05:45
commit 53c0140f58
10839 changed files with 1125847 additions and 0 deletions

View File

@ -0,0 +1,121 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\Admin\Repositories\CountryRepository;
use Modules\Admin\Repositories\FieldRepository;
use Modules\PMS\Models\Client;
use Modules\PMS\Repositories\ClientInterface;
class ClientController extends Controller
{
private $clientRepository;
private $fieldRepository;
private $countryRepository;
public function __construct(ClientInterface $clientRepository, FieldRepository $fieldRepository, CountryRepository $countryRepository)
{
$this->clientRepository = $clientRepository;
$this->fieldRepository = $fieldRepository;
$this->countryRepository = $countryRepository;
}
/**
* Display a listing of the resource.
*/
public function index()
{
$data['title'] = 'Client List';
$data['clients'] = $this->clientRepository->findAll();
return view('pms::client.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Client';
$data['status'] = Client::STATUS;
$data['editable'] = false;
$data['genderList'] = $this->fieldRepository->getDropdownByAlias('gender');
$data['salutationList'] = $this->fieldRepository->getDropdownByAlias('salutation');
$data['countryList'] = $this->countryRepository->pluck();
return view('pms::client.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$inputData = $request->all();
try {
$this->clientRepository->create($inputData);
toastr()->success('Client Created Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('client.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Client';
$data['status'] = Client::STATUS;
$data['client'] = $this->clientRepository->getClientById($id);
return view('pms::client.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Client';
$data['status'] = Client::STATUS;
$data['editable'] = true;
$data['client'] = $this->clientRepository->getClientById($id);
$data['genderList'] = $this->fieldRepository->getDropdownByAlias('gender');
$data['salutationList'] = $this->fieldRepository->getDropdownByAlias('salutation');
$data['countryList'] = $this->countryRepository->pluck();
return view('pms::client.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
$inputData = $request->except(['_method', '_token']);
try {
$this->clientRepository->update($id, $inputData);
toastr()->success('Client Update Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('client.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->clientRepository->delete($id);
toastr()->success('Client Deleted Succesfully');
} catch (\Throwable $th) {
//throw $th;
toastr()->error($th->getMessage());
}
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PMSController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('pms::index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('pms::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
//
}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('pms::show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('pms::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

@ -0,0 +1,136 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\Employee\Repositories\EmployeeInterface;
use Modules\PMS\Models\Project;
use Modules\PMS\Repositories\ClientInterface;
use Modules\PMS\Repositories\ProjectInterface;
class ProjectController extends Controller
{
private $projectRepository;
private $clientRepository;
private $employeeRepository;
public function __construct(
ProjectInterface $projectRepository,
ClientInterface $clientRepository,
EmployeeInterface $employeeRepository) {
$this->projectRepository = $projectRepository;
$this->clientRepository = $clientRepository;
$this->employeeRepository = $employeeRepository;
}
/**
* Display a listing of the resource.
*/
public function index()
{
$data['title'] = 'Project List';
$data['projects'] = $this->projectRepository->findAll();
// ->map(function ($project) {
// return $project;
// });
// dd($data['projects']->toArray());
return view('pms::project.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Project';
$data['status'] = Project::STATUS;
$data['categoryList'] = Project::CATEGORY;
$data['clientList'] = $this->clientRepository->pluck();
$data['memberList'] = $this->employeeRepository->pluck();
$data['departmentList'] = [];
return view('pms::project.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$inputData = $request->all();
// dd($inputData);
// try {
$this->projectRepository->create($inputData);
foreach($request->members_id as $memberId) {
$employeemodel=$this->employeeRepository->getEmployeeById($memberId);
// dd($employeemodel->user);
sendNotification($employeemodel->user, [
'msg' => 'You have been assigned to a Project', ]);
}
toastr()->success('Project Created Succesfully');
// } catch (\Throwable $th) {
// toastr()->error($th->getMessage());
// }
return redirect()->route('project.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Project';
$data['project'] = $this->projectRepository->getProjectById($id);
$data['status'] = Project::STATUS;
$data['countryList'] = [1 => 'Nepal'];
return view('pms::project.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Project';
$data['project'] = $this->projectRepository->getProjectById($id);
$data['status'] = Project::STATUS;
$data['categoryList'] = Project::CATEGORY;
$data['clientList'] = $this->clientRepository->pluck();
$data['memberList'] = $this->employeeRepository->pluck();
$data['departmentList'] = [];
return view('pms::project.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
$inputData = $request->except(['_method', '_token']);
try {
$this->projectRepository->update($id, $inputData);
toastr()->success('Project Update Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('project.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->projectRepository->delete($id);
toastr()->success('Project Deleted Succesfully');
} catch (\Throwable $th) {
//throw $th;
toastr()->error($th->getMessage());
}
}
}

View File

@ -0,0 +1,162 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\Employee\Repositories\EmployeeInterface;
use Modules\PMS\Models\Task;
use Modules\PMS\Repositories\ProjectInterface;
use Modules\PMS\Repositories\TaskInterface;
class TaskController extends Controller
{
private $taskRepository;
private $projectRepository;
private $employeeRepository;
public function __construct(
TaskInterface $taskRepository,
ProjectInterface $projectRepository,
EmployeeInterface $employeeRepository) {
$this->taskRepository = $taskRepository;
$this->projectRepository = $projectRepository;
$this->employeeRepository = $employeeRepository;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$filters = $request->all();
$data['title'] = 'Task List';
$data['tasks'] = $this->taskRepository->findAll($filters);
$data['statusList'] = Task::STATUS;
// dd($data['tasks']->toArray());
return view('pms::task.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Task';
$data['status'] = Task::STATUS;
$data['priority'] = Task::PRIORITY;
$data['categoryList'] = Task::CATEGORY;
$data['projectList'] = $this->projectRepository->pluck();
$data['memberList'] = $this->employeeRepository->pluck();
return view('pms::task.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$inputData = $request->all();
try {
$this->taskRepository->create($inputData);
foreach($request->assigned_id as $memberId) {
$employeemodel=$this->employeeRepository->getEmployeeById($memberId);
// dd($employeemodel->user);
sendNotification($employeemodel->user, [
'msg' => 'A Task has been assigned to you', ]);
}
toastr()->success('Task Created Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('task.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Task';
$data['task'] = $this->taskRepository->getTaskById($id);
$data['status'] = Task::STATUS;
return view('pms::task.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Task';
$data['task'] = $this->taskRepository->getTaskById($id);
$data['status'] = Task::STATUS;
$data['priority'] = Task::PRIORITY;
$data['categoryList'] = Task::CATEGORY;
$data['projectList'] = $this->projectRepository->pluck();
$data['memberList'] = $this->employeeRepository->pluck();
return view('pms::task.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
$inputData = $request->except(['_method', '_token']);
try {
$this->taskRepository->update($id, $inputData);
toastr()->success('Task Update Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('task.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->taskRepository->delete($id);
toastr()->success('Task Deleted Succesfully');
} catch (\Throwable $th) {
//throw $th;
toastr()->error($th->getMessage());
}
}
public function kanban()
{
$data['title'] = 'Kanban Board';
$data['tasks'] = Task::select('*')->get()->groupBy('status');
$data['statusList'] = Task::STATUS;
return view('pms::task.kanban', $data);
}
public function changeStatus(Request $request)
{
try {
$taskModel = $this->taskRepository->getTaskById($request->id);
$taskModel->status = $request->changeStatus;
$taskModel->save();
return response()->json([
'status' => true,
'msg' => 'Status Changed',
], 200);
} catch (\Throwable $th) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
], 400);
}
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\PMS\Models\Ticket;
use Modules\PMS\Repositories\TicketInterface;
class TicketController extends Controller
{
private $ticketRepository;
public function __construct(TicketInterface $ticketRepository)
{
$this->ticketRepository = $ticketRepository;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$data['title'] = 'Ticket List';
$data['tickets'] = $this->ticketRepository->findAll();
$data['statusList'] = Ticket::STATUS;
return view('pms::ticket.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Ticket';
$data['statusList'] = Ticket::STATUS;
return view('pms::ticket.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$inputData = $request->all();
$this->ticketRepository->create($inputData);
toastr()->success('Ticket Created Succesfully');
return redirect()->route('ticket.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Ticket';
$data['tickets'] = $this->ticketRepository->getTicketById($id);
return view('pms::ticket.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Ticket';
$data['ticket'] = $this->ticketRepository->getTicketById($id);
return view('pms::ticket.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
$inputData = $request->except(['_method', '_token']);
try {
$this->ticketRepository->update($id, $inputData);
toastr()->success('Ticket Update Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('ticket.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->ticketRepository->delete($id);
toastr()->success('Ticket Deleted Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
}
}

View File

View File

@ -0,0 +1,26 @@
<?php
namespace Modules\PMS\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ClientRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
//
];
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
}

View File

View File

@ -0,0 +1,21 @@
<?php
namespace Modules\PMS\Models;
use App\Traits\CreatedUpdatedBy;
use App\Traits\StatusTrait;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
use StatusTrait, CreatedUpdatedBy;
/**
* The attributes that are mass assignable.
*/
protected $table = 'tbl_clients';
protected $guarded = [];
protected $appends = ['status_name'];
}

View File

@ -0,0 +1,36 @@
<?php
namespace Modules\PMS\Models;
use App\Traits\CreatedUpdatedBy;
use App\Traits\StatusTrait;
use Illuminate\Database\Eloquent\Model;
use Modules\Employee\Models\Employee;
class Project extends Model
{
use StatusTrait, CreatedUpdatedBy;
protected $table = 'tbl_projects';
protected $fillable = ['project_code', 'project_name', 'client_id', 'project_category_id', 'members_id', 'start_date', 'end_date', 'summary', 'status', 'createdBy', 'updatedBy', 'created_at', 'updated_at'];
protected $appends = ['status_name'];
protected $casts = [
'members_id' => 'array',
];
const CATEGORY = [
10 => 'Vue',
11 => 'Laravel',
];
public function client()
{
return $this->belongsTo(Client::class, 'client_id');
}
public function members()
{
return Employee::whereIn('id', $this->members_id)->get();
}
}

View File

@ -0,0 +1,112 @@
<?php
namespace Modules\PMS\Models;
use App\Traits\CreatedUpdatedBy;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Modules\Employee\Models\Employee;
class Task extends Model
{
use CreatedUpdatedBy;
protected $table = 'tbl_tasks';
protected $guarded = [];
protected $appends = ['status_name', 'priority_status'];
const CATEGORY = [
10 => 'Vue',
11 => 'Laravel',
];
const PRIORITY = [
10 => 'High',
11 => 'Meduim',
12 => 'Low',
];
const STATUS = [
10 => 'Incomplete',
11 => 'To DO',
12 => 'Doing',
13 => 'In Review',
14 => 'Completed',
];
protected $casts = [
'assigned_id' => 'array',
];
protected function statusName(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
switch ($attributes['status']) {
case '10':
$color = 'danger';
break;
case '11':
$color = 'info';
break;
case '12':
$color = 'primary';
break;
case '13':
$color = 'warning';
break;
case '14':
$color = 'success';
break;
default:
$color = 'light';
break;
}
return collect([
'status' => self::STATUS[$attributes['status']],
'color' => $color]);
},
set: fn($value) => $value,
);
}
protected function priorityStatus(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
switch ($attributes['priority']) {
case '10':
return '<span class="badge bg-danger">' . self::PRIORITY[$attributes['priority']] . '</span>';
break;
case '11':
return '<span class="badge bg-info">' . self::PRIORITY[$attributes['priority']] . '</span>';
break;
case '12':
return '<span class="badge bg-primary">' . self::PRIORITY[$attributes['priority']] . '</span>';
break;
default:
# code...
break;
}
},
set: fn($value) => $value,
);
}
public function project()
{
return $this->belongsTo(Project::class, 'project_id');
}
public function assigned()
{
return $this->belongsTo(Employee::class, 'assigned_id');
}
public function taskCategory()
{
return self::CATEGORY[$this->task_category_id ?? null];
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Modules\PMS\Models;
use Illuminate\Database\Eloquent\Model;
use Modules\Employee\Models\Employee;
class Ticket extends Model
{
/**
* The attributes that are mass assignable.
*/
protected $table = 'tbl_tickets';
protected $fillable = ['subject', 'employee_id', 'assign_group_id', 'project_id', 'desc', 'file', 'ticket_type', 'status'];
const STATUS = [
1 => 'Pending',
2 => 'Approved',
3 => 'Rejected',
];
public function project()
{
return $this->belongsTo(Project::class, 'project_id');
}
public function employee()
{
return $this->belongsTo(Employee::class, 'employee_id');
}
}

View File

View File

View File

@ -0,0 +1,126 @@
<?php
namespace Modules\PMS\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Modules\PMS\Repositories\ClientInterface;
use Modules\PMS\Repositories\ClientRepository;
use Modules\PMS\Repositories\ProjectInterface;
use Modules\PMS\Repositories\ProjectRepository;
use Modules\PMS\Repositories\TaskInterface;
use Modules\PMS\Repositories\TaskRepository;
use Modules\PMS\Repositories\TicketInterface;
use Modules\PMS\Repositories\TicketRepository;
class PMSServiceProvider extends ServiceProvider
{
protected string $moduleName = 'PMS';
protected string $moduleNameLower = 'pms';
/**
* 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(TicketInterface::class, TicketRepository::class);
$this->app->bind(ClientInterface::class, ClientRepository::class);
$this->app->bind(ProjectInterface::class, ProjectRepository::class);
$this->app->bind(TaskInterface::class, TaskRepository::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\PMS\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('PMS', '/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('PMS', '/routes/api.php'));
}
}

View File

View File

@ -0,0 +1,14 @@
<?php
namespace Modules\PMS\Repositories;
interface ClientInterface
{
public function findAll();
public function getClientById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
}

View File

@ -0,0 +1,39 @@
<?php
namespace Modules\PMS\Repositories;
use Modules\PMS\Models\Client;
class ClientRepository implements ClientInterface
{
public function findAll()
{
return Client::paginate(20);
}
public function getClientById($ClientId)
{
return Client::findOrFail($ClientId);
}
public function delete($ClientId)
{
Client::destroy($ClientId);
}
public function create($ClientDetails)
{
return Client::create($ClientDetails);
}
public function update($ClientId, array $newDetails)
{
return Client::whereId($ClientId)->update($newDetails);
}
public function pluck()
{
return Client::pluck('client_name', 'id');
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Modules\PMS\Repositories;
interface ProjectInterface
{
public function findAll();
public function getProjectById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
}

View File

@ -0,0 +1,39 @@
<?php
namespace Modules\PMS\Repositories;
use Modules\PMS\Models\Project;
class ProjectRepository implements ProjectInterface
{
public function findAll()
{
return Project::paginate(20);
}
public function getProjectById($ProjectId)
{
return Project::findOrFail($ProjectId);
}
public function delete($ProjectId)
{
Project::destroy($ProjectId);
}
public function create($ProjectDetails)
{
return Project::create($ProjectDetails);
}
public function update($ProjectId, array $newDetails)
{
return Project::whereId($ProjectId)->update($newDetails);
}
public function pluck()
{
return Project::pluck('project_name', 'id');
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Modules\PMS\Repositories;
interface TaskInterface
{
public function findAll($filters = [], $limit = null, $offset = null);
public function getTaskById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
}

View File

@ -0,0 +1,56 @@
<?php
namespace Modules\PMS\Repositories;
use Illuminate\Support\Facades\DB;
use Modules\PMS\Models\Task;
class TaskRepository implements TaskInterface
{
public function findAll($filters = [], $limit = null, $offset = null)
{
return Task::when($filters, function ($query) use ($filters) {
if (isset($filters["search"])) {
$search = $filters['search'];
$query->whereAny(['title'], 'LIKE', "%$search%");
}
if (isset($filters["status"])) {
$query->where("status", $filters["status"]);
}
if (isset($filters["date"])) {
$explodeDate = explode("to", $filters['date']);
// dd($filters['date'], preg_replace('/\s+/', '', $explodeDate[1]));
$query->whereBetween("start_date", [$explodeDate[0], preg_replace('/\s+/', '', $explodeDate[1])]);
}
})->get();
}
public function getTaskById($TaskId)
{
return Task::findOrFail($TaskId);
}
public function delete($TaskId)
{
Task::destroy($TaskId);
}
public function create($TaskDetails)
{
return Task::create($TaskDetails);
}
public function update($TaskId, array $newDetails)
{
return Task::whereId($TaskId)->update($newDetails);
}
public function pluck()
{
return Task::pluck(DB::raw('CONCAT(first_name," ", middle_name , " ",last_name) AS full_name'), 'id');
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Modules\PMS\Repositories;
interface TicketInterface
{
public function findAll();
public function getTicketById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
}

View File

@ -0,0 +1,40 @@
<?php
namespace Modules\PMS\Repositories;
use Illuminate\Support\Facades\DB;
use Modules\PMS\Models\Ticket;
class TicketRepository implements TicketInterface
{
public function findAll()
{
return Ticket::paginate(20);
}
public function getTicketById($TicketId)
{
return Ticket::findOrFail($TicketId);
}
public function delete($TicketId)
{
Ticket::destroy($TicketId);
}
public function create($TicketDetails)
{
return Ticket::create($TicketDetails);
}
public function update($TicketId, array $newDetails)
{
return Ticket::whereId($TicketId)->update($newDetails);
}
public function pluck()
{
return Ticket::pluck('Ticket_name', 'id');
}
}

30
Modules/PMS/composer.json Normal file
View File

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

View File

View File

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

View File

View File

View File

@ -0,0 +1,40 @@
<?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_clients', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('salutation_id')->nullable();
$table->string('client_name')->nullable();
$table->unsignedBigInteger('country_id')->nullable();
$table->string('email')->nullable();
$table->string('company_name')->nullable();
$table->string('company_address')->nullable();
$table->string('phone')->nullable();
$table->unsignedBigInteger('gender_id')->nullable();
$table->unsignedBigInteger('profile_pic')->nullable();
$table->longText('desc')->nullable();
$table->integer('status')->default(11);
$table->unsignedBigInteger('createdBy')->nullable();
$table->unsignedBigInteger('updatedBy')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tbl_clients');
}
};

View File

@ -0,0 +1,40 @@
<?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_projects', function (Blueprint $table) {
$table->id();
$table->string('project_code')->nullable();
$table->string('project_name')->nullable();
$table->unsignedBigInteger('client_id')->nullable();
$table->unsignedBigInteger('department_id')->nullable();
$table->unsignedBigInteger('project_category_id')->nullable();
$table->json('members_id')->nullable();
$table->date('start_date')->nullable();
$table->date('end_date')->nullable();
$table->longText('summary')->nullable();
$table->longText('key_notes')->nullable();
$table->integer('status')->default(11);
$table->unsignedBigInteger('createdBy')->nullable();
$table->unsignedBigInteger('updatedBy')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tbl_projects');
}
};

View File

@ -0,0 +1,38 @@
<?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_tasks', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->unsignedBigInteger('task_category_id')->nullable();
$table->unsignedBigInteger('project_id')->nullable();
$table->date('start_date')->nullable();
$table->date('due_date')->nullable();
$table->json('assigned_id')->nullable();
$table->longText('desc')->nullable();
$table->integer('status')->default(11);
$table->integer('priority')->nullable();
$table->unsignedBigInteger('createdBy')->nullable();
$table->unsignedBigInteger('updatedBy')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tbl_tasks');
}
};

View File

@ -0,0 +1,34 @@
<?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_tickets', function (Blueprint $table) {
$table->id();
$table->string('subject');
$table->unsignedBigInteger('employee_id')->nullable();
$table->unsignedBigInteger('assign_group_id')->nullable();
$table->unsignedBigInteger('project_id')->nullable();
$table->text('desc')->nullable();
$table->string('file')->nullable();
$table->string('ticket_type')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tbl_tickets');
}
};

View File

View File

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

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

@ -0,0 +1,11 @@
{
"name": "PMS",
"alias": "pms",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\PMS\\Providers\\PMSServiceProvider"
],
"files": []
}

15
Modules/PMS/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

View File

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

View File

@ -0,0 +1,24 @@
@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($client, 'PUT')->route('client.update', $client->id)->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data'])->open() }}
@include('pms::client.partials.action')
{{ html()->closeModelForm() }}
<!--end row-->
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,71 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
<div class="mb-2 text-end">
@can('client.create')
<a href="{{ route('client.create') }}" class="btn btn-success btn-md waves-effect waves-light"><i
class="ri-add-fill me-1 align-bottom"></i> Add</a>
@endcan
</div>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table id="buttons-datatables" class="display table-sm table-bordered table" style="width:100%">
<thead>
<tr>
<th>S.N</th>
<th>Client Name</th>
<th>Email</th>
<th>Company</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@forelse ($clients as $key => $client)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $client->client_name }}</td>
<td>{{ $client->email_address }}</td>
<td>{{ $client->company }}</td>
<td>{!! $client->status_name !!}</td>
<td>
<div class="hstack flex-wrap gap-3">
@can('client.show')
<a href="{{ route('client.show', $client->id) }}" class="link-info fs-15">
<i class="ri-eye-line"></i>
</a>
@endcan
@can('client.edit')
<a href="{{ route('client.edit', $client->id) }}" class="link-success fs-15 edit-item-btn"><i
class="ri-edit-2-line"></i></a>
@endcan
@can('client.destroy')
<a href="javascript:void(0);" data-link="{{ route('client.destroy', $client->id) }}"
data-id="{{ $client->id }}" class="link-danger fs-15 remove-item-btn"><i
class="ri-delete-bin-line"></i></a>
@endcan
</div>
</td>
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!--end row-->
</div>
</div>
@endsection

View File

@ -0,0 +1,103 @@
<div class="row">
<div class="col-lg-9">
<div class="card">
<div class="card-body">
<div class="row gy-3">
<div class="col-md-6">
{{ html()->label('Salutation')->class('form-label') }}
{{ html()->select('salutation_id', $salutationList)->class('form-control select2')->placeholder('Salutation')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Client Name')->class('form-label') }}
{{ html()->text('client_name')->class('form-control')->placeholder('Client Name')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Email')->class('form-label') }}
{{ html()->email('email')->class('form-control')->placeholder('Email Address')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Client Name')->class('form-label') }}
{{ html()->text('client_name')->class('form-control')->placeholder('Client Name')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Gender')->class('form-label') }}
{{ html()->select('gender_id', $genderList)->class('form-control select2')->placeholder('Select Gender')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Country')->class('form-label') }}
{{ html()->select('country_id', $countryList)->class('form-control select2')->placeholder('Select Country')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Phone Number')->class('form-label') }}
{{ html()->input($type = 'tel', $name = 'phone', $value = null)->class('form-control')->placeholder('+(977) 9812345678') }}
</div>
<div class="col-md-6">
{{ html()->label('Company Name')->class('form-label') }}
{{ html()->text('company_name')->class('form-control')->placeholder('Company Name') }}
</div>
<div class="col-md-6">
{{ html()->label('Company Adress')->class('form-label') }}
{{ html()->text('company_address')->class('form-control')->placeholder('Company Address') }}
</div>
<div class="col-md-12">
{{ html()->label('Description')->class('form-label') }}
{{ html()->textarea('desc')->class('form-control ckeditor-classic') }}
</div>
</div>
</div>
</div>
<!-- end card -->
</div>
<!-- end col -->
<div class="col-lg-3">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Publish</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Status')->class('form-label') }}
{{ html()->select('status', $status)->class('form-control select2')->placeholder('Select Status') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Profile Picture</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Image')->class('form-label visually-hidden') }}
{{ html()->file('profile_pic')->class('form-control dropify') }}
</div>
</div>
</div>
<!-- end card body -->
<div class="card-footer">
<x-form-buttons :editable="$editable" label="Add" href="{{route('client.index')}}" />
</div>
</div>
<!-- end card -->
</div>
<!-- end col -->
</div>

View File

@ -0,0 +1,49 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
<div class="row">
<div class="col-md-8">
<div class="card card-body p-4">
<div>
<div class="table-responsive">
<table class="table-borderless mb-0 table">
<tbody>
<tr>
<th><span class="fw-medium">Client Name</span></th>
<td>{{ $client->client_name }}</td>
</tr>
<tr>
<th><span class="fw-medium">Company</span></th>
<td>{{ $client->company }}</td>
</tr>
<tr>
<th><span class="fw-medium">Email</span></th>
<td>{{ $client->email_address }}</td>
</tr>
<tr>
<th><span class="fw-medium">Address</span></th>
<td>{{ $client->address }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="mb-3 text-end">
<a href="{{ route('client.index') }}" class="btn btn-secondary w-sm">Back</a>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,7 @@
@extends('pms::layouts.master')
@section('content')
<h1>Hello World</h1>
<p>Module: {!! config('pms.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>PMS 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-pms', 'resources/assets/sass/app.scss') }} --}}
</head>
<body>
@yield('content')
{{-- Vite JS --}}
{{-- {{ module_vite('build-pms', 'resources/assets/js/app.js') }} --}}
</body>

View File

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

View File

@ -0,0 +1,22 @@
@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($project, 'PUT')->route('project.update', $project->id)->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data'])->open() }}
@include('pms::project.partials.action')
{{ html()->closeModelForm() }}
<!--end row-->
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,91 @@
@extends('layouts.app')
@inject('employeeRepository', 'Modules\Employee\Repositories\EmployeeRepository')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
<div class="mb-2 text-end">
<a href="{{ route('project.create') }}" class="btn btn-success btn-md waves-effect waves-light"><i
class="ri-add-fill me-1 align-bottom"></i> Add</a>
</div>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table id="buttons-datatables" class="display table-sm table-bordered table" style="width:100%">
<thead>
<tr>
<th>S.N</th>
<th>Code</th>
<th>Project Name</th>
<th>Members</th>
<th>Start Date</th>
<th>Deadline</th>
<th>Client</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@forelse ($projects as $key => $project)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $project->project_code }}</td>
<td>{{ $project->project_name }}</td>
<td>
<div class="avatar-group flex-nowrap">
@isset($project->members_id)
@foreach ($project->members_id as $memberId)
<div class="avatar-group-item">
<a href="javascript: void(0);" class="d-inline-block">
<img
src="{{ asset(optional($employeeRepository->getEmployeeById($memberId))->profile_pic) }}"
alt="" class="rounded-circle avatar-xxs">
</a>
</div>
@endforeach
@endisset
</div>
</td>
<td>{{ $project->start_date }}</td>
<td class="text-danger">{{ $project->end_date }}</td>
<td>{{ optional($project->client)->client_name }}</td>
<td>{!! $project->status_name !!}</td>
<td>
<div class="hstack flex-wrap gap-3">
@can('project.show')
<a href="{{ route('project.show', $project->id) }}" class="link-info fs-15">
<i class="ri-eye-line"></i>
</a>
@endcan
@can('project.edit')
<a href="{{ route('project.edit', $project->id) }}"
class="link-success fs-15 edit-item-btn"><i class="ri-edit-2-line"></i></a>
@endcan
@can('project.destroy')
<a href="javascript:void(0);" data-link="{{ route('project.destroy', $project->id) }}"
data-id="{{ $project->id }}" class="link-danger fs-15 remove-item-btn"><i
class="ri-delete-bin-line"></i></a>
@endcan
</div>
</td>
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!--end row-->
</div>
</div>
@endsection

View File

@ -0,0 +1,125 @@
<div class="row">
<div class="col-lg-8">
<div class="card">
<div class="card-body">
<div class="row gy-1">
<div class="col-md-6">
{{ html()->label('Project Code')->class('form-label') }}
{{ html()->text('project_code')->class('form-control')->placeholder('Enter Project Code')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Project Name')->class('form-label') }}
{{ html()->text('project_name')->class('form-control')->placeholder('Enter Project Name')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Project Category')->class('form-label') }}
{{ html()->select('project_category_id', $categoryList)->class('form-control select2')->placeholder('Select Project Category') }}
</div>
<div class="col-md-6">
{{ html()->label('Client')->class('form-label') }}
{{ html()->select('client_id', $clientList)->class('form-control select2')->placeholder('Select Client') }}
</div>
<div class="col-md-6">
{{ html()->label('Department')->class('form-label') }}
{{ html()->select('department_id', $departmentList)->class('form-control select2')->placeholder('Select Department') }}
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Summary')->class('form-label') }}
{{ html()->textarea('summary')->class('form-control ckeditor-classic') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Key Notes')->class('form-label') }}
{{ html()->textarea('key_notes')->class('form-control ckeditor-classic') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mb-3 text-end">
<a href="{{ route('project.index') }}" class="btn btn-danger w-sm">Cancel</a>
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
</div>
<!-- end col -->
<div class="col-lg-4">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Publish</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Status')->class('form-label') }}
{{ html()->select('status', $status)->class('form-control')->required() }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Team Members</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{-- {{ html()->label('Team Members')->class('form-label') }} --}}
{{ html()->multiselect('members_id[]', $memberList)->class('form-control select2')->value($project->members_id ?? null)->attributes(['multiple'])->required() }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Date</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Start Date')->class('form-label') }}
{{ html()->date('start_date')->class('form-control')->placeholder('Choose Start Date') }}
</div>
<div class="col-md-12">
{{ html()->label('End Date')->class('form-label') }}
{{ html()->date('end_date')->class('form-control')->placeholder('Choose End Date') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
</div>
<!-- end col -->
</div>

View File

@ -0,0 +1,62 @@
@extends('layouts.app')
@inject('employeeRepository', 'Modules\Employee\Repositories\EmployeeRepository')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
<div class="row">
<div class="col-md-8">
<div class="card card-body p-4">
<div>
<div class="table-responsive">
<table class="table-borderless mb-0 table">
<tbody>
<tr>
<th><span class="fw-medium">Project Name</span></th>
<td>{{ $project->project_name }}</td>
</tr>
<tr>
<th><span class="fw-medium">Code</span></th>
<td>{{ $project->project_code }}</td>
</tr>
<tr>
<th><span class="fw-medium">Members</span></th>
<td>
<div class="avatar-group flex-nowrap">
@foreach ($project->members_id as $memberId)
<div class="avatar-group-item">
<a href="javascript: void(0);" class="d-inline-block">
<img
src="{{ asset(optional($employeeRepository->getEmployeeById($memberId))->profile_pic) }}"
alt="" class="rounded-circle avatar-xxs">
</a>
</div>
@endforeach
</div>
</td>
</tr>
<tr>
<th><span class="fw-medium">Summary</span></th>
<td>{{ $project->summary }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="mb-3 text-end">
<a href="{{ route('project.index') }}" class="btn btn-secondary w-sm">Back</a>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

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

View File

@ -0,0 +1,22 @@
@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($task, 'PUT')->route('task.update', $task->id)->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data'])->open() }}
@include('pms::task.partials.action')
{{ html()->closeModelForm() }}
<!--end row-->
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,88 @@
@extends('layouts.app')
@inject('employeeRepository', 'Modules\Employee\Repositories\EmployeeRepository')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
@include('pms::task.partials.menu')
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table id="buttons-datatables" class="display table-sm table-bordered table" style="width:100%">
<thead>
<tr>
<th>S.N</th>
<th>Task</th>
<th>Project</th>
<th>Start Date</th>
<th>Deadline</th>
<th>Assigned</th>
<th>Priority</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@forelse ($tasks as $key => $task)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $task->title }}</td>
<td>{{ optional($task->project)->project_name }}</td>
<td>{{ $task->start_date }}</td>
<td class="text-danger">{{ $task->due_date }}</td>
<td>
<div class="avatar-group flex-nowrap">
@isset($task->assigned_id)
@foreach ($task->assigned_id as $assignedId)
<div class="avatar-group-item">
<a href="javascript: void(0);" class="d-inline-block">
<img
src="{{ asset(optional($employeeRepository->getEmployeeById($assignedId))->profile_pic) }}"
alt="" class="rounded-circle avatar-xxs">
</a>
</div>
@endforeach
@endisset
</div>
</td>
<td>{!! $task->priority_status !!}</td>
<td>
<span class="badge bg-{{ $task->status_name['color'] }}"> {!! $task->status_name['status'] !!} </span>
</td>
<td>
<div class="hstack flex-wrap gap-3">
@can('task.show')
<a href="{{ route('task.show', $task->id) }}" class="link-info fs-15">
<i class="ri-eye-line"></i>
</a>
@endcan
@can('task.edit')
<a href="{{ route('task.edit', $task->id) }}" class="link-success fs-15 edit-item-btn"><i
class="ri-edit-2-line"></i></a>
@endcan
@can('task.destroy')
<a href="javascript:void(0);" data-link="{{ route('task.destroy', $task->id) }}"
data-id="{{ $task->id }}" class="link-danger fs-15 remove-item-btn"><i
class="ri-delete-bin-line"></i></a>
@endcan
</div>
</td>
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!--end row-->
</div>
</div>
@endsection

View File

@ -0,0 +1,118 @@
@extends('layouts.app')
@inject('employeeRepository', 'Modules\Employee\Repositories\EmployeeRepository')
@push('css')
<link rel="stylesheet" type="text/css" href="{{ asset('assets/libs/dragula/dragula.min.css') }}" />
@endpush
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
@include('pms::task.partials.menu')
<div class="row">
<div class="col-lg-12">
<div class="tasks-board mb-3" id="kanbanboard">
@foreach ($statusList as $statuskey => $statusItem)
<div class="tasks-list" data-status-key="{{ $statuskey }}">
<div class="d-flex mb-3">
<div class="flex-grow-1">
<h6 class="fs-14 text-uppercase fw-semibold mb-0">{{ $statusItem }} <small
class="badge bg-info totaltask-badge ms-1 align-bottom">{{ array_key_exists($statuskey, $tasks->toArray()) ? count($tasks[$statuskey]) : 0 }}</small>
</h6>
</div>
</div>
<div data-simplebar class="tasks-wrapper mx-n3 px-3">
<div id="{{ strtolower(str_replace(' ', '-', $statusItem)) }}-task" class="tasks">
@if (array_key_exists($statuskey, $tasks->toArray()))
@foreach ($tasks[$statuskey] as $task)
<div class="card tasks-box" data-id="{{ $task->id }}">
<div class="card-body">
<div class="d-flex mb-2">
<div class="flex-grow-1">
<h6 class="fs-15 text-truncate task-title mb-0"><a
href="{{ route('task.show', $task->id) }}" class="d-block">{{ $task->title }}</a>
</h6>
</div>
<div class="flex-shrink-0">
<a href="javascript:void(0);" class="text-muted" id="dropdownMenuLink12"
data-bs-toggle="dropdown" aria-expanded="false"><i class="ri-more-fill"></i></a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink12">
<li><a class="dropdown-item" href="{{ route('task.show', $task->id) }}"><i
class="ri-eye-fill text-muted me-2 align-bottom"></i> View</a></li>
<li><a class="dropdown-item" href="{{ route('task.edit', $task->id) }}"><i
class="ri-edit-2-line text-muted me-2 align-bottom"></i> Edit</a></li>
<li><a class="dropdown-item" data-bs-toggle="modal" href="#deleteRecordModal"><i
class="ri-delete-bin-5-line text-muted me-2 align-bottom"></i> Delete</a></li>
</ul>
</div>
</div>
<p class="text-muted">{{ $task->desc }}</p>
<div class="d-flex align-items-center">
<div class="flex-grow-1">
<span class="badge text-bg-light">{{ $task->taskCategory() }}</span>
</div>
<div class="flex-shrink-0">
<div class="avatar-group">
@isset($task->assigned_id)
@foreach ($task->assigned_id as $assignedId)
<a href="javascript: void(0);" class="avatar-group-item" data-bs-toggle="tooltip"
data-bs-trigger="hover" data-bs-placement="top"
title="{{ optional($employeeRepository->getEmployeeById($assignedId))->full_name }}">
<img
src="{{ asset(optional($employeeRepository->getEmployeeById($assignedId))->profile_pic) }}"
alt="" class="rounded-circle avatar-xxs">
</a>
@endforeach
@endisset
</div>
</div>
</div>
</div>
<!--end card-body-->
<div class="card-footer border-top-dashed">
<div class="d-flex">
<div class="flex-grow-1">
<span class="text-muted text-info"><i class="ri-time-line align-bottom"></i>
{{ date('d M, Y', strtotime($task->start_date)) }}</span>
</div>
<div class="flex-shrink-0">
{!! $task->priority_status !!}
</div>
</div>
</div>
<div class="progress progress-sm">
<div class="progress-bar bg-{{ $task->status_name['color'] }}" role="progressbar"
style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
@endforeach
@endif
<!--end card-->
</div>
<!--end tasks-->
</div>
</div>
@endforeach
</div>
</div>
</div>
<!--end row-->
</div>
</div>
@endsection
@push('js')
<script src="{{ asset('assets/libs/dragula/dragula.min.js') }}"></script>
<script src="{{ asset('assets/libs/dom-autoscroller/dom-autoscroller.min.js') }}"></script>
<script src="{{ asset('assets/js/pages/tasks-kanban.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,106 @@
<div class="row">
<div class="col-lg-8">
<div class="card">
<div class="card-body">
<div class="row gy-1">
<div class="col-md-12">
{{ html()->label('Title')->class('form-label') }}
{{ html()->text('title')->class('form-control')->placeholder('Enter Title')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Task Category')->class('form-label') }}
{{ html()->select('task_category_id', $categoryList)->class('form-control')->placeholder('Select Task Category')->required() }}
</div>
<div class="col-md-6">
{{ html()->label('Project')->class('form-label') }}
{{ html()->select('project_id', $projectList)->class('form-control')->placeholder('Select Project')->required() }}
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Description')->class('form-label') }}
{{ html()->textarea('desc')->class('form-control ckeditor-classic')->placeholder('..') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mb-3 text-end">
<a href="{{ route('task.index') }}" class="btn btn-danger w-sm">Cancel</a>
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
</div>
<!-- end col -->
<div class="col-lg-4">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Publish</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Status')->class('form-label') }}
{{ html()->select('status', $status)->class('form-control')->required() }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Team Members</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->multiselect('assigned_id[]', $memberList)->class('form-control select2')->value($task->assigned_id ?? null)->attributes(['multiple', 'id' => 'assigned_id'])->required() }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Date</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Priority')->class('form-label') }}
{{ html()->select('priority', $priority)->class('form-control')->required() }}
</div>
<div class="col-md-12">
{{ html()->label('Start Date')->class('form-label') }}
{{ html()->date('start_date')->class('form-control')->placeholder('Choose Start Date') }}
</div>
<div class="col-md-12">
{{ html()->label('Due Date')->class('form-label') }}
{{ html()->date('due_date')->class('form-control')->placeholder('Choose Due Date') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
</div>
<!-- end col -->
</div>

View File

@ -0,0 +1,75 @@
<div class="card">
<div class="card-body">
<div class="row g-2">
<div class="col-sm-8">
{{ html()->form('GET')->route('task.index')->open() }}
<div class="row g-3">
<div class="col-xl-3">
<div class="search-box">
{{ html()->text('search')->class('form-control search')->value(request('search'))->placeholder('Search...') }}
<i class="ri-search-line search-icon"></i>
</div>
</div>
<div class="col-sm-4">
<div class="">
{{ html()->text('date')->class('form-control')->value(request('date'))->placeholder('Date Range')->attributes([
'id' => 'datepicker-range',
'data-provider' => 'flatpickr',
'data-date-format' => 'Y-m-d',
'data-range-date' => 'true',
]) }}
</div>
</div>
<div class="col-sm-3">
<div>
{{ html()->select('status', $statusList)->placeholder('Select Status')->value(request('status'))->class('form-control select2') }}
</div>
</div>
<!--end col-->
<div class="col-sm-2">
<div>
<button type="submit" class="btn btn-primary">
<i class="ri-equalizer-fill me-2"></i>Filters</button>
{{-- <a href="{{ route('task.index') }}" class="btn btn-danger">
<i class="ri-bin-fill me-2"></i>Reset</a> --}}
</div>
</div>
<!--end col-->
</div>
<!--end row-->
{{ html()->form()->close() }}
</div>
<!--end col-->
<div class="col-sm-auto ms-auto">
<div class="list-grid-nav hstack gap-1">
<a href="{{ route('task.index') }}" id="list-view-button"
class="btn btn-soft-info nav-link btn-icon {{ Route::is('task.index') ? 'active' : '' }} fs-14"><i
class="ri-list-unordered"></i></a>
<a href="{{ route('task.kanban') }}" id="grid-view-button"
class="btn btn-soft-info nav-link btn-icon fs-14 {{ Route::is('task.kanban') ? 'active' : '' }}"><i
class="ri-grid-fill"></i></a>
<a href="{{ route('task.create') }}" class="btn btn-success btn-md waves-effect waves-light"><i
class="ri-add-fill me-1 align-bottom"></i> Add</a>
</div>
</div>
<!--end col-->
</div>
<!--end row-->
</div>
</div>
{{-- <div class="d-flex justify-content-end hstack my-2 ms-auto gap-2">
<a href="{{ route('task.index') }}" class="btn btn-primary btn-icon waves-effect waves-light"><i
class="ri-list-unordered"></i></a>
<a href="{{ route('task.kanban') }}" class="btn btn-danger btn-icon waves-effect waves-light"><i
class="ri-grid-fill"></i></a>
<a href="{{ route('task.create') }}" class="btn btn-success btn-md waves-effect waves-light"><i
class="ri-add-fill me-1 align-bottom"></i> Add</a>
</div> --}}

View File

@ -0,0 +1,49 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
<div class="row">
<div class="col-md-8">
<div class="card card-body p-4">
<div>
<div class="table-responsive">
<table class="table-borderless mb-0 table">
<tbody>
<tr>
<th><span class="fw-medium">Title</span></th>
<td>{{ $task->title }}</td>
</tr>
<tr>
<th><span class="fw-medium">Task Category</span></th>
<td>{{ $task->task_category_id }}</td>
</tr>
<tr>
<th><span class="fw-medium">Project</span></th>
<td>{{ $task->project_id }}</td>
</tr>
<tr>
<th><span class="fw-medium">Description</span></th>
<td>{{ $task->desc }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="mb-3 text-end">
<a href="{{ route('task.index') }}" class="btn btn-secondary w-sm">Back</a>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

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

View File

@ -0,0 +1,22 @@
@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($ticket, 'PUT')->route('ticket.update', $ticket->id)->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data'])->open() }}
@include('pms::ticket.partials.action')
{{ html()->closeModelForm() }}
<!--end row-->
</div>
<!-- container-fluid -->
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

@ -0,0 +1,72 @@
@extends('layouts.app')
@inject('employeeRepository', 'Modules\Employee\Repositories\EmployeeRepository')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
@include('pms::ticket.partials.menu')
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table id="buttons-datatables" class="display table-sm table-bordered table" style="width:100%">
<thead>
<tr>
<th>S.N</th>
<th>Ticket</th>
<th>Assigned</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@forelse ($tickets as $key => $ticket)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $ticket->subject }}</td>
<td>
<div class="avatar-group flex-nowrap">
<div class="avatar-group-item">
Assigned
</div>
</div>
</td>
<td>
{{-- <span class="badge bg-{{ $task->status_name['color'] }}"> {!! $task->status_name['status'] !!} </span> --}}Status
</td>
<td>
<div class="hstack flex-wrap gap-3">
@can('ticket.show')
<a href="{{ route('ticket.show', $ticket->id) }}" class="link-info fs-15">
<i class="ri-eye-line"></i>
</a>
@endcan
@can('ticket.edit')
<a href="{{ route('ticket.edit', $ticket->id) }}" class="link-success fs-15 edit-item-btn"><i
class="ri-edit-2-line"></i></a>
@endcan
@can('ticket.destroy')
<a href="javascript:void(0);" data-link="{{ route('ticket.destroy', $ticket->id) }}"
data-id="{{ $ticket->id }}" class="link-danger fs-15 remove-item-btn"><i
class="ri-delete-bin-line"></i></a>
@endcan
</div>
</td>
</tr>
@empty
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!--end row-->
</div>
</div>
@endsection

View File

@ -0,0 +1,54 @@
<div class="row">
<div class="col-lg-8">
<div class="card">
<div class="card-body">
<div class="row gy-1">
<div class="col-md-12">
{{ html()->label('Subject')->class('form-label') }}
{{ html()->text('subject')->class('form-control')->placeholder('Enter Subject')->required() }}
{{ html()->div('Please enter subject')->class('invalid-feedback') }}
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Description')->class('form-label') }}
{{ html()->textarea('desc')->class('form-control ckeditor-classic')->placeholder('..') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
<div class="mb-3 text-end">
<a href="{{ route('ticket.index') }}" class="btn btn-danger w-sm">Cancel</a>
<button type="submit" class="btn btn-success w-sm">Save</button>
</div>
</div>
<!-- end col -->
<div class="col-lg-4">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Publish</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
{{ html()->label('Status')->class('form-label') }}
{{ html()->select('status', $statusList)->class('form-control') }}
</div>
</div>
</div>
<!-- end card body -->
</div>
<!-- end card -->
</div>
<!-- end col -->
</div>

View File

@ -0,0 +1,52 @@
<div class="card">
<div class="card-body">
<div class="row g-2">
<div class="col-sm-8">
{{ html()->form('GET')->route('ticket.index')->open() }}
<div class="row g-3">
<div class="col-xl-3">
<div class="search-box">
{{ html()->text('search')->class('form-control search')->value(request('search'))->placeholder('Search...') }}
<i class="ri-search-line search-icon"></i>
</div>
</div>
<div class="col-sm-4">
<div class="">
{{ html()->text('date')->class('form-control')->value(request('date'))->placeholder('Date Range')->attributes([
'id' => 'datepicker-range',
'data-provider' => 'flatpickr',
'data-date-format' => 'Y-m-d',
'data-range-date' => 'true',
]) }}
</div>
</div>
<!--end col-->
<div class="col-sm-2">
<div>
<button type="submit" class="btn btn-primary">
<i class="ri-equalizer-fill me-2"></i>Filters</button>
{{-- <a href="{{ route('task.index') }}" class="btn btn-danger">
<i class="ri-bin-fill me-2"></i>Reset</a> --}}
</div>
</div>
<!--end col-->
</div>
<!--end row-->
{{ html()->form()->close() }}
</div>
<!--end col-->
<div class="col-sm-auto ms-auto">
<div class="list-grid-nav hstack gap-1">
<a href="{{ route('ticket.create') }}" class="btn btn-success btn-md waves-effect waves-light"><i
class="ri-add-fill me-1 align-bottom"></i> Add</a>
</div>
</div>
<!--end col-->
</div>
<!--end row-->
</div>
</div>

View File

@ -0,0 +1,40 @@
@extends('layouts.app')
@section('content')
<div class="page-content">
<div class="container-fluid">
@include('layouts.partials.breadcrumb', ['title' => $title])
<div class="row">
<div class="col-md-8">
<div class="card card-body p-4">
<div>
<div class="table-responsive">
<table class="table-borderless mb-0 table">
<tbody>
<tr>
<th><span class="fw-medium">Title</span></th>
<td>{{ $ticket->subject }}</td>
</tr>
<tr>
<th><span class="fw-medium">Description</span></th>
<td>{{ $ticket->desc }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="mb-3 text-end">
<a href="{{ route('ticket.index') }}" class="btn btn-secondary w-sm">Back</a>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('js')
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
@endpush

View File

View File

@ -0,0 +1,19 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\PMS\Http\Controllers\PMSController;
/*
*--------------------------------------------------------------------------
* 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('pms', PMSController::class)->names('pms');
});

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\PMS\Http\Controllers\ClientController;
use Modules\PMS\Http\Controllers\PMSController;
use Modules\PMS\Http\Controllers\ProjectController;
use Modules\PMS\Http\Controllers\TaskController;
use Modules\PMS\Http\Controllers\TicketController;
/*
|--------------------------------------------------------------------------
| 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('pms', PMSController::class)->names('pms');
Route::resource('client', ClientController::class)->names('client');
Route::resource('project', ProjectController::class)->names('project');
Route::get('task/kanban', [TaskController::class, 'kanban'])->name('task.kanban');
Route::get('task/changeStatus', [TaskController::class, 'changeStatus'])->name('task.changeStatus');
Route::resource('task', TaskController::class)->names('task');
Route::resource('ticket', TicketController::class)->names('ticket');
});

View File

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