Skip to content
This repository was archived by the owner on Dec 3, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b9e907d
Add pet preferences page with Polish translations and routing
TomaszRebizant Aug 28, 2025
862cd93
edit style of form, add background, extract config adn styles
TomaszRebizant Aug 29, 2025
fe7899e
Improve form design and functionality
TomaszRebizant Aug 29, 2025
ef13c11
Restore all preference functionality
TomaszRebizant Sep 1, 2025
0a50c46
Refactor preferences page
TomaszRebizant Sep 2, 2025
d0d5e57
remove trails mode in background gradient
TomaszRebizant Sep 2, 2025
4eecd43
clean app.css
TomaszRebizant Sep 2, 2025
b1ff888
add pinia to the project
TomaszRebizant Sep 2, 2025
cf3fd8c
fix linter errors
TomaszRebizant Sep 3, 2025
695256a
make linter fixes
TomaszRebizant Sep 3, 2025
601fc45
Merge branch 'main' into 21-pet-preferences-selection-page
TomaszRebizant Sep 3, 2025
d19f219
resolve issue causing make test to fail
TomaszRebizant Sep 3, 2025
afe92b1
clean code
TomaszRebizant Sep 4, 2025
03db946
navigate to dashboard after applying filters
TomaszRebizant Sep 9, 2025
cfc2238
use database data in Pet Show view
TomaszRebizant Sep 10, 2025
d7c4f63
merge: main into 21-pet-preferences-selection-page; resolve Preferenc…
TomaszRebizant Sep 10, 2025
981e34c
remove dark mode
TomaszRebizant Sep 10, 2025
00d15c7
delete dark mode
TomaszRebizant Sep 10, 2025
97c7d2f
fix dark mode
TomaszRebizant Sep 10, 2025
e7f70f1
delete comment
TomaszRebizant Sep 10, 2025
069d421
fix linter errors
TomaszRebizant Sep 10, 2025
812ddb2
Revert package-lock.json to previous state
TomaszRebizant Sep 11, 2025
22e2be8
fix errors
TomaszRebizant Sep 11, 2025
6b83de6
fix test issues
TomaszRebizant Sep 11, 2025
67d21bd
Merge branch 'main' into 21-pet-preferences-selection-page
TomaszRebizant Sep 11, 2025
eb5b4be
add small fixes
TomaszRebizant Sep 11, 2025
0cccc0a
Add PR sugestions
TomaszRebizant Sep 12, 2025
c56b977
linter fixes
TomaszRebizant Sep 12, 2025
534dd9e
fix tags in specific pet view
TomaszRebizant Sep 15, 2025
a471ff8
linter fixes
TomaszRebizant Sep 15, 2025
7672601
delete comments
TomaszRebizant Sep 15, 2025
b8f13a0
improve accessibility across UI components
TomaszRebizant Sep 15, 2025
011a1d4
remoeve empty lines
TomaszRebizant Sep 15, 2025
602463c
fix linter errors
TomaszRebizant Sep 16, 2025
5beb228
Dashboard fixes, pet view improvements, preferences UX, connecting pr…
TomaszRebizant Sep 17, 2025
87045dd
Merge branch 'main' into 21-pet-preferences-selection-page
TomaszRebizant Sep 17, 2025
298ecfe
fix tests
TomaszRebizant Sep 17, 2025
e5e9cc7
Add cursor pointer improvements to UI elements
TomaszRebizant Sep 17, 2025
fe6a9e5
Merge branch 'main' into 21-pet-preferences-selection-page
TomaszRebizant Sep 18, 2025
7ed679a
Merge branch 'main' into 21-pet-preferences-selection-page
TomaszRebizant Sep 19, 2025
11d4a21
add image handling
TomaszRebizant Sep 21, 2025
25437e6
Delete .vite files
krzysztofkozyra021 Sep 21, 2025
e2fb116
linter
krzysztofkozyra021 Sep 21, 2025
cbd69bf
Merge main ,resolve conflicts
krzysztofkozyra021 Sep 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions app/Http/Controllers/PetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use App\Models\Pet;
use App\Services\TagService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

Expand All @@ -19,9 +20,12 @@ public function __construct(
private TagService $tagService,
) {}

