From e055af9248ff7c4daa2dbe9f26889ac472fa2ba2 Mon Sep 17 00:00:00 2001 From: Gregor Klevze Date: Sun, 8 Feb 2026 10:42:01 +0100 Subject: [PATCH] current state --- .copilot/favourites_artworks.md | 181 ++++++ .copilot/update_user_schema.md | 312 +++++++++ app/Chat.php | 6 +- .../Commands/ImportLegacyFavourites.php | 137 ++++ app/Console/Commands/ImportLegacyUsers.php | 8 +- .../Commands/ImportWallzCategories.php | 92 +++ .../Controllers/Admin/ArtworkController.php | 39 ++ .../Controllers/CategoryPageController.php | 31 +- app/Http/Controllers/Controller.php | 9 +- .../Dashboard/ArtworkController.php | 102 +++ app/Http/Controllers/GalleryController.php | 41 ++ app/Http/Controllers/Legacy/ArtController.php | 4 +- .../Controllers/Legacy/AvatarController.php | 2 +- .../Controllers/Legacy/BuddiesController.php | 37 ++ .../Controllers/Legacy/ChatController.php | 2 +- .../Legacy/FavouritesController.php | 146 +++++ .../Legacy/InterviewController.php | 14 +- .../Legacy/InterviewsController.php | 2 +- .../Legacy/MonthlyCommentatorsController.php | 2 +- .../Legacy/MyBuddiesController.php | 57 ++ .../Controllers/Legacy/NewsController.php | 4 +- .../Legacy/PhotographyController.php | 81 +++ .../Legacy/ReceivedCommentsController.php | 38 ++ .../Legacy/StatisticsController.php | 66 ++ .../Legacy/TodayInHistoryController.php | 6 +- .../Legacy/TopAuthorsController.php | 69 -- .../Legacy/TopFavouritesController.php | 2 +- .../Controllers/Legacy/UserController.php | 120 ++++ app/Http/Controllers/LegacyController.php | 84 +-- app/Http/Controllers/ManageController.php | 47 +- .../Dashboard/UpdateArtworkRequest.php | 24 + app/Models/User.php | 6 + app/Models/UserFavorite.php | 29 + app/Services/LegacyService.php | 112 ++-- composer.json | 1 + composer.lock | 272 +++++++- ..._07_000001_create_user_favorites_table.php | 32 + package-lock.json | 398 +++++++++++- package.json | 3 +- public/css/nova.css | 187 ++++++ public/js/nova.js | 24 + public/legacy/js/nova.js | 24 + public/nova.html | 597 ++++++++++++++++++ resources/js/nova.js | 223 +++++++ resources/scss/nova.scss | 5 + resources/views/artworks/edit.blade.php | 85 +++ resources/views/artworks/index.blade.php | 104 +++ resources/views/blank.blade.php | 18 + resources/views/dashboard.blade.php | 52 +- resources/views/layouts/nova.blade.php | 177 ++++++ resources/views/layouts/nova/footer.blade.php | 11 + resources/views/layouts/nova/header.blade.php | 0 .../views/layouts/nova/toolbar.blade.php | 214 +++++++ .../views/legacy/_artwork_card.blade.php | 37 +- resources/views/legacy/buddies.blade.php | 44 ++ .../views/legacy/category-slug.blade.php | 150 +++-- resources/views/legacy/favourites.blade.php | 73 +++ resources/views/legacy/gallery.blade.php | 60 ++ resources/views/legacy/interview.blade.php | 2 +- resources/views/legacy/mybuddies.blade.php | 56 ++ resources/views/legacy/photography.blade.php | 55 ++ .../views/legacy/received-comments.blade.php | 63 ++ resources/views/legacy/statistics.blade.php | 81 +++ resources/views/legacy/toolbar.blade.php | 2 +- resources/views/legacy/user.blade.php | 153 +++++ .../vendor/pagination/bootstrap-3.blade.php | 36 ++ routes/legacy.php | 42 +- routes/web.php | 10 + storage/debugbar/.gitignore | 2 + vite.config.js | 7 +- 70 files changed, 4882 insertions(+), 330 deletions(-) create mode 100644 .copilot/favourites_artworks.md create mode 100644 .copilot/update_user_schema.md create mode 100644 app/Console/Commands/ImportLegacyFavourites.php create mode 100644 app/Console/Commands/ImportWallzCategories.php create mode 100644 app/Http/Controllers/Admin/ArtworkController.php create mode 100644 app/Http/Controllers/Dashboard/ArtworkController.php create mode 100644 app/Http/Controllers/GalleryController.php create mode 100644 app/Http/Controllers/Legacy/BuddiesController.php create mode 100644 app/Http/Controllers/Legacy/FavouritesController.php create mode 100644 app/Http/Controllers/Legacy/MyBuddiesController.php create mode 100644 app/Http/Controllers/Legacy/PhotographyController.php create mode 100644 app/Http/Controllers/Legacy/ReceivedCommentsController.php create mode 100644 app/Http/Controllers/Legacy/StatisticsController.php create mode 100644 app/Http/Controllers/Legacy/UserController.php create mode 100644 app/Http/Requests/Dashboard/UpdateArtworkRequest.php create mode 100644 app/Models/UserFavorite.php create mode 100644 database/migrations/2026_02_07_000001_create_user_favorites_table.php create mode 100644 public/css/nova.css create mode 100644 public/js/nova.js create mode 100644 public/legacy/js/nova.js create mode 100644 public/nova.html create mode 100644 resources/js/nova.js create mode 100644 resources/scss/nova.scss create mode 100644 resources/views/artworks/edit.blade.php create mode 100644 resources/views/artworks/index.blade.php create mode 100644 resources/views/blank.blade.php create mode 100644 resources/views/layouts/nova.blade.php create mode 100644 resources/views/layouts/nova/footer.blade.php create mode 100644 resources/views/layouts/nova/header.blade.php create mode 100644 resources/views/layouts/nova/toolbar.blade.php create mode 100644 resources/views/legacy/buddies.blade.php create mode 100644 resources/views/legacy/favourites.blade.php create mode 100644 resources/views/legacy/gallery.blade.php create mode 100644 resources/views/legacy/mybuddies.blade.php create mode 100644 resources/views/legacy/photography.blade.php create mode 100644 resources/views/legacy/received-comments.blade.php create mode 100644 resources/views/legacy/statistics.blade.php create mode 100644 resources/views/legacy/user.blade.php create mode 100644 resources/views/vendor/pagination/bootstrap-3.blade.php create mode 100644 storage/debugbar/.gitignore diff --git a/.copilot/favourites_artworks.md b/.copilot/favourites_artworks.md new file mode 100644 index 00000000..a46c6286 --- /dev/null +++ b/.copilot/favourites_artworks.md @@ -0,0 +1,181 @@ +# 1️⃣ Final SQL – New Favorites Table (Artwork-only) + +**Table name:** `user_favorites` +**Scope:** users ↔ artworks +**Engine:** InnoDB +**Charset:** utf8mb4 + +```sql +CREATE TABLE user_favorites ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + + user_id BIGINT UNSIGNED NOT NULL, + artwork_id BIGINT UNSIGNED NOT NULL, + + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + + UNIQUE KEY uniq_user_artwork (user_id, artwork_id), + KEY idx_artwork (artwork_id), + KEY idx_user_created (user_id, created_at), + + CONSTRAINT fk_user_favorites_user + FOREIGN KEY (user_id) REFERENCES users(id) + ON DELETE CASCADE, + + CONSTRAINT fk_user_favorites_artwork + FOREIGN KEY (artwork_id) REFERENCES artworks(id) + ON DELETE CASCADE +) ENGINE=InnoDB + DEFAULT CHARSET=utf8mb4 + COLLATE=utf8mb4_unicode_ci; +``` + +This is **production-ready** and matches everything we discussed: + +* no legacy fields +* no duplication +* proper constraints +* fast queries + +--- + +# 2️⃣ VS Code Agent Markdown (Laravel 12 Migration Prompt) + +Save this as for example: + +``` +.vscode/agents/laravel-user-favorites-migration.md +``` + +or + +``` +.cursor/rules/laravel-user-favorites.md +``` + +--- + +```markdown +# Laravel 12 – User Favorites Migration & Model + +## Context +We are migrating legacy "favourites" functionality into a clean, modern Laravel 12 system. +Each user can add artworks to their favorites list. +This is a many-to-many relationship between users and artworks. + +Legacy table MUST NOT be reused. + +--- + +## Goal +Create a Laravel 12 database migration and Eloquent model for a new table named: + +``` + +user_favorites + +```` + +This table stores **which user favorited which artwork**, with a timestamp. + +--- + +## Database Requirements + +### Table: user_favorites + +| Column | Type | Notes | +|------|------|------| +| id | BIGINT UNSIGNED | Primary key | +| user_id | BIGINT UNSIGNED | FK → users.id | +| artwork_id | BIGINT UNSIGNED | FK → artworks.id | +| created_at | TIMESTAMP | When artwork was favorited | + +### Constraints & Indexes + +- UNIQUE (user_id, artwork_id) + → prevents duplicate favorites + +- INDEX artwork_id + → fast favorite count per artwork + +- INDEX (user_id, created_at) + → fast "my favorites" queries + +### Foreign Keys + +- user_id → users.id (ON DELETE CASCADE) +- artwork_id → artworks.id (ON DELETE CASCADE) + +### Engine & Charset + +- Engine: InnoDB +- Charset: utf8mb4 +- Collation: utf8mb4_unicode_ci + +--- + +## Laravel Migration Requirements + +- Use `Schema::create` +- Use `foreignId()->constrained()->cascadeOnDelete()` +- Use `timestamps()` **ONLY if created_at is needed** + (do NOT add updated_at) + +- Add explicit indexes and unique constraints + +--- + +## Laravel Model Requirements + +### Model: UserFavorite + +- Table: `user_favorites` +- `$timestamps = false` (created_at handled manually or via DB default) +- Fillable: + - user_id + - artwork_id + - created_at + +### Relationships + +```php +UserFavorite belongsTo User +UserFavorite belongsTo Artwork +```` + +--- + +## Additional Notes + +* This table is interaction-based, NOT content-based +* Do NOT store favorite counts here +* Favorite counts will be aggregated separately (Redis or statistics table) +* This table must be lean and write-optimized + +--- + +## Deliverables + +* Migration file for Laravel 12 +* Eloquent model `UserFavorite` +* Proper naming and clean schema +* No legacy fields, no polymorphic logic + +Generate clean, production-quality code. + +```` + +--- + +## 3️⃣ How to Use This in VS Code (Quick Steps) + +1. Paste markdown into `.vscode/agents/` or `.cursor/rules/` +2. Open VS Code +3. Ask your AI agent: + > “Create Laravel 12 migration and model based on this document” +4. Review generated migration +5. Run: +```bash +php artisan migrate +```` diff --git a/.copilot/update_user_schema.md b/.copilot/update_user_schema.md new file mode 100644 index 00000000..3c8043a8 --- /dev/null +++ b/.copilot/update_user_schema.md @@ -0,0 +1,312 @@ +# Skinbase – User Schema Review & Upgrade Plan + +**Database:** MySQL / Percona 8.x +**Project:** Skinbase (new system, no legacy dependencies) +**Reviewed tables:** users, user_profiles, user_social_links, user_statistics + +--- + +## 1. Overview + +The current user-related database schema is **well designed**, modern, and suitable +for long-term growth. +Key strengths include: + +- Clear separation of concerns +- Proper use of foreign keys and cascading deletes +- BigInt primary keys +- Soft deletes on users +- Migration-friendly legacy password handling + +This document summarizes: +- what is already good +- recommended optimizations +- future-proofing steps (non-breaking) +- performance considerations for scale + +--- + +## 2. users Table + +### 2.1 What’s Good + +- Unique `username` and `email` +- `legacy_password_algo` allows smooth migration from old systems +- `needs_password_reset` improves security posture +- Role stored as string allows flexibility in early stages +- Soft deletes enabled + +### 2.2 Recommended Indexes + +Add indexes for common query patterns: + +```sql +CREATE INDEX idx_users_active ON users (is_active); +CREATE INDEX idx_users_role ON users (role); +CREATE INDEX idx_users_last_visit ON users (last_visit_at); +```` + +These improve: + +* active user filtering +* admin queries +* “last seen” or online user features + +### 2.3 Future Role Normalization (Planned) + +Current approach is fine short-term: + +```text +role = 'user' | 'admin' | 'moderator' +``` + +Planned future upgrade: + +* `roles` table +* `user_roles` pivot table (many-to-many) + +This allows: + +* multiple roles per user +* temporary or scoped roles +* better permission modeling + +⚠️ No immediate action required — just avoid hard-coding role logic. + +### 2.4 Optional Security Enhancements + +Recommended additions (optional but advised): + +```sql +last_password_change_at TIMESTAMP NULL, +failed_login_attempts INT UNSIGNED DEFAULT 0, +locked_until TIMESTAMP NULL +``` + +Enables: + +* rate limiting +* temporary account locking +* better auditability + +--- + +## 3. user_profiles Table + +### 3.1 Strengths + +* Clean one-to-one relationship with `users` +* Public profile data separated from auth data +* Nullable fields for progressive profile completion +* Inclusive gender enum with safe default +* Localization-ready (`language`, `country_code`) + +### 3.2 Country Handling Recommendation + +Prefer using only: + +```text +country_code (ISO 3166-1 alpha-2) +``` + +Benefits: + +* language-independent +* avoids inconsistent country naming +* easier frontend mapping + +`country` text field can be deprecated later if needed. + +### 3.3 Avatar & Media Metadata (Future) + +Current: + +```text +avatar VARCHAR(255) +``` + +Recommended future approach: + +```text +avatar_hash CHAR(64) +avatar_ext VARCHAR(10) +avatar_updated_at TIMESTAMP +``` + +This aligns with: + +* hash-based file storage +* CDN-friendly URLs +* cache invalidation control + +--- + +## 4. user_social_links Table + +### 4.1 Current Design + +* One row per platform per user +* Unique constraint on `(user_id, platform)` +* Cascade delete enabled + +This is solid. + +### 4.2 Platform Normalization (Recommended) + +Current: + +```text +platform VARCHAR(32) +``` + +Risk: + +* inconsistent values (`twitter`, `x`, `Twitter`, etc.) + +Options: + +**Option A – Enum (simple):** + +```sql +ENUM('twitter','x','instagram','deviantart','artstation','github','website') +``` + +**Option B – Reference Table (best long-term):** + +* `social_platforms` +* foreign key `platform_id` + +Option B is preferred for Skinbase as platforms evolve. + +--- + +## 5. user_statistics Table + +### 5.1 Strengths + +* Isolated counters +* One row per user +* Minimal row size +* Clean FK relationship + +### 5.2 Performance Warning (Important) + +Avoid frequent direct updates like: + +```sql +UPDATE user_statistics SET downloads = downloads + 1; +``` + +At scale, this causes: + +* row locking +* write contention +* degraded performance + +### 5.3 Recommended Strategy + +* Use **Redis** (or in-memory cache) for real-time increments +* Periodically flush aggregated values to MySQL +* Use jobs / cron for batch updates + +This ensures: + +* fast user interactions +* scalable statistics tracking + +--- + +## 6. Charset & Collation + +Current: + +```text +utf8mb4_unicode_ci +``` + +This is correct and safe. + +Optional upgrade (MySQL 8+): + +```text +utf8mb4_0900_ai_ci +``` + +Benefits: + +* newer Unicode rules +* slightly better performance + +Not required immediately. + +--- + +## 7. Tables Planned for Future Expansion + +Not required now, but expected as Skinbase grows: + +### 7.1 user_activity_log + +* logins +* uploads +* profile edits +* moderation actions + +### 7.2 user_followers + +* artist-to-artist following +* social graph features + +### 7.3 user_settings + +* privacy preferences +* notification settings +* email subscriptions + +These should remain **separate tables** to avoid bloating `users`. + +--- + +## 8. Laravel Implementation Notes + +Recommended model casting: + +```php +protected $casts = [ + 'is_active' => 'boolean', + 'needs_password_reset' => 'boolean', + 'email_verified_at' => 'datetime', + 'last_visit_at' => 'datetime', +]; +``` + +Best practices: + +* Eager load profiles (`with('profile')`) +* Cache public profile + statistics +* Keep statistics out of main user queries + +--- + +## 9. Final Verdict + +**Schema quality:** Excellent +**Scalability:** Very good +**Migration readiness:** Excellent +**Long-term Skinbase fit:** Excellent + +The current schema is production-ready and significantly better than typical legacy +user databases. Most future improvements can be introduced **without breaking changes**. + +Primary future wins: + +* Redis-backed statistics +* normalized roles and social platforms +* hash-based media storage + +--- + +**Status:** Approved for production +**Next steps:** API design, public profile queries, legacy user migration + +``` diff --git a/app/Chat.php b/app/Chat.php index faa95f6b..f23720c5 100644 --- a/app/Chat.php +++ b/app/Chat.php @@ -22,7 +22,7 @@ class Chat return; } - $last = DB::connection('legacy')->table('chat') + $last = DB::table('chat') ->select('message') ->where('user_id', $userId) ->orderByDesc('chat_id') @@ -30,7 +30,7 @@ class Chat ->first(); if (!$last || ($last->message ?? '') !== $tekst) { - DB::connection('legacy')->table('chat')->insert([ + DB::table('chat')->insert([ 'time' => now(), 'sender' => $username, 'user_id' => $userId, @@ -43,7 +43,7 @@ class Chat { $output = "