Skip to content

Commit 6ce6c6a

Browse files
authored
merge: pull request #26 from marksxiety/chore/adjustments
PR: Chore/adjustments
2 parents 0ce3978 + 5276287 commit 6ce6c6a

42 files changed

Lines changed: 2070 additions & 294 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,9 @@ AWS_USE_PATH_STYLE_ENDPOINT=false
6464
VITE_APP_NAME="${APP_NAME}"
6565

6666
AI_API_KEY=
67-
AI_MODEL=
67+
AI_MODEL=
68+
69+
ADMIN_NAME=Admin
70+
ADMIN_EMAIL=admin@example.com
71+
ADMIN_EMPLOYEEID=ADMIN001
72+
ADMIN_PASSWORD=changeme

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
.env
99
.env.backup
1010
.env.production
11-
/setup/config.json
1211
.phpunit.result.cache
1312
Homestead.json
1413
Homestead.yaml

CHANGELOG.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,55 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [v1.6.0] - 2026-05-09
6+
7+
### Added
8+
9+
- `OrganizationUnitController` with store, update, and destroy endpoints
10+
- Admin CRUD routes for organization units behind `admin` middleware
11+
- Organization unit management section in admin settings page with add, edit, and delete
12+
- `HasScopedQueries` trait to scope queries by organization unit (returns `null` for admin)
13+
- User reassignment flow when deleting an organization unit
14+
- `calcHours` helper with per-item and total queue hours display
15+
- Scrollable form and queue panels with fixed height
16+
- `FloatingThemeToggle` component on login, register, forgot password, and reset password pages
17+
18+
### Changed
19+
20+
- Scoped user listing, overtime, dashboard, required hours, and schedule queries by org unit via `HasScopedQueries`
21+
- Admin users no longer scoped to an org unit (`organization_unit_id` set to `null`)
22+
- Removed hardcoded org unit from report date range form
23+
- Redesigned overtime queue cards with simplified styling and status badges
24+
- Converted `defaultShiftCodes` to computed, removed week remove button
25+
- Flattened admin System dropdown into direct Configuration link
26+
27+
## [v1.5.0] - 2026-05-05
28+
29+
### Added
30+
31+
- `settings` database table and `Setting` model for system configuration
32+
- `SettingsController` with index and update endpoints
33+
- Admin settings page (`Admin/Settings.vue`) for managing shift codes, overtime rules, and system preferences
34+
- Admin dashboard (`Admin/Index.vue`) with the same overtime dashboard as approver
35+
- `admin-approver` middleware group allowing admin to access all approver routes
36+
- "System" dropdown in navigation visible only to admin users
37+
- Admin user seeder reading credentials from `ADMIN_*` environment variables
38+
- Default settings seeder (shift codes, minimum overtime hours, overtime minute step)
39+
40+
### Changed
41+
42+
- Migrated all configuration from `setup/config.json` to `settings` database table
43+
- `OvertimeCalculator` now reads `minimum_overtime_hours` from database instead of filesystem
44+
- Admin role is a superset of approver with additional system settings access
45+
- `/setup/config` endpoint now reads from `settings` table instead of JSON file
46+
- Restricted public registration to `employee` and `approver` roles only (admin created via seeder)
47+
- Rewrote `OvertimeCalculatorTest` and `OvertimeRequestValidationTest` to use database-backed settings
48+
49+
### Removed
50+
51+
- `make:config` artisan command (replaced by admin settings UI)
52+
- `setup/config.json` file dependency (replaced by database)
53+
554
## [v1.4.1] - 2026-04-26
655

756
### Added

app/Console/Commands/MakeConfigCommand.php

Lines changed: 0 additions & 41 deletions
This file was deleted.

app/Http/Controllers/AuthController.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212
use Illuminate\Support\Facades\Password;
1313
use Illuminate\Support\Facades\Storage;
1414
use Illuminate\Validation\Rules\Password as PasswordRule;
15+
use App\Traits\HasScopedQueries;
1516

1617
class AuthController extends Controller
1718
{
19+
use HasScopedQueries;
1820
public function register(Request $request)
1921
{
2022

2123
$data = $request->validate([
2224
'name' => 'required|string|max:255',
2325
'employeeid' => 'required|unique:users|string|max:255',
2426
'organization_unit_id' => 'required|exists:organization_units,id',
25-
'role' => ['required', Rule::in(['employee', 'approver', 'admin'])],
27+
'role' => ['required', Rule::in(['employee', 'approver'])],
2628
'email' => 'required|string|email|max:255|unique:users',
2729
'password' => 'required|string|min:8|confirmed',
2830
], [
@@ -147,9 +149,14 @@ public function loadUserProfile()
147149
public function RegisteredUsers()
148150
{
149151
try {
150-
$currentOrgUnitId = Auth::user()->organization_unit_id;
152+
$orgUnitId = $this->getOrgUnitId();
153+
$usersQuery = User::query()->orderBy('id', 'asc');
151154

152-
$users = User::query()->where('organization_unit_id', $currentOrgUnitId)->orderBy('id', 'asc')->get()
155+
if ($orgUnitId !== null) {
156+
$usersQuery->where('organization_unit_id', $orgUnitId);
157+
}
158+
159+
$users = $usersQuery->get()
153160
->map(function ($user) {
154161
$user->avatar_url = $user->avatar
155162
? Storage::url($user->avatar)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Models\OrganizationUnit;
6+
use App\Models\User;
7+
use Illuminate\Http\Request;
8+
9+
class OrganizationUnitController extends Controller
10+
{
11+
public function store(Request $request)
12+
{
13+
$validated = $request->validate([
14+
'unit_path' => ['required', 'string', 'max:50', 'unique:organization_units,unit_path'],
15+
]);
16+
17+
OrganizationUnit::create($validated);
18+
19+
return redirect()->back()->with('message', 'Organization unit created successfully.');
20+
}
21+
22+
public function update(Request $request, OrganizationUnit $organization_unit)
23+
{
24+
$validated = $request->validate([
25+
'unit_path' => ['required', 'string', 'max:50', 'unique:organization_units,unit_path,' . $organization_unit->id],
26+
]);
27+
28+
$organization_unit->update($validated);
29+
30+
return redirect()->back()->with('message', 'Organization unit updated successfully.');
31+
}
32+
33+
public function destroy(OrganizationUnit $organization_unit)
34+
{
35+
$validated = request()->validate([
36+
'reassign_to' => ['required', 'integer', 'exists:organization_units,id'],
37+
]);
38+
39+
$fallback = OrganizationUnit::find($validated['reassign_to']);
40+
41+
if ($fallback->id === $organization_unit->id) {
42+
return redirect()->back()->withErrors(['reassign_to' => 'Cannot reassign users to the unit being deleted.']);
43+
}
44+
45+
User::where('organization_unit_id', $organization_unit->id)
46+
->update(['organization_unit_id' => $fallback->id]);
47+
48+
$organization_unit->delete();
49+
50+
return redirect()->back()->with('message', 'Organization unit deleted successfully. Affected users were reassigned to "' . $fallback->unit_path . '".');
51+
}
52+
}

0 commit comments

Comments
 (0)