temp
parent
0177c3cc7e
commit
d5a3224bf1
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if(!Schema::hasColumn('users', 'role')) {
|
||||||
|
Schema::table('users', function($t){
|
||||||
|
$t->string('role');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 716 B |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 112 KiB |
@ -1,3 +1,100 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
|
||||||
|
.react-datepicker__input-container > input {
|
||||||
|
@apply block w-full text-base md:text-sm bg-white border border-gray-300 shadow-sm input input-bordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker-popper {
|
||||||
|
@apply z-40 w-72 text-sm bg-white shadow px-3 py-2 border-2 border-gray-200 rounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker-left {
|
||||||
|
@apply absolute left-0 right-auto top-11 transform-none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker-right {
|
||||||
|
@apply absolute right-0 left-auto top-11 transform-none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__portal {
|
||||||
|
@apply absolute z-10 w-72 text-sm transform-none bg-white shadow px-3 py-2 top-12 right-0 border-2 border-gray-200 rounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__month-container {
|
||||||
|
@apply flex flex-col;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__month {
|
||||||
|
@apply flex flex-col;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__current-month {
|
||||||
|
@apply ml-2.5 text-lg font-semibold text-gray-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__week {
|
||||||
|
@apply flex justify-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day-names {
|
||||||
|
@apply flex justify-around text-gray-400 font-medium text-center text-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day-name {
|
||||||
|
@apply w-8 h-8 flex items-center justify-center py-1 rounded-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation {
|
||||||
|
@apply absolute top-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation--previous {
|
||||||
|
@apply right-12 w-8 h-8 rounded transition flex items-center justify-center hover:bg-gray-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__navigation--next {
|
||||||
|
@apply right-4 w-8 h-8 rounded transition flex items-center justify-center hover:bg-gray-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day {
|
||||||
|
@apply mb-1 w-8 h-8 flex items-center justify-center py-1 text-sm leading-loose transition text-gray-700 rounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--disabled {
|
||||||
|
@apply cursor-not-allowed opacity-40 hover:bg-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--outside-month {
|
||||||
|
@apply text-gray-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--in-range {
|
||||||
|
@apply bg-gray-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--in-selecting-range {
|
||||||
|
@apply bg-blue-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selecting-range-start {
|
||||||
|
@apply bg-white border-2 border-blue-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selecting-range-end {
|
||||||
|
@apply bg-white border-2 border-blue-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selected {
|
||||||
|
@apply bg-blue-500 text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--range-start {
|
||||||
|
@apply bg-blue-500 text-white hover:text-gray-700 hover:bg-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--range-end {
|
||||||
|
@apply bg-blue-500 text-white hover:text-gray-700 hover:bg-white;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
export default function ApplicationLogo({ className }) {
|
export default function ApplicationLogo({ className }) {
|
||||||
return (
|
return (
|
||||||
<svg className={className} viewBox="0 0 316 316" xmlns="http://www.w3.org/2000/svg">
|
<div className="w-20">
|
||||||
<path d="M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z" />
|
<img src="/img/yamato-cash-portal-icon.png" className="mx-auto" alt="logo Yamato Operation Portal"/>
|
||||||
</svg>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import DatePicker from "react-datepicker";
|
||||||
|
|
||||||
|
export const DatePickerRangeInput = ({
|
||||||
|
startDate,
|
||||||
|
setStartDate,
|
||||||
|
endDate,
|
||||||
|
setEndDate,
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
if(typeof(endDate) === 'string') {
|
||||||
|
endDate = new Date(endDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex space-x-1">
|
||||||
|
<div className="relative">
|
||||||
|
<DatePicker
|
||||||
|
selected={startDate}
|
||||||
|
onChange={(dates) => {
|
||||||
|
const [start, end] = dates;
|
||||||
|
setStartDate(start);
|
||||||
|
setEndDate(end);
|
||||||
|
}}
|
||||||
|
selectsRange
|
||||||
|
startDate={startDate}
|
||||||
|
endDate={endDate}
|
||||||
|
nextMonthButtonLabel=">"
|
||||||
|
previousMonthButtonLabel="<"
|
||||||
|
popperClassName="react-datepicker-left"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,63 @@
|
|||||||
|
import { Inertia } from "@inertiajs/inertia";
|
||||||
|
import qs from "qs";
|
||||||
|
|
||||||
|
const PageLink = ({ active, label, url, params }) => {
|
||||||
|
const className = `mr-1 mb-1 px-4 py-3 border border-solid border-gray-300 rounded text-sm bg-white hover:bg-white ${
|
||||||
|
active &&
|
||||||
|
"focus:outline-none focus:border-gray-700 focus:text-gray-700 border-gray-600 bg-gray-600 text-white hover:bg-gray-400"
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const onClick = () => {
|
||||||
|
Inertia.get(
|
||||||
|
`${url}&${qs.stringify(params)}`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
replace: true,
|
||||||
|
// preserveState: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={className} onClick={onClick}>
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: label }}></span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Previous, if on first page
|
||||||
|
// Next, if on last page
|
||||||
|
// and dots, if exists (...)
|
||||||
|
const PageInactive = ({ label }) => {
|
||||||
|
const className =
|
||||||
|
"mr-1 mb-1 px-4 py-3 text-sm border rounded border-solid border-gray-300 text-gray";
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={className}
|
||||||
|
dangerouslySetInnerHTML={{ __html: label }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ({ links = [], params = null }) => {
|
||||||
|
// dont render, if there's only 1 page (previous, 1, next)
|
||||||
|
if (links.length === 3) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-wrap mt-6 -mb-1">
|
||||||
|
{links.map(({ active, label, url }) => {
|
||||||
|
return url === null ? (
|
||||||
|
<PageInactive key={label} label={label} />
|
||||||
|
) : (
|
||||||
|
<PageLink
|
||||||
|
key={label}
|
||||||
|
label={label}
|
||||||
|
active={active}
|
||||||
|
url={url}
|
||||||
|
params={params}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
export function useDebounce(value, delay) {
|
||||||
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedValue(value);
|
||||||
|
}, delay);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [value, delay]);
|
||||||
|
return debouncedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useModalState(state = false) {
|
||||||
|
const [isOpen, setIsOpen] = useState(state);
|
||||||
|
const toggle = () => {
|
||||||
|
setIsOpen(!isOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [data, setData] = useState(null);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isOpen,
|
||||||
|
toggle,
|
||||||
|
setIsOpen,
|
||||||
|
data,
|
||||||
|
setData,
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,273 @@
|
|||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import { usePrevious } from "react-use";
|
||||||
|
import { Inertia } from "@inertiajs/inertia";
|
||||||
|
|
||||||
|
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||||
|
import Pagination from "@/Components/Pagination";
|
||||||
|
import { DatePickerRangeInput } from "@/Components/DatePickerInput";
|
||||||
|
import { useModalState } from "@/Hook";
|
||||||
|
import { Head } from '@inertiajs/inertia-react';
|
||||||
|
import { formatDate } from "@/Utils";
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
export default function Dashboard(props) {
|
||||||
|
const { _startDate, _endDate, _limit } = props
|
||||||
|
|
||||||
|
const [startDate, setStartDate] = useState(_startDate)
|
||||||
|
const [endDate, setEndDate] = useState(_endDate)
|
||||||
|
|
||||||
|
const { data: bookings, links } = props.booking;
|
||||||
|
const [bookingsChecked, setBookingsChecked] = useState(
|
||||||
|
bookings.map((booking) => {
|
||||||
|
return {
|
||||||
|
...booking,
|
||||||
|
isChecked: false,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const [limit, setLimit] = useState(_limit)
|
||||||
|
const preValue = usePrevious(`${search}-${startDate}-${endDate}-${limit}`);
|
||||||
|
const [booking, setBooking] = useState(null);
|
||||||
|
const [ids, setIds] = useState({});
|
||||||
|
|
||||||
|
|
||||||
|
const formModal = useModalState(false);
|
||||||
|
const handleEdit = (booking = null) => {
|
||||||
|
setBooking(booking);
|
||||||
|
formModal.toggle();
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmModal = useModalState(false);
|
||||||
|
const handleDelete = (booking) => {
|
||||||
|
confirmModal.setData(booking);
|
||||||
|
confirmModal.toggle();
|
||||||
|
};
|
||||||
|
|
||||||
|
const detailModal = useModalState(false);
|
||||||
|
const handleDetail = (booking = null) => {
|
||||||
|
setBooking(booking);
|
||||||
|
detailModal.toggle();
|
||||||
|
};
|
||||||
|
|
||||||
|
const bookingModal = useModalState(false);
|
||||||
|
const handleBooking = () => {
|
||||||
|
bookingModal.toggle();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDelete = () => {
|
||||||
|
const booking = confirmModal.data;
|
||||||
|
if (booking != null) {
|
||||||
|
Inertia.delete(
|
||||||
|
route("monitoring-booking.destroy", booking), {
|
||||||
|
onSuccess: () => toast.success("item delete"),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckedCheckbox = (e) => {
|
||||||
|
setBookingsChecked(
|
||||||
|
bookingsChecked.map((booking) => {
|
||||||
|
if (booking.id === e.target.defaultValue * 1) {
|
||||||
|
return {
|
||||||
|
...booking,
|
||||||
|
isChecked: !booking.isChecked,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return booking;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseOverExport = () => {
|
||||||
|
let params = bookingsChecked
|
||||||
|
.map((booking) => {
|
||||||
|
if (booking.isChecked) {
|
||||||
|
return booking.id;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter((isChecked) => {
|
||||||
|
return isChecked !== undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
setIds(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckAll = (e) => {
|
||||||
|
setBookingsChecked((prevBookingsChecked) => {
|
||||||
|
return prevBookingsChecked.map((booking) => {
|
||||||
|
return {
|
||||||
|
...booking,
|
||||||
|
isChecked: e.target.checked,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = { ids };
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setBookingsChecked(
|
||||||
|
bookings.map((booking) => {
|
||||||
|
return {
|
||||||
|
...booking,
|
||||||
|
isChecked: false,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, [bookings]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (preValue) {
|
||||||
|
Inertia.get(
|
||||||
|
route(route().current()),
|
||||||
|
{ q: search, startDate, endDate, limit },
|
||||||
|
{
|
||||||
|
replace: true,
|
||||||
|
preserveState: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}, [search, startDate, endDate, limit])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthenticatedLayout
|
||||||
|
auth={props.auth}
|
||||||
|
errors={props.errors}
|
||||||
|
>
|
||||||
|
<Head title="Booking" />
|
||||||
|
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="mx-auto max-w-7xl p-4 bg-white overflow-hidden shadow-sm sm:rounded-lg min-h-screen">
|
||||||
|
<div className='flex justify-between space-x-0 lg:space-x-1 flex-row mb-2'>
|
||||||
|
<div className='flex space-x-1'>
|
||||||
|
<div className='btn'>Tambah</div>
|
||||||
|
<div className='btn'>Import Excel</div>
|
||||||
|
</div>
|
||||||
|
<div className='btn'>Export Excel</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-between space-y-1 lg:space-y-0 space-x-0 lg:space-x-1 flex-col lg:flex-row'>
|
||||||
|
<div>
|
||||||
|
Terakhir diperbarui: {props.last_updated
|
||||||
|
? formatDate(props.last_updated).format('DD/MM/Y hh:mm')
|
||||||
|
: 'Belum ada pembaruan'}
|
||||||
|
</div>
|
||||||
|
<div className='flex lg:space-x-2 space-x-0 lg:space-y-0 space-y-1 flex-col lg:flex-row'>
|
||||||
|
<div className='flex space-x-1'>
|
||||||
|
<DatePickerRangeInput
|
||||||
|
startDate={new Date(startDate)}
|
||||||
|
setStartDate={setStartDate}
|
||||||
|
endDate={endDate}
|
||||||
|
setEndDate={setEndDate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input className='input input-bordered w-full' placeholder='search'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="overflow-x-auto mt-2">
|
||||||
|
<table className="table w-full table-zebra">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox checkbox-xs"
|
||||||
|
onChange={(e) =>handleCheckAll(e)}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
<th>Master AWB</th>
|
||||||
|
<th>Flight Number</th>
|
||||||
|
<th>Departure</th>
|
||||||
|
<th>Destination</th>
|
||||||
|
<th>Booked</th>
|
||||||
|
<th>Packaging</th>
|
||||||
|
<th>Used</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Opsi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{bookingsChecked.map((booking) => (
|
||||||
|
<tr key={booking.id}>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox checkbox-xs"
|
||||||
|
onChange={(e) => handleCheckedCheckbox(e)}
|
||||||
|
checked={booking.isChecked}
|
||||||
|
value={booking.id}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>{booking.master_awb}</td>
|
||||||
|
<td>{booking.flight_number}</td>
|
||||||
|
<td>
|
||||||
|
{formatDate(booking.departure).format('DD/MM/yyyy')}
|
||||||
|
</td>
|
||||||
|
<td>{booking.destination}</td>
|
||||||
|
<td>{booking.booked}</td>
|
||||||
|
<td>{booking.kemasan}</td>
|
||||||
|
<td>{booking.used}</td>
|
||||||
|
<td>
|
||||||
|
{+booking.is_available === 0
|
||||||
|
? 'Available'
|
||||||
|
: 'Closed'}
|
||||||
|
</td>
|
||||||
|
<td className="flex gap-1">
|
||||||
|
<button
|
||||||
|
className="btn btn-neutral btn-xs"
|
||||||
|
onClick={() => handleDetail(booking)}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-neutral btn-xs"
|
||||||
|
onClick={() => handleEdit(booking)}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-neutral btn-xs"
|
||||||
|
onClick={() => handleDelete(booking)}
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className='flex w-full'>
|
||||||
|
<div className="flex mx-auto items-end mt-4">
|
||||||
|
<Pagination
|
||||||
|
links={links}
|
||||||
|
params={{
|
||||||
|
q: search,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
limit,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<select
|
||||||
|
className="select select-bordered w-full max-w-xs"
|
||||||
|
onChange={(e) => setLimit(e.target.value)}
|
||||||
|
value={limit}
|
||||||
|
>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
<option value="100">100</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AuthenticatedLayout>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||||
|
import { Head } from '@inertiajs/inertia-react';
|
||||||
|
|
||||||
|
export default function Dashboard(props) {
|
||||||
|
return (
|
||||||
|
<AuthenticatedLayout
|
||||||
|
auth={props.auth}
|
||||||
|
errors={props.errors}
|
||||||
|
>
|
||||||
|
<Head title="Expense" />
|
||||||
|
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="mx-auto max-w-7xl p-2 bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||||
|
<div className='flex justify-between space-x-0 lg:space-x-1 flex-row mb-2'>
|
||||||
|
<div className='btn'>Tambah</div>
|
||||||
|
<div className='btn'>Export Excel</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-between space-y-1 lg:space-y-0 space-x-0 lg:space-x-1 flex-col lg:flex-row'>
|
||||||
|
<div>
|
||||||
|
<div>Jumlah Record : 100</div>
|
||||||
|
<div>Jumlah Halaman : 24</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex lg:space-x-2 space-x-0 lg:space-y-0 space-y-1 flex-col lg:flex-row'>
|
||||||
|
<div className='flex space-x-1'>
|
||||||
|
<input className='input input-bordered w-full lg:w-32' placeholder='start date' defaultValue={'01/10/2023'}/>
|
||||||
|
<input className='input input-bordered w-full lg:w-32' placeholder='end date'defaultValue={'01/10/2023'}/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input className='input input-bordered w-full' placeholder='search'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AuthenticatedLayout>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
export const formatDate = (date) => {
|
||||||
|
return moment(date);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function formatIDR(amount) {
|
||||||
|
const idFormatter = new Intl.NumberFormat("id-ID");
|
||||||
|
return idFormatter.format(amount);
|
||||||
|
}
|
Loading…
Reference in New Issue