Allowance check

This commit is contained in:
ISMAIL MASSERAN
2026-04-14 02:34:00 +00:00
parent 0c4d200839
commit 3775c4a876
100 changed files with 81493 additions and 3226 deletions
@@ -1,78 +1,193 @@
<template>
<div class="panel panel-default">
<div class="panel panel-default nominee-add-page">
<div class="panel-body">
<form class="row" method="POST" id="add_form" :action="data.API + 'nominee'" enctype="mutlipart/formdata"
@submit.prevent="add()">
<div class="col-md-8">
<div class="nominee-add-page__header clearfix">
<h4 class="pull-left nominee-add-page__title">
<i class="fa fa-user-plus text-muted"></i> Tambah Calon
</h4>
<router-link
:to="{ name: 'Maklumat Calon', query: { position_id: position_id } }"
class="btn btn-default pull-right"
>
<i class="fa fa-arrow-left"></i> Kembali
</router-link>
</div>
<div class="form-group">
<label for="name">Nama Calon</label>
<input type="text" name="name" class="form-control" required />
<p class="text-muted small nominee-add-page__intro">
Lengkapkan maklumat calon. Medan bertanda <span class="text-danger">*</span> adalah wajib.
</p>
<form
class="nominee-add-form"
method="POST"
id="add_form"
:action="data.API + 'nominee'"
enctype="multipart/form-data"
@submit.prevent="add()"
>
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="nominee-name">Nama Calon <span class="text-danger">*</span></label>
<input
id="nominee-name"
type="text"
name="name"
class="form-control"
placeholder="Nama penuh"
required
/>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="nominee-no-anggota">No. Anggota <span class="text-danger">*</span></label>
<input
id="nominee-no-anggota"
type="text"
name="no_anggota"
class="form-control"
placeholder="No. keahlian"
required
/>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="nominee-unit">Unit <span class="text-danger">*</span></label>
<input
id="nominee-unit"
type="text"
name="unit"
class="form-control"
required
/>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="nominee-umur">Umur <span class="text-danger">*</span></label>
<input
id="nominee-umur"
type="number"
name="umur"
class="form-control"
min="1"
max="120"
placeholder="Tahun"
required
/>
</div>
</div>
</div>
<div class="form-group">
<label for="nominee-jawatan-sekarang">Jawatan Sekarang <span class="text-danger">*</span></label>
<input
id="nominee-jawatan-sekarang"
type="text"
name="jawatan_sekarang"
class="form-control"
required
/>
</div>
<div class="form-group">
<label for="nominee-education">Taraf Pendidikan</label>
<input
id="nominee-education"
type="text"
name="education"
class="form-control"
placeholder="Pilihan"
/>
</div>
<div class="form-group">
<label for="nominee-experience">Pengalaman Kerja</label>
<textarea
id="nominee-experience"
name="experience"
class="form-control"
rows="4"
placeholder="Pilihan — senaraikan pengalaman relevan"
></textarea>
</div>
<div class="form-group">
<label for="nominee-position-id">Jawatan Dicalonkan <span class="text-danger">*</span></label>
<select
id="nominee-position-id"
class="form-control"
v-model="position_id"
name="position_id"
required
>
<option value="0" disabled> Pilih jawatan </option>
<option
v-for="position in data.positions"
:key="position.id"
:value="position.id"
>
{{ position.name }}
</option>
</select>
</div>
</div>
<div class="form-group">
<label for="no_anggota">No. Anggota</label>
<input type="text" name="no_anggota" class="form-control" required />
<div class="col-md-4">
<div class="nominee-add-photo panel panel-default">
<div class="panel-heading">
<strong><i class="fa fa-camera"></i> Gambar calon</strong>
<span class="text-muted small nominee-add-photo__hint">Pilihan</span>
</div>
<div class="panel-body">
<div
class="nominee-add-photo__preview"
:class="{ 'nominee-add-photo__preview--empty': !imageUrl }"
>
<img v-if="imageUrl" :src="imageUrl" alt="Pratonton gambar calon" />
<div v-else class="nominee-add-photo__placeholder">
<i class="fa fa-picture-o"></i>
<span>Tiada gambar dipilih</span>
</div>
</div>
<label class="btn btn-default btn-block nominee-add-photo__browse" for="nominee-file-input">
<i class="fa fa-folder-open"></i> Pilih fail
</label>
<input
id="nominee-file-input"
name="photo"
type="file"
class="nominee-add-photo__input"
accept="image/*"
@change="handleImageChange"
/>
<p class="text-muted small nominee-add-photo__formats">PNG, JPG atau GIF</p>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="unit">Unit</label>
<input type="text" name="unit" class="form-control" required />
</div>
<hr class="nominee-add-form__rule" />
<div class="form-group">
<label for="unit">Umur</label>
<input type="text" name="umur" class="form-control" required />
</div>
<div class="form-group">
<label for="unit">Jawatan Sekarang</label>
<input type="text" name="jawatan_sekarang" class="form-control" required />
</div>
<div class="form-group">
<label for="education">Taraf Pendidikan</label>
<input type="text" name="education" class="form-control" placeholder="(Optional)" />
</div>
<div class="form-group">
<label for="pengalaman">Pengalaman Kerja</label>
<textarea name="pengalaman" class="form-control" placeholder="(Optional)"></textarea>
</div>
<div class="form-group">
<label for="position_id">Jawatan</label>
<select class="form-control" v-model="position_id" name="position_id" required>
<option value="0" disabled>--- Pilih Jawatan ---</option>
<option v-for="position in data.positions" :key="position.id" :value="position.id">{{ position.name }}</option>
</select>
</div>
<!-- <div class="form-group">
<label for="partylist_id">Partylist</label>
<select class="form-control" name="partylist_id">
<option value="">--- Select Partylist (Optional) ---</option>
<option v-for="partylist in data.partylists" :value="partylist.id">{{ partylist.name }}</option>
</select>
</div> -->
<div id="imagePreview">
<img :src="imageUrl" v-if="imageUrl" alt="Preview">
</div>
<div>
<label for="image">Muatnaik Gambar</label>
<input name="photo" type="file" accept="image/*" id="file-input" @change="handleImageChange">
</div>
<div class="form-group pull-right">
<router-link :to="{ name: 'Maklumat Calon', query: { position_id: position_id } }"
class="btn btn-default">
Cancel
</router-link>
<input type="submit" value="Submit" class="btn btn-info">
</div>
<div class="clearfix nominee-add-form__actions">
<router-link
:to="{ name: 'Maklumat Calon', query: { position_id: position_id } }"
class="btn btn-default"
>
<i class="fa fa-times"></i> Batal
</router-link>
<button type="submit" class="btn btn-primary" :disabled="loading">
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
<i v-else class="fa fa-check"></i>
{{ loading ? 'Menghantar…' : 'Simpan calon' }}
</button>
</div>
</form>
</div>
@@ -83,7 +198,7 @@
export default {
data: function () {
return {
imageUrl: '',
imageUrl: '',
loading: false
}
},
@@ -102,8 +217,8 @@ export default {
vm.$router.push({ name: 'Maklumat Calon' });
},
error: function (error) {
alert('Nominee with the same name has already registered');
location.reload();
alert('Nominee with the same name has already registered');
location.reload();
$.notifyClose();
vm.loading = false;
vm.util.showResult(error, 'error', 'ajax');
@@ -114,27 +229,23 @@ export default {
})
},
handleImageChange(event) {
const file = event.target.files[0]; // Get the selected file
const imageType = /image.*/; // RegExp to check if the file is an image
handleImageChange(event) {
const file = event.target.files[0];
const imageType = /image.*/;
// Check if the selected file is an image
if (file && file.type.match(imageType)) {
const reader = new FileReader(); // Create a FileReader object
if (file && file.type.match(imageType)) {
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = e.target.result; // Set the imageUrl to the data URL of the image
document.getElementById('imagePreview').style.display = 'block'; // Display the div
};
reader.onload = (e) => {
this.imageUrl = e.target.result;
};
reader.readAsDataURL(file); // Read the image data as a data URL
} else {
// Clear the file input and hide the div if the selected file is not an image
event.target.value = '';
this.imageUrl = '';
document.getElementById('imagePreview').style.display = 'none';
}
}
reader.readAsDataURL(file);
} else {
event.target.value = '';
this.imageUrl = '';
}
}
},
computed: {
@@ -152,16 +263,115 @@ export default {
</script>
<style scoped>
#imagePreview {
width: 200px;
height: 200px;
border: 1px solid #ccc;
margin-bottom: 10px;
display: none; /* Initially hide the div */
}
.nominee-add-page__header {
margin-bottom: 12px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
#imagePreview img {
max-width: 100%;
max-height: 100%;
}
.nominee-add-page__title {
margin-top: 0;
margin-bottom: 0;
font-weight: 600;
}
.nominee-add-page__title .fa {
margin-right: 6px;
}
.nominee-add-page__intro {
margin-bottom: 18px;
}
.nominee-add-photo .panel-heading {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
}
.nominee-add-photo__hint {
font-weight: normal;
}
.nominee-add-photo__preview {
width: 100%;
aspect-ratio: 1;
max-height: 240px;
border-radius: 4px;
overflow: hidden;
background: #f9f9f9;
border: 1px dashed #ccc;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12px;
}
.nominee-add-photo__preview--empty {
min-height: 180px;
}
.nominee-add-photo__preview img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.nominee-add-photo__placeholder {
text-align: center;
color: #999;
padding: 16px;
}
.nominee-add-photo__placeholder .fa {
font-size: 36px;
display: block;
margin-bottom: 8px;
opacity: 0.65;
}
.nominee-add-photo__placeholder span {
display: block;
font-size: 12px;
}
.nominee-add-photo__input {
position: absolute;
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
z-index: -1;
}
.nominee-add-photo__browse {
margin-bottom: 0;
}
.nominee-add-photo__formats {
margin: 8px 0 0;
text-align: center;
}
.nominee-add-form__rule {
margin-top: 8px;
margin-bottom: 16px;
border-top-color: #eee;
}
.nominee-add-form__actions {
text-align: right;
}
.nominee-add-form__actions .btn + .btn {
margin-left: 8px;
}
@media (max-width: 991px) {
.nominee-add-photo {
margin-top: 8px;
}
}
</style>