profileShare

rasmusjy / splitapp-backend-microservices

Read-only snapshot

No repository description.

main default branch 501 files Expires Sep 13, 2026, 9:06 AM
PollsClientController.cs 4,573 bytes
1 using System.Security.Claims;
2 using SplitApp.WebApp.Application.DTO;
3 using SplitApp.WebApp.Application.Services;
4 using SplitApp.Modules.Trips.Domain.Entities;
5 using SplitApp.Modules.Trips.Domain.Enums;
6 using SplitApp.Modules.Expenses.Domain.Entities;
7 using SplitApp.Modules.Expenses.Domain.Enums;
8 using Microsoft.AspNetCore.Authorization;
9 using Microsoft.AspNetCore.Identity;
10 using Microsoft.AspNetCore.Mvc;
11
12 namespace SplitApp.WebApp.Controllers;
13
14 [Authorize]
15 public class PollsClientController : Controller
16 {
17 private readonly ITripService _tripService;
18 private readonly IPollService _pollService;
19
20 public PollsClientController(
21 ITripService tripService,
22 IPollService pollService)
23 {
24 _tripService = tripService;
25 _pollService = pollService;
26 }
27
28 private Guid GetUserId() => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
29
30 // GET: PollsClient?tripId=xxx
31 public async Task<IActionResult> Index(Guid tripId)
32 {
33 var userId = GetUserId();
34 if (!await _tripService.IsParticipantAsync(tripId, userId)) return Forbid();
35
36 var trip = await _tripService.GetByIdAsync(tripId, userId);
37 if (trip == null) return NotFound();
38
39 var polls = await _pollService.GetByTripIdAsync(tripId, userId);
40
41 ViewData["TripId"] = tripId;
42 ViewData["TripName"] = trip.Name;
43
44 return View(polls);
45 }
46
47 // GET: PollsClient/Create?tripId=xxx
48 public async Task<IActionResult> Create(Guid tripId)
49 {
50 var userId = GetUserId();
51 if (!await _tripService.IsParticipantAsync(tripId, userId)) return Forbid();
52
53 ViewData["TripId"] = tripId;
54 return View();
55 }
56
57 // POST: PollsClient/Create
58 [HttpPost]
59 [ValidateAntiForgeryToken]
60 public async Task<IActionResult> Create(Guid tripId, string question, bool allowMultipleVotes,
61 bool isAnonymous, string option1, string option2, string? option3, string? option4, string? option5)
62 {
63 var userId = GetUserId();
64 if (!await _tripService.IsParticipantAsync(tripId, userId)) return Forbid();
65
66 if (string.IsNullOrWhiteSpace(question) || string.IsNullOrWhiteSpace(option1) ||
67 string.IsNullOrWhiteSpace(option2))
68 {
69 ModelState.AddModelError("", "Question and at least 2 options are required.");
70 ViewData["TripId"] = tripId;
71 return View();
72 }
73
74 var poll = new TripPollBllDto
75 {
76 TripId = tripId,
77 CreatedByUserId = userId,
78 Question = question,
79 AllowMultipleVotes = allowMultipleVotes,
80 IsAnonymous = isAnonymous
81 };
82
83 var options = new[] { option1, option2, option3, option4, option5 }
84 .Where(o => !string.IsNullOrWhiteSpace(o))
85 .Select(o => o!)
86 .ToList();
87
88 var created = await _pollService.CreatePollWithOptionsAsync(poll, options);
89
90 return RedirectToAction(nameof(Details), new { id = created.Id });
91 }
92
93 // GET: PollsClient/Details/5
94 public async Task<IActionResult> Details(Guid id)
95 {
96 var userId = GetUserId();
97 var poll = await _pollService.GetByIdWithDetailsAsync(id, userId);
98
99 if (poll == null) return NotFound();
100
101 ViewData["TripId"] = poll.TripId;
102 ViewData["UserId"] = userId;
103 ViewData["IsCreator"] = poll.CreatedByUserId == userId;
104
105 return View(poll);
106 }
107
108 // POST: PollsClient/Vote
109 [HttpPost]
110 [ValidateAntiForgeryToken]
111 public async Task<IActionResult> Vote(Guid pollId, Guid optionId)
112 {
113 var userId = GetUserId();
114 var poll = await _pollService.GetByIdAsync(pollId, userId);
115
116 if (poll == null) return NotFound();
117
118 if (poll.ClosedAt != null) return RedirectToAction(nameof(Details), new { id = pollId });
119
120 await _pollService.ToggleVoteAsync(pollId, optionId, userId);
121
122 return RedirectToAction(nameof(Details), new { id = pollId });
123 }
124
125 // POST: PollsClient/Close/5
126 [HttpPost]
127 [ValidateAntiForgeryToken]
128 public async Task<IActionResult> Close(Guid id)
129 {
130 var userId = GetUserId();
131 var (ok, errorCode) = await _pollService.ClosePollAsync(id, userId, organizerAllowed: false);
132 if (!ok)
133 {
134 return errorCode switch
135 {
136 "notfound" => NotFound(),
137 "forbidden" => Forbid(),
138 _ => NotFound()
139 };
140 }
141
142 return RedirectToAction(nameof(Details), new { id });
143 }
144 }
145