public function index(): Response
public function index(Request $request): Response
{
$pets = Pet::query()->latest()->paginate(15);
$pets = Pet::query()
->with("tags")
->latest()
->paginate(50);

return Inertia::render("Dashboard/Dashboard", [
"pets" => PetIndexResource::collection($pets),
Expand Down
7 changes: 6 additions & 1 deletion app/Http/Controllers/PreferenceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

class PreferenceController extends Controller
{
public function show(): Response
{
return Inertia::render("Preferences/Preferences");
}

public function index(PetMatcher $matcher): Response
{
$user = request()->user();
Expand All @@ -24,7 +29,7 @@ public function index(PetMatcher $matcher): Response
->get()
->map(function (Pet $pet) use ($preference, $matcher): array {
$matchPercentage = $preference
? $matcher->match($pet->toArray(), $preference->preferences)
? $matcher->match($pet->toArray(), (array)($preference->preferences ?? []))
: 0;

return [
Expand Down
6 changes: 6 additions & 0 deletions app/Http/Resources/PetIndexResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ public function toArray($request): array
"species" => $pet->species,
"breed" => $pet->breed,
"sex" => $pet->sex,
"age" => $pet->age,
"size" => $pet->size,
"weight" => $pet->weight,
"color" => $pet->color,
"description" => $pet->description,
"behavioral_notes" => $pet->behavioral_notes,
"adoption_status" => $pet->adoption_status,
"tags" => $pet->tags->pluck("name")->values(),
];
}
}
30 changes: 22 additions & 8 deletions app/Services/PetMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,38 @@ class PetMatcher
{
public function match(array $petData, array $preferences): float
{
$normalized = [];

foreach ($preferences as $field => $prefValues) {
if (!is_array($prefValues)) {
continue;
}
$list = array_is_list($prefValues) ? $prefValues : [$prefValues];
$normalized[$field] = array_values(array_filter($list, static fn($p) => is_array($p) && (array_key_exists("value", $p) || array_key_exists("weight", $p))));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function types

}

$score = 0.0;
$maxScore = 0.0;

foreach ($preferences as $field => $prefValues) {
foreach ($normalized as $field => $prefValues) {
foreach ($prefValues as $pref) {
$weight = (float)($pref["weight"] ?? 1);
$maxScore += $weight;

if ($field === "tags" && isset($petData["tags"]) && is_array($petData["tags"])) {
$tagValues = array_map(
fn(array $tag): string|int => $tag["name"] ?? $tag["id"],
$petData["tags"],
);
if ($field === "tags") {
$petTags = isset($petData["tags"]) && is_array($petData["tags"]) ? $petData["tags"] : [];
$tagValues = array_map(static function ($tag) {
if (is_array($tag)) {
return $tag["name"] ?? $tag["id"] ?? null;
}

return $tag;
}, $petTags);

if (in_array($pref["value"], $tagValues, true)) {
if (array_key_exists("value", $pref) && in_array($pref["value"], $tagValues, true)) {
$score += $weight;
}
} elseif (isset($petData[$field]) && $petData[$field] === $pref["value"]) {
} elseif (isset($petData[$field]) && array_key_exists("value", $pref) && $petData[$field] === $pref["value"]) {
$score += $weight;
}
}
Expand Down
1 change: 1 addition & 0 deletions database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public function run(): void
{
$this->call([
DemoSeeder::class,
PetsOnlySeeder::class,
]);
}
}
134 changes: 134 additions & 0 deletions database/seeders/PetsOnlySeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?php

declare(strict_types=1);

namespace Database\Seeders;

use App\Models\Pet;
use App\Models\PetShelter;
use App\Models\Tag;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class PetsOnlySeeder extends Seeder
{
public function run(): void
{
$driver = DB::connection()->getDriverName();

if ($driver === "pgsql") {
DB::statement("TRUNCATE TABLE pet_tag RESTART IDENTITY CASCADE");
DB::statement("TRUNCATE TABLE pets RESTART IDENTITY CASCADE");
} elseif ($driver === "mysql") {
DB::statement("SET FOREIGN_KEY_CHECKS=0;");
DB::table("pet_tag")->truncate();
DB::table("pets")->truncate();
DB::statement("SET FOREIGN_KEY_CHECKS=1;");
} else {
DB::table("pet_tag")->truncate();
DB::table("pets")->truncate();
}

if (PetShelter::count() < 5) {
PetShelter::factory()->count(5 - PetShelter::count())->create();
}

$requiredTagNames = [
"friendly", "playful", "calm", "active", "gentle", "smart", "independent", "curious",
"good with kids", "good with dogs", "good with cats", "house trained", "leash trained", "low shedding",
];

foreach ($requiredTagNames as $name) {
Tag::firstOrCreate(["name" => $name]);
}

$tags = Tag::whereIn("name", $requiredTagNames)->get();
$shelters = PetShelter::all();

$curatedPets = [
["name" => "Buddy", "species" => "dog", "breed" => "Labrador Retriever", "sex" => "male", "age" => 24, "size" => "large", "weight" => 28.5, "color" => "yellow", "adoption_status" => "available", "tags" => ["friendly", "playful", "good with kids"]],
["name" => "Luna", "species" => "cat", "breed" => "Siamese", "sex" => "female", "age" => 12, "size" => "small", "weight" => 3.8, "color" => "seal point", "adoption_status" => "available", "tags" => ["curious", "smart", "independent"]],
["name" => "Max", "species" => "dog", "breed" => "German Shepherd", "sex" => "male", "age" => 36, "size" => "large", "weight" => 32.0, "color" => "black and tan", "adoption_status" => "available", "tags" => ["smart", "active", "leash trained"]],
["name" => "Bella", "species" => "dog", "breed" => "Golden Retriever", "sex" => "female", "age" => 48, "size" => "large", "weight" => 29.0, "color" => "golden", "adoption_status" => "available", "tags" => ["gentle", "friendly", "good with kids"]],
["name" => "Oliver", "species" => "cat", "breed" => "British Shorthair", "sex" => "male", "age" => 24, "size" => "medium", "weight" => 5.5, "color" => "blue", "adoption_status" => "available", "tags" => ["calm", "low shedding"]],
["name" => "Milo", "species" => "cat", "breed" => "Maine Coon", "sex" => "male", "age" => 36, "size" => "large", "weight" => 7.2, "color" => "brown tabby", "adoption_status" => "available", "tags" => ["friendly", "good with kids"]],
["name" => "Coco", "species" => "dog", "breed" => "Poodle", "sex" => "female", "age" => 60, "size" => "medium", "weight" => 18.0, "color" => "white", "adoption_status" => "available", "tags" => ["smart", "low shedding", "house trained"]],
["name" => "Charlie", "species" => "dog", "breed" => "Beagle", "sex" => "male", "age" => 24, "size" => "medium", "weight" => 11.0, "color" => "tricolor", "adoption_status" => "available", "tags" => ["curious", "playful"]],
["name" => "Rocky", "species" => "dog", "breed" => "Boxer", "sex" => "male", "age" => 48, "size" => "large", "weight" => 30.5, "color" => "fawn", "adoption_status" => "available", "tags" => ["active", "friendly"]],
["name" => "Daisy", "species" => "dog", "breed" => "Bulldog", "sex" => "female", "age" => 36, "size" => "medium", "weight" => 22.0, "color" => "brindle", "adoption_status" => "available", "tags" => ["gentle", "calm"]],
["name" => "Simba", "species" => "cat", "breed" => "Bengal", "sex" => "male", "age" => 24, "size" => "medium", "weight" => 4.5, "color" => "brown spotted", "adoption_status" => "available", "tags" => ["active", "curious"]],
["name" => "Chloe", "species" => "cat", "breed" => "Ragdoll", "sex" => "female", "age" => 36, "size" => "large", "weight" => 6.0, "color" => "seal bicolor", "adoption_status" => "available", "tags" => ["gentle", "friendly"]],
["name" => "Nala", "species" => "cat", "breed" => "Sphynx", "sex" => "female", "age" => 24, "size" => "medium", "weight" => 3.2, "color" => "pink", "adoption_status" => "available", "tags" => ["friendly", "curious"]],
["name" => "Sadie", "species" => "dog", "breed" => "Dachshund", "sex" => "female", "age" => 72, "size" => "small", "weight" => 8.0, "color" => "red", "adoption_status" => "available", "tags" => ["independent", "house trained"]],
["name" => "Zeus", "species" => "dog", "breed" => "Rottweiler", "sex" => "male", "age" => 60, "size" => "large", "weight" => 45.0, "color" => "black and tan", "adoption_status" => "available", "tags" => ["smart", "leash trained"]],
["name" => "Lily", "species" => "dog", "breed" => "Yorkshire Terrier", "sex" => "female", "age" => 48, "size" => "small", "weight" => 3.2, "color" => "blue and tan", "adoption_status" => "available", "tags" => ["playful", "low shedding"]],
["name" => "Leo", "species" => "cat", "breed" => "Russian Blue", "sex" => "male", "age" => 36, "size" => "medium", "weight" => 4.2, "color" => "blue", "adoption_status" => "available", "tags" => ["calm", "smart"]],
["name" => "Misty", "species" => "cat", "breed" => "Persian", "sex" => "female", "age" => 60, "size" => "medium", "weight" => 4.0, "color" => "white", "adoption_status" => "available", "tags" => ["gentle", "low shedding"]],
["name" => "Finn", "species" => "dog", "breed" => "Border Collie", "sex" => "male", "age" => 24, "size" => "medium", "weight" => 19.0, "color" => "black and white", "adoption_status" => "available", "tags" => ["smart", "active"]],
["name" => "Zoe", "species" => "cat", "breed" => "Norwegian Forest", "sex" => "female", "age" => 48, "size" => "large", "weight" => 5.8, "color" => "brown tabby", "adoption_status" => "available", "tags" => ["friendly", "curious"]],
];

foreach ($curatedPets as $data) {
$descBySpecies = [
"dog" => "Lubi spacery i zabawę, łagodny w domu i towarzyski na zewnątrz.",
"cat" => "Ciekawska i spokojna, lubi wylegiwać się na słońcu i bawić wędką.",
];
$healthPool = ["healthy", "healthy", "healthy", "recovering"];
$health = $healthPool[array_rand($healthPool)];
$currentTreatment = $health === "recovering" ? "Krótka rekonwalescencja po szczepieniu, zalecany odpoczynek." : null;
$sterilized = rand(0, 1) === 1;
$vaccinated = rand(0, 1) === 1;
$hasChip = rand(0, 1) === 1;
$chip = $hasChip ? strtoupper(Str::random(12)) : null;
$dewormed = rand(0, 1) === 1;
$deflea = rand(0, 1) === 1;
$medicalTests = $health === "healthy" ? "basic: negative" : "blood: normal; xray: clear";
$food = collect(["dry", "wet", "mixed"])->random();
$behavioral = $data["species"] === "dog" ? "Spokojny w domu, energiczny na zewnątrz." : "Lubi drapaki i ciche otoczenie.";
$admission = now()->subDays(rand(7, 180));
$city = collect(["Warsaw", "Krakow", "Gdansk", "Wroclaw", "Poznan"])->random();
$adoptionUrl = "https://adopt.local/pets/" . Str::slug($data["name"] . " " . $data["breed"]);

$pet = Pet::create([
"name" => $data["name"],
"adoption_url" => $adoptionUrl,
"species" => $data["species"],
"breed" => $data["breed"],
"sex" => $data["sex"],
"age" => $data["age"],
"size" => $data["size"],
"weight" => $data["weight"],
"color" => $data["color"],
"sterilized" => $sterilized,
"description" => $descBySpecies[$data["species"]] ?? "Przyjazny i towarzyski.",
"health_status" => $health,
"current_treatment" => $currentTreatment,
"vaccinated" => $vaccinated,
"has_chip" => $hasChip,
"chip_number" => $chip,
"dewormed" => $dewormed,
"deflea_treated" => $deflea,
"medical_tests" => $medicalTests,
"food_type" => $food,
"attitude_to_people" => "friendly",
"attitude_to_dogs" => "friendly",
"attitude_to_cats" => "neutral",
"attitude_to_children" => "gentle",
"activity_level" => collect(["low", "medium", "high"])->random(),
"behavioral_notes" => $behavioral,
"admission_date" => $admission,
"found_location" => $city,
"adoption_status" => $data["adoption_status"],
"shelter_id" => $shelters->random()->id,
"is_accepted" => true,
]);

$tagIds = $tags->whereIn("name", $data["tags"])->pluck("id")->toArray();

if (!empty($tagIds)) {
$pet->tags()->sync($tagIds);
}
}
}
}
15 changes: 15 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import blumilkDefault from '@blumilksoftware/eslint-config'
import globals from 'globals'

export default [
...blumilkDefault,
{
languageOptions: {
globals: {
...globals.browser,
...globals.es2022,
},
},
rules: {
'n/no-unsupported-features/node-builtins': ['error', {
allowExperimental: true,
ignores: ['fetch', 'localStorage', 'sessionStorage', 'AbortController'],
}],
},
},
]
Loading
Loading