Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
42764af
Fix onboarding page layout to match standard container structure
buger Sep 14, 2025
78962cb
Fix unit deletion route parameters and add comprehensive test coverage
buger Sep 14, 2025
618ea3b
Convert PHPUnit @test annotations to PHP 8 attributes
buger Sep 14, 2025
2cdab90
Add Visor Code Review GitHub Action
buger Sep 14, 2025
ed50a02
Update Visor Code Review to v0.1.2 with Google API key
buger Sep 14, 2025
680a003
Update Visor Code Review to v0.1.3
buger Sep 14, 2025
abdf0ad
Fix topic routes and update layouts to 3-column grid
buger Sep 14, 2025
1636e6a
Optimize PHPStan configuration for better performance and fewer false…
buger Sep 14, 2025
e272bc7
Fix failing TopicControllerTest validation and deletion tests
buger Sep 14, 2025
a4fa7c6
Add comprehensive profile functionality and fix language switching
buger Sep 14, 2025
b68ec76
Implement comprehensive regional format preferences system
buger Sep 15, 2025
39790e5
Add comprehensive test coverage for regional format preferences system
buger Sep 15, 2025
168d1c5
Fix regional format system bugs and enhance test reliability
buger Sep 15, 2025
ba611a5
Implement comprehensive learning materials system for topics
buger Sep 15, 2025
360e4f1
Implement Phase 2: GitHub-style markdown editor with drag-drop uploads
buger Sep 15, 2025
3861dc3
Implement Phase 4: Unified markdown editor with real-time live preview
buger Sep 15, 2025
299a6fd
Implement Phase 7: Beautiful kids view rendering with comprehensive c…
buger Sep 15, 2025
2fd1aa6
Implement Phase 8: Comprehensive testing and optimization with PHPSta…
buger Sep 15, 2025
2cfa039
Update visor-code-review.yml
buger Sep 16, 2025
07e76a9
Update workflow to trigger on issue events
buger Sep 16, 2025
4afdeda
Update visor-code-review.yml
buger Sep 16, 2025
f47e336
Update visor-code-review.yml
buger Sep 16, 2025
1879759
Update visor-code-review.yml with permissions
buger Sep 16, 2025
e131066
Update Visor action version to v0.1.10
buger Sep 16, 2025
7a50c2d
Update Visor action version to v0.1.12
buger Sep 16, 2025
e9c9559
Modify Visor Code Review workflow parameters
buger Sep 16, 2025
4a250df
Update visor-code-review.yml
buger Sep 16, 2025
1768e74
Update visor-code-review.yml
buger Sep 16, 2025
a4a3d74
Update visor-code-review.yml
buger Sep 16, 2025
84f71d8
Fix all failing tests in unified markdown learning materials system
buger Sep 15, 2025
ef26604
Fix remaining test failures and achieve test suite success
buger Sep 15, 2025
0c42139
Fix dropdown flash on page load
buger Sep 16, 2025
b7b1c6d
πŸ”’ Fix critical security vulnerabilities and complete unified markdown…
buger Sep 16, 2025
31a69ce
Fix PHPStan errors from removed migration methods
buger Sep 16, 2025
53c176f
Update visor-code-review.yml
buger Sep 17, 2025
9792fc7
🎯 Complete flashcard-topic migration and restore hooks
buger Sep 17, 2025
1fbaeb7
Update visor-code-review.yml
buger Sep 20, 2025
c2c32a6
πŸ›‘οΈ Fix critical security vulnerabilities and performance issues
buger Sep 20, 2025
248500d
Fix CI test failures caused by temporary file creation restrictions
buger Sep 21, 2025
9adf4be
Document CI test database fix
buger Sep 21, 2025
1ba2027
πŸ”§ Fix CI failures with correct database configuration and security up…
buger Sep 21, 2025
4c78c2d
Fix CI test failures by implementing CI-specific test command
buger Sep 21, 2025
0d7267e
🎯 Complete CI fix: Resolve all file creation issues in tests
buger Sep 21, 2025
8f54391
Fix three critical test failures to achieve 100% test pass rate
buger Sep 21, 2025
5ff0bb4
🎯 Trigger fresh CI run - all tests passing locally (861/861)
buger Sep 21, 2025
8223afd
Fix CI test failures by resolving environment configuration issues
buger Sep 21, 2025
ab63b1a
🎯 Final CI fix: Resolve environment configuration mismatches
buger Sep 21, 2025
17ae884
πŸš€ Fix Visor performance issues with comprehensive optimizations
buger Sep 21, 2025
4742e58
πŸ”’ Fix critical race condition vulnerability in one-time access tokens
buger Sep 21, 2025
c65dde4
πŸš€ Major refactor: Fix N+1 queries & implement topic-only flashcard sy…
buger Sep 21, 2025
7c2523e
Complete topic-only flashcard architecture migration and achieve 0 te…
buger Sep 22, 2025
6577bde
Fix topic creation route parameter issue and add comprehensive tests
buger Sep 22, 2025
49e112f
Add comprehensive Subject β†’ Unit β†’ Topic β†’ Flashcard workflow test
buger Sep 22, 2025
e24993a
πŸŽ‰ ACHIEVE 100% WORKING Subject β†’ Unit β†’ Topic β†’ Flashcard workflow
buger Sep 22, 2025
7295010
Fix flashcard creation HTMX target errors and complete topic-only arc…
buger Sep 22, 2025
56d65f6
Merge main branch to resolve PR conflicts
buger Sep 22, 2025
ef63413
Merge latest main branch changes
buger Sep 22, 2025
9933f7d
πŸ”’ Fix XSS vulnerabilities in flashcard system
buger Sep 22, 2025
b0fbc2d
Resolve merge conflicts in units/show.blade.php
buger Sep 22, 2025
346882f
Fix remaining Supabase patterns causing BadMethodCallException
buger Sep 22, 2025
8179f93
Fix all remaining Supabase patterns causing BadMethodCallException er…
buger Sep 22, 2025
2fceff5
Fix invisible Create Session button in modal
buger Sep 22, 2025
fa617d2
Fix 403 error in session creation - use proper topic->unit->subject r…
buger Sep 22, 2025
72f7a98
Add missing session delete functionality
buger Sep 22, 2025
b2caa31
Fix HTTP method mismatch for commitment-type update
buger Sep 22, 2025
1907ef9
Add missing calendar CRUD routes
buger Sep 22, 2025
b0e3e78
Add comprehensive E2E test suite for core functionality
buger Sep 22, 2025
561019d
Fix topics.flashcards.list route parameter mismatch
buger Sep 22, 2025
2fad910
Fix Russian UI translations and pluralization issues
buger Sep 23, 2025
6d9cfbb
Fix N+1 query performance issues across planning and subjects
buger Sep 24, 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
122 changes: 110 additions & 12 deletions app/Http/Controllers/FlashcardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -964,25 +964,27 @@
/**
* Display flashcards list view for HTMX.
*/
public function listView(Request $request, int $unitId): View|Response
public function listView(Request $request, int $topicId): View|Response
{
try {
if (! auth()->check()) {
return response('Unauthorized', 401);
}

// Verify unit exists and user has access
$unit = Unit::with(['subject'])->findOrFail($unitId);
if ((int) $unit->subject->user_id !== auth()->id()) {
// Verify topic exists and user has access
$topic = Topic::with(['unit.subject'])->findOrFail($topicId);
if ((int) $topic->unit->subject->user_id !== auth()->id()) {
return response('Access denied', 403);
}

// Get flashcards with pagination
$flashcards = $unit->allFlashcards()
$flashcards = $topic->flashcards()
->orderBy('created_at', 'desc')
->paginate(20);

return view('flashcards.partials.flashcard-list', compact('flashcards', 'unit'));
$unit = $topic->unit; // For backward compatibility with the template

return view('flashcards.partials.flashcard-list', compact('flashcards', 'topic', 'unit'));

} catch (\Exception $e) {
Log::error('Error fetching flashcards for list view: '.$e->getMessage());
Expand Down Expand Up @@ -1020,6 +1022,102 @@
}
}

/**
* Show the form for creating a new flashcard for a specific topic.
*/
public function createForTopic(Request $request, int $topicId): View|Response
{
try {
if (! auth()->check()) {
return response('Unauthorized', 401);
}

// Verify topic exists and user has access
$topic = Topic::with(['unit.subject'])->findOrFail($topicId);
if ((int) $topic->unit->subject->user_id !== auth()->id()) {
return response('Access denied', 403);
}

return view('flashcards.partials.flashcard-modal', [
'unit' => $topic->unit,
'topic' => $topic,
'flashcard' => null, // Creating new
'isEdit' => false,
]);

} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
return response('Topic not found', 404);
} catch (\Exception $e) {
Log::error('Error loading topic flashcard creation form: '.$e->getMessage());

return response('Unable to load form', 500);
}
}

