#23 - wip
This commit is contained in:
parent
a62a428781
commit
5a51f24342
51
app/Helpers/YearPeriodRetriever.php
Normal file
51
app/Helpers/YearPeriodRetriever.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Helpers;
|
||||
|
||||
use Toby\Models\YearPeriod;
|
||||
|
||||
class YearPeriodRetriever
|
||||
{
|
||||
public const SESSION_KEY = "selected_year_period";
|
||||
|
||||
public function selected(): YearPeriod
|
||||
{
|
||||
/** @var YearPeriod $yearPeriod */
|
||||
$yearPeriod = YearPeriod::query()->find(session()->get(static::SESSION_KEY));
|
||||
|
||||
return $yearPeriod !== null ? $yearPeriod : $this->current();
|
||||
}
|
||||
|
||||
public function current(): YearPeriod
|
||||
{
|
||||
return YearPeriod::current();
|
||||
}
|
||||
|
||||
public function links(): array
|
||||
{
|
||||
$current = $this->selected();
|
||||
|
||||
$years = YearPeriod::query()->whereIn("year", $this->offset($current->year))->get();
|
||||
$navigation = $years->map(fn(YearPeriod $yearPeriod) => $this->toNavigation($yearPeriod));
|
||||
|
||||
return [
|
||||
"current" => $current->year,
|
||||
"navigation" => $navigation->toArray(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function offset(int $year): array
|
||||
{
|
||||
return range($year - 2, $year + 2);
|
||||
}
|
||||
|
||||
protected function toNavigation(YearPeriod $yearPeriod): array
|
||||
{
|
||||
return [
|
||||
"year" => $yearPeriod->year,
|
||||
"link" => route("year-periods.select", $yearPeriod->id),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Inertia\Response;
|
||||
use Toby\Http\Resources\VacationLimitResource;
|
||||
use Toby\Http\Resources\YearPeriodResource;
|
||||
use Toby\Models\YearPeriod;
|
||||
|
||||
class VacationDaysController extends Controller
|
||||
{
|
||||
public function edit(Request $request): Response
|
||||
{
|
||||
$year = $request->query("year", Carbon::now()->year);
|
||||
|
||||
/** @var YearPeriod $yearPeriod */
|
||||
$yearPeriod = YearPeriod::query()->where("year", $year)->firstOrFail();
|
||||
$previousYearPeriod = YearPeriod::query()->where("year", $year - 1)->first();
|
||||
$nextYearPeriod = YearPeriod::query()->where("year", $year + 1)->first();
|
||||
|
||||
|
||||
return inertia("VacationDays", [
|
||||
"vacationLimits" => VacationLimitResource::collection($yearPeriod->vacationLimits()->with("user")->get()),
|
||||
"yearPeriods" => [
|
||||
"prev" => $previousYearPeriod ? new YearPeriodResource($previousYearPeriod) : null,
|
||||
"current" => new YearPeriodResource($yearPeriod),
|
||||
"next" => $nextYearPeriod ? new YearPeriodResource($nextYearPeriod) : null,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request)
|
||||
{
|
||||
dump($request->get("items"));
|
||||
}
|
||||
}
|
35
app/Http/Controllers/VacationLimitController.php
Normal file
35
app/Http/Controllers/VacationLimitController.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Arr;
|
||||
use Inertia\Response;
|
||||
use Toby\Http\Requests\VacationLimitRequest;
|
||||
use Toby\Http\Resources\VacationLimitResource;
|
||||
use Toby\Models\VacationLimit;
|
||||
|
||||
class VacationLimitController extends Controller
|
||||
{
|
||||
public function edit(): Response
|
||||
{
|
||||
return inertia("VacationLimits", [
|
||||
"limits" => VacationLimitResource::collection(VacationLimit::query()->with("user")->get()),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(VacationLimitRequest $request): RedirectResponse
|
||||
{
|
||||
foreach ($request->data() as $data) {
|
||||
$limit = VacationLimit::query()->find($data["id"]);
|
||||
|
||||
$limit->update(Arr::only($data, ["has_vacation", "days"]));
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with("success", __("Vacation limits have been updated"));
|
||||
}
|
||||
}
|
@ -6,10 +6,15 @@ namespace Toby\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Middleware;
|
||||
use Toby\Helpers\YearPeriodRetriever;
|
||||
use Toby\Http\Resources\UserResource;
|
||||
|
||||
class HandleInertiaRequests extends Middleware
|
||||
{
|
||||
public function __construct(protected YearPeriodRetriever $yearPeriodRetriever)
|
||||
{
|
||||
}
|
||||
|
||||
public function share(Request $request): array
|
||||
{
|
||||
$user = $request->user();
|
||||
@ -22,6 +27,7 @@ class HandleInertiaRequests extends Middleware
|
||||
"success" => $request->session()->get("success"),
|
||||
"error" => $request->session()->get("error"),
|
||||
],
|
||||
"years" => fn() => $user ? $this->yearPeriodRetriever->links() : [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
30
app/Http/Requests/VacationLimitRequest.php
Normal file
30
app/Http/Requests/VacationLimitRequest.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class VacationLimitRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
"items" => ["required", "array"],
|
||||
"items.*.id" => ["required", "exists:vacation_limits,id"],
|
||||
"items.*.hasVacation" => ["required", "boolean"],
|
||||
"items.*.days" => ["exclude_if:items.*.hasVacation,false", "required", "integer", "min:0"],
|
||||
];
|
||||
}
|
||||
|
||||
public function data(): Collection
|
||||
{
|
||||
return $this->collect("items")->map(fn(array $item): array => [
|
||||
"id" => $item["id"],
|
||||
"has_vacation" => $item["hasVacation"],
|
||||
"days" => $item["days"],
|
||||
]);
|
||||
}
|
||||
}
|
@ -8,11 +8,12 @@ use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class VacationLimitResource extends JsonResource
|
||||
{
|
||||
public static $wrap = null;
|
||||
public static $wrap = false;
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"user" => new UserResource($this->user),
|
||||
"hasVacation" => $this->has_vacation,
|
||||
"days" => $this->days,
|
||||
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class YearPeriodResource extends JsonResource
|
||||
{
|
||||
public static $wrap = false;
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
"id" => $this->id,
|
||||
"year" => $this->year,
|
||||
];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@ class VacationLimit extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
"has_vacation" => "boolean",
|
||||
];
|
||||
|
@ -7,7 +7,9 @@ namespace Toby\Providers;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Toby\Models\User;
|
||||
use Toby\Models\VacationLimit;
|
||||
use Toby\Observers\UserObserver;
|
||||
use Toby\Scopes\SelectedYearPeriodScope;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -16,5 +18,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
User::observe(UserObserver::class);
|
||||
|
||||
Carbon::macro("toDisplayString", fn() => $this->translatedFormat("j F Y"));
|
||||
|
||||
VacationLimit::addGlobalScope($this->app->make(SelectedYearPeriodScope::class));
|
||||
}
|
||||
}
|
||||
|
22
app/Scopes/SelectedYearPeriodScope.php
Normal file
22
app/Scopes/SelectedYearPeriodScope.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Scopes;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Scope;
|
||||
use Toby\Helpers\YearPeriodRetriever;
|
||||
|
||||
class SelectedYearPeriodScope implements Scope
|
||||
{
|
||||
public function __construct(protected YearPeriodRetriever $yearPeriodRetriever)
|
||||
{
|
||||
}
|
||||
|
||||
public function apply(Builder $builder, Model $model): Builder
|
||||
{
|
||||
return $builder->where("year_period_id", $this->yearPeriodRetriever->selected()->id);
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ class DatabaseSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
User::factory(35)->create();
|
||||
User::factory(14)->create();
|
||||
User::factory([
|
||||
"email" => env("LOCAL_EMAIL_FOR_LOGIN_VIA_GOOGLE"),
|
||||
])->create();
|
||||
|
2129
package-lock.json
generated
2129
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,8 @@
|
||||
"vue-loader": "^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browser-sync": "^2.27.7",
|
||||
"browser-sync-webpack-plugin": "^2.3.0",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-plugin-vue": "^8.2.0"
|
||||
}
|
||||
|
@ -10,45 +10,6 @@
|
||||
Zarządzaj dostepnymi dniami urlopów dla użytkowników.
|
||||
</p>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<span class="relative z-0 inline-flex shadow-sm rounded-md">
|
||||
<InertiaLink
|
||||
v-if="yearPeriods.prev"
|
||||
:preserve-scroll="true"
|
||||
replace
|
||||
href="/vacation-days"
|
||||
:data="{year: yearPeriods.prev.year}"
|
||||
class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-blumilk-500 focus:border-blumilk-500"
|
||||
>
|
||||
<ChevronLeftIcon class="h-5 w-5" />
|
||||
</InertiaLink>
|
||||
<span
|
||||
v-else
|
||||
class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500"
|
||||
>
|
||||
<ChevronLeftIcon class="h-5 w-5" />
|
||||
</span>
|
||||
<span class="-ml-px relative inline-flex items-center px-2 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-500">
|
||||
{{ yearPeriods.current.year }}
|
||||
</span>
|
||||
<InertiaLink
|
||||
v-if="yearPeriods.next"
|
||||
:preserve-scroll="true"
|
||||
href="/vacation-days"
|
||||
replace
|
||||
:data="{year: yearPeriods.next.year}"
|
||||
class="-ml-px relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-blumilk-500 focus:border-blumilk-500"
|
||||
>
|
||||
<ChevronRightIcon class="h-5 w-5" />
|
||||
</InertiaLink>
|
||||
<span
|
||||
v-else
|
||||
class="-ml-px relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500"
|
||||
>
|
||||
<ChevronRightIcon class="h-5 w-5" />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-gray-200">
|
||||
<div class="overflow-x-auto xl:overflow-x-visible overflow-y-auto xl:overflow-y-visible">
|
||||
@ -84,7 +45,7 @@
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-100">
|
||||
<tr
|
||||
v-for="item in form.items"
|
||||
v-for="(item, index) in form.items"
|
||||
:key="item.id"
|
||||
class="hover:bg-blumilk-25"
|
||||
>
|
||||
@ -128,14 +89,15 @@
|
||||
v-model="item.days"
|
||||
type="number"
|
||||
min="0"
|
||||
class="block w-full shadow-sm rounded-md sm:text-sm"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': false, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': true }"
|
||||
class="block w-full shadow-sm rounded-md sm:text-sm disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none disabled:cursor-not-allowed"
|
||||
:disabled="!item.hasVacation"
|
||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`items.${index}.days`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`items.${index}.days`] }"
|
||||
>
|
||||
<p
|
||||
v-if="false"
|
||||
v-if="form.errors[`items.${index}.days`]"
|
||||
class="mt-2 text-sm text-red-600"
|
||||
>
|
||||
{{ form.errors.name }}
|
||||
{{ form.errors[`items.${index}.days`] }}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
@ -153,20 +115,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="flex justify-end py-3 px-4">
|
||||
<div class="space-x-3">
|
||||
<InertiaLink
|
||||
href="/users"
|
||||
class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||
>
|
||||
Anuluj
|
||||
</InertiaLink>
|
||||
<button
|
||||
type="submit"
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||
>
|
||||
Zapisz
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||
>
|
||||
Zapisz
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -175,30 +129,27 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Switch } from '@headlessui/vue';
|
||||
import {ChevronLeftIcon, ChevronRightIcon} from '@heroicons/vue/solid';
|
||||
import {Switch} from '@headlessui/vue';
|
||||
import {useForm} from '@inertiajs/inertia-vue3';
|
||||
|
||||
export default {
|
||||
name: 'VacationDays',
|
||||
name: 'VacationLimits',
|
||||
components: {
|
||||
Switch,
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
},
|
||||
props: {
|
||||
vacationLimits: {
|
||||
limits: {
|
||||
type: Object,
|
||||
default: () => null,
|
||||
},
|
||||
yearPeriods: {
|
||||
years: {
|
||||
type: Object,
|
||||
default: () => null,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const form = useForm({
|
||||
items: props.vacationLimits.data,
|
||||
items: props.limits.data,
|
||||
});
|
||||
|
||||
return {
|
||||
@ -209,9 +160,16 @@ export default {
|
||||
submitVacationDays() {
|
||||
this.form
|
||||
.transform(data => ({
|
||||
data,
|
||||
items: data.items.map(item => ({
|
||||
id: item.id,
|
||||
hasVacation: item.hasVacation,
|
||||
days: item.hasVacation ? item.days : null,
|
||||
})),
|
||||
}))
|
||||
.put('/vacation-days');
|
||||
.put('/vacation-days', {
|
||||
preserveState: (page) => Object.keys(page.props.errors).length,
|
||||
preserveScroll: true,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
@ -19,6 +19,53 @@
|
||||
|
||||
<!-- Right section on desktop -->
|
||||
<div class="hidden lg:ml-4 lg:flex lg:items-center lg:py-5 lg:pr-0.5">
|
||||
<div class="mr-4">
|
||||
<Menu
|
||||
as="div"
|
||||
class="relative inline-block text-left"
|
||||
>
|
||||
<div>
|
||||
<MenuButton class="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-1 focus:ring-gray-300">
|
||||
{{ years.current }}
|
||||
<ChevronDownIcon class="-mr-1 ml-2 h-5 w-5" />
|
||||
</MenuButton>
|
||||
</div>
|
||||
|
||||
<transition
|
||||
enter-active-class="transition ease-out duration-100"
|
||||
enter-from-class="transform opacity-0 scale-95"
|
||||
enter-to-class="transform opacity-100 scale-100"
|
||||
leave-active-class="transition ease-in duration-75"
|
||||
leave-from-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-95"
|
||||
>
|
||||
<MenuItems class="origin-top-right absolute right-0 mt-2 w-32 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
<div class="py-1">
|
||||
<MenuItem
|
||||
v-for="(item, index) in years.navigation"
|
||||
:key="index"
|
||||
v-slot="{ active }"
|
||||
>
|
||||
<InertiaLink
|
||||
:href="item.link"
|
||||
as="button"
|
||||
method="post"
|
||||
:preserve-state="false"
|
||||
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'flex w-full px-4 py-2 text-sm']"
|
||||
>
|
||||
{{ item.year }}
|
||||
<CheckIcon
|
||||
v-if="item.year === years.current"
|
||||
class="h-5 w-5 text-blumilk-500 ml-2"
|
||||
/>
|
||||
</InertiaLink>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</MenuItems>
|
||||
</transition>
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="flex-shrink-0 p-1 text-cyan-200 rounded-full hover:text-white hover:bg-white hover:bg-opacity-10 focus:outline-none focus:ring-2 focus:ring-white"
|
||||
@ -246,6 +293,7 @@ import {
|
||||
import {BellIcon, MenuIcon, XIcon} from '@heroicons/vue/outline';
|
||||
import {computed} from 'vue';
|
||||
import {usePage} from '@inertiajs/inertia-vue3';
|
||||
import {ChevronDownIcon, CheckIcon} from '@heroicons/vue/solid';
|
||||
|
||||
export default {
|
||||
name: 'MainMenu',
|
||||
@ -263,9 +311,12 @@ export default {
|
||||
BellIcon,
|
||||
MenuIcon,
|
||||
XIcon,
|
||||
ChevronDownIcon,
|
||||
CheckIcon,
|
||||
},
|
||||
setup() {
|
||||
const user = computed(() => usePage().props.value.auth.user);
|
||||
const years = computed(() => usePage().props.value.years);
|
||||
|
||||
const navigation = [
|
||||
{name: 'Strona główna', href: '/', current: true},
|
||||
@ -282,6 +333,7 @@ export default {
|
||||
|
||||
return {
|
||||
user,
|
||||
years,
|
||||
navigation,
|
||||
userNavigation,
|
||||
};
|
||||
|
@ -2,11 +2,14 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Toby\Helpers\YearPeriodRetriever;
|
||||
use Toby\Http\Controllers\GoogleController;
|
||||
use Toby\Http\Controllers\LogoutController;
|
||||
use Toby\Http\Controllers\UserController;
|
||||
use Toby\Http\Controllers\VacationDaysController;
|
||||
use Toby\Http\Controllers\VacationLimitController;
|
||||
use Toby\Models\YearPeriod;
|
||||
|
||||
Route::middleware("auth")->group(function (): void {
|
||||
Route::get("/", fn() => inertia("Dashboard"))->name("dashboard");
|
||||
@ -15,8 +18,14 @@ Route::middleware("auth")->group(function (): void {
|
||||
Route::resource("users", UserController::class);
|
||||
Route::post("users/{user}/restore", [UserController::class, "restore"])->withTrashed();
|
||||
|
||||
Route::get("/vacation-days", [VacationDaysController::class, "edit"])->name("vacation.days");
|
||||
Route::put("/vacation-days", [VacationDaysController::class, "update"]);
|
||||
Route::get("/vacation-days", [VacationLimitController::class, "edit"])->name("vacation.days");
|
||||
Route::put("/vacation-days", [VacationLimitController::class, "update"]);
|
||||
|
||||
Route::post("year-periods/{yearPeriod}/select", function (Request $request, YearPeriod $yearPeriod) {
|
||||
$request->session()->put(YearPeriodRetriever::SESSION_KEY, $yearPeriod->id);
|
||||
|
||||
return redirect()->back();
|
||||
})->name("year-periods.select");
|
||||
});
|
||||
|
||||
Route::middleware("guest")->group(function (): void {
|
||||
|
@ -5,10 +5,10 @@ declare(strict_types=1);
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Tests\TestCase;
|
||||
use Tests\FeatureTestCase;
|
||||
use Toby\Models\User;
|
||||
|
||||
class AuthenticationTest extends TestCase
|
||||
class AuthenticationTest extends FeatureTestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
||||
|
@ -6,10 +6,10 @@ namespace Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
use Tests\TestCase;
|
||||
use Tests\FeatureTestCase;
|
||||
use Toby\Models\User;
|
||||
|
||||
class InertiaTest extends TestCase
|
||||
class InertiaTest extends FeatureTestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
||||
|
@ -8,11 +8,11 @@ use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
use Tests\TestCase;
|
||||
use Tests\FeatureTestCase;
|
||||
use Toby\Enums\EmploymentForm;
|
||||
use Toby\Models\User;
|
||||
|
||||
class UserTest extends TestCase
|
||||
class UserTest extends FeatureTestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
||||
|
21
tests/FeatureTestCase.php
Normal file
21
tests/FeatureTestCase.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
use Tests\Traits\InteractsWithYearPeriods;
|
||||
|
||||
abstract class FeatureTestCase extends BaseTestCase
|
||||
{
|
||||
use CreatesApplication;
|
||||
use InteractsWithYearPeriods;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->createCurrentYearPeriod();
|
||||
}
|
||||
}
|
38
tests/Traits/InteractsWithYearPeriods.php
Normal file
38
tests/Traits/InteractsWithYearPeriods.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Traits;
|
||||
|
||||
use Illuminate\Foundation\Testing\Concerns\InteractsWithSession;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Toby\Helpers\YearPeriodRetriever;
|
||||
use Toby\Models\YearPeriod;
|
||||
|
||||
trait InteractsWithYearPeriods
|
||||
{
|
||||
use InteractsWithSession;
|
||||
|
||||
public function createYearPeriod(int $year): YearPeriod
|
||||
{
|
||||
/** @var YearPeriod $yearPeriod */
|
||||
$yearPeriod = YearPeriod::factory()->create(["year" => $year]);
|
||||
|
||||
return $yearPeriod;
|
||||
}
|
||||
|
||||
public function createCurrentYearPeriod(): YearPeriod
|
||||
{
|
||||
return $this->createYearPeriod(Carbon::now()->year);
|
||||
}
|
||||
|
||||
public function markYearPeriodAsSelected(YearPeriod $yearPeriod): void
|
||||
{
|
||||
$this->session([YearPeriodRetriever::SESSION_KEY => $yearPeriod->id]);
|
||||
}
|
||||
|
||||
public function clearSelectedYearPeriod(): void
|
||||
{
|
||||
$this->session([]);
|
||||
}
|
||||
}
|
@ -7,12 +7,14 @@ namespace Tests\Unit;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Tests\TestCase;
|
||||
use Tests\Traits\InteractsWithYearPeriods;
|
||||
use Toby\Jobs\CheckYearPeriod;
|
||||
use Toby\Models\YearPeriod;
|
||||
|
||||
class CheckYearPeriodTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
use InteractsWithYearPeriods;
|
||||
|
||||
public function testYearPeriodsAreCreatedWhenDontExist(): void
|
||||
{
|
||||
@ -54,9 +56,7 @@ class CheckYearPeriodTest extends TestCase
|
||||
$now = Carbon::now();
|
||||
Carbon::setTestNow($now);
|
||||
|
||||
YearPeriod::factory([
|
||||
"year" => $now->year,
|
||||
]);
|
||||
$this->createCurrentYearPeriod();
|
||||
|
||||
$this->assertDatabaseMissing("year_periods", [
|
||||
"year" => $now->year + 1,
|
||||
@ -74,12 +74,8 @@ class CheckYearPeriodTest extends TestCase
|
||||
$now = Carbon::now();
|
||||
Carbon::setTestNow($now);
|
||||
|
||||
YearPeriod::factory([
|
||||
"year" => $now->year,
|
||||
])->create();
|
||||
YearPeriod::factory([
|
||||
"year" => $now->year + 1,
|
||||
])->create();
|
||||
$this->createCurrentYearPeriod();
|
||||
$this->createYearPeriod($now->year + 1);
|
||||
|
||||
$this->assertDatabaseCount("year_periods", 2);
|
||||
|
||||
|
83
tests/Unit/YearPeriodRetrieverTest.php
Normal file
83
tests/Unit/YearPeriodRetrieverTest.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Illuminate\Foundation\Testing\Concerns\InteractsWithSession;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Tests\TestCase;
|
||||
use Tests\Traits\InteractsWithYearPeriods;
|
||||
use Toby\Helpers\YearPeriodRetriever;
|
||||
use Toby\Models\YearPeriod;
|
||||
|
||||
class YearPeriodRetrieverTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
use InteractsWithSession;
|
||||
use InteractsWithYearPeriods;
|
||||
|
||||
public Carbon $current;
|
||||
public YearPeriod $previousYearPeriod;
|
||||
public YearPeriod $currentYearPeriod;
|
||||
public YearPeriod $nextYearPeriod;
|
||||
public YearPeriodRetriever $yearPeriodRetriever;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->current = Carbon::now();
|
||||
Carbon::setTestNow($this->current);
|
||||
|
||||
$this->yearPeriodRetriever = new YearPeriodRetriever();
|
||||
|
||||
$this->previousYearPeriod = $this->createYearPeriod($this->current->year - 1);
|
||||
$this->currentYearPeriod = $this->createCurrentYearPeriod();
|
||||
$this->nextYearPeriod = $this->createYearPeriod($this->current->year + 1);
|
||||
}
|
||||
|
||||
public function testRetrievesCorrectCurrentYearPeriod(): void
|
||||
{
|
||||
$this->assertSame($this->currentYearPeriod->id, $this->yearPeriodRetriever->current()->id);
|
||||
}
|
||||
|
||||
public function testRetrievesCurrentYearPeriodWhenNoSelected(): void
|
||||
{
|
||||
$this->clearSelectedYearPeriod();
|
||||
|
||||
$this->assertSame($this->currentYearPeriod->id, $this->yearPeriodRetriever->selected()->id);
|
||||
}
|
||||
|
||||
public function testRetrievesCorrectYearPeriodWhenSelected(): void
|
||||
{
|
||||
$this->markYearPeriodAsSelected($this->nextYearPeriod);
|
||||
|
||||
$this->assertSame($this->nextYearPeriod->id, $this->yearPeriodRetriever->selected()->id);
|
||||
}
|
||||
|
||||
public function testLinks(): void
|
||||
{
|
||||
$expected = [
|
||||
"current" => $this->current->year,
|
||||
"navigation" => [
|
||||
[
|
||||
"year" => $this->previousYearPeriod->year,
|
||||
"link" => route("year-periods.select", $this->previousYearPeriod)
|
||||
],
|
||||
[
|
||||
"year" => $this->currentYearPeriod->year,
|
||||
"link" => route("year-periods.select", $this->currentYearPeriod)
|
||||
],
|
||||
[
|
||||
"year" => $this->nextYearPeriod->year,
|
||||
"link" => route("year-periods.select", $this->nextYearPeriod)
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
$this->assertSame($expected, $this->yearPeriodRetriever->links());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user