Add new models and page for motions
This commit is contained in:
146
app/Livewire/Motion/Search.php
Normal file
146
app/Livewire/Motion/Search.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Motion;
|
||||
|
||||
use App\Enums\Parties as PartyEnum;
|
||||
use App\Services\RiksdagenService;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Url;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class Search extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
#[Url]
|
||||
public $query = '';
|
||||
|
||||
#[Url]
|
||||
public $party = '';
|
||||
|
||||
#[Url]
|
||||
public $dateInterval = '';
|
||||
|
||||
private $paginator;
|
||||
|
||||
public $loading = false;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->searchMotions();
|
||||
}
|
||||
|
||||
public function updatedQuery()
|
||||
{
|
||||
$this->resetPage();
|
||||
$this->searchMotions();
|
||||
}
|
||||
|
||||
public function updatedParty()
|
||||
{
|
||||
$this->resetPage();
|
||||
$this->searchMotions();
|
||||
}
|
||||
|
||||
public function updatedDateInterval()
|
||||
{
|
||||
$this->resetPage();
|
||||
$this->searchMotions();
|
||||
}
|
||||
|
||||
public function searchMotions()
|
||||
{
|
||||
if (empty($this->query) && empty($this->party) && empty($this->dateInterval)) {
|
||||
$this->paginator = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->loading = true;
|
||||
|
||||
$cacheKey = 'motions_'.md5($this->query.$this->party.$this->dateInterval.$this->getPage());
|
||||
|
||||
$result = Cache::remember($cacheKey, 60 * 5, function () {
|
||||
return app(RiksdagenService::class)->searchMotions(
|
||||
query: $this->query,
|
||||
party: $this->party,
|
||||
dateInterval: $this->dateInterval,
|
||||
page: $this->getPage()
|
||||
);
|
||||
});
|
||||
|
||||
$motions = $result->original->dokumentlista->dokument ?? [];
|
||||
$totalResults = (int) ($result->original->dokumentlista->{'@traffar'} ?? 0);
|
||||
$perPage = 20; // Default items per page from Riksdag API
|
||||
$currentPage = $this->getPage();
|
||||
|
||||
$this->paginator = new LengthAwarePaginator(
|
||||
items: collect($motions),
|
||||
total: $totalResults,
|
||||
perPage: $perPage,
|
||||
currentPage: $currentPage,
|
||||
options: [
|
||||
'path' => request()->url(),
|
||||
'pageName' => 'page',
|
||||
]
|
||||
);
|
||||
|
||||
$this->loading = false;
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function motions()
|
||||
{
|
||||
return $this->paginator ? collect($this->paginator->items()) : collect();
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function totalResults()
|
||||
{
|
||||
return $this->paginator ? $this->paginator->total() : 0;
|
||||
}
|
||||
|
||||
public function clearFilters()
|
||||
{
|
||||
$this->query = '';
|
||||
$this->party = '';
|
||||
$this->dateInterval = '';
|
||||
$this->resetPage();
|
||||
$this->searchMotions();
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function parties()
|
||||
{
|
||||
return collect(PartyEnum::cases())->mapWithKeys(function ($party) {
|
||||
return [$party->value => $party->label()];
|
||||
});
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function dateIntervals()
|
||||
{
|
||||
return [
|
||||
'2025/26' => '2025/26',
|
||||
'2024/25' => '2024/25',
|
||||
'2023/24' => '2023/24',
|
||||
'2022/23' => '2022/23',
|
||||
'2021/22' => '2021/22',
|
||||
'2020/21' => '2020/21',
|
||||
'2019/20' => '2019/20',
|
||||
'2018/19' => '2018/19',
|
||||
];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$this->searchMotions();
|
||||
|
||||
return view('livewire.motion.search', [
|
||||
'paginatedMotions' => $this->paginator,
|
||||
])->title('Sök Motioner - Riksdagen App');
|
||||
}
|
||||
}
|
||||
71
app/Livewire/Motion/Show.php
Normal file
71
app/Livewire/Motion/Show.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Motion;
|
||||
|
||||
use App\Services\RiksdagenService;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public $motionId;
|
||||
|
||||
public $motion;
|
||||
|
||||
private RiksdagenService $service;
|
||||
|
||||
public function mount($motionId)
|
||||
{
|
||||
$this->motionId = $motionId;
|
||||
$this->service = app(RiksdagenService::class);
|
||||
|
||||
$result = Cache::remember('motion_'.$motionId, 24 * 60 * 60, function () use ($motionId) {
|
||||
return $this->service->getMotion($motionId);
|
||||
});
|
||||
|
||||
$this->motion = $result->original->dokumentlista->dokument[0] ?? null;
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function riksdagenUrl()
|
||||
{
|
||||
return 'https://www.riksdagen.se/sv/dokument-lagar/dokument/'.$this->motionId;
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function authors()
|
||||
{
|
||||
if (! $this->motion || ! isset($this->motion->dokintressent->intressent)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$intressenter = $this->motion->dokintressent->intressent;
|
||||
if (! is_array($intressenter)) {
|
||||
$intressenter = [$intressenter];
|
||||
}
|
||||
|
||||
return collect($intressenter)->where('roll', 'undertecknare');
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function attachments()
|
||||
{
|
||||
if (! $this->motion || ! isset($this->motion->filbilaga->fil)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$files = $this->motion->filbilaga->fil;
|
||||
if (! is_array($files)) {
|
||||
$files = [$files];
|
||||
}
|
||||
|
||||
return collect($files);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.motion.show')
|
||||
->title(($this->motion->titel ?? 'Motion').' - Riksdagen App');
|
||||
}
|
||||
}
|
||||
@@ -2,30 +2,35 @@
|
||||
|
||||
namespace App\Livewire\Person;
|
||||
|
||||
use Livewire\Component;
|
||||
use App\Services\RiksdagenService;
|
||||
use App\Enums\Parties;
|
||||
use App\Services\RiksdagenService;
|
||||
use Livewire\Component;
|
||||
|
||||
class Search extends Component
|
||||
{
|
||||
public $firstName = '';
|
||||
|
||||
public $lastName = '';
|
||||
|
||||
public $party = '';
|
||||
|
||||
public $results = [];
|
||||
|
||||
public $parties = [];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->parties = collect(Parties::cases())->sortBy(fn($party) => $party->label())->toArray();
|
||||
$this->parties = collect(Parties::cases())->sortBy(fn ($party) => $party->label())->toArray();
|
||||
}
|
||||
|
||||
public function search()
|
||||
{
|
||||
$service = app(RiksdagenService::class);
|
||||
|
||||
$this->results = $service->searchPerson(
|
||||
firstName: $this->firstName,
|
||||
lastName: $this->lastName,
|
||||
party: $this->party
|
||||
party: $this->party,
|
||||
)->original;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
namespace App\Livewire\Person;
|
||||
|
||||
use Livewire\Component;
|
||||
use App\Services\RiksdagenService;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Asantibanez\LivewireCharts\Models\PieChartModel;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Lazy;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Lazy()]
|
||||
class Show extends Component
|
||||
@@ -17,9 +18,15 @@ class Show extends Component
|
||||
|
||||
public $votes = [];
|
||||
|
||||
public $motions = [];
|
||||
|
||||
public $votesByYear = [];
|
||||
|
||||
public $selectedYear;
|
||||
public $motionsByYear = [];
|
||||
|
||||
public $votesSelectedYear;
|
||||
|
||||
public $motionsSelectedYear;
|
||||
|
||||
public $selectedUppdragTab = 'current';
|
||||
|
||||
@@ -27,47 +34,87 @@ class Show extends Component
|
||||
|
||||
public $previousUppdrag = [];
|
||||
|
||||
private RiksdagenService $service;
|
||||
|
||||
public function mount($personId)
|
||||
{
|
||||
$this->personId = $personId;
|
||||
$service = app(RiksdagenService::class);
|
||||
$result = $service->searchPerson(mp_id: $personId);
|
||||
$this->service = app(RiksdagenService::class);
|
||||
$result = Cache::remember('person_'.$personId, 24 * 60 * 60, function () use ($personId) {
|
||||
return $this->service->searchPerson(mp_id: $personId);
|
||||
});
|
||||
$this->person = $result->original->personlista->person ?? null;
|
||||
|
||||
$this->getPersonVotes();
|
||||
$this->getPersonMotions();
|
||||
$this->groupUppdrag();
|
||||
}
|
||||
|
||||
#[Computed()]
|
||||
public function riksdagenUrl()
|
||||
{
|
||||
return "https://www.riksdagen.se/sv/ledamoter-partier/ledamot/" . $this->person->tilltalsnamn . "-" . $this->person->efternamn . "_" . $this->personId;
|
||||
return 'https://www.riksdagen.se/sv/ledamoter-partier/ledamot/'.$this->person->tilltalsnamn.'-'.$this->person->efternamn.'_'.$this->personId;
|
||||
}
|
||||
|
||||
public function getPersonVotes()
|
||||
{
|
||||
$service = app(RiksdagenService::class);
|
||||
$result = $service->searchVotes(mp_id: $this->personId);
|
||||
$result = Cache::remember('person_votes_'.$this->personId, 24 * 60 * 60, function () {
|
||||
return $this->service->searchVotes(mp_id: $this->personId);
|
||||
});
|
||||
|
||||
$votesList = $result->original->voteringlista->votering ?? [];
|
||||
|
||||
// Group votes by year (from rm field like 2025/26)
|
||||
// Group votes by "rm" field (e.g., 2024/25)
|
||||
foreach ($votesList as $vote) {
|
||||
$year = explode('/', $vote->rm)[0]; // Extract year from rm like "2025/26"
|
||||
if (!isset($this->votesByYear[$year])) {
|
||||
$this->votesByYear[$year] = [];
|
||||
$rm = $vote->rm;
|
||||
if (! isset($this->votesByYear[$rm])) {
|
||||
$this->votesByYear[$rm] = [];
|
||||
}
|
||||
$this->votesByYear[$year][] = $vote;
|
||||
$this->votesByYear[$rm][] = $vote;
|
||||
}
|
||||
|
||||
// Set default selected year to the most recent
|
||||
if (!empty($this->votesByYear)) {
|
||||
$this->selectedYear = max(array_keys($this->votesByYear));
|
||||
if (! empty($this->votesByYear)) {
|
||||
// Sort keys as strings (e.g., 2024/25, 2023/24, ...)
|
||||
$years = array_keys($this->votesByYear);
|
||||
rsort($years, SORT_STRING);
|
||||
$this->votesSelectedYear = $years[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function selectYear($year)
|
||||
public function getPersonMotions()
|
||||
{
|
||||
$this->selectedYear = $year;
|
||||
$result = Cache::remember('person_motions_'.$this->personId, 24 * 60 * 60, function () {
|
||||
return $this->service->getPersonMotions(mp_id: $this->personId);
|
||||
});
|
||||
$motionsList = $result->original->dokumentlista->dokument ?? [];
|
||||
|
||||
// Group votes by "rm" field (e.g., 2024/25)
|
||||
foreach ($motionsList as $motion) {
|
||||
$rm = $motion->rm;
|
||||
if (! isset($this->motionsByYear[$rm])) {
|
||||
$this->motionsByYear[$rm] = [];
|
||||
}
|
||||
$this->motionsByYear[$rm][] = $motion;
|
||||
}
|
||||
|
||||
// Set default selected year to the most recent
|
||||
if (! empty($this->motionsByYear)) {
|
||||
// Sort keys as strings (e.g., 2024/25, 2023/24, ...)
|
||||
$years = array_keys($this->motionsByYear);
|
||||
rsort($years, SORT_STRING);
|
||||
$this->motionsSelectedYear = $years[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function selectVotesYear($year)
|
||||
{
|
||||
$this->votesSelectedYear = $year;
|
||||
}
|
||||
|
||||
public function selectMotionsYear($year)
|
||||
{
|
||||
$this->motionsSelectedYear = $year;
|
||||
}
|
||||
|
||||
public function selectUppdragTab($tab)
|
||||
@@ -77,7 +124,7 @@ class Show extends Component
|
||||
|
||||
public function groupUppdrag()
|
||||
{
|
||||
if (!$this->person || !isset($this->person->personuppdrag->uppdrag)) {
|
||||
if (! $this->person || ! isset($this->person->personuppdrag->uppdrag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -98,11 +145,11 @@ class Show extends Component
|
||||
}
|
||||
|
||||
// Sort by date (most recent first)
|
||||
usort($this->currentUppdrag, function($a, $b) {
|
||||
usort($this->currentUppdrag, function ($a, $b) {
|
||||
return \Carbon\Carbon::parse($b->from)->timestamp - \Carbon\Carbon::parse($a->from)->timestamp;
|
||||
});
|
||||
|
||||
usort($this->previousUppdrag, function($a, $b) {
|
||||
usort($this->previousUppdrag, function ($a, $b) {
|
||||
return \Carbon\Carbon::parse($b->tom ?: $b->from)->timestamp - \Carbon\Carbon::parse($a->tom ?: $a->from)->timestamp;
|
||||
});
|
||||
}
|
||||
@@ -110,16 +157,16 @@ class Show extends Component
|
||||
#[Computed()]
|
||||
public function votingStatistics()
|
||||
{
|
||||
if (!$this->selectedYear || !isset($this->votesByYear[$this->selectedYear])) {
|
||||
if (! $this->votesSelectedYear || ! isset($this->votesByYear[$this->votesSelectedYear])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$votes = $this->votesByYear[$this->selectedYear];
|
||||
$votes = $this->votesByYear[$this->votesSelectedYear];
|
||||
$statistics = [];
|
||||
|
||||
foreach ($votes as $vote) {
|
||||
$voteType = $vote->rost;
|
||||
if (!isset($statistics[$voteType])) {
|
||||
if (! isset($statistics[$voteType])) {
|
||||
$statistics[$voteType] = 0;
|
||||
}
|
||||
$statistics[$voteType]++;
|
||||
@@ -133,8 +180,8 @@ class Show extends Component
|
||||
{
|
||||
$statistics = $this->votingStatistics;
|
||||
|
||||
$pieChart = (new PieChartModel())
|
||||
->setTitle('Voteringsstatistik för ' . $this->selectedYear)
|
||||
$pieChart = (new PieChartModel)
|
||||
->setTitle('Voteringsstatistik för '.$this->votesSelectedYear)
|
||||
->setAnimated(true)
|
||||
->withDataLabels();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user