Merge branch '462-display-calendar-items-for-person' into 'master'

Improve the display of upcoming calendar items within the person render box

Closes #462

See merge request Chill-Projet/chill-bundles!928
This commit is contained in:
2025-12-08 12:45:01 +00:00
3 changed files with 75 additions and 3 deletions

View File

@@ -43,6 +43,7 @@ use DateTime;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria; use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\Order;
use Doctrine\Common\Collections\ReadableCollection; use Doctrine\Common\Collections\ReadableCollection;
use Doctrine\Common\Collections\Selectable; use Doctrine\Common\Collections\Selectable;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@@ -139,6 +140,12 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
#[ORM\ManyToMany(targetEntity: Calendar::class, mappedBy: 'persons')] #[ORM\ManyToMany(targetEntity: Calendar::class, mappedBy: 'persons')]
private Collection $calendars; private Collection $calendars;
/**
* @var Collection<int, Calendar>&Selectable<int, Calendar>
*/
#[ORM\OneToMany(mappedBy: 'person', targetEntity: Calendar::class)]
private Collection $directCalendars;
/** /**
* The person's center. * The person's center.
* *
@@ -406,6 +413,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
public function __construct() public function __construct()
{ {
$this->calendars = new ArrayCollection(); $this->calendars = new ArrayCollection();
$this->directCalendars = new ArrayCollection();
$this->accompanyingPeriodParticipations = new ArrayCollection(); $this->accompanyingPeriodParticipations = new ArrayCollection();
$this->spokenLanguages = new ArrayCollection(); $this->spokenLanguages = new ArrayCollection();
$this->addresses = new ArrayCollection(); $this->addresses = new ArrayCollection();
@@ -866,6 +874,30 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
return $this->calendars; return $this->calendars;
} }
/**
* Get next calendars for this person (calendars with start date after today).
* Only returns calendars that are directly linked to this person via the person property,
* not those linked through AccompanyingPeriods.
*
* @param int|null $limit Optional limit for the number of results
*
* @return array<Calendar>
*/
public function getNextCalendarsForPerson(?int $limit = null): array
{
$today = new \DateTimeImmutable('today');
$criteria = Criteria::create()
->where(Criteria::expr()->gte('startDate', $today))
->orderBy(['startDate' => Order::Ascending]);
if (null !== $limit) {
$criteria->setMaxResults($limit);
}
return $this->directCalendars->matching($criteria)->toArray();
}
public function getCenter(): ?Center public function getCenter(): ?Center
{ {
if (null !== $this->centerCurrent) { if (null !== $this->centerCurrent) {
@@ -1119,7 +1151,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
->where( ->where(
$expr->eq('shareHousehold', false) $expr->eq('shareHousehold', false)
) )
->orderBy(['startDate' => \Doctrine\Common\Collections\Order::Descending]); ->orderBy(['startDate' => Order::Descending]);
return $this->getHouseholdParticipations() return $this->getHouseholdParticipations()
->matching($criteria); ->matching($criteria);
@@ -1141,7 +1173,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
->where( ->where(
$expr->eq('shareHousehold', true) $expr->eq('shareHousehold', true)
) )
->orderBy(['startDate' => \Doctrine\Common\Collections\Order::Descending, 'id' => \Doctrine\Common\Collections\Order::Descending]); ->orderBy(['startDate' => Order::Descending, 'id' => Order::Descending]);
return $this->getHouseholdParticipations() return $this->getHouseholdParticipations()
->matching($criteria); ->matching($criteria);

View File

@@ -212,4 +212,3 @@
</div> </div>
</div> </div>
{%- endif -%} {%- endif -%}

View File

@@ -301,6 +301,47 @@
'customButtons': { 'after': _self.button_person_after(person), 'before': _self.button_person_before((person)) } 'customButtons': { 'after': _self.button_person_after(person), 'before': _self.button_person_before((person)) }
}) }} }) }}
{% set calendars = [] %}
{% for c in person.getNextCalendarsForPerson(10) %}
{% if is_granted('CHILL_CALENDAR_CALENDAR_SEE', c) %}
{% set calendars = calendars|merge([c]) %}
{% endif %}
{% endfor %}
{% if calendars|length > 0 %}
<div class="wrap-list periods-list">
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'chill_calendar.Next calendars'|trans }}</h3>
</div>
<div class="wl-col list">
<div class="calendar-list">
<ul class="calendar-list">
{% for c in calendars %}
<li>
{% if is_granted('CHILL_CALENDAR_CALENDAR_EDIT', c) %}
<a href="{{ chill_path_add_return_path('chill_calendar_calendar_edit', { id: c.id }) }}">
<span class="badge bg-secondary">
{{ c.startDate|format_datetime('long', 'short') }}
</span>
</a>
{% else %}
<span class="badge bg-secondary">
{{ c.startDate|format_datetime('long', 'short') }}
</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% if is_granted('CHILL_CALENDAR_CALENDAR_SEE', person) %}
<a href="{{ chill_path_add_return_path('chill_calendar_calendar_list_by_person', {'id': person.id}) }}" class="calendar-list__global"><i class="fa fa-list"></i></a>
{% endif %}
</div>
</div>
</div>
</div>
{% endif %}
{#- 'acps' is for AcCompanyingPeriodS #} {#- 'acps' is for AcCompanyingPeriodS #}
{%- set acps = [] %} {%- set acps = [] %}
{%- set acpsClosed = [] %} {%- set acpsClosed = [] %}