/**
* Store a flashcard for a specific topic and return the updated list view.
*/
public function storeForTopic(FlashcardRequest $request, int $topicId): View|Response
{
try {
if (! auth()->check()) {
return response('Unauthorized', 401);

Check warning on line 1064 in app/Http/Controllers/FlashcardController.php

View check run for this annotation

probelabs / Visor: quality

maintainability Issue

The authorization logic (checking `auth()->check()` and verifying topic ownership via `(int) $topic->unit->subject->user_id !== auth()->id()`) is duplicated across multiple methods (`listView`, `createForTopic`, `storeForTopic`). This violates the DRY (Don't Repeat Yourself) principle and makes the authorization rules harder to manage and test.
Raw output
Refactor the authorization logic into a more reusable component. The best practice in Laravel is to use a Form Request for validation and authorization in `store` methods, and a Policy class (e.g., `TopicPolicy`) for `view` and other actions. This centralizes the logic, making it easier to update and test.
}

// Verify topic exists and user has access

Check warning on line 1067 in app/Http/Controllers/FlashcardController.php

View check run for this annotation

probelabs / Visor: security

security Issue

The `storeForTopic` method logs all validated data for a new flashcard at the `info` level, including potentially sensitive user content like `question`, `answer`, and `hint`. This data will be written to application logs in cleartext, increasing the risk of data exposure if log files are compromised.
Raw output
Avoid logging sensitive user-provided content. For debugging purposes, log only non-sensitive identifiers (like the user ID or the new flashcard ID after it's saved) or filter the `$validated` array to exclude sensitive fields before logging.
$topic = Topic::with(['unit.subject'])->findOrFail($topicId);
if ((int) $topic->unit->subject->user_id !== auth()->id()) {
return response('Access denied', 403);
}

$validated = $request->validated();
\Log::info('Topic flashcard validation data:', $validated);

// Ensure topic_id is set for topic-only architecture
$validated['topic_id'] = $topicId;

$flashcard = new Flashcard($validated);

Check failure on line 1079 in app/Http/Controllers/FlashcardController.php

View check run for this annotation

probelabs / Visor: security

security Issue

Validation errors from `$flashcard->validateCardData()` are directly embedded in an HTML response without escaping. If a custom validation rule were to include user-provided input in its error message, this could lead to a Reflected XSS vulnerability.
Raw output
All dynamic content rendered in an HTML context must be escaped to prevent XSS. Use the `htmlspecialchars()` function on the error messages before embedding them in the response.

Check warning on line 1079 in app/Http/Controllers/FlashcardController.php

View check run for this annotation

probelabs / Visor: style

style Issue

The controller returns raw HTML strings for validation errors, mixing presentation logic (HTML/CSS) with controller logic. This violates the Separation of Concerns principle and makes the UI harder to maintain. This pattern is repeated on lines 1093, 1119, 1201, 1390, 1473, 1600, and 1878.
Raw output
Create a dedicated Blade partial for rendering errors. The controller should return a response rendering this view with the error data. For example: `return response()->view('partials.form-error', ['errors' => $cardErrors], 422);`

// Validate card-specific data
$cardErrors = $flashcard->validateCardData();
if (! empty($cardErrors)) {
return response('<div class="text-red-500">'.implode('<br>', $cardErrors).'</div>', 422);
}

if ($flashcard->save()) {

Check warning on line 1087 in app/Http/Controllers/FlashcardController.php

View check run for this annotation

probelabs / Visor: performance

performance Issue

After fetching a paginated list of flashcards, a second, redundant query (`$topic->flashcards()->count()`) is executed to get the total count. The paginator object already contains this information from its initial query, making this database call unnecessary.
Raw output
Remove the redundant database call by retrieving the total count directly from the paginator instance using `$flashcards->total()`.
// Return updated topic flashcards list with count update
$flashcards = $topic->flashcards()
->where('is_active', true)
->orderBy('created_at', 'desc')
->paginate(20);

$flashcardCount = $topic->flashcards()->count();

// Include OOB update for the flashcard count in header
$unit = $topic->unit;
$listView = view('flashcards.partials.flashcard-list', compact('flashcards', 'topic', 'unit'))->render();
$countUpdate = '<span class="ml-2 text-sm font-normal text-gray-600" id="topic-flashcard-count" hx-swap-oob="true">('.$flashcardCount.')</span>';

return response($listView.$countUpdate)
->header('HX-Trigger', 'flashcardCreated');

Check failure on line 1102 in app/Http/Controllers/FlashcardController.php

View check run for this annotation

probelabs / Visor: quality

architecture Issue

The controller returns raw HTML strings containing Tailwind CSS classes for displaying validation errors (e.g., in `storeForTopic`). This mixes presentation logic with controller logic, violating the Separation of Concerns principle. It makes the UI difficult to maintain, as any style changes would require modifying controller code instead of a single view file. This pattern is repeated in multiple methods in this file.
Raw output
To improve maintainability and adhere to architectural best practices, create a dedicated Blade partial for rendering errors. The controller should then return a response that renders this view with the error data. For example: `return response()->view('partials.form-error', ['errors' => $cardErrors], 422);`
}

return response('Failed to create flashcard', 500);

} catch (\Illuminate\Validation\ValidationException $e) {
$errors = collect($e->validator->errors()->all())->implode('<br>');
\Log::error('Topic flashcard validation errors:', $e->validator->errors()->toArray());

return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
return response('Topic not found', 404);
} catch (\Exception $e) {
Log::error('Error creating topic flashcard: '.$e->getMessage());

return response('Unable to create flashcard', 500);
}
}

/**
* Show the form for editing a flashcard.
*/
Expand Down Expand Up @@ -1113,7 +1211,7 @@
$errors = collect($e->validator->errors()->all())->implode('<br>');
\Log::error('Flashcard validation errors:', $e->validator->errors()->toArray());

return response('<div class="text-red-500">'.$errors.'</div>', 422);
return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Exception $e) {
Log::error('Error creating flashcard: '.$e->getMessage());

Expand Down Expand Up @@ -1198,7 +1296,7 @@
} catch (\Illuminate\Validation\ValidationException $e) {
$errors = collect($e->validator->errors()->all())->implode('<br>');

return response('<div class="text-red-500">'.$errors.'</div>', 422);
return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Exception $e) {
Log::error('Error updating flashcard: '.$e->getMessage());

Expand Down Expand Up @@ -1387,7 +1485,7 @@
} catch (\Illuminate\Validation\ValidationException $e) {
$errors = collect($e->validator->errors()->all())->implode('<br>');

return response('<div class="text-red-500">'.$errors.'</div>', 422);
return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Exception $e) {
Log::error('Error previewing import: '.$e->getMessage());

Expand Down Expand Up @@ -1470,7 +1568,7 @@
} catch (\Illuminate\Validation\ValidationException $e) {
$errors = collect($e->validator->errors()->all())->implode('<br>');

return response('<div class="text-red-500">'.$errors.'</div>', 422);
return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Exception $e) {
Log::error('Error executing import: '.$e->getMessage());

Expand Down Expand Up @@ -1596,7 +1694,7 @@
} catch (\Illuminate\Validation\ValidationException $e) {
$errors = collect($e->validator->errors()->all())->implode('<br>');

return response('<div class="text-red-500">'.$errors.'</div>', 422);
return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Exception $e) {
Log::error('Error generating print preview: '.$e->getMessage());

Expand Down Expand Up @@ -1875,7 +1973,7 @@
} catch (\Illuminate\Validation\ValidationException $e) {
$errors = collect($e->validator->errors()->all())->implode('<br>');

return response('<div class="text-red-500">'.$errors.'</div>', 422);
return response('<div class="text-red-500">'.htmlspecialchars($errors).'</div>', 422);
} catch (\Exception $e) {
Log::error('Error generating export preview: '.$e->getMessage());

Expand Down
48 changes: 35 additions & 13 deletions app/Http/Controllers/PlanningController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;

class PlanningController extends Controller
Expand Down Expand Up @@ -42,7 +43,7 @@
}

// Get all sessions for selected child organized by status
$allSessions = Session::forChild($selectedChild->id);
$allSessions = Session::forChild($selectedChild->id)->with('topic.unit.subject')->get();
$sessionsByStatus = [
'backlog' => $allSessions->where('status', 'backlog'),
'planned' => $allSessions->where('status', 'planned'),
Expand All @@ -51,23 +52,24 @@
];

// Get catch-up sessions for selected child
$catchUpSessions = CatchUpSession::pending($selectedChild->id);
$catchUpSessions = CatchUpSession::pending($selectedChild->id)->with('topic.unit.subject')->get();

// Get all topics for this child's subjects that don't have sessions yet
$subjects = Subject::where('user_id', $userId)->orderBy('name')->get();
$subjects = Subject::where('user_id', $userId)
->with(['units.topics' => function ($query) {
$query->with('unit.subject');
}])
->orderBy('name')
->get();

$availableTopics = collect([]);
$existingTopicIds = $allSessions->pluck('topic_id')->toArray();

foreach ($subjects as $subject) {
/** @var \App\Models\Subject $subject */
$units = $subject->units;
foreach ($units as $unit) {
/** @var \App\Models\Unit $unit */
$topics = $unit->topics;
foreach ($topics as $topic) {
/** @var \App\Models\Topic $topic */
foreach ($subject->units as $unit) {
foreach ($unit->topics as $topic) {
// Check if topic already has sessions for this child
$existingSession = $allSessions->where('topic_id', $topic->id)->first();
if (! $existingSession) {
if (! in_array($topic->id, $existingTopicIds)) {
$availableTopics->push($topic);
}
}
Expand Down Expand Up @@ -157,7 +159,7 @@
}

// Verify topic belongs to user's subjects (through unit -> subject)
$subject = $topic->subject;
$subject = $topic->unit->subject;
if (! $subject || $subject->user_id != auth()->id()) {
abort(403, 'Topic does not belong to user');
}
Expand Down Expand Up @@ -666,5 +668,25 @@
$days = ['', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

return $days[$day] ?? '';
}

Check warning on line 671 in app/Http/Controllers/PlanningController.php

View check run for this annotation

probelabs / Visor: quality

documentation Issue

The new public method `destroySession` lacks a PHPDoc block. Consistent documentation is crucial for maintainability, especially for public API endpoints. All public methods should have a clear PHPDoc explaining their purpose, parameters, and return values.
Raw output
Add a PHPDoc block to the `destroySession` method to maintain consistency with the project's documentation standards.

public function destroySession(int $sessionId): Response
{
$session = Session::find($sessionId);
if (! $session) {
abort(404);
}

// Verify session belongs to user's child
$child = $session->child;
if (! $child || $child->user_id != auth()->id()) {
abort(403);
}

// Delete the session

Check warning on line 686 in app/Http/Controllers/PlanningController.php

View check run for this annotation

probelabs / Visor: style

documentation Issue

The new public method `destroySession` lacks a PHPDoc block. For consistency and maintainability, all public methods should have clear documentation explaining their purpose, parameters, and return values.
Raw output
Add a complete PHPDoc block to the `destroySession` method.
$session->delete();

// Return empty content to remove the session card from the UI
return response('')->header('HX-Trigger', 'sessionDeleted');
}
}
2 changes: 1 addition & 1 deletion app/Http/Controllers/SubjectController.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function index(Request $request)

// Get subjects for the selected child or show empty state
if ($selectedChild) {
$subjects = $selectedChild->subjects()->orderBy('name')->get();
$subjects = $selectedChild->subjects()->withCount('units')->orderBy('name')->get();
} else {
$subjects = collect([]);
}
Expand Down
12 changes: 6 additions & 6 deletions app/Http/Controllers/TopicController.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
}

$validated = $request->validate([
'name' => 'required|string|max:255',
'title' => 'required|string|max:255',
'description' => 'nullable|string|max:10000',
'estimated_minutes' => 'required|integer|min:5|max:480',
'required' => 'boolean',
Expand All @@ -148,10 +148,10 @@
$contentMetadata = $richContent['metadata'];
}

// Use 'name' field but store as 'title' in the model

Check warning on line 151 in app/Http/Controllers/TopicController.php

View check run for this annotation

probelabs / Visor: quality

documentation Issue

The comment `// Use 'name' field but store as 'title' in the model` is outdated and misleading. The validation and creation logic were updated to use `title` directly, but the comment was not removed. This can cause confusion for future developers. Similar outdated comments exist on lines 222 and 373.
Raw output
Remove the outdated comments to ensure the code's documentation accurately reflects its current implementation. The code is now self-explanatory.
$topic = Topic::create([
'unit_id' => $unitId,
'title' => $validated['name'], // Store name as title
'title' => $validated['title'], // Store title as title

Check notice on line 154 in app/Http/Controllers/TopicController.php

View check run for this annotation

probelabs / Visor: style

style Issue

The comment `// Store title as title` is tautological and adds no value, as the code `'title' => $validated['title']` is self-explanatory. This also applies to similar comments on lines 225 and 376.
Raw output
Remove the redundant comment. The code is clear on its own.
'description' => $description,
'content_format' => $contentFormat,
'content_metadata' => $contentMetadata,
Expand Down Expand Up @@ -202,7 +202,7 @@
}

$validated = $request->validate([
'name' => 'required|string|max:255',
'title' => 'required|string|max:255',
'description' => 'nullable|string',
'content_format' => 'nullable|in:plain,markdown,html',
'estimated_minutes' => 'required|integer|min:5|max:480',
Expand All @@ -222,7 +222,7 @@
// Use 'name' field but store as 'title' in the model
$topic = Topic::create([
'unit_id' => $unitId,
'title' => $validated['name'], // Store name as title
'title' => $validated['title'], // Store title as title
'description' => $description,
'content_format' => $contentFormat,
'content_metadata' => $contentMetadata,
Expand Down Expand Up @@ -354,7 +354,7 @@
}

$validated = $request->validate([
'name' => 'required|string|max:255',
'title' => 'required|string|max:255',
'description' => 'nullable|string',
'content_format' => 'nullable|in:plain,markdown,html',
'estimated_minutes' => 'required|integer|min:5|max:480',
Expand All @@ -373,7 +373,7 @@

// Use 'name' field but store as 'title' in the model
$topic->update([
'title' => $validated['name'], // Store name as title
'title' => $validated['title'], // Store title as title
'description' => $description,
'content_format' => $contentFormat,
'content_metadata' => $contentMetadata,
Expand Down
3 changes: 1 addition & 2 deletions app/Models/Child.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace App\Models;

use App\Services\SupabaseClient;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
Expand Down Expand Up @@ -96,7 +95,7 @@ public function scopeForUser($query, int|string $userId)
*
* @return \Illuminate\Database\Eloquent\Collection<int, Child>
*/
public static function forUser(int|string $userId, ?SupabaseClient $supabase = null): \Illuminate\Database\Eloquent\Collection
public static function forUser(int|string $userId): \Illuminate\Database\Eloquent\Collection
{
return self::where('user_id', $userId)->orderBy('name')->get();
}
Expand Down
4 changes: 2 additions & 2 deletions app/Models/Flashcard.php
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ public function canBeAccessedBy(string $userId): bool
*
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\Flashcard>
*/
public static function forUnit(int $unitId, $supabase = null): \Illuminate\Database\Eloquent\Collection
public static function forUnit(int $unitId): \Illuminate\Database\Eloquent\Collection
{
return self::where('unit_id', $unitId)
->whereNull('topic_id') // Only unit-scoped flashcards
Expand All @@ -316,7 +316,7 @@ public static function forUnit(int $unitId, $supabase = null): \Illuminate\Datab
*
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\Flashcard>
*/
public static function forTopic(int $topicId, $supabase = null): \Illuminate\Database\Eloquent\Collection
public static function forTopic(int $topicId): \Illuminate\Database\Eloquent\Collection
{
return self::where('topic_id', $topicId)->where('is_active', true)->orderBy('created_at')->get();
}
Expand Down
6 changes: 3 additions & 3 deletions app/Models/Subject.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ public function scopeForChild($query, int $childId)
* Compatibility methods for existing controllers that expect SupabaseClient
* These maintain API compatibility during migration
*/
public static function forUser(string $userId, $supabase = null): Collection
public static function forUser(string $userId): Collection
{
return self::where('user_id', $userId)->orderBy('name')->get();
}

public static function forChild(int $childId, $supabase = null): Collection
public static function forChild(int $childId): Collection
{
return self::where('child_id', $childId)->orderBy('name')->get();
}
Expand All @@ -129,7 +129,7 @@ public function getUnitCount(): int
/**
* Compatibility method for controllers that still pass SupabaseClient
*/
public function getUnitCount_compat($supabase = null): int
public function getUnitCount_compat(): int
{
return $this->getUnitCount();
}
Expand Down
Loading
Loading