Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andreiio committed Nov 5, 2024
1 parent b8adcf8 commit dfa3bc5
Show file tree
Hide file tree
Showing 78 changed files with 932 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
22
23 changes: 23 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"trailingComma": "es5",
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true,
"vueIndentScriptAndStyle": true,
"overrides": [
{
"files": ["*.yml", "*.yaml"],
"options": {
"tabWidth": 2
}
},
{
"files": ["*.php"],
"options": {
"printWidth": 120
}
}
]
}
42 changes: 42 additions & 0 deletions app/DataTransferObjects/ProgressData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace App\DataTransferObjects;

use InvalidArgumentException;

readonly class ProgressData
{
public int|float $max;

public int|float $value;

public function __construct(int|float|string $value, int|float|string $max)
{
$this->value = $this->ensureNumeric($value);
$this->max = $this->ensureNumeric($max);
}

public function percent(): float
{
return min(100, max(0, $this->value / $this->max * 100));
}

protected function ensureNumeric(mixed $value): int|float
{
if (\is_int($value) || \is_float($value)) {
return $value;
}

if (! is_numeric($value)) {
throw new InvalidArgumentException('Value must be a numeric type.');
}

if (filter_var($value, \FILTER_VALIDATE_FLOAT) !== false) {
return \floatval($value);
}

return \intval($value);
}
}
35 changes: 35 additions & 0 deletions app/Livewire/Map.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace App\Livewire;

use Illuminate\Support\Facades\Vite;
use Livewire\Attributes\Computed;
use Livewire\Component;

class Map extends Component
{
public ?string $country = null;

public ?string $county = null;

#[Computed]
public function url(): string
{
if ($this->country) {
return Vite::asset('resources/geojson/countries.geojson');
}

if ($this->county) {
return Vite::asset("resources/geojson/localities/{$this->county}.geojson");
}

return Vite::asset('resources/geojson/counties.geojson');
}

public function render()
{
return view('livewire.map');
}
}
91 changes: 91 additions & 0 deletions app/Livewire/Pages/ElectionPage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

declare(strict_types=1);

namespace App\Livewire\Pages;

use App\Models\County;
use App\Models\Election;
use App\Models\Locality;
use Exception;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Url;
use Livewire\Component;

abstract class ElectionPage extends Component implements HasForms
{
use InteractsWithForms;

public Election $election;

#[Url(as: 'tara')]
public ?string $country = null;

#[Url(as: 'judet')]
public ?int $county = null;

#[Url(as: 'localitate')]
public ?int $locality = null;

public function form(Form $form): Form
{
return $form
->columns(2)
->schema([
Select::make('county')
->options(County::pluck('name', 'id'))
->searchable()
->live()
->afterStateUpdated(function (Set $set) {
$set('locality', null);
})
->placeholder('Național'),

Select::make('locality')
->options(
fn (Get $get) => Locality::query()
->where('county_id', $get('county'))
->limit(1000)
->pluck('name', 'id')
)
->searchable()
->live(),

]);
}

#[Computed]
protected function level(): string
{
if ($this->country) {
return 'country';
}

if ($this->county) {
return 'county';
}

return 'national';

if ($this->locality) {
return 'locality';
}

throw new Exception;
}

/**
* Used to refresh the map when the country or county changes.
*/
#[Computed]
public function mapKey(): string
{
return md5("map-{$this->country}-{$this->county}");
}
}
16 changes: 16 additions & 0 deletions app/Livewire/Pages/ElectionResults.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace App\Livewire\Pages;

use Livewire\Attributes\Layout;

class ElectionResults extends ElectionPage
{
#[Layout('components.layouts.timeline')]
public function render()
{
return view('livewire.pages.election-results');
}
}
23 changes: 0 additions & 23 deletions app/Livewire/Pages/ElectionTurnout.php

This file was deleted.

69 changes: 69 additions & 0 deletions app/Livewire/Pages/ElectionTurnouts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace App\Livewire\Pages;

use App\DataTransferObjects\ProgressData;
use App\Models\Turnout;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Tpetry\QueryExpressions\Function\Aggregate\Sum;
use Tpetry\QueryExpressions\Language\Alias;

class ElectionTurnouts extends ElectionPage
{
#[Layout('components.layouts.timeline')]
public function render(): View
{
return view('livewire.pages.election-turnouts');
}

#[Computed]
public function aggregate(): ?ProgressData
{
$result = Turnout::query()
->where('election_id', $this->election->id)
->select([
new Alias(new Sum('initial_total'), 'initial_total'),
new Alias(new Sum('total'), 'total'),
])
->when($this->county, function (Builder $query) {
$query->where('county_id', $this->county)
->groupBy('county_id')
->addSelect('county_id');
})
->toBase()
->first();

if (blank($result)) {
return null;
}

return new ProgressData(
value: \intval($result->total),
max: \intval($result->initial_total),
);
}

#[Computed]
public function data(): Collection
{
return Turnout::query()
->where('election_id', $this->election->id)
->select([
new Alias(new Sum('initial_total'), 'initial_total'),
new Alias(new Sum('total'), 'total'),
])
->when($this->county, function (Builder $query) {
$query->where('county_id', $this->county)
->groupBy('locality_id')
->addSelect('locality_id');
})
->toBase()
->get();
}
}
2 changes: 1 addition & 1 deletion app/Models/ScheduledJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,6 @@ public function disk(): Filesystem

public function getSourcePath(string $filename): string
{
return \sprintf('source/%s/%s', $this->election_id, $filename);
return \sprintf('source/%s/%s/%s', $this->election_id, $this->id, $filename);
}
}
3 changes: 3 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\QueryException;
use Illuminate\Support\Number;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;

Expand Down Expand Up @@ -36,6 +37,8 @@ public function boot(): void
Model::preventAccessingMissingAttributes($shouldBeEnabled);
});

Number::useLocale($this->app->getLocale());

$this->resolveSchedule();

$this->setSeoDefaults();
Expand Down
30 changes: 30 additions & 0 deletions app/View/Components/Progress/Bar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace App\View\Components\Progress;

use Illuminate\Contracts\View\View;
use Illuminate\Support\Number;

class Bar extends Base
{
public function render(): View
{
return view('components.progress.bar');
}

public function label(): string
{
if ($this->percent) {
return Number::percentage($this->percent(), 2);
}

return Number::format($this->value);
}

public function percent(): float
{
return min(100, max(0, $this->value / $this->max * 100));
}
}
Loading

0 comments on commit dfa3bc5

Please sign in to comment.