json([ 'bell_sounds' => BellSound::where('is_active', true)->orderBy('order')->get(), 'background_sounds' => BackgroundSound::where('is_active', true)->orderBy('order')->get(), 'background_images' => Image::where('type', 'public')->get(), ]); } // USER: their saved timers (ذخیره‌شده‌های من). public function index() { $presets = TimerPreset::with(TimerPreset::RELATIONS) ->where('user_id', auth()->id()) ->latest() ->get(); return response()->json($presets); } public function show($id) { $preset = TimerPreset::with(TimerPreset::RELATIONS) ->where('user_id', auth()->id()) ->findOrFail($id); return response()->json($preset); } public function store(Request $request) { $data = $this->validatePreset($request); $preset = TimerPreset::create($data + ['user_id' => auth()->id()]); return response()->json([ 'message' => 'Timer saved successfully', 'preset' => $preset->load(TimerPreset::RELATIONS), ], 201); } public function update(Request $request, $id) { $preset = TimerPreset::where('user_id', auth()->id())->findOrFail($id); $data = $this->validatePreset($request, false); $preset->fill($data)->save(); return response()->json([ 'message' => 'Timer updated successfully', 'preset' => $preset->load(TimerPreset::RELATIONS), ]); } public function destroy($id) { $preset = TimerPreset::where('user_id', auth()->id())->findOrFail($id); $preset->delete(); return response()->json(['message' => 'Timer deleted successfully']); } private function validatePreset(Request $request, bool $creating = true): array { $required = $creating ? 'required' : 'sometimes'; return $request->validate([ 'name' => "$required|string|max:255", 'duration_seconds' => "$required|integer|min:1", 'start_bell_id' => 'nullable|exists:bell_sounds,id', 'end_bell_id' => 'nullable|exists:bell_sounds,id', 'interval_bell_id' => 'nullable|exists:bell_sounds,id', 'interval_seconds' => 'nullable|integer|min:1', 'interval_repeat' => 'nullable|integer|min:1', 'background_sound_id' => 'nullable|exists:background_sounds,id', 'background_image_id' => 'nullable|exists:images,id', 'volume' => 'nullable|integer|min:0|max:100', ]); } }