diff --git a/src/Forum/Components/MissionRSVPs.php b/src/Forum/Components/MissionRSVPs.php index 2ff7a0e..d1cf8e6 100644 --- a/src/Forum/Components/MissionRSVPs.php +++ b/src/Forum/Components/MissionRSVPs.php @@ -5,65 +5,36 @@ namespace Forumify\PerscomPlugin\Forum\Components; use Forumify\PerscomPlugin\Perscom\Entity\Mission; -use Forumify\PerscomPlugin\Perscom\Entity\MissionRSVP; -use Forumify\PerscomPlugin\Perscom\Entity\PerscomUser; -use Forumify\PerscomPlugin\Perscom\Entity\Unit; -use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; -use Symfony\UX\LiveComponent\Attribute\LiveProp; -use Symfony\UX\LiveComponent\DefaultActionTrait; +use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; -#[AsLiveComponent('Perscom\\MissionRSVPs', '@ForumifyPerscomPlugin/frontend/components/mission_rsvps.html.twig')] +#[AsTwigComponent('Perscom\\MissionStats', '@ForumifyPerscomPlugin/frontend/components/mission_stats.html.twig')] class MissionRSVPs { - #[LiveProp] public Mission $mission; - use DefaultActionTrait; - - /** - * @return array}> - */ - public function getRSVPs(): array + public function getGoing(): int { - $rsvps = []; + $count = 0; + foreach ($this->mission->getRsvps() as $rsvp) { - $user = $rsvp->getUser(); - if ($user === null) { - continue; + if ($rsvp->isGoing() === true) { + $count++; } - - $rsvps[] = [ - 'rsvp' => $rsvp, - 'user' => $user, - ]; } - return $this->groupByUnit($rsvps); + return $count; } - /** - * @param array $rsvps - * @return array}> - */ - private function groupByUnit(array $rsvps): array + public function getAbsent(): int { - $units = []; - foreach ($rsvps as $rsvp) { - $user = $rsvp['user']; - $unit = $user->getUnit(); - if ($unit === null) { - continue; - } + $count = 0; - $unitId = $unit->getPerscomId(); - if (!isset($units[$unitId])) { - $units[$unitId]['unit'] = $unit; + foreach ($this->mission->getRsvps() as $rsvp) { + if ($rsvp->isGoing() === false) { + $count++; } - - $units[$unitId]['rsvps'][] = $rsvp; } - uasort($units, fn (array $a, array $b): int => $a['unit']->getPosition() <=> $b['unit']->getPosition()); - return $units; + return $count; } } diff --git a/src/Forum/Components/MissionRoster.php b/src/Forum/Components/MissionRoster.php new file mode 100644 index 0000000..c667f70 --- /dev/null +++ b/src/Forum/Components/MissionRoster.php @@ -0,0 +1,84 @@ +unitsWithRSVPs !== null) { + return $this->unitsWithRSVPs; + } + + $this->loadRSVPs(); + $units = []; + + foreach ($this->rsvpsByUserId as $rsvp) { + $user = $rsvp->getUser(); + $unit = $user?->getUnit(); + + if ($unit && !isset($units[$unit->getId()])) { + $units[$unit->getId()] = $unit; + } + } + + uasort($units, fn (Unit $a, Unit $b) => $a->getPosition() <=> $b->getPosition()); + return $this->unitsWithRSVPs = $units; + } + + public function getUsersInUnitWithRSVPs(Unit $unit): array + { + $this->loadRSVPs(); + $users = []; + + foreach ($unit->getUsers() as $user) { + if (isset($this->rsvpsByUserId[$user->getId()])) { + $users[$user->getId()] = $user; + } + } + + $this->userService->sortPerscomUsers($users); + return $users; + } + + public function getRSVPForUser(PerscomUser $user): ?MissionRSVP + { + $this->loadRSVPs(); + return $this->rsvpsByUserId[$user->getId()] ?? null; + } + + private function loadRSVPs(): void + { + if (!empty($this->rsvpsByUserId)) { + return; + } + + foreach ($this->mission->getRsvps() as $rsvp) { + if ($user = $rsvp->getUser()) { + $this->rsvpsByUserId[$user->getId()] = $rsvp; + } + } + } +} diff --git a/templates/frontend/components/mission_roster.html.twig b/templates/frontend/components/mission_roster.html.twig new file mode 100644 index 0000000..4ea5e76 --- /dev/null +++ b/templates/frontend/components/mission_roster.html.twig @@ -0,0 +1,34 @@ +
+ {% set units = this.unitsWithRSVPs %} + + {% if units is not empty %} + + {% else %} +
+
+ No attendance has been marked yet. +
+
+ {% endif %} +
diff --git a/templates/frontend/components/mission_rsvp_button.html.twig b/templates/frontend/components/mission_rsvp_button.html.twig index 11fa77b..9cba9e2 100644 --- a/templates/frontend/components/mission_rsvp_button.html.twig +++ b/templates/frontend/components/mission_rsvp_button.html.twig @@ -1,45 +1,47 @@ {% set rsvp = this.rsvp %} {% set going = rsvp is not null and rsvp.going %}
-
- {% if going %} - - {% elseif rsvp is not null %} - - {% else %} - - {% endif %} -
diff --git a/templates/frontend/components/mission_rsvps.html.twig b/templates/frontend/components/mission_rsvps.html.twig deleted file mode 100644 index c9fc0f8..0000000 --- a/templates/frontend/components/mission_rsvps.html.twig +++ /dev/null @@ -1,29 +0,0 @@ -
- {% for rsvp in this.RSVPs %} -
-
{{ rsvp.unit.name }}
-
    - {% for userRsvp in rsvp.rsvps %} - {% set user = userRsvp.user %} -
  • - {% if user.rank is not null and user.rank.image is not null %} - - {% endif %} - {{ user.name }} - {% if userRsvp.rsvp.going %} - - {% else %} - - {% endif %} -
  • - {% endfor %} -
