-
Notifications
You must be signed in to change notification settings - Fork 3
mission view redesign #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| 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 Forumify\PerscomPlugin\Perscom\Service\PerscomUserService; | ||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||
| use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; | ||
|
|
||
| #[AsTwigComponent('Forumify\\Perscom\\MissionRoster', '@ForumifyPerscomPlugin/frontend/components/mission_roster.html.twig')] | ||
| class MissionRoster extends AbstractController | ||
| { | ||
|
|
||
| public Mission $mission; | ||
|
|
||
| private array $rsvpsByUserId = []; | ||
| private ?array $unitsWithRSVPs = null; | ||
|
|
||
| public function __construct( | ||
| private readonly PerscomUserService $userService, | ||
| ) { | ||
| } | ||
|
|
||
| public function getUnitsWithRSVPs(): array | ||
| { | ||
| if ($this->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; | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+72
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change this function to also return That way it's very clear in the usages what it returns, and it's not some magic private variable. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| <div {{ attributes }}> | ||
| {% set units = this.unitsWithRSVPs %} | ||
|
|
||
| {% if units is not empty %} | ||
| <ul> | ||
| {% for unit in units %} | ||
| {% set users = this.getUsersInUnitWithRSVPs(unit) %} | ||
| {% if users is not empty %} | ||
| <li class="card mb-4"> | ||
| <div class="card-title">{{ unit.name }}</div> | ||
| <ul class="card-body"> | ||
| {% for user in users %} | ||
| <li class="text-small"> | ||
| <a href="{{ path('perscom_user', { id: user.id }) }}" class="btn-link w-100"> | ||
| {% include '@ForumifyPerscomPlugin/frontend/mission/components/soldier_row.html.twig' with { | ||
| soldier: user, | ||
| rsvp: this.getRSVPForUser(user) | ||
| } only %} | ||
| </a> | ||
| </li> | ||
| {% endfor %} | ||
| </ul> | ||
| </li> | ||
| {% endif %} | ||
| {% endfor %} | ||
| </ul> | ||
| {% else %} | ||
| <div class="card"> | ||
| <div class="card-body text-center text-muted"> | ||
| No attendance has been marked yet. | ||
| </div> | ||
| </div> | ||
| {% endif %} | ||
| </div> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,45 +1,47 @@ | ||
| {% set rsvp = this.rsvp %} | ||
| {% set going = rsvp is not null and rsvp.going %} | ||
| <div {{ attributes }}> | ||
| <div {{ stimulus_controller('forumify/forumify-platform/menu', { placement: 'bottom-end' }) }}> | ||
| {% if going %} | ||
| <button class="btn-link" {{ stimulus_target('forumify/forumify-platform/menu', 'openButton') }}> | ||
| <i class="ph ph-check" style="color: green"></i>{{ 'perscom.mission.rsvp.going'|trans }} | ||
| </button> | ||
| {% elseif rsvp is not null %} | ||
| <button class="btn-link" {{ stimulus_target('forumify/forumify-platform/menu', 'openButton') }}> | ||
| <i class="ph ph-x-circle" style="color: red"></i>{{ 'perscom.mission.rsvp.not_going'|trans }} | ||
| </button> | ||
| {% else %} | ||
| <button class="btn-primary" {{ stimulus_target('forumify/forumify-platform/menu', 'openButton') }}> | ||
| <i class="ph ph-calendar"></i>{{ 'perscom.mission.rsvp.rsvp'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| <div class="menu" {{ stimulus_target('forumify/forumify-platform/menu', 'menu') }}> | ||
| {% if rsvp is null or not going %} | ||
| <button class="btn-link" {{ | ||
| stimulus_action('live', 'action', parameters: { action: 'toggle', going: true }) | ||
| |stimulus_action('forumify/forumify-platform/menu', 'close') | ||
| }}> | ||
| <i class="ph ph-check-circle" style="color: green"></i>{{ 'perscom.mission.rsvp.going'|trans }} | ||
| <div class="flex gap-2 items-center"> | ||
| <div {{ stimulus_controller('forumify/forumify-platform/menu', { placement: 'bottom-end' }) }}> | ||
| {% if going %} | ||
| <button class="btn-link" {{ stimulus_target('forumify/forumify-platform/menu', 'openButton') }}> | ||
| <i class="ph ph-check" style="color: green"></i>{{ 'perscom.mission.rsvp.going'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| {% if rsvp is null or going %} | ||
| <button class="btn-link" {{ | ||
| stimulus_action('live', 'action', parameters: { action: 'toggle', going: false }) | ||
| |stimulus_action('forumify/forumify-platform/menu', 'close') | ||
| }}> | ||
| {% elseif rsvp is not null %} | ||
| <button class="btn-link" {{ stimulus_target('forumify/forumify-platform/menu', 'openButton') }}> | ||
| <i class="ph ph-x-circle" style="color: red"></i>{{ 'perscom.mission.rsvp.not_going'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| {% if rsvp is not null %} | ||
| <button class="btn-link" {{ | ||
| stimulus_action('live', 'action', parameters: { action: 'cancel' }) | ||
| |stimulus_action('forumify/forumify-platform/menu', 'close') | ||
| }}> | ||
| <i class="ph ph-prohibit-inset" style="color: gray"></i>{{ 'perscom.mission.rsvp.remove_rsvp'|trans }} | ||
| {% else %} | ||
| <button class="btn-primary" {{ stimulus_target('forumify/forumify-platform/menu', 'openButton') }}> | ||
| <i class="ph ph-calendar"></i>{{ 'perscom.mission.rsvp.rsvp'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| <div class="menu" {{ stimulus_target('forumify/forumify-platform/menu', 'menu') }}> | ||
| {% if rsvp is null or not going %} | ||
| <button class="btn-link" {{ | ||
| stimulus_action('live', 'action', parameters: { action: 'toggle', going: true }) | ||
| |stimulus_action('forumify/forumify-platform/menu', 'close') | ||
| }}> | ||
| <i class="ph ph-check-circle" style="color: green"></i>{{ 'perscom.mission.rsvp.going'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| {% if rsvp is null or going %} | ||
| <button class="btn-link" {{ | ||
| stimulus_action('live', 'action', parameters: { action: 'toggle', going: false }) | ||
| |stimulus_action('forumify/forumify-platform/menu', 'close') | ||
| }}> | ||
| <i class="ph ph-x-circle" style="color: red"></i>{{ 'perscom.mission.rsvp.not_going'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| {% if rsvp is not null %} | ||
| <button class="btn-link" {{ | ||
| stimulus_action('live', 'action', parameters: { action: 'cancel' }) | ||
| |stimulus_action('forumify/forumify-platform/menu', 'close') | ||
| }}> | ||
| <i class="ph ph-prohibit-inset" style="color: gray"></i>{{ 'perscom.mission.rsvp.remove_rsvp'|trans }} | ||
| </button> | ||
| {% endif %} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <div class="flex gap-10 justify-center mt-2"> | ||
| <div class="flex flex-col"> | ||
| <span style="color:green;">{{ this.getGoing }}</span> | ||
| {{ 'perscom.mission.rsvp.going'|trans }} | ||
| </div> | ||
| <div class="flex flex-col"> | ||
| <span style="color:red;">{{ this.getAbsent }}</span> | ||
| {{ 'perscom.mission.rsvp.not_going'|trans }} | ||
| </div> | ||
| </div> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| <div class="flex justify-between items-center w-100"> | ||
| <div class="w-5 text-left"> | ||
| {% if soldier.rank is not null and soldier.rank.image is not null %} | ||
| <img width="24px" height="24px" src="{{ asset(soldier.rank.image, 'perscom.asset') }}" alt=""> | ||
| {% endif %} | ||
| </div> | ||
| <div class="w-35 text-center"> | ||
| <span class="hide-phone"> | ||
| {% if soldier.rank is not null %} | ||
| {{ soldier.rank.name }} | ||
| {% endif %} | ||
| </span> | ||
| {{ soldier.name }} | ||
| </div> | ||
| <div class="w-20 text-center hide-phone"> | ||
| {% if soldier.position is not null %} | ||
| {{ soldier.position.name }} | ||
| {% endif %} | ||
| </div> | ||
| <div class="w-20 text-center hide-phone"> | ||
| {% if soldier.position is not null %} | ||
| {{ soldier.specialty.name }} | ||
| {% endif %} | ||
| </div> | ||
| <div class="w-15 text-center"> | ||
| {% if rsvp is not null %} | ||
| {% include '@ForumifyPerscomPlugin/frontend/mission/components/status.html.twig' with { | ||
| rsvp: rsvp | ||
| } only %} | ||
| {% else %} | ||
| <span class="text-muted">No RSVP</span> | ||
| {% endif %} | ||
| </div> | ||
| </div> |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it's a little overkill to have this in a separate twig file? Unless there's a good reason for it, like it's being used in multiple locations? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 %} | ||
|
|
||
| <span class="badge {{ statusClass }}" style="color:{{ statusColor }};">{{ statusText }}</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big fan of the assign-return, just split them up.