DONE: add portal setting endpoint for admin to update

This commit is contained in:
ISMAIL MASSERAN
2026-04-23 11:40:44 +08:00
parent 051ec7f48f
commit e0b8ea77eb
12 changed files with 518 additions and 78 deletions
@@ -54,6 +54,10 @@
<a href="#"><b>Log Aktiviti</b></a>
</router-link>
<router-link :to="{ name: 'Tetapan Portal' }" v-if="data.user.role == 1" tag="li">
<a href="#"><b>Tetapan Portal</b></a>
</router-link>
</ul>
<ul class="nav navbar-right navbar-nav">
@@ -0,0 +1,143 @@
<template>
<div class="container col-md-10 col-md-offset-1">
<h4>Tetapan Portal (MAT / Mesyuarat)</h4>
<div class="panel panel-default">
<div class="panel-body">
<div class="form-group">
<label>Label pautan (Home) contoh: MAT KE-29</label>
<input v-model="form.home_mat_label" type="text" class="form-control" placeholder="MAT KE-29">
</div>
<div class="form-group">
<label>Banner (Home)</label>
<!-- <div v-if="form.home_banner_image_path" class="help-block">
Semasa: <code>{{ form.home_banner_image_path }}</code>
</div> -->
<input type="file" class="form-control" @change="onBannerChange" accept="image/*">
</div>
<hr>
<div class="form-group">
<label>Label KoPKB (Zoom) contoh: KoPKB KALI KE-29/2025</label>
<input v-model="form.zoom_meeting_label" type="text" class="form-control" placeholder="KoPKB KALI KE-29/2025">
</div>
<div class="form-group">
<label>Ayat penerangan (Zoom)</label>
<textarea v-model="form.zoom_subtitle" class="form-control" rows="3"
placeholder="Sertai Mesyuarat Agung Tahunan..."></textarea>
</div>
<div class="form-group">
<label>Gambar</label>
<!-- <div class="help-block">
Guna path seperti <code>/storage/...</code> atau <code>/images/...</code>. Link luar
(<code>https://...</code>) akan diabaikan.
</div> -->
<input v-model="form.zoom_image_url" type="text" class="form-control"
placeholder="/storage/portal/meeting.png" disabled>
</div>
<div class="form-group">
<label>Pautan mesyuarat (Zoom) Google Meet</label>
<input v-model="form.zoom_meeting_url" type="text" class="form-control"
placeholder="https://meet.google.com/...">
</div>
<button class="btn btn-primary" :disabled="saving" @click="save">
<i class="fa fa-save"></i> {{ saving ? 'Menyimpan...' : 'Simpan' }}
</button>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
loading: false,
saving: false,
bannerFile: null,
form: {
home_mat_label: "",
home_banner_image_path: "",
zoom_meeting_label: "",
zoom_subtitle: "",
zoom_image_url: "",
zoom_meeting_url: ""
}
};
},
created() {
this.util.setTitle("MyKoPKB - Tetapan Portal");
this.fetch();
},
methods: {
onBannerChange(e) {
const files = e && e.target ? e.target.files : null;
this.bannerFile = files && files.length ? files[0] : null;
},
async fetch() {
this.loading = true;
try {
this.util.setAuthorization();
const res = await axios.get(config.API + "admin/portal-settings");
if (res && res.data && res.data.status === "success") {
const d = res.data.data || {};
this.form = {
home_mat_label: d.home_mat_label || "",
home_banner_image_path: d.home_banner_image_path || "",
zoom_meeting_label: d.zoom_meeting_label || "",
zoom_subtitle: d.zoom_subtitle || "",
zoom_image_url: d.zoom_image_url || "",
zoom_meeting_url: d.zoom_meeting_url || ""
};
} else {
this.util.showResult(res, "error");
}
} catch (e) {
this.util.showResult(e, "error");
} finally {
this.loading = false;
}
},
async save() {
if (this.saving) return;
this.saving = true;
try {
this.util.setAuthorization();
const fd = new FormData();
fd.append("home_mat_label", this.form.home_mat_label || "");
fd.append("zoom_meeting_label", this.form.zoom_meeting_label || "");
fd.append("zoom_subtitle", this.form.zoom_subtitle || "");
// zoom_image_url is intentionally not editable from UI (uses default icon / design).
fd.append("zoom_meeting_url", this.form.zoom_meeting_url || "");
if (this.bannerFile) fd.append("home_banner_image", this.bannerFile);
const res = await axios.post(config.API + "admin/portal-settings", fd, {
headers: { "Content-Type": "multipart/form-data" }
});
if (res && res.data && res.data.status === "success") {
this.util.notify("Berjaya simpan tetapan portal.", "success");
this.bannerFile = null;
await this.fetch();
} else {
this.util.showResult(res, "error");
}
} catch (e) {
this.util.showResult(e, "error");
} finally {
this.saving = false;
}
}
}
};
</script>