-
- {% endfor %} -
- -{% macro placeholder(props) %} -
- {% include '@Forumify/components/loader.html.twig' %} -
-{% endmacro %} diff --git a/templates/frontend/components/mission_stats.html.twig b/templates/frontend/components/mission_stats.html.twig new file mode 100644 index 0000000..6cc901d --- /dev/null +++ b/templates/frontend/components/mission_stats.html.twig @@ -0,0 +1,10 @@ +
+
+ {{ this.getGoing }} + {{ 'perscom.mission.rsvp.going'|trans }} +
+
+ {{ this.getAbsent }} + {{ 'perscom.mission.rsvp.not_going'|trans }} +
+
diff --git a/templates/frontend/mission/components/soldier_row.html.twig b/templates/frontend/mission/components/soldier_row.html.twig new file mode 100644 index 0000000..27a2546 --- /dev/null +++ b/templates/frontend/mission/components/soldier_row.html.twig @@ -0,0 +1,34 @@ +
+
+ {% if soldier.rank is not null and soldier.rank.image is not null %} + + {% endif %} +
+
+ + {% if soldier.rank is not null %} + {{ soldier.rank.name }} + {% endif %} + + {{ soldier.name }} +
+
+ {% if soldier.position is not null %} + {{ soldier.position.name }} + {% endif %} +
+
+ {% if soldier.position is not null %} + {{ soldier.specialty.name }} + {% endif %} +
+
+ {% if rsvp is not null %} + {% include '@ForumifyPerscomPlugin/frontend/mission/components/status.html.twig' with { + rsvp: rsvp + } only %} + {% else %} + No RSVP + {% endif %} +
+
diff --git a/templates/frontend/mission/components/status.html.twig b/templates/frontend/mission/components/status.html.twig new file mode 100644 index 0000000..a18bef4 --- /dev/null +++ b/templates/frontend/mission/components/status.html.twig @@ -0,0 +1,14 @@ +{% set statusClass = '' %} +{% set statusText = '' %} + +{% if rsvp.going == '1' %} + {% set statusClass = 'badge-success' %} + {% set statusText = 'Going' %} + {% set statusColor = 'green' %} +{% elseif rsvp.going == '0' %} + {% set statusClass = 'badge-danger' %} + {% set statusText = 'Not Going' %} + {% set statusColor = 'red' %} +{% endif %} + +{{ statusText }} diff --git a/templates/frontend/mission/mission.html.twig b/templates/frontend/mission/mission.html.twig index 7ac741b..15cef60 100644 --- a/templates/frontend/mission/mission.html.twig +++ b/templates/frontend/mission/mission.html.twig @@ -39,35 +39,60 @@ {% endif %} - {% if can('view_after_action_reports', mission.operation) and not mission.afterActionReports.empty %} -
-

{{ 'perscom.mission.aars'|trans }}

- {{ component('Perscom\\AfterActionReportList', { mission: mission }) }} +
+
+
+
+ {% if mission.operation.image %} +
+ +
+ {% endif %} + {{ component('Perscom\\MissionStats', {mission: mission}) }} +
+ {% block tabs %} + + + + {% endblock %} +
+
+
- {% endif %} -
-

{{ 'perscom.mission.mission'|trans }}

-

- {{ 'perscom.mission.start'|trans }} - {{ mission.start|format_date(true) }} -

- {% if mission.end %} -

- {{ 'perscom.mission.end'|trans }} - {{ mission.end|format_date(true) }} -

- {% endif %} -
- {{ mission.briefing|rich }} +
+ {% block tabpanels %} +
+
+
+

{{ 'perscom.mission.mission'|trans }}

+

+ {{ 'perscom.mission.start'|trans }} + {{ mission.start|format_date(true) }} +

+ {% if mission.end %} +

+ {{ 'perscom.mission.end'|trans }} + {{ mission.end|format_date(true) }} +

+ {% endif %} + {{ mission.briefing|rich }} +
+
+
+
+
+ {{ component('Forumify\\Perscom\\MissionRoster', {mission: mission}) }} +
+
+
+ {% if can('view_after_action_reports', mission.operation) and not mission.afterActionReports.empty %} +
+

{{ 'perscom.mission.aars'|trans }}

+ {{ component('Perscom\\AfterActionReportList', { mission: mission }) }} +
+ {% endif %} +
+ {% endblock %}
- {% if mission.operation.requestRsvp %} -
-

{{ 'perscom.mission.rsvps'|trans }}

- {{ component('Perscom\\MissionRSVPs', { - loading: 'lazy', - mission: mission, - }) }} -
- {% endif %} {% endblock %}