feat(falukant): add political office catalog feature and localization updates
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s
- Implemented the `getPoliticalOfficeCatalog` method in FalukantService to retrieve available political offices and their prerequisites based on user eligibility. - Updated FalukantController and FalukantRouter to include a new endpoint for accessing the political office catalog. - Enhanced PoliticsView component to display the list of political offices, including their details and application eligibility. - Added localization entries for the new offices tab in both German and English, improving user experience and accessibility.
This commit is contained in:
@@ -128,6 +128,59 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- OPEN Tab: hier zeigen wir 'openPolitics' -->
|
||||
<div v-else-if="activeTab === 'offices'" class="tab-pane">
|
||||
<div v-if="loading.offices" class="loading">{{ $t('loading') }}</div>
|
||||
<template v-else-if="politicalOffices.length">
|
||||
<p class="politics-age-requirement">
|
||||
{{ $t('falukant.politics.officesTab.ageRequirement') }}
|
||||
</p>
|
||||
<div class="politics-card-list">
|
||||
<article v-for="office in politicalOffices" :key="office.officeTypeId" class="politics-card">
|
||||
<div class="politics-card__header">
|
||||
<strong>{{ $t(`falukant.politics.offices.${office.officeTypeName}`) }}</strong>
|
||||
<span>{{ formatPoliticsRegionLevel(office.regionType) }}</span>
|
||||
</div>
|
||||
<div class="politics-card__meta">
|
||||
<div class="politics-card__meta-row">
|
||||
<span class="politics-card__meta-label">{{ $t('falukant.politics.officesTab.seatsPerRegion') }}:</span>
|
||||
<span class="politics-card__meta-value">{{ office.seatsPerRegion }}</span>
|
||||
</div>
|
||||
<div class="politics-card__meta-row">
|
||||
<span class="politics-card__meta-label">{{ $t('falukant.politics.officesTab.termLengthDays') }}:</span>
|
||||
<span class="politics-card__meta-value">{{ office.termLengthDays }}</span>
|
||||
</div>
|
||||
<div class="politics-card__meta-row">
|
||||
<span class="politics-card__meta-label">{{ $t('falukant.politics.officesTab.prerequisites') }}:</span>
|
||||
<span v-if="!office.requiredOfficeNames || !office.requiredOfficeNames.length" class="politics-card__meta-value">
|
||||
{{ $t('falukant.politics.officesTab.noPrerequisites') }}
|
||||
</span>
|
||||
<ul v-else class="politics-benefit-list">
|
||||
<li v-for="req in office.requiredOfficeNames" :key="req">
|
||||
{{ $t(`falukant.politics.offices.${req}`) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="politics-card__meta-row">
|
||||
<span class="politics-card__meta-label">{{ $t('falukant.politics.officesTab.canApplyNow') }}:</span>
|
||||
<span class="politics-card__meta-value">
|
||||
{{ office.canApplyNow
|
||||
? $t('falukant.politics.officesTab.yes')
|
||||
: $t('falukant.politics.officesTab.no') }}
|
||||
<template v-if="!office.canApplyNow">
|
||||
<span v-if="!office.canApplyByAge"> · {{ $t('falukant.politics.officesTab.blockedByAge') }}</span>
|
||||
<span v-if="!office.titleEligible"> · {{ $t('falukant.politics.officesTab.blockedByTitle') }}</span>
|
||||
<span v-if="!office.prerequisitesMet"> · {{ $t('falukant.politics.officesTab.blockedByPrerequisites') }}</span>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</template>
|
||||
<p v-else class="loading">{{ $t('falukant.politics.officesTab.none') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- OPEN Tab: hier zeigen wir 'openPolitics' -->
|
||||
<div v-else-if="activeTab === 'openPolitics'" class="tab-pane">
|
||||
<p class="politics-age-requirement">{{ $t('falukant.politics.open.ageRequirement') }}</p>
|
||||
@@ -235,10 +288,12 @@ export default {
|
||||
tabs: [
|
||||
{ value: 'current', label: 'falukant.politics.tabs.current' },
|
||||
{ value: 'powers', label: 'falukant.politics.tabs.powers' },
|
||||
{ value: 'offices', label: 'falukant.politics.tabs.offices' },
|
||||
{ value: 'openPolitics', label: 'falukant.politics.tabs.upcoming' },
|
||||
{ value: 'elections', label: 'falukant.politics.tabs.elections' }
|
||||
],
|
||||
currentPositions: [],
|
||||
politicalOffices: [],
|
||||
openPolitics: [],
|
||||
elections: [],
|
||||
selectedCandidates: {},
|
||||
@@ -255,6 +310,7 @@ export default {
|
||||
_appointSearchTimer: null,
|
||||
loading: {
|
||||
current: false,
|
||||
offices: false,
|
||||
openPolitics: false,
|
||||
elections: false,
|
||||
powers: false
|
||||
@@ -379,6 +435,9 @@ export default {
|
||||
if (tab === 'powers') {
|
||||
this.loadPowers();
|
||||
}
|
||||
if (tab === 'offices') {
|
||||
this.loadPoliticalOffices();
|
||||
}
|
||||
if (tab === 'openPolitics') {
|
||||
this.loadOpenPolitics();
|
||||
}
|
||||
@@ -411,6 +470,20 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
async loadPoliticalOffices() {
|
||||
this.loading.offices = true;
|
||||
try {
|
||||
const { data } = await apiClient.get('/api/falukant/politics/offices');
|
||||
this.politicalOffices = Array.isArray(data) ? data : [];
|
||||
} catch (err) {
|
||||
console.error('[PoliticsView] loadPoliticalOffices', err);
|
||||
this.politicalOffices = [];
|
||||
showApiError(this, err, this.$t('falukant.politics.officesTab.loadError'));
|
||||
} finally {
|
||||
this.loading.offices = false;
|
||||
}
|
||||
},
|
||||
|
||||
appointOptionKey(a) {
|
||||
return `${a.officeTypeId}:${a.regionId}`;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user