attributes->get('worker'); if (!$worker) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $tickets = SupportTicket::with('reason')->where('worker_id', $worker->id) ->orderBy('created_at', 'desc') ->get() ->map(function ($ticket) { return [ 'id' => $ticket->id, 'ticket_number' => $ticket->ticket_number, 'subject' => $ticket->subject, 'description' => $ticket->description, 'reason_id' => $ticket->reason_id, 'reason_name' => $ticket->reason ? $ticket->reason->reason : null, 'voice_note_url' => $ticket->voice_note_path ? asset('storage/' . $ticket->voice_note_path) : null, 'status' => $ticket->status, 'priority' => $ticket->priority, 'created_at' => $ticket->created_at->toIso8601String(), ]; }); return response()->json([ 'success' => true, 'tickets' => $tickets ]); } public function createTicketFromWorker(Request $request) { $worker = $request->attributes->get('worker'); if (!$worker) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $validator = Validator::make($request->all(), [ 'subject' => 'required|string|max:255', 'description' => 'required|string', 'priority' => 'nullable|string|in:low,medium,high', 'reason_id' => 'nullable|exists:report_reasons,id', 'voice_note' => 'nullable|file|mimes:mp3,wav,m4a,ogg,webm,aac,3gp,amr|max:10240', // 10MB limit ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } $voiceNotePath = null; if ($request->hasFile('voice_note')) { $voiceNotePath = $request->file('voice_note')->store('support_voice_notes', 'public'); } $ticket = SupportTicket::create([ 'ticket_number' => 'TKT-' . rand(100000, 999999), 'worker_id' => $worker->id, 'reason_id' => $request->reason_id, 'subject' => $request->subject, 'description' => $request->description, 'voice_note_path' => $voiceNotePath, 'priority' => $request->priority ?? 'medium', 'status' => 'open', ]); $ticket->load('reason'); return response()->json([ 'success' => true, 'message' => 'Ticket created successfully.', 'ticket' => [ 'id' => $ticket->id, 'ticket_number' => $ticket->ticket_number, 'subject' => $ticket->subject, 'description' => $ticket->description, 'reason_id' => $ticket->reason_id, 'reason_name' => $ticket->reason ? $ticket->reason->reason : null, 'voice_note_url' => $ticket->voice_note_path ? asset('storage/' . $ticket->voice_note_path) : null, 'status' => $ticket->status, 'priority' => $ticket->priority, 'created_at' => $ticket->created_at->toIso8601String(), ] ], 201); } public function replyToTicketFromWorker(Request $request, $id) { $worker = $request->attributes->get('worker'); if (!$worker) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $ticket = SupportTicket::where('worker_id', $worker->id)->find($id); if (!$ticket) { return response()->json(['success' => false, 'message' => 'Ticket not found.'], 404); } if ($ticket->status === 'closed') { return response()->json(['success' => false, 'message' => 'Cannot reply to a closed ticket.'], 422); } $validator = Validator::make($request->all(), [ 'message' => 'required|string', ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } $reply = SupportTicketReply::create([ 'support_ticket_id' => $ticket->id, 'worker_id' => $worker->id, 'message' => $request->message, ]); if ($ticket->status === 'resolved') { $ticket->update(['status' => 'open']); } return response()->json([ 'success' => true, 'message' => 'Reply posted successfully.', 'reply' => [ 'id' => $reply->id, 'message' => $reply->message, 'sender_name' => $reply->sender_name, 'created_at' => $reply->created_at->toIso8601String(), ] ], 201); } // ========================================== // EMPLOYER ENDPOINTS // ========================================== public function getTicketsForEmployer(Request $request) { $employer = $request->attributes->get('employer'); if (!$employer) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $tickets = SupportTicket::where('user_id', $employer->id) ->orderBy('created_at', 'desc') ->get() ->map(function ($ticket) { return [ 'id' => $ticket->id, 'ticket_number' => $ticket->ticket_number, 'subject' => $ticket->subject, 'description' => $ticket->description, 'status' => $ticket->status, 'priority' => $ticket->priority, 'created_at' => $ticket->created_at->toIso8601String(), ]; }); return response()->json([ 'success' => true, 'tickets' => $tickets ]); } public function createTicketFromEmployer(Request $request) { $employer = $request->attributes->get('employer'); if (!$employer) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $validator = Validator::make($request->all(), [ 'subject' => 'required|string|max:255', 'description' => 'required|string', 'priority' => 'nullable|string|in:low,medium,high', ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } $ticket = SupportTicket::create([ 'ticket_number' => 'TKT-' . rand(100000, 999999), 'user_id' => $employer->id, 'subject' => $request->subject, 'description' => $request->description, 'priority' => $request->priority ?? 'medium', 'status' => 'open', ]); return response()->json([ 'success' => true, 'message' => 'Ticket created successfully.', 'ticket' => [ 'id' => $ticket->id, 'ticket_number' => $ticket->ticket_number, 'subject' => $ticket->subject, 'description' => $ticket->description, 'status' => $ticket->status, 'priority' => $ticket->priority, 'created_at' => $ticket->created_at->toIso8601String(), ] ], 201); } public function replyToTicketFromEmployer(Request $request, $id) { $employer = $request->attributes->get('employer'); if (!$employer) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $ticket = SupportTicket::where('user_id', $employer->id)->find($id); if (!$ticket) { return response()->json(['success' => false, 'message' => 'Ticket not found.'], 404); } if ($ticket->status === 'closed') { return response()->json(['success' => false, 'message' => 'Cannot reply to a closed ticket.'], 422); } $validator = Validator::make($request->all(), [ 'message' => 'required|string', ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } $reply = SupportTicketReply::create([ 'support_ticket_id' => $ticket->id, 'user_id' => $employer->id, 'message' => $request->message, ]); if ($ticket->status === 'resolved') { $ticket->update(['status' => 'open']); } return response()->json([ 'success' => true, 'message' => 'Reply posted successfully.', 'reply' => [ 'id' => $reply->id, 'message' => $reply->message, 'sender_name' => $reply->sender_name, 'created_at' => $reply->created_at->toIso8601String(), ] ], 201); } // ========================================== // SHARED GET DETAILS // ========================================== public function getTicketDetail(Request $request, $id) { $worker = $request->attributes->get('worker'); $employer = $request->attributes->get('employer'); if (!$worker && !$employer) { return response()->json(['success' => false, 'message' => 'Unauthorized.'], 401); } $query = SupportTicket::with('reason')->where('id', $id); if ($worker) { $query->where('worker_id', $worker->id); } else { $query->where('user_id', $employer->id); } $ticket = $query->first(); if (!$ticket) { return response()->json(['success' => false, 'message' => 'Ticket not found.'], 404); } $replies = SupportTicketReply::where('support_ticket_id', $ticket->id) ->with(['user', 'worker']) ->orderBy('created_at', 'asc') ->get() ->map(function ($reply) { return [ 'id' => $reply->id, 'message' => $reply->message, 'sender_name' => $reply->sender_name, 'is_admin' => $reply->user && $reply->user->role === 'admin', 'is_developer_response' => (bool)$reply->is_developer_response, 'created_at' => $reply->created_at->toIso8601String(), ]; }); return response()->json([ 'success' => true, 'ticket' => [ 'id' => $ticket->id, 'ticket_number' => $ticket->ticket_number, 'subject' => $ticket->subject, 'description' => $ticket->description, 'reason_id' => $ticket->reason_id, 'reason_name' => $ticket->reason ? $ticket->reason->reason : null, 'voice_note_url' => $ticket->voice_note_path ? asset('storage/' . $ticket->voice_note_path) : null, 'status' => $ticket->status, 'priority' => $ticket->priority, 'created_at' => $ticket->created_at->toIso8601String(), ], 'replies' => $replies ]); } }