DONE: settle disable vote for voter with saham under 500, fix issue on...
This commit is contained in:
@@ -96,9 +96,19 @@
|
||||
{{ data.user.kehadiran == 1 ? 'FIZIKAL' : 'MAYA' }}
|
||||
</h5>
|
||||
|
||||
<router-link :to="{ name: 'Vote' }" class="btn btn-warning attendance-vote-button">
|
||||
Undi Sekarang
|
||||
</router-link>
|
||||
<template v-if="canVoteBySaham">
|
||||
<router-link :to="{ name: 'Vote' }" class="btn btn-warning attendance-vote-button">
|
||||
Undi Sekarang
|
||||
</router-link>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="alert alert-warning attendance-saham-block-alert" role="alert">
|
||||
{{ sahamVoteBlockedMessage }}
|
||||
</div>
|
||||
<button type="button" class="btn btn-warning attendance-vote-button" disabled>
|
||||
Undi Sekarang
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-else-if="data.user.kehadiran != 0 && !canProceedToVote" class="attendance-pending-card">
|
||||
@@ -291,6 +301,15 @@
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.attendance-saham-block-alert {
|
||||
margin: 0 auto 16px;
|
||||
max-width: 520px;
|
||||
text-align: left;
|
||||
border-radius: 12px;
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.attendance-pending-card {
|
||||
padding: 24px;
|
||||
border-radius: 18px;
|
||||
@@ -410,6 +429,16 @@ export default {
|
||||
if (!u || Number(u.kehadiran) === 0) return false;
|
||||
if (Number(u.kehadiran) !== 1) return true;
|
||||
return Boolean(u.fizikal_registration_verified_at);
|
||||
},
|
||||
|
||||
/** Saham (RM) must be at least 500 to vote — same rule as home / vote pages. */
|
||||
canVoteBySaham: function () {
|
||||
var s = Number(this.data && this.data.user && this.data.user.saham);
|
||||
return !Number.isNaN(s) && s >= 500;
|
||||
},
|
||||
|
||||
sahamVoteBlockedMessage: function () {
|
||||
return 'Undian tidak tersedia: jumlah saham anda mestilah sekurang-kurangnya RM 500.';
|
||||
}
|
||||
},
|
||||
|
||||
@@ -460,9 +489,10 @@ export default {
|
||||
vm.loading = false;
|
||||
|
||||
if (vm.util.showResult(response, 'success')) {
|
||||
// ✅ Redirect to vote page
|
||||
location.reload();
|
||||
vm.$router.push({ name: 'Vote' }); // OR use path: vm.$router.push('/vote');
|
||||
if (vm.canVoteBySaham) {
|
||||
vm.$router.push({ name: 'Vote' });
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
@@ -63,6 +63,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showSahamVoteBlockedMessage" class="row home-saham-block-row">
|
||||
<div class="col-xs-12">
|
||||
<div class="alert alert-warning home-saham-block-alert" role="alert">
|
||||
<span class="home-saham-block-icon" aria-hidden="true"><i class="fa fa-exclamation-triangle"></i></span>
|
||||
<span>{{ sahamVoteBlockedMessage }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row home-content-row">
|
||||
<div class="col-xs-12 col-md-6 home-column home-column--primary">
|
||||
<div class="home-section-container">
|
||||
@@ -198,6 +207,26 @@ export default {
|
||||
return Boolean(u.fizikal_registration_verified_at);
|
||||
},
|
||||
|
||||
/** Saham (RM) must be at least 500 to vote — see Voter model `saham`. */
|
||||
canVoteBySaham() {
|
||||
const s = Number(this.data?.user?.saham);
|
||||
return !Number.isNaN(s) && s >= 500;
|
||||
},
|
||||
|
||||
showSahamVoteBlockedMessage() {
|
||||
const election = this.data?.election || {};
|
||||
return (
|
||||
Number(election.status) === 2 &&
|
||||
!this.hasVoted() &&
|
||||
this.canProceedToVote &&
|
||||
!this.canVoteBySaham
|
||||
);
|
||||
},
|
||||
|
||||
sahamVoteBlockedMessage() {
|
||||
return "Undian tidak tersedia: jumlah saham anda mestilah sekurang-kurangnya RM 500.";
|
||||
},
|
||||
|
||||
quickLinks() {
|
||||
const user = this.data?.user || {};
|
||||
const election = this.data?.election || {};
|
||||
@@ -235,7 +264,8 @@ export default {
|
||||
if (
|
||||
Number(election.status) === 2 &&
|
||||
!this.hasVoted() &&
|
||||
this.canProceedToVote
|
||||
this.canProceedToVote &&
|
||||
this.canVoteBySaham
|
||||
) {
|
||||
links.push({
|
||||
key: "vote",
|
||||
@@ -273,8 +303,14 @@ export default {
|
||||
return links;
|
||||
},
|
||||
|
||||
/**
|
||||
* Tunai: kehadiran Fizikal, dan sama ada sudah mengundi atau tidak layak mengundi
|
||||
* (saham < RM500) tetapi kehadiran/tetapan mesyuarat sudah memenuhi syarat — masih boleh tuntut elaun.
|
||||
*/
|
||||
canGenerateClaimCode() {
|
||||
return Number(this.data?.user?.kehadiran) === 1 && this.hasVoted();
|
||||
if (Number(this.data?.user?.kehadiran) !== 1) return false;
|
||||
if (this.hasVoted()) return true;
|
||||
return this.canProceedToVote && !this.canVoteBySaham;
|
||||
},
|
||||
|
||||
kehadiranLabel() {
|
||||
@@ -602,6 +638,28 @@ export default {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.home-saham-block-row {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.home-saham-block-alert {
|
||||
margin-bottom: 0;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.home-saham-block-icon {
|
||||
flex-shrink: 0;
|
||||
font-size: 1.5rem;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.home-quick-links-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<div class="vote-page row col-md-10 col-md-offset-1">
|
||||
<div v-if="!canVoteBySaham" class="col-xs-12 vote-saham-block-banner">
|
||||
<div class="alert alert-danger vote-saham-block-alert" role="alert">
|
||||
<i class="fa fa-ban" aria-hidden="true"></i>
|
||||
<span>{{ sahamVoteBlockedMessage }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 vote-sidebar-column">
|
||||
<div class="vote-summary-card">
|
||||
<div class="vote-section-kicker">Ringkasan Undian</div>
|
||||
@@ -24,7 +30,8 @@
|
||||
</li>
|
||||
|
||||
<li class="list-group-item vote-summary-action">
|
||||
<button class="btn btn-success btn-block vote-submit-button" @click="checkUndi()">UNDI</button>
|
||||
<button class="btn btn-success btn-block vote-submit-button" :disabled="!canVoteBySaham"
|
||||
@click="checkUndi()">UNDI</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -98,7 +105,7 @@
|
||||
</div>
|
||||
<div class="modal-footer vote-modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Tutup</button>
|
||||
<button type="button" class="btn btn-primary" @click="submit()">Hantar</button>
|
||||
<button type="button" class="btn btn-primary" :disabled="!canVoteBySaham" @click="submit()">Hantar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,8 +114,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const SAHAM_MINIMUM_UNDIAN = 500;
|
||||
|
||||
export default {
|
||||
created: function () {
|
||||
const saham = Number(this.data?.user?.saham);
|
||||
if (Number.isNaN(saham) || saham < SAHAM_MINIMUM_UNDIAN) {
|
||||
this.util.notify(this.sahamVoteBlockedMessage, 'error');
|
||||
this.$router.push({ name: 'Voter Home' });
|
||||
return;
|
||||
}
|
||||
if (this.data.result.length > 0 || this.data.election.status != 2)
|
||||
this.$router.push({ name: 'Voter Home' })
|
||||
for (var i in this.data.positions) {
|
||||
@@ -130,6 +145,15 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
canVoteBySaham() {
|
||||
const s = Number(this.data?.user?.saham);
|
||||
return !Number.isNaN(s) && s >= SAHAM_MINIMUM_UNDIAN;
|
||||
},
|
||||
|
||||
sahamVoteBlockedMessage() {
|
||||
return 'Undian tidak tersedia: jumlah saham anda mestilah sekurang-kurangnya RM 500.';
|
||||
},
|
||||
|
||||
/** All nominee ids chosen across every position (sidebar + modal must use this, not selected[0]). */
|
||||
allSelectedNomineeIds() {
|
||||
var ids = [];
|
||||
@@ -143,6 +167,9 @@ export default {
|
||||
},
|
||||
|
||||
disabledCheckboxes() {
|
||||
if (!this.canVoteBySaham) {
|
||||
return this.data.nominees.map(() => true);
|
||||
}
|
||||
const selectedNomineeIds = this.allSelectedNomineeIds;
|
||||
return this.data.nominees.map(nominee => {
|
||||
return selectedNomineeIds.includes(nominee.id) ? false : this.checkDisabled();
|
||||
@@ -167,6 +194,10 @@ export default {
|
||||
this.util.showModal('#vote-modal')
|
||||
},
|
||||
submit: function () {
|
||||
if (!this.canVoteBySaham) {
|
||||
this.util.notify(this.sahamVoteBlockedMessage, 'error');
|
||||
return;
|
||||
}
|
||||
if (this.totalSelectedCount() !== this.max) {
|
||||
// No selections made
|
||||
this.util.notify(`Sila pastikan anda memilih (${this.max}) orang calon.`, 'error');
|
||||
@@ -288,6 +319,10 @@ export default {
|
||||
},
|
||||
|
||||
checkUndi: function () {
|
||||
if (!this.canVoteBySaham) {
|
||||
this.util.notify(this.sahamVoteBlockedMessage, 'error');
|
||||
return;
|
||||
}
|
||||
if (this.totalSelectedCount() <= 0) {
|
||||
this.util.notify('Sila pastikan anda memilih (1) orang calon.', 'error');
|
||||
} else {
|
||||
@@ -315,6 +350,25 @@ export default {
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
|
||||
.vote-saham-block-banner {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.vote-saham-block-alert {
|
||||
margin-bottom: 0;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.vote-saham-block-alert .fa {
|
||||
flex-shrink: 0;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.vote-sidebar-column,
|
||||
.vote-content-column {
|
||||
margin-bottom: 24px;
|
||||
|
||||
Reference in New Issue
Block a user