generated from theradcoza/Laravel-Docker-Dev-Template
Compare commits
3 Commits
shift-mana
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bc6781e17 | ||
|
|
c936670573 | ||
| 2475daca4b |
48
README.md
48
README.md
@@ -28,10 +28,52 @@ A shift management application for scheduling staff, tracking attendance, and ge
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Prerequisites
|
## Prerequisites
|
||||||
- Docker & Docker Compose
|
|
||||||
|
|
||||||
### Setup
|
- [Docker Desktop](https://www.docker.com/products/docker-desktop) installed
|
||||||
|
- [Docker Compose](https://docs.docker.com/compose/) (usually included with Docker Desktop)
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Clone the repository:**
|
||||||
|
```sh
|
||||||
|
git clone <your-repo-url>
|
||||||
|
cd bhoza-shift-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Copy the example environment file:**
|
||||||
|
```sh
|
||||||
|
cp src/.env.example src/.env
|
||||||
|
# Or manually create src/.env based on src/.env.example
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start the app with MariaDB:**
|
||||||
|
```sh
|
||||||
|
docker-compose --profile mysql up -d
|
||||||
|
```
|
||||||
|
This will start the app, Nginx, MariaDB, Redis, and Mailpit containers.
|
||||||
|
|
||||||
|
4. **Install Composer dependencies:**
|
||||||
|
```sh
|
||||||
|
docker-compose exec app composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Generate the application key:**
|
||||||
|
```sh
|
||||||
|
docker-compose exec app php artisan key:generate
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Run database migrations and seeders:**
|
||||||
|
```sh
|
||||||
|
docker-compose exec app php artisan migrate --seed
|
||||||
|
```
|
||||||
|
|
||||||
|
7. **Access the app:**
|
||||||
|
- Web: [http://localhost:8080](http://localhost:8080)
|
||||||
|
- Admin: [http://localhost:8080/admin/login](http://localhost:8080/admin/login)
|
||||||
|
- Mailpit: [http://localhost:8025](http://localhost:8025)
|
||||||
|
|
||||||
|
### Setup(Maybe you should run the one above 🤷🏿♂️)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone <repo-url> bhoza-shift-manager
|
git clone <repo-url> bhoza-shift-manager
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public static function form(Form $form): Form
|
|||||||
Forms\Components\Select::make('staffMembers')
|
Forms\Components\Select::make('staffMembers')
|
||||||
->label('Assign Staff')
|
->label('Assign Staff')
|
||||||
->multiple()
|
->multiple()
|
||||||
->relationship('staff', 'name')
|
->options(User::query()->pluck('name', 'id'))
|
||||||
->preload()
|
->preload()
|
||||||
->searchable(),
|
->searchable(),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -17,4 +17,17 @@ protected function mutateFormDataBeforeCreate(array $data): array
|
|||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function afterCreate(): void
|
||||||
|
{
|
||||||
|
$staffIds = $this->data['staffMembers'] ?? [];
|
||||||
|
|
||||||
|
if (empty($staffIds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->record->staff()->syncWithPivotValues(
|
||||||
|
$staffIds,
|
||||||
|
['assigned_by' => auth()->id()]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,14 @@ protected function getHeaderActions(): array
|
|||||||
->visible(fn () => $this->record->isPlanned()),
|
->visible(fn () => $this->record->isPlanned()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function afterSave(): void
|
||||||
|
{
|
||||||
|
$staffIds = $this->data['staffMembers'] ?? [];
|
||||||
|
|
||||||
|
$this->record->staff()->syncWithPivotValues(
|
||||||
|
$staffIds,
|
||||||
|
['assigned_by' => auth()->id()]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,13 @@ public function table(Table $table): Table
|
|||||||
Tables\Actions\AttachAction::make()
|
Tables\Actions\AttachAction::make()
|
||||||
->label('Add Staff')
|
->label('Add Staff')
|
||||||
->preloadRecordSelect()
|
->preloadRecordSelect()
|
||||||
->visible(fn () => $this->getOwnerRecord()->isPlanned()),
|
->visible(fn () => $this->getOwnerRecord()->isPlanned())
|
||||||
|
->action(function (array $data, $ownerRecord) {
|
||||||
|
$staffId = $data['record'] ?? null;
|
||||||
|
if ($staffId) {
|
||||||
|
app(\App\Services\ShiftService::class)->assignStaff($ownerRecord, [$staffId]);
|
||||||
|
}
|
||||||
|
}),
|
||||||
])
|
])
|
||||||
->actions([
|
->actions([
|
||||||
Tables\Actions\DetachAction::make()
|
Tables\Actions\DetachAction::make()
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public function createShift(array $data, ?array $staffIds = null): Shift
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if ($staffIds) {
|
if ($staffIds) {
|
||||||
|
logger()->info('Staff IDs:', $staffIds);
|
||||||
$this->assignStaff($shift, $staffIds);
|
$this->assignStaff($shift, $staffIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +103,11 @@ public function assignStaff(Shift $shift, array $staffIds): void
|
|||||||
}
|
}
|
||||||
|
|
||||||
$managerId = Auth::id();
|
$managerId = Auth::id();
|
||||||
|
|
||||||
|
if(!$managerId) {
|
||||||
|
throw new InvalidArgumentException('Authenticated user is required to assign staff.');
|
||||||
|
}
|
||||||
|
|
||||||
$syncData = [];
|
$syncData = [];
|
||||||
|
|
||||||
foreach ($staffIds as $staffId) {
|
foreach ($staffIds as $staffId) {
|
||||||
|
|||||||
@@ -13,11 +13,24 @@ class DatabaseSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
|
// Create the admin user
|
||||||
User::factory()->create([
|
User::factory()->create([
|
||||||
'name' => 'Admin User',
|
'name' => 'Admin User',
|
||||||
'email' => 'admin@example.com',
|
'email' => 'admin@example.com',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Create 10 random staff users
|
||||||
|
User::factory()->create(['name' => 'Staff One', 'email' => 'staff1@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Two', 'email' => 'staff2@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Three', 'email' => 'staff3@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Four', 'email' => 'staff4@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Five', 'email' => 'staff5@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Six', 'email' => 'staff6@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Seven', 'email' => 'staff7@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Eight', 'email' => 'staff8@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Nine', 'email' => 'staff9@example.com']);
|
||||||
|
User::factory()->create(['name' => 'Staff Ten', 'email' => 'staff10@example.com']);
|
||||||
|
|
||||||
$this->call(RolePermissionSeeder::class);
|
$this->call(RolePermissionSeeder::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user