Done ui niise

This commit is contained in:
Md Afiq Iskandar 2024-08-30 09:58:17 +08:00
parent 45bd30b143
commit 772d425fdd
17 changed files with 1537 additions and 608 deletions

View File

@ -1,6 +1,6 @@
<script setup>
useHead({
title: "Niise | Innovative solutions for captivating content",
title: "Niise",
description: "Home page",
htmlAttrs: {
lang: "en",

View File

@ -105,42 +105,78 @@ export default [
child: [],
meta: {},
},
{
title: "Tipografi",
path: "/tipografi",
icon: "ph:text-aa",
child: [],
meta: {},
},
{
title: "Senarai Mesej",
path: "/senarai-mesej",
icon: "ic:outline-mail",
child: [],
meta: {},
},
],
meta: {},
},
{
header: "Administration",
header: "Prototaip Forensik",
description: "",
child: [
{
title: "Configuration",
title: "FOR-01",
icon: "ph:number-circle-one-fill",
child: [
{
title: "Permohonan",
path: "/prototype/for-01/permohonan",
child: [],
},
{
title: "Kemaskini Daftar",
path: "/prototype/for-01/kemaskini-daftar",
child: [],
},
],
},
],
},
{
header: "Pengurusan",
description: "",
child: [
{
title: "Konfigurasi",
icon: "ic:outline-settings",
child: [
{
title: "Environment",
title: "Persekitaran",
path: "/devtool/config/environment",
},
],
},
{
title: "Menu Editor",
title: "Penyelia Menu",
icon: "ci:menu-alt-03",
path: "/devtool/menu-editor",
child: [],
},
{
title: "Manage Users",
title: "Penyelia Pengguna",
path: "/devtool/user-management",
icon: "ph:user-circle-gear",
child: [
{
title: "User List",
title: "Pengguna",
path: "/devtool/user-management/user-list",
icon: "",
child: [],
},
{
title: "Role List",
title: "Peranan",
path: "/devtool/user-management/role-list",
icon: "",
child: [],
@ -148,21 +184,21 @@ export default [
],
},
{
title: "Content",
title: "Kandungan",
icon: "mdi:pencil-ruler",
child: [
{
title: "Editor",
title: "Penyelia Kandungan",
path: "/devtool/content-editor",
},
{
title: "Template",
title: "Templat",
path: "/devtool/content-editor/template",
},
],
},
{
title: "API Editor",
title: "Penyelia API",
path: "/devtool/api-editor",
icon: "material-symbols:api-rounded",
child: [],

View File

@ -11,475 +11,328 @@ definePageMeta({
],
});
const data1 = ref([]);
const data2 = ref([]);
const data3 = ref([]);
const data4 = ref([]);
var sparkline1Data = [47, 45, 54, 38, 56, 24, 65];
var sparkline2Data = [61, 35, 66, 41, 59, 25, 32];
var sparkline3Data = [25, 18, 36, 41, 43, 35, 14];
var sparkline4Data = [8, 16, 22, 41, 43, 35, 14];
const changeKey = ref(0);
const customers = [
// Data baru untuk lapangan terbang teratas
const topAirports = ref([
{
name: "Iqmal",
age: "25",
city: "Kuala Lumpur",
country: "Malaysia",
totalPurchase: 1524,
purchase: 23,
rank: 1,
name: "Lapangan Terbang Antarabangsa Kuala Lumpur (KLIA)",
visitors: 62000000,
},
{
name: "Adi",
age: "45",
city: "Pulau Pinang",
country: "Malaysia",
totalPurchase: 643,
purchase: 14,
rank: 2,
name: "Lapangan Terbang Antarabangsa Kota Kinabalu",
visitors: 9000000,
},
{ rank: 3, name: "Lapangan Terbang Antarabangsa Penang", visitors: 8000000 },
{ rank: 4, name: "Lapangan Terbang Antarabangsa Kuching", visitors: 5500000 },
{
name: "Raziq",
age: "21",
city: "Kelantan",
country: "Malaysia",
totalPurchase: 543,
purchase: 12,
},
{
name: "Haqeem",
age: "19",
city: "Negeri Sembilan",
country: "Malaysia",
totalPurchase: 258,
purchase: 6,
},
];
const randomizeArray = function (arg) {
var array = arg.slice();
var currentIndex = array.length,
temporaryValue,
randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
data1.value.push({
name: "Revenues",
data: randomizeArray(sparkline1Data),
});
data2.value.push({
name: "Users",
data: randomizeArray(sparkline2Data),
});
data3.value.push({
name: "Products",
data: randomizeArray(sparkline3Data),
});
data4.value.push({
name: "Viewers",
data: randomizeArray(sparkline4Data),
});
const chartOptions = computed(() => ({
chart: {
type: "area",
sparkline: {
enabled: true,
},
},
stroke: {
curve: "smooth",
},
fill: {
opacity: 1,
},
labels: [...Array(7).keys()].map((n) => `2022-06-0${n + 1}`),
xaxis: {
type: "datetime",
},
}));
// Radial Chart
const radialData = ref([44, 55, 67, 83]);
const chartOptionsRadial = computed(() => ({
chart: {
height: 350,
type: "radialBar",
},
plotOptions: {
radialBar: {
dataLabels: {
style: {
colors: "#9CA3AF",
},
name: {
offsetY: 30,
fontSize: "18px",
},
value: {
offsetY: -15,
fontSize: "30px",
},
total: {
show: true,
label: "Total",
formatter: function (w) {
// By default this function returns the average of all series. The below is just an example to show the use of custom formatter function
return 249;
},
},
},
},
},
labels: ["Product A", "Product B", "Product C", "Product D"],
stroke: {
lineCap: "round",
},
}));
// Transaction Graph
const transactionData = ref([
{
name: "Bill A",
data: [...Array(12).keys()].map((n) => Math.round(Math.random() * 100)),
},
{
name: "Bill B",
data: [...Array(12).keys()].map((n) => Math.round(Math.random() * 100)),
rank: 5,
name: "Lapangan Terbang Antarabangsa Langkawi",
visitors: 3000000,
},
]);
const chartOptionsTransaction = computed(() => ({
chart: {
height: 350,
type: "area",
toolbar: {
show: false,
},
// Data baru untuk kad ringkasan pantas
const quickSummary = ref([
{ title: "Jumlah Pelawat", value: "10.5 Juta", icon: "ic:outline-people" },
{
title: "Pendapatan Pelancongan",
value: "RM 86.14 Bilion",
icon: "ic:outline-attach-money",
},
dataLabels: {
enabled: false,
{
title: "Tempoh Penginapan Purata",
value: "6.1 Hari",
icon: "ic:outline-hotel",
},
stroke: {
curve: "smooth",
{
title: "Kepuasan Pelancong",
value: "92%",
icon: "ic:outline-sentiment-satisfied",
},
colors: ["#6366F1", "#F97316"],
yaxis: {
labels: {
style: {
colors: "#9CA3AF",
fontSize: "12px",
]);
// Data Pelawat Malaysia
const visitorData = ref([
{
name: "Pelawat Tempatan",
data: [5000000, 5500000, 6000000, 6500000, 7000000, 7500000],
},
{
name: "Pelawat Asing",
data: [3000000, 3500000, 4000000, 4500000, 5000000, 5500000],
},
]);
// Data Pelawat Asing mengikut Negeri
const foreignVisitorsByState = ref([
{ state: "Selangor", visitors: 1500000 },
{ state: "Pulau Pinang", visitors: 1200000 },
{ state: "Johor", visitors: 1000000 },
{ state: "Sabah", visitors: 800000 },
{ state: "Sarawak", visitors: 600000 },
{ state: "Melaka", visitors: 500000 },
{ state: "Kedah", visitors: 400000 },
{ state: "Negeri Sembilan", visitors: 300000 },
{ state: "Perak", visitors: 250000 },
{ state: "Terengganu", visitors: 200000 },
{ state: "Kelantan", visitors: 150000 },
{ state: "Pahang", visitors: 100000 },
{ state: "Perlis", visitors: 50000 },
]);
// Lapangan Terbang Keberangkatan Teratas
const departureData = ref([
{ airport: "JFK", departures: 1500 },
{ airport: "LHR", departures: 1200 },
{ airport: "CDG", departures: 1000 },
{ airport: "DXB", departures: 800 },
{ airport: "SIN", departures: 600 },
]);
// Data Pelancong Berulang
const repeatVisitorsData = ref([
{ category: "1-2 kali", percentage: 45 },
{ category: "3-5 kali", percentage: 30 },
{ category: "6-10 kali", percentage: 15 },
{ category: ">10 kali", percentage: 10 },
]);
// Data Negara Asal Pelancong Asing Teratas
const topVisitorCountries = ref([
{ country: "Singapura", visitors: 1500000 },
{ country: "Indonesia", visitors: 1200000 },
{ country: "China", visitors: 1000000 },
{ country: "Thailand", visitors: 800000 },
{ country: "India", visitors: 600000 },
]);
const chartOptionsVisitors = computed(() => ({
chart: { height: 350, type: "line" },
stroke: { curve: "smooth", width: 2 },
xaxis: { categories: ["2018", "2019", "2020", "2021", "2022", "2023"] },
yaxis: { title: { text: "Bilangan Pelawat" } },
}));
const chartOptionsForeignVisitors = computed(() => ({
chart: { type: "bar" },
plotOptions: { bar: { horizontal: true } },
xaxis: { categories: foreignVisitorsByState.value.map((item) => item.state) },
}));
const chartOptionsDeparture = computed(() => ({
chart: { type: "bar" },
plotOptions: { bar: { horizontal: true } },
xaxis: { categories: departureData.value.map((item) => item.airport) },
}));
const chartOptionsRepeatVisitors = computed(() => ({
chart: { type: "pie" },
labels: repeatVisitorsData.value.map((item) => item.category),
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 200,
},
legend: {
position: "bottom",
},
},
},
],
}));
const chartOptionsTopCountries = computed(() => ({
chart: { type: "bar" },
plotOptions: {
bar: { horizontal: false, columnWidth: "55%", endingShape: "rounded" },
},
xaxis: {
type: "datetime",
categories: [
"2022-01-01",
"2022-02-01",
"2022-03-01",
"2022-04-01",
"2022-05-01",
"2022-06-01",
"2022-07-01",
"2022-08-01",
"2022-09-01",
"2022-10-01",
"2022-11-01",
"2022-12-01",
],
labels: {
style: {
colors: "#9CA3AF",
fontSize: "14px",
fontWeight: 400,
},
datetimeFormatter: {
month: "MMM",
},
},
},
legend: {
position: "top",
horizontalAlign: "left",
labels: {
colors: "#9CA3AF",
useSeriesColors: false,
},
},
dataLabels: { enabled: false },
stroke: { show: true, width: 2, colors: ["transparent"] },
xaxis: { categories: topVisitorCountries.value.map((item) => item.country) },
yaxis: { title: { text: "Bilangan Pelawat" } },
fill: { opacity: 1 },
tooltip: {
x: {
format: "MMMM",
y: {
formatter: function (val) {
return val.toLocaleString() + " pelawat";
},
},
},
}));
onMounted(() => {
setTimeout(() => {
changeKey.value++;
}, 500);
// Sebarang logik yang diperlukan semasa pemasangan
});
</script>
<template>
<div>
<LayoutsBreadcrumb />
<!-- First Row -->
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-x-6">
<!-- Summary Card #1 -->
<rs-card>
<div class="summary-1 pt-5 pb-3 px-5 flex items-center gap-4">
<!-- Kad Ringkasan Pantas -->
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-6">
<rs-card
v-for="(item, index) in quickSummary"
:key="index"
class="transition-all duration-300 hover:shadow-lg"
>
<div class="pt-5 pb-3 px-5 flex items-center gap-4">
<div
class="p-5 flex justify-center items-center bg-primary/20 rounded-2xl"
class="p-5 flex justify-center items-center bg-primary/20 rounded-2xl transition-all duration-300 hover:bg-primary/30"
>
<Icon class="text-primary" name="ic:outline-attach-money"></Icon>
<Icon class="text-primary text-3xl" :name="item.icon"></Icon>
</div>
<div class="flex-1 truncate">
<span class="block font-semibold text-xl leading-tight">
RM 100,000</span
>
<span class="text-base font-semibold text-gray-500"
>Total Revenues</span
>
<span class="block font-bold text-2xl leading-tight text-primary">
{{ item.value }}
</span>
<span class="text-sm font-medium text-gray-600">
{{ item.title }}
</span>
</div>
</div>
<client-only>
<VueApexCharts
:key="changeKey"
width="100%"
height="53"
:options="{
...chartOptions,
colors: ['#F43F5E'],
yaxis: {
min: 0,
max: Math.max(...data1[0].data) + 10,
},
}"
:series="data1"
></VueApexCharts>
</client-only>
</rs-card>
<!-- Summary Card #2 -->
<rs-card>
<div class="summary-2 pt-5 pb-3 px-5 flex items-center gap-4">
<div
class="p-5 flex justify-center items-center bg-indigo-100 rounded-2xl"
>
<Icon
class="text-indigo-500"
name="ic:outline-account-circle"
></Icon>
</div>
<div class="flex-1 truncate">
<span class="block font-semibold text-xl leading-tight"> 512</span>
<span class="text-base font-semibold text-gray-500"
>Total Users</span
>
</div>
</div>
<client-only>
<VueApexCharts
:key="changeKey"
width="100%"
height="53"
:options="{
...chartOptions,
colors: ['#6366F1'],
yaxis: {
min: 0,
max: Math.max(...data2[0].data) + 10,
},
}"
:series="data2"
></VueApexCharts>
</client-only>
</rs-card>
<!-- Summary Card #3 -->
<rs-card>
<div class="summary-3 pt-5 pb-3 px-5 flex items-center gap-4">
<div
class="p-5 flex justify-center items-center bg-orange-100 rounded-2xl"
>
<Icon class="text-orange-500" name="ic:outline-shopping-bag"></Icon>
</div>
<div class="flex-1 truncate">
<span class="block font-semibold text-xl leading-tight"> 20</span>
<span class="text-base font-semibold text-gray-500"
>Total Products</span
>
</div>
</div>
<client-only>
<VueApexCharts
:key="changeKey"
width="100%"
height="53"
:options="{
...chartOptions,
colors: ['#F97316'],
yaxis: {
min: 0,
max: Math.max(...data3[0].data) + 10,
},
}"
:series="data3"
></VueApexCharts>
</client-only>
</rs-card>
<!-- Summary Card #4 -->
<rs-card>
<div class="summary-4 pt-5 pb-3 px-5 flex items-center gap-4">
<div
class="p-5 flex justify-center items-center bg-blue-100 rounded-2xl"
>
<Icon class="text-blue-500" name="ic:outline-remove-red-eye"></Icon>
</div>
<div class="flex-1 truncate">
<span class="block font-semibold text-xl leading-tight">
2,452</span
>
<span class="text-base font-semibold text-gray-500"
>Total Viewers</span
>
</div>
</div>
<client-only>
<VueApexCharts
:key="changeKey"
width="100%"
height="53"
:options="{
...chartOptions,
colors: ['#3B82F6'],
yaxis: {
min: 0,
max: Math.max(...data4[0].data) + 10,
},
}"
:series="data4"
></VueApexCharts>
</client-only>
</rs-card>
</div>
<div class="flex flex-col md:flex-row gap-x-6">
<div class="w-12/2 md:w-8/12 flex flex-col">
<!-- Graph -->
<rs-card class="flex-1">
<template #header> Transaction </template>
<template #body>
<client-only>
<VueApexCharts
:key="changeKey"
width="100%"
height="300"
name="area"
:options="chartOptionsTransaction"
:series="transactionData"
></VueApexCharts
></client-only>
</template>
</rs-card>
<rs-card class="flex-1">
<template #header> Referral</template>
<template #body>
<div
v-for="(val, index) in customers"
:key="index"
class="flex justify-between items-center rounded-lg bg-[rgb(var(--bg-1))] p-5 first:mt-0 mt-3"
>
<div class="flex items-center gap-x-4">
<img
src="@/assets/img/avatar/user.webp"
class="h-10 w-10 rounded-lg"
/>
<div class="flex-1">
<div class="flex flex-col">
<span
class="text-gray-900 dark:text-white font-semibold text-lg"
>
{{ val.name }}
</span>
<span class="text-gray-600 dark:text-gray-50 text-sm">
RM{{ parseFloat(val.totalPurchase).toFixed(2) }} |
{{ val.purchase }} sold
</span>
</div>
</div>
</div>
<div>
<button
class="flex items-center p-4 rounded-full bg-[rgb(var(--bg-2))] hover:bg-[rgb(var(--bg-2))]/10 shadow-md"
>
<Icon size="20px" name="ic:baseline-mail-outline"></Icon>
</button>
</div>
</div>
</template>
</rs-card>
</div>
<div class="w-12/2 md:w-4/12 flex flex-col">
<!-- Monthly Target Radial -->
<rs-card class="flex-1">
<template #header> Monthly Target </template>
<template #body>
<client-only>
<VueApexCharts
:key="changeKey"
width="100%"
height="300"
name="radialBar"
:options="chartOptionsRadial"
:series="radialData"
></VueApexCharts>
</client-only>
<hr class="my-4" />
<p class="text-xl py-5 font-medium">Products</p>
<div
class="flex item-center gap-x-4"
:class="{
'mt-0': index === 0,
'mt-3': index !== 0,
}"
v-for="(val, index) in ['A', 'B', 'C', 'D', 'E']"
:key="index"
>
<img
src="@/assets/img/default-thumbnail.jpg"
class="h-20 w-20 object-cover rounded-lg"
/>
<div class="flex-1 flex items-center">
<div>
<span class="font-semibold text-lg leading-tight"
>Product {{ val }}</span
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
</div>
</div>
</div>
</template>
</rs-card>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<!-- Gambaran Keseluruhan Pelawat Malaysia -->
<rs-card class="col-span-1 lg:col-span-2">
<template #header>
<h2 class="text-xl font-bold text-primary">
Gambaran Keseluruhan Pelawat
</h2>
</template>
<template #body>
<client-only>
<VueApexCharts
width="100%"
height="350"
type="line"
:options="chartOptionsVisitors"
:series="visitorData"
></VueApexCharts>
</client-only>
</template>
</rs-card>
<!-- Pelawat Asing mengikut Negeri -->
<rs-card>
<template #header>
<h2 class="text-lg font-semibold text-primary">
Pelawat Asing mengikut Negeri
</h2>
</template>
<template #body>
<client-only>
<VueApexCharts
width="100%"
height="300"
type="bar"
:options="chartOptionsForeignVisitors"
:series="[
{ data: foreignVisitorsByState.map((item) => item.visitors) },
]"
></VueApexCharts>
</client-only>
</template>
</rs-card>
<!-- Pelancong Berulang -->
<rs-card>
<template #header>
<h2 class="text-lg font-semibold text-primary">
Kekerapan Lawatan Pelancong
</h2>
</template>
<template #body>
<client-only>
<VueApexCharts
width="100%"
height="300"
type="pie"
:options="chartOptionsRepeatVisitors"
:series="repeatVisitorsData.map((item) => item.percentage)"
></VueApexCharts>
</client-only>
</template>
</rs-card>
</div>
<!-- Negara Asal Pelancong Asing Teratas -->
<rs-card class="mb-6">
<template #header>
<h2 class="text-xl font-bold text-primary">
Negara Asal Pelancong Asing Teratas
</h2>
</template>
<template #body>
<client-only>
<VueApexCharts
width="100%"
height="350"
type="bar"
:options="chartOptionsTopCountries"
:series="[
{
name: 'Pelawat',
data: topVisitorCountries.map((item) => item.visitors),
},
]"
></VueApexCharts>
</client-only>
</template>
</rs-card>
<rs-card class="mb-6">
<template #header>
<h2 class="text-xl font-bold text-primary">
Lapangan Terbang Teratas dengan Pelawat Terbanyak
</h2>
</template>
<template #body>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
Kedudukan
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
Nama Lapangan Terbang
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
Jumlah Pelawat
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr
v-for="airport in topAirports"
:key="airport.rank"
class="hover:bg-gray-50 transition-colors duration-200"
>
<td class="px-6 py-4 whitespace-nowrap font-medium">
{{ airport.rank }}
</td>
<td class="px-6 py-4 whitespace-nowrap">{{ airport.name }}</td>
<td
class="px-6 py-4 whitespace-nowrap font-semibold text-primary"
>
{{ airport.visitors.toLocaleString() }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
</rs-card>
</div>
</template>

View File

@ -3,7 +3,7 @@
import { useThemeStore } from "~/stores/theme";
definePageMeta({
title: "API Code Editor",
title: "Penyunting Kod API",
middleware: ["auth"],
requiresAuth: true,
});
@ -63,8 +63,8 @@ if (data.value.statusCode === 200) {
} else {
$swal
.fire({
title: "Error",
text: "The API you are trying to edit is not found. Please choose a API to edit.",
title: "Ralat",
text: "API yang anda cuba sunting tidak dijumpai. Sila pilih API untuk disunting.",
icon: "error",
confirmButtonText: "Ok",
})
@ -134,8 +134,8 @@ const saveCode = async () => {
if (linterError.value) {
$swal.fire({
title: "Error",
text: "There is an error in your code. Please fix it before saving.",
title: "Ralat",
text: "Terdapat ralat dalam kod anda. Sila betulkannya sebelum menyimpan.",
icon: "error",
confirmButtonText: "Ok",
});
@ -153,8 +153,8 @@ const saveCode = async () => {
});
if (data.value.statusCode === 200) {
$swal.fire({
title: "Success",
text: "The code has been saved successfully.",
title: "Berjaya",
text: "Kod telah berjaya disimpan.",
icon: "success",
confirmButtonText: "Ok",
timer: 1000,
@ -175,11 +175,11 @@ const saveCode = async () => {
}}</rs-alert>
<rs-card>
<rs-tab fill>
<rs-tab-item title="Editor">
<rs-tab-item title="Penyunting">
<div class="flex justify-end gap-2 mb-4">
<rs-button class="!p-2" @click="formatCode">
<Icon name="simple-icons:prettier" size="20px" class="mr-1" />
Format Code</rs-button
Format Kod</rs-button
>
<rs-button class="!p-2" @click="saveCode">
<Icon
@ -187,7 +187,7 @@ const saveCode = async () => {
size="20px"
class="mr-1"
/>
Save API
Simpan API
</rs-button>
</div>
<Transition>
@ -198,12 +198,12 @@ const saveCode = async () => {
size="20px"
/>
<div>
<div class="font-bold">ESLint Error</div>
<div class="font-bold">Ralat ESLint</div>
<div class="text-sm">
{{ linterErrorText }}
</div>
<div class="text-xs mt-2">
Line: {{ linterErrorLine }} Column: {{ linterErrorColumn }}
Baris: {{ linterErrorLine }} Lajur: {{ linterErrorColumn }}
</div>
</div>
</div>
@ -216,7 +216,7 @@ const saveCode = async () => {
mode="javascript"
/>
</rs-tab-item>
<rs-tab-item title="API Tester">
<rs-tab-item title="Penguji API">
<rs-api-tester :url="route.query?.path" />
</rs-tab-item>
</rs-tab>

View File

@ -78,8 +78,8 @@ const saveAddAPI = async () => {
if (data.value.statusCode === 200) {
nuxtApp.$swal.fire({
title: "Success",
text: "The code has been saved successfully.",
title: "Berjaya",
text: "Kod telah berjaya disimpan.",
icon: "success",
confirmButtonText: "Ok",
timer: 1000,
@ -105,8 +105,8 @@ const saveEditAPI = async () => {
if (data.value.statusCode === 200) {
nuxtApp.$swal.fire({
title: "Success",
text: "The code has been saved successfully.",
title: "Berjaya",
text: "Kod telah berjaya disimpan.",
icon: "success",
confirmButtonText: "Ok",
timer: 1000,
@ -122,13 +122,14 @@ const saveEditAPI = async () => {
const deleteAPI = async (apiURL) => {
nuxtApp.$swal
.fire({
title: "Are you sure to delete this API?",
text: "You won't be able to revert this!",
title: "Adakah anda pasti untuk memadam API ini?",
text: "Anda tidak akan dapat memulihkan ini!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Yes, delete it!",
confirmButtonText: "Ya, padamkan!",
cancelButtonText: "Batal",
})
.then(async (result) => {
if (result.isConfirmed) {
@ -143,8 +144,8 @@ const deleteAPI = async (apiURL) => {
if (data.value.statusCode === 200) {
nuxtApp.$swal.fire({
title: "Success",
text: "The code has been saved successfully.",
title: "Berjaya",
text: "Kod telah berjaya disimpan.",
icon: "success",
confirmButtonText: "Ok",
timer: 1000,
@ -164,13 +165,13 @@ const deleteAPI = async (apiURL) => {
<template #header>
<div class="flex">
<Icon class="mr-2 flex justify-center" name="ic:outline-info"></Icon
>Info
>Maklumat
</div>
</template>
<template #body>
<p class="mb-4">
This page is used to edit the api for the server side. You can edit
the api by choosing the api to edit from the card list below.
Halaman ini digunakan untuk mengedit API untuk bahagian pelayan. Anda boleh mengedit
API dengan memilih API untuk diedit dari senarai kad di bawah.
</p>
</template>
</rs-card>
@ -180,14 +181,14 @@ const deleteAPI = async (apiURL) => {
<div class="flex justify-end items-center mb-4">
<rs-button @click="openModalAdd">
<Icon name="material-symbols:add" class="mr-1"></Icon>
Add API
Tambah API
</rs-button>
</div>
<!-- Search Button -->
<FormKit
v-model="searchText"
placeholder="Search Title..."
placeholder="Cari Tajuk..."
type="search"
class="mb-4"
/>
@ -214,7 +215,7 @@ const deleteAPI = async (apiURL) => {
name="material-symbols:code-blocks-outline-rounded"
class="mr-2"
/>
Code Editor
Editor Kod
</rs-button>
<div class="flex gap-2">
<rs-button @click="openModalEdit(api.url)">
@ -233,9 +234,9 @@ const deleteAPI = async (apiURL) => {
</rs-card>
<rs-modal
title="Add API"
title="Tambah API"
v-model="showModalAdd"
ok-title="Save"
ok-title="Simpan"
:ok-callback="saveAddAPI"
>
<FormKit type="text" label="Url" v-model="showModalAddForm.apiURL">
@ -248,9 +249,9 @@ const deleteAPI = async (apiURL) => {
</rs-modal>
<rs-modal
title="Add API"
title="Edit API"
v-model="showModalEdit"
ok-title="Save"
ok-title="Simpan"
:ok-callback="saveEditAPI"
>
<FormKit type="text" label="Url" v-model="showModalEditForm.apiURL">

View File

@ -1,6 +1,6 @@
<script setup>
definePageMeta({
title: "Code Editor",
title: "Penyunting Kod",
middleware: ["auth"],
requiresAuth: true,
});
@ -28,8 +28,8 @@ const page = router.getRoutes().find((page) => {
if (!route.query.page || !page) {
$swal
.fire({
title: "Error",
text: "The page you are trying to edit is not found. Please choose a page to edit.",
title: "Ralat",
text: "Halaman yang anda cuba sunting tidak dijumpai. Sila pilih halaman untuk disunting.",
icon: "error",
confirmButtonText: "Ok",
})
@ -62,8 +62,8 @@ if (data.value.statusCode === 200) {
if (data.value?.mode == "index") page.path = page.path + "/index";
} else {
$swal.fire({
title: "Error",
text: "The page you are trying to edit is not found. Please choose a page to edit. You will be redirected to the content editor page.",
title: "Ralat",
text: "Halaman yang anda cuba sunting tidak dijumpai. Sila pilih halaman untuk disunting. Anda akan dialihkan ke halaman penyunting kandungan.",
icon: "error",
confirmButtonText: "Ok",
timer: 3000,
@ -132,8 +132,8 @@ const saveCode = async () => {
if (linterError.value) {
$swal.fire({
title: "Error",
text: "There is an error in your code. Please fix it before saving.",
title: "Ralat",
text: "Terdapat ralat dalam kod anda. Sila betulkannya sebelum menyimpan.",
icon: "error",
confirmButtonText: "Ok",
});
@ -150,8 +150,8 @@ const saveCode = async () => {
});
if (data.value.statusCode === 200) {
$swal.fire({
title: "Success",
text: "The code has been saved successfully.",
title: "Berjaya",
text: "Kod telah berjaya disimpan.",
icon: "success",
confirmButtonText: "Ok",
timer: 1000,
@ -175,7 +175,7 @@ const saveCode = async () => {
<div class="flex justify-end gap-2 mb-4">
<rs-button class="!p-2" @click="formatCode">
<Icon name="simple-icons:prettier" size="20px" class="mr-1" />
Format Code</rs-button
Format Kod</rs-button
>
<rs-button class="!p-2" @click="saveCode">
<Icon
@ -183,7 +183,7 @@ const saveCode = async () => {
size="20px"
class="mr-1"
/>
Save Code
Simpan Kod
</rs-button>
</div>
<Transition>
@ -191,12 +191,12 @@ const saveCode = async () => {
<div class="flex gap-2">
<Icon name="material-symbols:error-outline-rounded" size="20px" />
<div>
<div class="font-bold">ESLint Error</div>
<div class="font-bold">Ralat ESLint</div>
<div class="text-sm">
{{ linterErrorText }}
</div>
<div class="text-xs mt-2">
Line: {{ linterErrorLine }} Column: {{ linterErrorColumn }}
Baris: {{ linterErrorLine }} Lajur: {{ linterErrorColumn }}
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
<script setup>
definePageMeta({
title: "Content Editor",
title: "Penyunting Kandungan",
middleware: ["auth"],
requiresAuth: true,
});
@ -15,7 +15,7 @@ const pages = getPages.filter((page) => {
return (
page.path.includes("/devtool") === false &&
page.meta?.title &&
page.meta?.title !== "Home" &&
page.meta?.title !== "Laman Utama" &&
page.name
);
});
@ -44,7 +44,7 @@ const capitalizeSentence = (sentence) => {
.join(" ");
};
const templateOptions = ref([{ label: "Select Template", value: "" }]);
const templateOptions = ref([{ label: "Pilih Templat", value: "" }]);
const selectTemplate = ref("");
const { data: templates } = await useFetch(
@ -74,13 +74,13 @@ const importTemplate = (pageName) => {
const confirmModal = async () => {
$swal
.fire({
title: "Are you sure you want to import this template?",
text: "This action cannot be undone.",
title: "Adakah anda pasti mahu mengimport templat ini?",
text: "Tindakan ini tidak boleh dibatalkan.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Yes",
confirmButtonText: "Ya",
})
.then(async (result) => {
if (result.isConfirmed) {
@ -98,7 +98,7 @@ const confirmModal = async () => {
if (res.value.statusCode == 200) {
$swal.fire({
title: "Success",
title: "Berjaya",
text: res.value.message,
icon: "success",
confirmButtonText: "Ok",
@ -123,14 +123,14 @@ const confirmModal = async () => {
<template #header>
<div class="flex">
<Icon class="mr-2 flex justify-center" name="ic:outline-info"></Icon
>Info
>Maklumat
</div>
</template>
<template #body>
<p class="mb-4">
This page is used to edit the content of a page. You can edit the
content of the page by choosing the page to edit from the card list
below.
Halaman ini digunakan untuk menyunting kandungan halaman. Anda boleh menyunting
kandungan halaman dengan memilih halaman untuk disunting dari senarai kad
di bawah.
</p>
</template>
</rs-card>
@ -140,7 +140,7 @@ const confirmModal = async () => {
<!-- Search Button -->
<FormKit
v-model="searchText"
placeholder="Search Title..."
placeholder="Cari Tajuk..."
type="search"
/>
@ -152,7 +152,7 @@ const confirmModal = async () => {
class="page border-2 border-gray-400 border-dashed rounded-lg"
style="min-height: 250px"
>
Add New Page
Tambah Halaman Baru
</div> -->
<div
v-for="page in searchPages()"
@ -180,13 +180,6 @@ const confirmModal = async () => {
class="button-list flex justify-between border-t pt-4 border-gray-300"
>
<div class="flex gap-x-2">
<nuxt-link
:to="`/devtool/content-editor/canvas?page=${page.name}`"
>
<rs-button variant="primary" class="!py-2 !px-3">
<Icon name="ph:paint-brush-broad"></Icon>
</rs-button>
</nuxt-link>
<nuxt-link
:to="`/devtool/content-editor/code?page=${page.name}`"
>
@ -214,18 +207,18 @@ const confirmModal = async () => {
<FormKit
v-model="selectTemplate"
type="select"
label="Content Template"
label="Templat Kandungan"
:options="templateOptions"
validation="required"
validation-visibility="dirty"
help="Please choose carefully the template that you want to import. This action cannot be undone."
help="Sila pilih dengan teliti templat yang anda ingin import. Tindakan ini tidak boleh dibatalkan."
/>
<template #footer>
<rs-button @click="showModal = false" variant="primary-text">
Cancel
Batal
</rs-button>
<rs-button @click="confirmModal" :disabled="!selectTemplate"
>Confirm</rs-button
>Sahkan</rs-button
>
</template>
</rs-modal>

View File

@ -1,6 +1,6 @@
<script setup>
definePageMeta({
title: "Template Editor",
title: "Penyunting Templat",
middleware: ["auth"],
requiresAuth: true,
});
@ -31,14 +31,14 @@ const searchTemplate = () => {
<template #header>
<div class="flex">
<Icon class="mr-2 flex justify-center" name="ic:outline-info"></Icon
>Info
>Maklumat
</div>
</template>
<template #body>
<p class="mb-4">
This webpage serves as a platform for template management, enabling
users to select and utilize templates for rendering pages according to
their chosen design.
Laman web ini berfungsi sebagai platform untuk pengurusan templat, membolehkan
pengguna memilih dan menggunakan templat untuk memaparkan halaman mengikut
reka bentuk pilihan mereka.
</p>
</template>
</rs-card>
@ -48,7 +48,7 @@ const searchTemplate = () => {
<!-- Search Button -->
<FormKit
v-model="searchText"
placeholder="Search Title..."
placeholder="Cari Tajuk..."
type="search"
/>
@ -60,7 +60,7 @@ const searchTemplate = () => {
class="page border-2 border-gray-400 border-dashed rounded-lg"
style="min-height: 250px"
>
Add New Page
Tambah Halaman Baru
</div> -->
<div
v-for="val in searchTemplate()"

View File

@ -1,6 +1,6 @@
<script setup>
definePageMeta({
title: "Template Viewer",
title: "Pelihat Templat",
middleware: ["auth"],
requiresAuth: true,
});

View File

@ -408,14 +408,14 @@ const addMenuFromList = () => {
<template #header>
<div class="flex">
<Icon class="mr-2 flex justify-center" name="ic:outline-info"></Icon
>Info
>Maklumat
</div>
</template>
<template #body>
<p class="mb-4">
This page is used to edit the menu of the website. You can add, edit,
and delete menu items. You can also change the order of the menu items
by dragging and dropping them.
Halaman ini digunakan untuk mengedit menu laman web. Anda boleh
menambah, mengedit, dan memadam item menu. Anda juga boleh mengubah
susunan item menu dengan menyeret dan melepaskannya.
</p>
</template>
</rs-card>
@ -423,11 +423,11 @@ const addMenuFromList = () => {
<rs-card>
<div class="pt-2">
<rs-tab fill>
<rs-tab-item title="All Menu">
<rs-tab-item title="Semua Menu">
<div class="flex justify-end items-center mb-4">
<rs-button @click="openModalAdd">
<Icon name="material-symbols:add" class="mr-1"></Icon>
Add Menu
Tambah Menu
</rs-button>
</div>
<!-- Table All Menu -->
@ -491,18 +491,18 @@ const addMenuFromList = () => {
</template>
</rs-table>
</rs-tab-item>
<rs-tab-item title="Manage Side Menu">
<rs-tab-item title="Urus Menu Sisi">
<div class="flex justify-end items-center mb-4">
<rs-button
class="mr-2"
@click="showCode ? (showCode = false) : (showCode = true)"
>
<Icon name="ic:baseline-code" class="mr-2"></Icon>
{{ showCode ? "Hide" : "Show" }} JSON Code
{{ showCode ? "Sembunyikan" : "Tunjukkan" }} Kod JSON
</rs-button>
<rs-button @click="overwriteJsonFileLocal(sideMenuList)">
<Icon name="mdi:content-save-outline" class="mr-2"></Icon>
Save Menu
Simpan Menu
</rs-button>
</div>
@ -510,7 +510,7 @@ const addMenuFromList = () => {
<div>
<FormKit
type="search"
placeholder="Search Menu..."
placeholder="Cari Menu..."
outer-class="mb-5"
v-model="searchInput"
/>
@ -526,7 +526,9 @@ const addMenuFromList = () => {
:sort="false"
>
<template #item="{ element }">
<rs-card class="p-4 mb-4 border-2 border-[rgb(var(--border-color))] !shadow-none">
<rs-card
class="p-4 mb-4 border-2 border-[rgb(var(--border-color))] !shadow-none"
>
<div class="flex justify-between items-center">
<p>
{{ kebabtoTitle(element.name) }} (

View File

@ -1,6 +1,6 @@
<script setup>
definePageMeta({
title: "Role List",
title: "Senarai Peranan",
middleware: ["auth"],
requiresAuth: true,
});
@ -38,8 +38,8 @@ const showModalDeleteForm = ref({
});
const statusDropdown = ref([
{ label: "Active", value: "ACTIVE" },
{ label: "Inactive", value: "INACTIVE" },
{ label: "Aktif", value: "ACTIVE" },
{ label: "Tidak Aktif", value: "INACTIVE" },
]);
const roleListbyUser = ref([]);
@ -199,8 +199,8 @@ const saveUser = async () => {
if (data.value.statusCode === 200) {
$swal.fire({
icon: "success",
title: "Success",
text: "User has been added successfully",
title: "Berjaya",
text: "Pengguna telah berjaya ditambah",
});
await getUserList();
@ -209,7 +209,7 @@ const saveUser = async () => {
} else {
$swal.fire({
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -227,8 +227,8 @@ const saveRole = async () => {
$swal.fire({
position: "center",
icon: "success",
title: "Success",
text: "Role has been updated successfully",
title: "Berjaya",
text: "Peranan telah berjaya dikemas kini",
timer: 1000,
showConfirmButton: false,
});
@ -242,7 +242,7 @@ const saveRole = async () => {
} else {
$swal.fire({
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -257,8 +257,8 @@ const saveRole = async () => {
$swal.fire({
position: "center",
icon: "success",
title: "Success",
text: "Role has been added",
title: "Berjaya",
text: "Peranan telah ditambah",
timer: 1000,
showConfirmButton: false,
});
@ -272,7 +272,7 @@ const saveRole = async () => {
} else {
$swal.fire({
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -290,8 +290,8 @@ const deleteRole = async () => {
$swal.fire({
position: "center",
icon: "success",
title: "Success",
text: "User has been deleted",
title: "Berjaya",
text: "Pengguna telah dipadam",
timer: 1000,
showConfirmButton: false,
});
@ -304,7 +304,7 @@ const deleteRole = async () => {
$swal.fire({
position: "center",
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -331,13 +331,13 @@ function groupRoleByUser() {
<template #header>
<div class="flex">
<Icon class="mr-2 flex justify-center" name="ic:outline-info"></Icon
>Info
>Maklumat
</div>
</template>
<template #body>
<p class="mb-4">
This page is only accessible by admin users. You can manage users
here. You can also add new users. You can also change user roles.
Halaman ini hanya boleh diakses oleh pengguna admin. Anda boleh menguruskan pengguna
di sini. Anda juga boleh menambah pengguna baru. Anda juga boleh menukar peranan pengguna.
</p>
</template>
</rs-card>
@ -345,11 +345,11 @@ function groupRoleByUser() {
<rs-card>
<div class="pt-2">
<rs-tab fill>
<rs-tab-item title="All Role">
<rs-tab-item title="Semua Peranan">
<div class="flex justify-end items-center mb-4">
<rs-button @click="openModal(null, 'add')">
<Icon name="material-symbols:add" class="mr-1"></Icon>
Add Role
Tambah Peranan
</rs-button>
</div>
<rs-table
@ -397,31 +397,31 @@ function groupRoleByUser() {
</rs-card>
<rs-modal
:title="modalType == 'edit' ? 'Edit Role' : 'Add Role'"
ok-title="Save"
:title="modalType == 'edit' ? 'Sunting Peranan' : 'Tambah Peranan'"
ok-title="Simpan"
:ok-callback="saveRole"
v-model="showModal"
>
<FormKit
type="text"
v-model="showModalForm.name"
label="Name"
label="Nama"
validation="required"
validation-visibility="live"
/>
<FormKit
type="textarea"
v-model="showModalForm.description"
label="Description"
label="Penerangan"
/>
<div class="flex justify-between items-center mb-2">
<label
class="formkit-label font-semibold text-gray-700 dark:text-gray-200 blockfont-semibold text-sm formkit-invalid:text-red-500 dark:formkit-invalid:text-danger"
for="input_4"
>
Users
Pengguna
</label>
<rs-button size="sm" @click="openModalUser"> Add User </rs-button>
<rs-button size="sm" @click="openModalUser"> Tambah Pengguna </rs-button>
</div>
<v-select
class="formkit-vselect"
@ -432,7 +432,7 @@ function groupRoleByUser() {
<FormKit
type="checkbox"
v-model="checkAllUser"
label="All Users"
label="Semua Pengguna"
input-class="icon-check"
/>
<FormKit
@ -446,9 +446,9 @@ function groupRoleByUser() {
<!-- Modal Role -->
<rs-modal
title="Add User"
ok-title="Save"
cancel-title="Back"
title="Tambah Pengguna"
ok-title="Simpan"
cancel-title="Kembali"
:cancel-callback="closeModalUser"
:ok-callback="saveUser"
v-model="showModalUser"
@ -457,19 +457,19 @@ function groupRoleByUser() {
type="text"
v-model="showModalUserForm.username"
name="username"
label="Username"
label="Nama Pengguna"
/>
<FormKit
type="text"
v-model="showModalUserForm.fullname"
name="fullname"
label="Fullname"
label="Nama Penuh"
/>
<FormKit
type="text"
v-model="showModalUserForm.email"
name="email"
label="Email"
label="E-mel"
validation="email"
validation-visibility="dirty"
/>
@ -477,7 +477,7 @@ function groupRoleByUser() {
type="mask"
v-model="showModalUserForm.phone"
name="phone"
label="Phone"
label="Telefon"
mask="###########"
/>
@ -492,14 +492,14 @@ function groupRoleByUser() {
<!-- Modal Delete Confirmation -->
<rs-modal
title="Delete Confirmation"
ok-title="Yes"
cancel-title="No"
title="Pengesahan Padam"
ok-title="Ya"
cancel-title="Tidak"
:ok-callback="deleteRole"
v-model="showModalDelete"
>
<p>
Are you sure want to delete this role ({{ showModalDeleteForm.name }})?
Adakah anda pasti mahu memadam peranan ini ({{ showModalDeleteForm.name }})?
</p>
</rs-modal>
</div>

View File

@ -37,8 +37,8 @@ const showModalDeleteForm = ref({
});
const statusDropdown = ref([
{ label: "Active", value: "ACTIVE" },
{ label: "Inactive", value: "INACTIVE" },
{ label: "Aktif", value: "ACTIVE" },
{ label: "Tidak Aktif", value: "INACTIVE" },
]);
const checkAllRole = ref(false);
@ -195,8 +195,8 @@ const saveUser = async () => {
$swal.fire({
position: "center",
icon: "success",
title: "Success",
text: "User has been added",
title: "Berjaya",
text: "Pengguna telah ditambah",
timer: 1000,
showConfirmButton: false,
});
@ -210,7 +210,7 @@ const saveUser = async () => {
$swal.fire({
position: "center",
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -225,8 +225,8 @@ const saveUser = async () => {
$swal.fire({
position: "center",
icon: "success",
title: "Success",
text: "User has been updated",
title: "Berjaya",
text: "Pengguna telah dikemaskini",
timer: 1000,
showConfirmButton: false,
});
@ -240,7 +240,7 @@ const saveUser = async () => {
$swal.fire({
position: "center",
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -258,8 +258,8 @@ const deleteUser = async () => {
$swal.fire({
position: "center",
icon: "success",
title: "Success",
text: "User has been deleted",
title: "Berjaya",
text: "Pengguna telah dipadam",
timer: 1000,
showConfirmButton: false,
});
@ -272,7 +272,7 @@ const deleteUser = async () => {
$swal.fire({
position: "center",
icon: "error",
title: "Error",
title: "Ralat",
text: data.value.message,
});
}
@ -298,7 +298,7 @@ const saveRole = async () => {
if (data.value.statusCode === 200) {
$swal.fire({
position: "center",
title: "Success",
title: "Berjaya",
text: data.value.message,
icon: "success",
timer: 1000,
@ -310,7 +310,7 @@ const saveRole = async () => {
} else {
$swal.fire({
position: "center",
title: "Error",
title: "Ralat",
text: data.value.message,
icon: "error",
});
@ -338,13 +338,13 @@ function groupUserByRole() {
<template #header>
<div class="flex">
<Icon class="mr-2 flex justify-center" name="ic:outline-info"></Icon
>Info
>Maklumat
</div>
</template>
<template #body>
<p class="mb-4">
This page is only accessible by admin users. You can manage users
here. You can also add new users. You can also change user roles.
Halaman ini hanya boleh diakses oleh pengguna admin. Anda boleh menguruskan pengguna
di sini. Anda juga boleh menambah pengguna baru. Anda juga boleh menukar peranan pengguna.
</p>
</template>
</rs-card>
@ -352,11 +352,11 @@ function groupUserByRole() {
<rs-card>
<div class="pt-2">
<rs-tab fill>
<rs-tab-item title="All User">
<rs-tab-item title="Semua Pengguna">
<div class="flex justify-end items-center mb-4">
<rs-button @click="openModal(null, 'add')">
<Icon name="material-symbols:add" class="mr-1"></Icon>
Add User
Tambah Pengguna
</rs-button>
</div>
<rs-table
@ -405,8 +405,8 @@ function groupUserByRole() {
</rs-card>
<rs-modal
:title="modalType == 'edit' ? 'Edit User' : 'Add User'"
ok-title="Save"
:title="modalType == 'edit' ? 'Sunting Pengguna' : 'Tambah Pengguna'"
ok-title="Simpan"
:ok-callback="saveUser"
v-model="showModal"
>
@ -414,20 +414,20 @@ function groupUserByRole() {
type="text"
v-model="showModalForm.username"
name="username"
label="Username"
label="Nama Pengguna"
:disabled="modalType == 'edit' ? true : false"
/>
<FormKit
type="text"
v-model="showModalForm.fullname"
name="fullname"
label="Fullname"
label="Nama Penuh"
/>
<FormKit
type="text"
v-model="showModalForm.email"
name="email"
label="Email"
label="E-mel"
validation="email"
validation-visibility="dirty"
/>
@ -435,7 +435,7 @@ function groupUserByRole() {
type="mask"
v-model="showModalForm.phone"
name="phone"
label="Phone"
label="Telefon"
mask="###########"
/>
<div class="flex justify-between items-center mb-2">
@ -443,9 +443,9 @@ function groupUserByRole() {
class="formkit-label flex items-center gap-x-4 font-semibold text-gray-700 dark:text-gray-200 blockfont-semibold text-sm formkit-invalid:text-red-500 dark:formkit-invalid:text-danger"
for="input_4"
>
Role
Peranan
</label>
<rs-button size="sm" @click="openModalRole"> Add Role </rs-button>
<rs-button size="sm" @click="openModalRole"> Tambah Peranan </rs-button>
</div>
<v-select
class="formkit-vselect"
@ -456,7 +456,7 @@ function groupUserByRole() {
<FormKit
type="checkbox"
v-model="checkAllRole"
label="All Role"
label="Semua Peranan"
input-class="icon-check"
/>
<FormKit
@ -470,9 +470,9 @@ function groupUserByRole() {
<!-- Modal Role -->
<rs-modal
title="Add Role"
ok-title="Save"
cancel-title="Back"
title="Tambah Peranan"
ok-title="Simpan"
cancel-title="Kembali"
:cancel-callback="closeModalRole"
:ok-callback="saveRole"
v-model="showModalRole"
@ -480,27 +480,27 @@ function groupUserByRole() {
<FormKit
type="text"
v-model="showModalRoleForm.role"
label="Name"
label="Nama"
validation="required"
validation-visibility="live"
/>
<FormKit
type="textarea"
v-model="showModalRoleForm.description"
label="Description"
label="Penerangan"
/>
</rs-modal>
<!-- Modal Delete Confirmation -->
<rs-modal
title="Delete Confirmation"
ok-title="Yes"
cancel-title="No"
title="Pengesahan Padam"
ok-title="Ya"
cancel-title="Tidak"
:ok-callback="deleteUser"
v-model="showModalDelete"
>
<p>
Are you sure want to delete this user ({{
Adakah anda pasti mahu memadam pengguna ini ({{
showModalDeleteForm.username
}})?
</p>

View File

@ -0,0 +1,233 @@
<script setup>
definePageMeta({
title: "Kemaskini Daftar FR2",
breadcrumb: [
{
name: "Kemaskini Daftar FR2",
type: "current",
},
],
});
const router = useRouter();
const { $swal } = useNuxtApp();
const caseId = ref("");
const equipmentCondition = ref(false);
const officerQualification = ref(false);
const methodApplicability = ref(false);
const externalSupport = ref(false);
const taskAcceptance = ref("");
const officerComments = ref("");
const showForm = ref(false);
const verifyCase = async () => {
if (!caseId.value) {
$swal.fire({
icon: "error",
title: "ID Kes diperlukan",
text: "Sila masukkan ID Kes untuk menyemak.",
timer: 3000,
});
return;
}
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
$swal.fire({
icon: "success",
title: "ID Kes disahkan",
text: "Maklumat kes telah berjaya diambil.",
timer: 3000,
});
showForm.value = true;
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal mengesahkan ID Kes",
text: "Sila cuba lagi atau hubungi pentadbir sistem.",
timer: 3000,
});
}
};
const updateForm = async () => {
if (!validateForm()) {
return;
}
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
$swal.fire({
icon: "success",
title: "Rekod telah berjaya dikemas kini",
text: "Maklumat telah dikemas kini dalam sistem.",
timer: 3000,
});
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal mengemas kini rekod",
text: "Sila cuba lagi atau hubungi pentadbir sistem.",
timer: 3000,
});
}
};
const submitForm = async () => {
if (!validateForm()) {
return;
}
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
$swal.fire({
icon: "success",
title: "Rekod telah berjaya disahkan",
text: "Maklumat telah disahkan dan disimpan dalam sistem.",
timer: 3000,
});
router.push("/dashboard");
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal mengesahkan rekod",
text: "Sila cuba lagi atau hubungi pentadbir sistem.",
timer: 3000,
});
}
};
const validateForm = () => {
if (
!equipmentCondition.value ||
!officerQualification.value ||
!methodApplicability.value ||
!taskAcceptance.value
) {
$swal.fire({
icon: "error",
title: "Borang tidak lengkap",
text: "Sila lengkapkan semua maklumat yang diperlukan.",
timer: 3000,
});
return false;
}
if (taskAcceptance.value === "Tidak" && !officerComments.value) {
$swal.fire({
icon: "error",
title: "Komen diperlukan",
text: "Sila berikan komen kerana tugas tidak diterima.",
timer: 3000,
});
return false;
}
return true;
};
</script>
<template>
<div class="">
<LayoutsBreadcrumb class="mb-6" />
<RsCard class="mb-6 shadow-lg">
<template #header>
<h2 class="text-2xl">Kemaskini Daftar FR2</h2>
</template>
<template #body>
<div class="space-y-8">
<div>
<h3 class="text-lg font-medium mb-4 text-gray-700">
Pengesahan ID Kes
</h3>
<div class="flex flex-col gap-4">
<FormKit
type="text"
name="caseId"
label="ID Kes"
validation="required"
:validation-messages="{
required: 'Sila masukkan ID Kes',
}"
v-model="caseId"
class="flex-grow"
:classes="{
outer: 'mb-0',
}"
/>
<RsButton @click="verifyCase" variant="primary" class="mb-1"
>Semak</RsButton
>
</div>
</div>
<FormKit
v-if="showForm"
type="form"
@submit="submitForm"
:actions="false"
>
<div>
<h3 class="text-lg font-medium mb-4 text-gray-700">Borang FR2</h3>
<div class="space-y-4">
<FormKit
type="checkbox"
name="equipmentCondition"
label="Peralatan dalam keadaan baik untuk analisis/pemeriksaan"
v-model="equipmentCondition"
/>
<FormKit
type="checkbox"
name="officerQualification"
label="Pegawai berkelayakan untuk analisis/pemeriksaan"
v-model="officerQualification"
/>
<FormKit
type="checkbox"
name="methodApplicability"
label="Kaedah boleh dilaksanakan dan diterima untuk analisis"
v-model="methodApplicability"
/>
<FormKit
type="checkbox"
name="externalSupport"
label="Sokongan luar diperlukan"
v-model="externalSupport"
/>
<FormKit
type="select"
name="taskAcceptance"
label="Penerimaan Tugas"
:options="[
{ label: 'Ya', value: 'Ya' },
{ label: 'Tidak', value: 'Tidak' },
]"
validation="required"
:validation-messages="{
required: 'Sila pilih penerimaan tugas',
}"
v-model="taskAcceptance"
/>
<FormKit
type="textarea"
name="officerComments"
label="Komen Pegawai"
v-model="officerComments"
/>
</div>
</div>
<div class="mt-8 flex justify-end space-x-4">
<RsButton @click="updateForm" variant="secondary"
>Kemas Kini</RsButton
>
<!-- <RsButton type="submit" variant="primary">Sahkan</RsButton> -->
</div>
</FormKit>
</div>
</template>
</RsCard>
</div>
</template>

View File

@ -0,0 +1,334 @@
<script setup>
definePageMeta({
title: "Permohonan Online",
breadcrumb: [
{
name: "Permohonan Online",
type: "current",
},
],
});
const router = useRouter();
const { $swal } = useNuxtApp();
const applicantRank = ref("");
const applicantName = ref("");
const applicantOfficerNumber = ref("");
const sameAsSender = ref(false);
const showConfirmationModal = ref(false);
const showDateTimeModal = ref(false);
const availableTimeSlots = ref([]);
const formData = ref({});
onMounted(() => {
// Fetch applicant details from the system
fetchApplicantDetails();
});
const fetchApplicantDetails = async () => {
try {
// Simulated fetch of applicant details
applicantRank.value = "Inspector";
applicantName.value = "John Doe";
applicantOfficerNumber.value = "123456";
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal mendapatkan maklumat pemohon",
text: "Sila cuba lagi.",
timer: 5000,
});
}
};
const toggleSenderDetails = (value) => {
sameAsSender.value = value;
};
const submitForm = (formData) => {
// Store form data for later use
formData.value = formData;
showConfirmationModal.value = true;
};
const confirmSubmission = async () => {
showConfirmationModal.value = false;
try {
// Simulated form submission
$swal.fire({
icon: "success",
title: "Permohonan pemeriksaan forensik telah dihantar",
timer: 5000,
});
showDateTimeModal.value = true;
fetchAvailableTimeSlots();
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal menghantar permohonan",
text: "Sila cuba lagi.",
timer: 5000,
});
}
};
const fetchAvailableTimeSlots = async () => {
try {
// Simulated fetch of available time slots
availableTimeSlots.value = [
{ label: "9:00 AM", value: "09:00" },
{ label: "10:00 AM", value: "10:00" },
{ label: "11:00 AM", value: "11:00" },
];
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal mendapatkan slot masa yang tersedia",
text: "Sila cuba lagi.",
timer: 5000,
});
}
};
const confirmDateTimeSlot = async () => {
try {
// Simulated confirmation of date and time slot
const data = { caseId: "FOR-2023-001" };
$swal.fire({
icon: "success",
title: "Janji temu telah disahkan",
text: `Nombor rujukan kes: ${data.caseId}`,
timer: 5000,
});
showDateTimeModal.value = false;
router.push("/dashboard"); // Redirect to dashboard or confirmation page
} catch (error) {
$swal.fire({
icon: "error",
title: "Gagal mengesahkan janji temu",
text: "Sila cuba lagi.",
timer: 5000,
});
}
};
</script>
<template>
<div>
<LayoutsBreadcrumb class="mb-6" />
<FormKit type="form" @submit="submitForm" :actions="false">
<!-- Butir Permohonan Card -->
<RsCard class="mb-6">
<template #header>
<h2 class="text-2xl font-semibold">Butir Permohonan</h2>
</template>
<template #body>
<div class="space-y-6">
<div>
<h3 class="text-lg font-medium mb-3">Butir-butir Pemohon</h3>
<div class="bg-gray-100 p-4 rounded-lg">
<p>
<span class="font-medium">Nama:</span> {{ applicantName }}
</p>
<p>
<span class="font-medium">Pangkat:</span> {{ applicantRank }}
</p>
<p>
<span class="font-medium">Nombor Pegawai:</span>
{{ applicantOfficerNumber }}
</p>
</div>
</div>
<div>
<h3 class="text-lg font-medium mb-3">
Butir-butir Penghantar Barang Kes
</h3>
<FormKit
type="checkbox"
name="sameAsSender"
label="Penghantar Barang Kes Sama Dengan Pemohon"
v-model="sameAsSender"
/>
<div v-if="!sameAsSender" class="mt-4 space-y-4">
<FormKit
type="text"
name="senderName"
label="Nama Penghantar Barang Kes"
validation="required"
:validation-messages="{
required: 'Sila masukkan nama penghantar barang kes',
}"
/>
<FormKit
type="text"
name="senderRank"
label="Pangkat Penghantar Barang Kes"
validation="required"
:validation-messages="{
required: 'Sila masukkan pangkat penghantar barang kes',
}"
/>
<FormKit
type="text"
name="senderOfficerNumber"
label="Nombor Pegawai Penghantar Barang Kes"
validation="required|number|length:6"
:validation-messages="{
required:
'Sila masukkan nombor pegawai penghantar barang kes',
number: 'Nombor pegawai mesti dalam bentuk nombor',
length: 'Nombor pegawai mesti mempunyai 6 digit',
}"
/>
</div>
</div>
</div>
</template>
</RsCard>
<!-- Maklumat Kes Card -->
<RsCard class="mb-6">
<template #header>
<h2 class="text-2xl font-semibold">Maklumat Kes</h2>
</template>
<template #body>
<div class="space-y-6">
<div>
<h3 class="text-lg font-medium mb-3">Maklumat Barang Kes</h3>
<div class="space-y-4">
<FormKit
type="select"
name="jenisBarang"
label="Jenis Barang"
:options="[
{ label: 'Pasport', value: 'pasport' },
{ label: 'Malpass', value: 'malpass' },
{ label: 'Cap Keselamatan', value: 'capKeselamatan' },
{ label: 'Cap Jari', value: 'capJari' },
{ label: 'Pemeriksaan Siber', value: 'pemeriksaanSiber' },
{ label: 'Tulisan Tangan', value: 'tulisanTangan' },
{ label: 'I-Kad', value: 'iKad' },
{ label: 'Lain-lain', value: 'lainLain' },
]"
validation="required"
:validation-messages="{
required: 'Sila pilih jenis barang',
}"
/>
<FormKit
type="text"
name="tandaBarang"
label="Tanda Barang"
validation="required"
:validation-messages="{
required: 'Sila masukkan tanda barang',
}"
/>
<FormKit
type="text"
name="keadaanBarang"
label="Keadaan Barang"
validation="required"
:validation-messages="{
required: 'Sila masukkan keadaan barang',
}"
/>
<FormKit
type="number"
name="kuantitiBarang"
label="Kuantiti Barang"
validation="required|number|min:1"
:validation-messages="{
required: 'Sila masukkan kuantiti barang',
number: 'Kuantiti mesti dalam bentuk nombor',
min: 'Kuantiti mesti sekurang-kurangnya 1',
}"
/>
</div>
</div>
<div>
<h3 class="text-lg font-medium mb-3">Maklumat Tambahan</h3>
<div class="space-y-4">
<FormKit
type="textarea"
name="ringkasanKes"
label="Ringkasan Kenyataan Kes"
/>
<FormKit
type="text"
name="nomorKertasSiasatan"
label="Nombor Kertas Siasatan"
/>
<FormKit
type="text"
name="nomorLaporanPolis"
label="Nombor Laporan Polis"
/>
</div>
</div>
</div>
</template>
</RsCard>
<div class="text-center">
<FormKit
type="submit"
label="Hantar Permohonan"
input-class="text-white font-bold py-2 px-4 rounded w-full"
/>
</div>
</FormKit>
<!-- Confirmation Modal -->
<RsModal v-model="showConfirmationModal" title="Pengesahan Permohonan">
<template #body>
<p>Adakah anda pasti untuk menghantar permohonan ini?</p>
</template>
<template #footer>
<RsButton @click="showConfirmationModal = false" variant="secondary"
>Kembali</RsButton
>
<RsButton @click="confirmSubmission" variant="primary">Sahkan</RsButton>
</template>
</RsModal>
<!-- Date and Time Slot Selection Modal -->
<RsModal v-model="showDateTimeModal" title="Pilih Tarikh dan Slot Masa">
<template #body>
<FormKit
type="date"
name="appointmentDate"
label="Tarikh Janji Temu"
validation="required|after:today"
:validation-messages="{
required: 'Sila pilih tarikh janji temu',
after: 'Tarikh janji temu mestilah selepas tarikh hari ini',
}"
/>
<FormKit
type="select"
name="timeSlot"
label="Slot Masa"
:options="availableTimeSlots"
validation="required"
:validation-messages="{
required: 'Sila pilih slot masa',
}"
/>
</template>
<template #footer>
<RsButton @click="showDateTimeModal = false" variant="secondary"
>Kembali</RsButton
>
<RsButton @click="confirmDateTimeSlot" variant="primary"
>Sahkan</RsButton
>
</template>
</RsModal>
</div>
</template>

View File

@ -0,0 +1,193 @@
<script setup>
definePageMeta({
title: "Senarai Mesej",
breadcrumb: [
{
name: "Senarai Mesej",
type: "current",
},
],
});
const messages = ref([
{
id: 1,
sender: "Admin",
subject: "Selamat Datang",
preview: "Selamat datang ke sistem mesej kami...",
content:
"Selamat datang ke sistem mesej kami. Kami berharap anda akan menikmati pengalaman menggunakan sistem ini. Jika ada sebarang pertanyaan, sila hubungi kami.",
date: "1-50 daripada 528",
isRead: true,
},
{
id: 2,
sender: "Spotify",
subject: "Tawaran Istimewa untuk Anda",
preview: "Dapatkan langganan premium dengan harga istimewa...",
content:
"Dapatkan langganan premium dengan harga istimewa! Hanya untuk masa yang terhad, nikmati muzik tanpa had dengan harga yang sangat berpatutan.",
date: "11:59 malam",
isRead: false,
},
{
id: 3,
sender: "Ahmad Zulkifli",
subject: "Mesyuarat Projek Baru",
preview: "Sila hadir ke mesyuarat projek baru pada...",
content:
"Sila hadir ke mesyuarat projek baru pada hari Isnin, 10 Julai 2023, jam 10 pagi di Bilik Mesyuarat Utama. Kita akan membincangkan perancangan dan pembahagian tugas untuk projek baru ini.",
date: "10:21 malam",
isRead: false,
},
{
id: 4,
sender: "Syarikat ABC",
subject: "Tawaran Kerja",
preview: "Kami dengan sukacitanya menawarkan anda jawatan...",
content:
"Kami dengan sukacitanya menawarkan anda jawatan Pengaturcara Kanan di Syarikat ABC. Sila baca lampiran untuk maklumat lanjut tentang tawaran ini dan hubungi kami jika anda mempunyai sebarang pertanyaan.",
date: "8:37 malam",
isRead: false,
},
{
id: 5,
sender: "Puan Mariam",
subject: "Peringatan: Bayaran Bil",
preview: "Ini adalah peringatan untuk pembayaran bil anda...",
content:
"Ini adalah peringatan untuk pembayaran bil anda yang telah tamat tempoh. Sila jelaskan bayaran sebelum 30 Jun 2023 untuk mengelakkan sebarang caj lewat.",
date: "4:38 petang",
isRead: false,
},
]);
const selectedMessages = ref([]);
const currentMessage = ref(null);
const selectMessage = (messageId) => {
const index = selectedMessages.value.indexOf(messageId);
if (index === -1) {
selectedMessages.value.push(messageId);
} else {
selectedMessages.value.splice(index, 1);
}
};
const deleteSelectedMessages = () => {
messages.value = messages.value.filter(
(message) => !selectedMessages.value.includes(message.id)
);
selectedMessages.value = [];
currentMessage.value = null;
};
const readMessage = (message) => {
currentMessage.value = message;
if (!message.isRead) {
message.isRead = true;
}
};
const closeMessage = () => {
currentMessage.value = null;
};
const addNewMessage = () => {
const newId = messages.value.length + 1;
const newMessage = {
id: newId,
sender: "New Sender",
subject: "New Subject",
preview: "This is a new message...",
content:
"This is the full content of the new message. You can edit this to add more details.",
date: new Date().toLocaleString(),
isRead: false,
};
messages.value.unshift(newMessage);
};
</script>
<template>
<div class="bg-gray-100 min-h-screen">
<LayoutsBreadcrumb />
<div class="container mx-auto">
<rs-card>
<div class="flex items-center justify-between p-5">
<h2 class="text-xl font-semibold text-gray-800">Senarai Mesej</h2>
<div class="flex space-x-2">
<rs-button @click="addNewMessage" variant="success">
Tambah Mesej
</rs-button>
<rs-button
@click="deleteSelectedMessages"
variant="danger"
:disabled="selectedMessages.length === 0"
>
Buang ({{ selectedMessages.length }})
</rs-button>
</div>
</div>
<div class="divide-y divide-gray-200">
<div
v-for="message in messages"
:key="message.id"
@click="readMessage(message)"
class="flex items-center p-4 hover:bg-gray-50 transition duration-150 ease-in-out cursor-pointer"
:class="{ 'bg-blue-50': selectedMessages.includes(message.id) }"
>
<input
type="checkbox"
:checked="selectedMessages.includes(message.id)"
@click.stop="selectMessage(message.id)"
class="mr-4 h-5 w-5 text-blue-600"
/>
<div class="flex-grow">
<div class="flex items-center justify-between">
<span
class="font-medium text-gray-900"
:class="{ 'font-bold': !message.isRead }"
>
{{ message.sender }}
</span>
<span class="text-sm text-gray-500">{{ message.date }}</span>
</div>
<div class="mt-1">
<span
class="text-sm font-medium text-gray-900"
:class="{ 'font-bold': !message.isRead }"
>
{{ message.subject }}
</span>
<span class="text-sm text-gray-600">
- {{ message.preview }}</span
>
</div>
</div>
</div>
</div>
</rs-card>
<!-- Message Content Modal -->
<rs-modal v-model="currentMessage" title="Message Details">
<template v-if="currentMessage">
<p class="text-sm text-gray-600 mb-2">
From: {{ currentMessage.sender }}
</p>
<p class="text-sm text-gray-600 mb-4">
Date: {{ currentMessage.date }}
</p>
<div class="border-t pt-4">
<p class="text-gray-800">{{ currentMessage.content }}</p>
</div>
</template>
</rs-modal>
</div>
</div>
</template>
<style scoped>
/* Add any additional styles here */
</style>

284
pages/tipografi/index.vue Normal file
View File

@ -0,0 +1,284 @@
<script setup>
definePageMeta({
title: "Tipografi",
breadcrumb: [
{
name: "Tipografi",
type: "current",
},
],
});
const showCode1 = ref(false);
const showCode2 = ref(false);
const showCode3 = ref(false);
const showCode4 = ref(false);
const tooltips = ref({});
const copyCode = (codeId) => {
const codeElement = document.getElementById(codeId);
if (codeElement) {
const codeText = codeElement.textContent;
navigator.clipboard.writeText(codeText).then(() => {
tooltips.value[codeId] = "Kod disalin!";
setTimeout(() => {
tooltips.value[codeId] = "";
}, 2000);
});
}
};
</script>
<template>
<div>
<LayoutsBreadcrumb />
<rs-card>
<template #header> Tipografi </template>
<template #body>
<p class="mb-4">
Dokumentasi tipografi untuk pembangun untuk melihat dan menggunakan.
</p>
</template>
</rs-card>
<!-- Tajuk -->
<rs-card>
<template #header> Tajuk </template>
<template #body>
<div class="space-y-2">
<h1 class="text-4xl font-bold">Tajuk 1</h1>
<h2 class="text-3xl font-bold">Tajuk 2</h2>
<h3 class="text-2xl font-bold">Tajuk 3</h3>
<h4 class="text-xl font-bold">Tajuk 4</h4>
<h5 class="text-lg font-bold">Tajuk 5</h5>
<h6 class="text-base font-bold">Tajuk 6</h6>
</div>
<div class="flex justify-end mt-2">
<button
class="text-sm border border-slate-200 py-1 px-3 rounded-lg"
@click="showCode1 ? (showCode1 = false) : (showCode1 = true)"
>
Tunjukkan Kod
</button>
</div>
<ClientOnly>
<transition name="fade">
<div v-show="showCode1" v-highlight>
<div class="relative">
<button
@click="copyCode('code1')"
class="absolute top-4 right-2 text-sm bg-gray-300 hover:bg-gray-300 py-1 px-3 rounded z-10"
>
Salin Kod
</button>
<transition name="tooltip">
<span
v-if="tooltips['code1']"
class="absolute top-0 right-0 mt-12 mr-2 bg-black text-white text-xs rounded py-1 px-2 z-10"
>
{{ tooltips["code1"] }}
</span>
</transition>
<pre id="code1" class="language-html">
<code>
&lt;h1 class="text-4xl font-bold"&gt;Tajuk 1&lt;/h1&gt;
&lt;h2 class="text-3xl font-bold"&gt;Tajuk 2&lt;/h2&gt;
&lt;h3 class="text-2xl font-bold"&gt;Tajuk 3&lt;/h3&gt;
&lt;h4 class="text-xl font-bold"&gt;Tajuk 4&lt;/h4&gt;
&lt;h5 class="text-lg font-bold"&gt;Tajuk 5&lt;/h5&gt;
&lt;h6 class="text-base font-bold"&gt;Tajuk 6&lt;/h6&gt;
</code>
</pre>
</div>
</div>
</transition>
</ClientOnly>
</template>
</rs-card>
<!-- Perenggan -->
<rs-card>
<template #header> Perenggan </template>
<template #body>
<p class="mb-2">
Ini adalah perenggan lalai. Ia menggunakan saiz fon asas dan
ketinggian baris.
</p>
<p class="text-sm mb-2">
Ini adalah perenggan kecil menggunakan kelas text-sm.
</p>
<p class="text-lg mb-2">
Ini adalah perenggan besar menggunakan kelas text-lg.
</p>
<p class="font-light mb-2">Ini adalah perenggan berat ringan.</p>
<p class="font-semibold mb-2">Ini adalah perenggan separa tebal.</p>
<div class="flex justify-end mt-2">
<button
class="text-sm border border-slate-200 py-1 px-3 rounded-lg"
@click="showCode2 ? (showCode2 = false) : (showCode2 = true)"
>
Tunjukkan Kod
</button>
</div>
<ClientOnly>
<transition name="fade">
<div v-show="showCode2" v-highlight>
<div class="relative">
<button
@click="copyCode('code2')"
class="absolute top-4 right-2 text-sm bg-gray-300 hover:bg-gray-300 py-1 px-3 rounded z-10"
>
Salin Kod
</button>
<transition name="tooltip">
<span
v-if="tooltips['code2']"
class="absolute top-0 right-0 mt-12 mr-2 bg-black text-white text-xs rounded py-1 px-2 z-10"
>
{{ tooltips["code2"] }}
</span>
</transition>
<pre id="code2" class="language-html">
<code>
&lt;p&gt;Ini adalah perenggan lalai. Ia menggunakan saiz fon asas dan ketinggian baris.&lt;/p&gt;
&lt;p class="text-sm"&gt;Ini adalah perenggan kecil menggunakan kelas text-sm.&lt;/p&gt;
&lt;p class="text-lg"&gt;Ini adalah perenggan besar menggunakan kelas text-lg.&lt;/p&gt;
&lt;p class="font-light"&gt;Ini adalah perenggan berat ringan.&lt;/p&gt;
&lt;p class="font-semibold"&gt;Ini adalah perenggan separa tebal.&lt;/p&gt;
</code>
</pre>
</div>
</div>
</transition>
</ClientOnly>
</template>
</rs-card>
<!-- Warna Teks -->
<rs-card>
<template #header> Warna Teks </template>
<template #body>
<p class="text-primary mb-2">Ini adalah teks warna utama.</p>
<p class="text-secondary mb-2">Ini adalah teks warna sekunder.</p>
<p class="text-gray-500 mb-2">Ini adalah teks warna kelabu.</p>
<p class="text-red-500 mb-2">Ini adalah teks warna merah.</p>
<p class="text-green-500 mb-2">Ini adalah teks warna hijau.</p>
<div class="flex justify-end mt-2">
<button
class="text-sm border border-slate-200 py-1 px-3 rounded-lg"
@click="showCode3 ? (showCode3 = false) : (showCode3 = true)"
>
Tunjukkan Kod
</button>
</div>
<ClientOnly>
<transition name="fade">
<div v-show="showCode3" v-highlight>
<div class="relative">
<button
@click="copyCode('code3')"
class="absolute top-4 right-2 text-sm bg-gray-300 hover:bg-gray-300 py-1 px-3 rounded z-10"
>
Salin Kod
</button>
<transition name="tooltip">
<span
v-if="tooltips['code3']"
class="absolute top-0 right-0 mt-12 mr-2 bg-black text-white text-xs rounded py-1 px-2 z-10"
>
{{ tooltips["code3"] }}
</span>
</transition>
<pre id="code3" class="language-html">
<code>
&lt;p class="text-primary"&gt;Ini adalah teks warna utama.&lt;/p&gt;
&lt;p class="text-secondary"&gt;Ini adalah teks warna sekunder.&lt;/p&gt;
&lt;p class="text-gray-500"&gt;Ini adalah teks warna kelabu.&lt;/p&gt;
&lt;p class="text-red-500"&gt;Ini adalah teks warna merah.&lt;/p&gt;
&lt;p class="text-green-500"&gt;Ini adalah teks warna hijau.&lt;/p&gt;
</code>
</pre>
</div>
</div>
</transition>
</ClientOnly>
</template>
</rs-card>
<!-- Gaya Fon -->
<rs-card>
<template #header> Gaya Fon </template>
<template #body>
<p class="italic mb-2">Ini adalah teks condong.</p>
<p class="font-bold mb-2">Ini adalah teks tebal.</p>
<p class="underline mb-2">Ini adalah teks bergaris.</p>
<p class="line-through mb-2">Ini adalah teks dicoret.</p>
<p class="uppercase mb-2">Ini adalah teks huruf besar.</p>
<p class="lowercase mb-2">Ini adalah teks huruf kecil.</p>
<p class="capitalize mb-2">Ini adalah teks huruf awal besar.</p>
<div class="flex justify-end mt-2">
<button
class="text-sm border border-slate-200 py-1 px-3 rounded-lg"
@click="showCode4 ? (showCode4 = false) : (showCode4 = true)"
>
Tunjukkan Kod
</button>
</div>
<ClientOnly>
<transition name="fade">
<div v-show="showCode4" v-highlight>
<div class="relative">
<button
@click="copyCode('code4')"
class="absolute top-4 right-2 text-sm bg-gray-300 hover:bg-gray-300 py-1 px-3 rounded z-10"
>
Salin Kod
</button>
<transition name="tooltip">
<span
v-if="tooltips['code4']"
class="absolute top-0 right-0 mt-12 mr-2 bg-black text-white text-xs rounded py-1 px-2 z-10"
>
{{ tooltips["code4"] }}
</span>
</transition>
<pre id="code4" class="language-html">
<code>
&lt;p class="italic"&gt;Ini adalah teks condong.&lt;/p&gt;
&lt;p class="font-bold"&gt;Ini adalah teks tebal.&lt;/p&gt;
&lt;p class="underline"&gt;Ini adalah teks bergaris.&lt;/p&gt;
&lt;p class="line-through"&gt;Ini adalah teks dicoret.&lt;/p&gt;
&lt;p class="uppercase"&gt;Ini adalah teks huruf besar.&lt;/p&gt;
&lt;p class="lowercase"&gt;Ini adalah teks huruf kecil.&lt;/p&gt;
&lt;p class="capitalize"&gt;Ini adalah teks huruf awal besar.&lt;/p&gt;
</code>
</pre>
</div>
</div>
</transition>
</ClientOnly>
</template>
</rs-card>
</div>
</template>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.tooltip-enter-active,
.tooltip-leave-active {
transition: opacity 0.3s;
}
.tooltip-enter,
.tooltip-leave-to {
opacity: 0;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB