notifService = $notifService; } // ── Helper: obtener usuario logueado ── private function getUser() { if (!session()->has('user_logged_in')) { return null; } $tipo = session('user_tipo'); $id = session('user_id'); if ($tipo === 'jugador') { return ['user' => Jugador::find($id), 'tipo' => $tipo]; } return ['user' => Aficionado::find($id), 'tipo' => $tipo]; } // ══════════════════════════════════ // PANEL PRINCIPAL // ══════════════════════════════════ public function index(Request $request) { $data = $this->getUser(); if (!$data || !$data['user']) { session()->flush(); return redirect('/?logout_msg=' . urlencode('Tu usuario no fue encontrado. Iniciá sesión nuevamente.')); } $user = $data['user']; $userTipo = $data['tipo']; $userId = session('user_id'); // Cargar relaciones de club/equipos para jugadores if ($userTipo === 'jugador') { $user->load(['clubActual', 'equipos.club']); } // Obtener QRs del usuario (eventos que NO estén borrados) if ($userTipo === 'jugador') { $qrCodes = QrCode::whereHas('evento') ->where('id_jugador', $user->id_jugador) ->orderBy('creado', 'desc') ->get(); } else { $qrCodes = QrCode::whereHas('evento') ->where('id_aficionado', $user->id_aficionado) ->orderBy('creado', 'desc') ->get(); } // Obtener beneficios de promociones $promoQrs = PromoQr::with('promocion') ->where('id_usuario', $userId) ->where('tipo_usuario', $userTipo) ->orderBy('generado_en', 'desc') ->get(); return view('panel.index', compact('user', 'userTipo', 'qrCodes', 'promoQrs')); } // ══════════════════════════════════ // ACTUALIZAR DATOS // ══════════════════════════════════ public function actualizarDatos(Request $request) { $data = $this->getUser(); if (!$data) return redirect('/'); $request->validate([ 'email' => 'required|email', 'telefono' => 'required|string', 'localidad' => 'nullable|string', ]); $user = $data['user']; if ($data['tipo'] === 'jugador') { $user->update([ 'email' => $request->input('email'), 'telefono' => $request->input('telefono'), ]); } else { $user->update([ 'email' => $request->input('email'), 'telefono' => $request->input('telefono'), 'localidad' => $request->input('localidad'), ]); } return back()->with('panel_msg', 'Datos actualizados correctamente.'); } // ══════════════════════════════════ // CAMBIAR CONTRASEÑA // ══════════════════════════════════ public function cambiarPassword(Request $request) { $data = $this->getUser(); if (!$data) return redirect('/'); $request->validate([ 'password_actual' => 'required|string', 'password_nueva' => 'required|confirmed|min:6', ]); $user = $data['user']; if ($user->password) { if (!Hash::check($request->input('password_actual'), $user->password)) { return back()->with('panel_error', 'La contraseña actual es incorrecta.'); } } $user->update([ 'password' => bcrypt($request->input('password_nueva')), ]); return back()->with('panel_msg', 'Contraseña cambiada correctamente.'); } // ══════════════════════════════════ // SOLICITAR QR PARA EVENTO // ══════════════════════════════════ public function solicitarQr(Request $request) { $data = $this->getUser(); if (!$data || !$data['user']) return redirect('/'); $user = $data['user']; $userTipo = $data['tipo']; $id_evento = $request->input('id_evento'); $evento = Evento::with(['equipoLocal', 'equipoVisitante'])->find($id_evento); if (!$evento) { return back()->with('panel_error', 'Evento no encontrado.'); } $qrs_a_generar = 0; if ($userTipo === 'jugador') { // Verificar si ya generó QRs para este evento $yaGenero = QrCode::where('id_evento', $id_evento) ->where('id_jugador', $user->id_jugador) ->count(); if ($yaGenero > 0) { return back()->with('panel_error', 'Ya solicitaste QRs para este evento.'); } // Verificar si el jugador está activo if (!$user->activo) { return back()->with('panel_error', 'Tu registro no está activo. Completá tu registro primero.'); } // Verificar si pertenece a alguno de los equipos del evento $pertenece = DB::table('jugador_equipo') ->where('id_jugador', $user->id_jugador) ->whereIn('id_equipo', array_filter([$evento->id_equipo_local, $evento->id_equipo_visitante])) ->exists(); if ($pertenece) { $qrs_a_generar = $evento->limite_qr_jugador ?? 3; // Límite configurable $tipoQr = 'invitado'; } else { // Check if category is "libre" $edadCategoria = date('Y') - \Carbon\Carbon::parse($user->fecha_nacimiento)->format('Y'); $categoriaDB = \App\Models\Categoria::where('edad_min', '<=', $edadCategoria) ->where('edad_max', '>=', $edadCategoria) ->first(); if ($categoriaDB && $categoriaDB->es_libre) { $qrs_a_generar = 1; $tipoQr = 'libre_50'; // Identificador para 50% de descuento } else { return back()->with('panel_error', 'No podés generar QR para este partido ya que no pertenecés a los equipos ni sos categoría Libre. Deberás abonar la totalidad de la entrada en puerta.'); } } if ($qrs_a_generar === 0) { return back()->with('panel_error', 'No se permiten QRs para este evento.'); } // Generar QRs for ($i = 0; $i < $qrs_a_generar; $i++) { QrCode::create([ 'id_qr' => uniqid('qr_'), 'id_evento' => $id_evento, 'id_jugador' => $user->id_jugador, 'tipo_qr' => $tipoQr ?? 'invitado', 'escaneos_restantes' => 1, 'creado' => now(), ]); } } else { // Aficionado: no puede solicitar QRs para eventos return back()->with('panel_error', 'Los aficionados no pueden solicitar QRs para eventos. Adquirí tu entrada directamente en el lugar.'); } // Enviar mail con QRs try { Mail::to($user->email)->send(new QrCodeMail($user, $evento, $qrs_a_generar)); } catch (\Exception $e) { Log::error("Error enviando mail de QRs: " . $e->getMessage()); } // Notificación interna $this->notifService->enviar( $userTipo, $userTipo === 'jugador' ? $user->id_jugador : $user->id_aficionado, 'sistema', '🎫 QRs Generados', "Tus {$qrs_a_generar} QR(s) para el evento " . ($evento->nombre_evento ?? 'seleccionado') . " ya están disponibles.", route('panel.mis.qrs', ['evento' => $id_evento]) ); return redirect()->route('panel.mis.qrs', ['evento' => $id_evento]) ->with('panel_msg', "¡QR(s) generados correctamente! ({$qrs_a_generar})"); } // ══════════════════════════════════ // MIS QRS (per evento) // ══════════════════════════════════ public function misQrs(Request $request) { $data = $this->getUser(); if (!$data || !$data['user']) return redirect('/'); $user = $data['user']; $userTipo = $data['tipo']; $id_evento = $request->query('evento'); // Traer QRs del usuario (solo de eventos activos) $query = QrCode::whereHas('evento') ->with(['evento.equipoLocal.club', 'evento.equipoVisitante.club', 'evento.torneo']); if ($userTipo === 'jugador') { $query->where('id_jugador', $user->id_jugador); $user->load('clubActual'); } else { $query->where('id_aficionado', $user->id_aficionado); } if ($id_evento) { $query->where('id_evento', $id_evento); $evento = Evento::find($id_evento); } else { $evento = null; } $qrs = $query->orderBy('creado', 'desc')->get(); // Adjuntar información de grupo si hay torneo foreach ($qrs as $qr) { if ($qr->evento && $qr->evento->id_torneo && $qr->evento->id_equipo_local) { $rel = DB::table('torneo_equipo') ->where('id_torneo', $qr->evento->id_torneo) ->where('id_equipo', $qr->evento->id_equipo_local) ->first(); if ($rel) { $qr->evento->grupo_nombre = $rel->grupo ?? 'General'; } } } return view('panel.mis_qrs', compact('user', 'userTipo', 'qrs', 'evento')); } // ══════════════════════════════════ // GENERAR QR PARA PROMOCIÓN // ══════════════════════════════════ public function generarPromoQr(Request $request) { $data = $this->getUser(); if (!$data || !$data['user']) return redirect('/'); $user = $data['user']; $userTipo = $data['tipo']; $userId = session('user_id'); $id_promo = $request->input('id_promo'); $promo = Promocion::find($id_promo); if (!$promo) { return back()->with('panel_error', 'Promoción no encontrada.'); } // Verificar si ya generó QR para esta promo $yaGenero = PromoQr::where('id_promo', $id_promo) ->where('id_usuario', $userId) ->where('tipo_usuario', $userTipo) ->count(); if ($yaGenero > 0) { return back()->with('panel_error', 'Ya generaste un QR para esta promoción.'); } $id_qr = bin2hex(random_bytes(8)); PromoQr::create([ 'id_qr' => $id_qr, 'id_promo' => $id_promo, 'id_usuario' => $userId, 'tipo_usuario' => $userTipo, 'generado_en' => now(), 'usado' => false, ]); return redirect()->route('panel.promo.qr.ver', ['id' => $id_qr]) ->with('panel_msg', '¡QR de beneficio generado correctamente!'); } // ══════════════════════════════════ // VER QR DE PROMOCIÓN // ══════════════════════════════════ public function verPromoQr($id) { $data = $this->getUser(); if (!$data || !$data['user']) return redirect('/'); $user = $data['user']; $userTipo = $data['tipo']; if ($userTipo === 'jugador') { $user->load('clubActual'); } $promoQr = PromoQr::with('promocion') ->where('id_qr', $id) ->where('id_usuario', session('user_id')) ->where('tipo_usuario', $userTipo) ->firstOrFail(); return view('panel.promo_qr', compact('promoQr', 'user', 'userTipo')); } }