Update styling
parent
aec9c7a94b
commit
23e66323fd
|
@ -4,7 +4,7 @@ import {
|
|||
PiCheckCircleFill,
|
||||
PiWarningCircleFill,
|
||||
PiXCircleFill,
|
||||
PiCalendarPlusFill
|
||||
PiCalendarPlusFill,
|
||||
} from "react-icons/pi";
|
||||
import pelindoLogo from "@/assets/logos/Logo_Baru_Pelindo_(2021).png";
|
||||
import dephubLogo from "@/assets/logos/LOGO_KEMENTERIAN_PERHUBUNGAN_REPUBLIK_INDONESIA.png";
|
||||
|
@ -40,11 +40,16 @@ export function Index() {
|
|||
const [clock, setClock] = useState("00:00:00");
|
||||
const [date, setDate] = useState("");
|
||||
const [currentScheduleIndex, setCurrentScheduleIndex] = useState(0);
|
||||
const [grouppedSchedules, setGrouppedSchedules] = useState<{
|
||||
const [grouppedSchedules, setGrouppedSchedules] = useState<
|
||||
{
|
||||
key: string;
|
||||
items: Schedule[];
|
||||
}[][]>([]);
|
||||
const [companyInfo, setCompanyInfo] = useState<Record<string, {logo_location: string | null}>>(importCompanyInfo);
|
||||
}[][]
|
||||
>([]);
|
||||
const [companyInfo, setCompanyInfo] =
|
||||
useState<Record<string, { logo_location: string | null }>>(
|
||||
importCompanyInfo
|
||||
);
|
||||
|
||||
const [data, setData] = useState<{
|
||||
harbor: {
|
||||
|
@ -65,48 +70,75 @@ export function Index() {
|
|||
};
|
||||
|
||||
const groupDepartureDatetimes = (data: Schedule[], chunkSize = 5) => {
|
||||
const sortDates = data.sort((x, y) => dayjs(x.departure_datetime).unix() - dayjs(y.departure_datetime).unix())
|
||||
const sortDates = data.sort(
|
||||
(x, y) =>
|
||||
dayjs(x.departure_datetime).unix() - dayjs(y.departure_datetime).unix()
|
||||
);
|
||||
const scheduleChunks = chunkArray(sortDates, chunkSize);
|
||||
const tempResult = [];
|
||||
|
||||
const todayDatetime = dayjs();
|
||||
const tomorrowDatetime = dayjs().add(1, 'days');
|
||||
const tomorrowDatetime = dayjs().add(1, "days");
|
||||
|
||||
for(const scheduleChunk of scheduleChunks){
|
||||
const tempHolder: Record<string, Schedule[]> = {}
|
||||
for(const schedule of scheduleChunk){
|
||||
const parseDatetime = dayjs(schedule.departure_datetime).diff(dayjs(), 'days')
|
||||
if(parseDatetime == 0){
|
||||
if(!(`(Hari Ini) - ${todayDatetime.format("DD MMMM YYYY")}|1` in tempHolder))
|
||||
tempHolder[`(Hari Ini) - ${todayDatetime.format("DD MMMM YYYY")}|1`] = [];
|
||||
tempHolder[`(Hari Ini) - ${todayDatetime.format("DD MMMM YYYY")}|1`].push(schedule);
|
||||
for (const scheduleChunk of scheduleChunks) {
|
||||
const tempHolder: Record<string, Schedule[]> = {};
|
||||
for (const schedule of scheduleChunk) {
|
||||
const parseDatetime = dayjs(schedule.departure_datetime).diff(
|
||||
dayjs(),
|
||||
"days"
|
||||
);
|
||||
if (parseDatetime == 0) {
|
||||
if (
|
||||
!(
|
||||
`(Hari Ini) - ${todayDatetime.format("DD MMMM YYYY")}|1` in
|
||||
tempHolder
|
||||
)
|
||||
)
|
||||
tempHolder[
|
||||
`(Hari Ini) - ${todayDatetime.format("DD MMMM YYYY")}|1`
|
||||
] = [];
|
||||
tempHolder[
|
||||
`(Hari Ini) - ${todayDatetime.format("DD MMMM YYYY")}|1`
|
||||
].push(schedule);
|
||||
}
|
||||
|
||||
if(parseDatetime == 1){
|
||||
if(!(`(Besok) - ${tomorrowDatetime.format("DD MMMM YYYY")}|2` in tempHolder))
|
||||
tempHolder[`(Besok) - ${tomorrowDatetime.format("DD MMMM YYYY")}|2`] = [];
|
||||
tempHolder[`(Besok) - ${tomorrowDatetime.format("DD MMMM YYYY")}|2`].push(schedule);
|
||||
if (parseDatetime == 1) {
|
||||
if (
|
||||
!(
|
||||
`(Besok) - ${tomorrowDatetime.format("DD MMMM YYYY")}|2` in
|
||||
tempHolder
|
||||
)
|
||||
)
|
||||
tempHolder[
|
||||
`(Besok) - ${tomorrowDatetime.format("DD MMMM YYYY")}|2`
|
||||
] = [];
|
||||
tempHolder[
|
||||
`(Besok) - ${tomorrowDatetime.format("DD MMMM YYYY")}|2`
|
||||
].push(schedule);
|
||||
}
|
||||
|
||||
if(parseDatetime > 1){
|
||||
if(!(`Mendatang|3` in tempHolder))
|
||||
tempHolder[`Mendatang|3`] = [];
|
||||
if (parseDatetime > 1) {
|
||||
if (!(`Mendatang|3` in tempHolder)) tempHolder[`Mendatang|3`] = [];
|
||||
tempHolder[`Mendatang|3`].push(schedule);
|
||||
}
|
||||
}
|
||||
tempResult.push(tempHolder)
|
||||
tempResult.push(tempHolder);
|
||||
}
|
||||
|
||||
|
||||
const finaleResult = [];
|
||||
|
||||
for(const groupped of tempResult){
|
||||
|
||||
for (const groupped of tempResult) {
|
||||
const temporaryFinale = [];
|
||||
const sortItAgain = Object.keys(groupped).sort((idA, idB) => (( (idA.split("|")[1]! as unknown as number) > (idB.split("|")[1]! as unknown as number) ? 1 : -1)))
|
||||
for(const key of sortItAgain){
|
||||
temporaryFinale.push({key: key.split("|")[0], items: groupped[key]})
|
||||
const sortItAgain = Object.keys(groupped).sort((idA, idB) =>
|
||||
(idA.split("|")[1]! as unknown as number) >
|
||||
(idB.split("|")[1]! as unknown as number)
|
||||
? 1
|
||||
: -1
|
||||
);
|
||||
for (const key of sortItAgain) {
|
||||
temporaryFinale.push({ key: key.split("|")[0], items: groupped[key] });
|
||||
}
|
||||
finaleResult.push(temporaryFinale)
|
||||
finaleResult.push(temporaryFinale);
|
||||
}
|
||||
|
||||
return finaleResult;
|
||||
|
@ -140,196 +172,194 @@ export function Index() {
|
|||
*/
|
||||
setInterval(() => {
|
||||
const _clock = dayjs().format("HH:mm:ss");
|
||||
const _date = dayjs().format("DD MMMM YYYY");
|
||||
const _date = dayjs().format("DD MMM YYYY");
|
||||
setClock(_clock);
|
||||
setDate(_date);
|
||||
}, 1000);
|
||||
|
||||
setGrouppedSchedules(groupDepartureDatetimes(data.schedules, 6));
|
||||
setGrouppedSchedules(groupDepartureDatetimes(data.schedules, 5));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if(grouppedSchedules.length != 0){
|
||||
if (grouppedSchedules.length != 0) {
|
||||
setInterval(() => {
|
||||
setCurrentScheduleIndex(current => (current + 1) % grouppedSchedules.length)
|
||||
setCurrentScheduleIndex(
|
||||
(current) => (current + 1) % grouppedSchedules.length
|
||||
);
|
||||
}, 10000);
|
||||
}
|
||||
}, [grouppedSchedules]);
|
||||
|
||||
return (
|
||||
<div className="h-screen" style={{ backgroundImage: `url(${bgImage})` }}>
|
||||
<div className="p-4 grid grid-cols-12 gap-8" style={{height: "85%"}}>
|
||||
<div className="col-span-8">
|
||||
<div className="flex flex-col bg-white border shadow-sm rounded-xl p-4 md:p-5 h-full">
|
||||
<h3 className="text-4xl font-bold text-gray-800 text-center">
|
||||
KEBERANGKATAN
|
||||
</h3>
|
||||
|
||||
<div className="mt-10">
|
||||
<table className="min-w-full max-w-full divide-y divide-gray-200 overflow-y-scroll">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-xl font-bold uppercase w-2/5"
|
||||
>
|
||||
Kapal
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-xl font-bold uppercase w-1/5"
|
||||
>
|
||||
Tujuan
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-xl font-bold uppercase"
|
||||
style={{ width: "20%" }}
|
||||
>
|
||||
Wkt. Keberangkatan
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-xl font-bold uppercase w-1/4"
|
||||
>
|
||||
Status
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200">
|
||||
{
|
||||
grouppedSchedules[currentScheduleIndex] != undefined && grouppedSchedules[currentScheduleIndex].map((x, i) => <>
|
||||
<tr key={i}>
|
||||
<td colSpan={4} className="text-center py-4">
|
||||
<div className="flex gap-2 justify-center">
|
||||
<PiCalendarDotsBold size={28} />
|
||||
<span className="text-lg font-bold">
|
||||
{x.key}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{
|
||||
x.items.map((y, j) => <tr key={j}>
|
||||
<td className="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-800 odd:bg-white even:bg-gray-100">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<div>
|
||||
<CompanyLogo location={companyInfo[y.company_code].logo_location} width={64} />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-xl font-bold">
|
||||
{y.ship_name}
|
||||
</h4>
|
||||
<h5 className="text-lg">{y.dock_name}</h5>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-2 whitespace-nowrap text-sm text-gray-800">
|
||||
<h3 className="text-xl font-medium text-center">
|
||||
{y.destination}
|
||||
</h3>
|
||||
</td>
|
||||
<td className="px-4 py-2 whitespace-nowrap text-sm text-gray-800">
|
||||
{
|
||||
x.key == "Mendatang" && <h3 className="text-xl font-medium text-center">
|
||||
{dayjs(y.departure_datetime).format("DD-MMM-YYYY")}
|
||||
</h3>
|
||||
}
|
||||
<h3 className="text-xl font-medium text-center">
|
||||
{dayjs(y.departure_datetime).format("HH:mm")} {timezone}
|
||||
</h3>
|
||||
</td>
|
||||
<td className="px-4 py-2 text-sm font-medium">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
{
|
||||
y.status == ScheduleStatus.NOT_AVAILABLE && <>
|
||||
<PiXCircleFill size={32} className="text-red-500" />
|
||||
<h3 className="text-xl">Belum tersedia</h3>
|
||||
</>
|
||||
}
|
||||
{
|
||||
y.status == ScheduleStatus.SCHEDULED && <>
|
||||
<PiCalendarPlusFill size={32} className="text-yellow-500" />
|
||||
<h3 className="text-xl">Dijadwalkan</h3>
|
||||
</>
|
||||
}
|
||||
{
|
||||
y.status == ScheduleStatus.AVAILABLE && <>
|
||||
<PiCheckCircleFill size={32} className="text-green-700" />
|
||||
<h3 className="text-xl">Tersedia</h3>
|
||||
</>
|
||||
}
|
||||
{
|
||||
y.status == ScheduleStatus.PREPARE_TO_DEPART && <>
|
||||
<PiWarningCircleFill size={32} className="text-yellow-500" />
|
||||
<h3 className="text-xl">Bersiap Berangkat</h3>
|
||||
</>
|
||||
}
|
||||
{
|
||||
y.status == ScheduleStatus.CANCELED && <>
|
||||
<PiXCircleFill size={32} className="text-red-500" />
|
||||
<h3 className="text-xl">Dibatalkan</h3>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</tr>)
|
||||
}
|
||||
</>)
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<>
|
||||
<div className="h-screen pl-4 pr-4 pt-4">
|
||||
<div className="grid grid-cols-12 items-center">
|
||||
<div className="col-span-4">
|
||||
<div className="flex items-center">
|
||||
<img src={ferinesiaLogo} className="max-h-12" />
|
||||
<h3 className="ml-2 text-6xl font-bold text-[#117AD1]">
|
||||
FERI<span className="text-[#FFCE46]">NESIA</span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<h3 className="text-5xl font-bold text-center text-[#2F95FA]">
|
||||
PELABUHAN BASTIONG
|
||||
</h3>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<h3 className="text-3xl font-bold text-right">
|
||||
{date} {clock} {timezone}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<div className="flex flex-col bg-white border shadow-sm rounded-xl p-4 md:p-5 h-full">
|
||||
<h3 className="text-3xl font-bold text-gray-800 text-center">
|
||||
{data.harbor.name}
|
||||
</h3>
|
||||
<h3 className="text-xl font-bold text-gray-800 text-center">
|
||||
{data.harbor.address}
|
||||
</h3>
|
||||
<div className="grid grid-cols-12 gap-8 mt-8" style={{ height: "80%" }}>
|
||||
<div className="col-span-12">
|
||||
<div className="flex flex-col bg-white border shadow-sm rounded-xl p-4 md:p-5 h-full">
|
||||
<h3 className="text-4xl font-bold text-gray-800 text-center underline">
|
||||
KEBERANGKATAN
|
||||
</h3>
|
||||
|
||||
<div className="mt-12">
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<PiClock size={64} />
|
||||
<h3 className="text-3xl font-semibold">{date}</h3>
|
||||
<h3 className="text-3xl font-semibold">
|
||||
{clock} {timezone}
|
||||
</h3>
|
||||
</div>
|
||||
{/* <div className="flex flex-col items-center gap-1 mt-6">
|
||||
<WiNightAltRainMix size={64} />
|
||||
<h3 className="text-3xl font-semibold">
|
||||
Hujan Cerah, 30°C
|
||||
</h3>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className="mt-12">
|
||||
<div className="w-full">
|
||||
<video className="w-full h-80 border rounded-lg" loop={true} autoPlay={true} controls={true}>
|
||||
<source src={data.embed_link[0]} type="video/mp4" />
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-12">
|
||||
<div className="flex flex-row gap-3 items-center justify-center">
|
||||
<img src={dephubLogo} className="h-10" />
|
||||
<img src={pelindoLogo} className="max-h-7" />
|
||||
<img src={ferinesiaLogo} className="max-h-7" />
|
||||
<h4 className="text-md">didukung oleh Ferinesia</h4>
|
||||
<div className="mt-8">
|
||||
<table className="min-w-full max-w-full divide-y divide-gray-200 overflow-y-scroll">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-4xl uppercase"
|
||||
style={{ width: "10%", letterSpacing: "3px" }}
|
||||
>
|
||||
JAM
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-4xl font-bold uppercase w-2/5"
|
||||
style={{letterSpacing: "3px"}}
|
||||
>
|
||||
KAPAL
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-4xl font-bold uppercase w-1/5"
|
||||
style={{letterSpacing: "3px"}}
|
||||
>
|
||||
TUJUAN
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="text-center text-4xl font-bold uppercase w-1/4"
|
||||
style={{letterSpacing: "3px"}}
|
||||
>
|
||||
STATUS
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200">
|
||||
{grouppedSchedules[currentScheduleIndex] != undefined &&
|
||||
grouppedSchedules[currentScheduleIndex].map((x, i) => (
|
||||
<>
|
||||
<tr key={i}>
|
||||
<td colSpan={4} className="text-center py-4">
|
||||
<div className="flex gap-2 justify-center">
|
||||
<PiCalendarDotsBold size={38} />
|
||||
<span className="text-3xl font-bold uppercase">
|
||||
{x.key}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{x.items.map((y, j) => (
|
||||
<tr key={j} className="odd:bg-[#598eee] even:bg-[#dde8fc] odd:text-[#ffffff] even:text-[#0f79cf]">
|
||||
<td className="px-4 py-2 whitespace-nowrap text-sm ">
|
||||
<h3 className="text-4xl font-bold text-center uppercase">
|
||||
{x.key == "Mendatang" ? dayjs(y.departure_datetime).format("DD-MMM-YYYY") : dayjs(y.departure_datetime).format("HH:mm ") + timezone}
|
||||
|
||||
</h3>
|
||||
</td>
|
||||
<td className="px-4 py-2 whitespace-nowrap text-sm font-medium ">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<div>
|
||||
<CompanyLogo
|
||||
location={
|
||||
companyInfo[y.company_code]
|
||||
.logo_location
|
||||
}
|
||||
width={72}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-4xl font-medium uppercase">
|
||||
{y.ship_name}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-2 whitespace-nowrap text-sm ">
|
||||
<h3 className="text-4xl font-medium text-center uppercase">
|
||||
{y.destination}
|
||||
</h3>
|
||||
</td>
|
||||
<td className="px-4 py-2 font-medium">
|
||||
<div className="flex flex-row items-center gap-2 uppercase">
|
||||
{y.status == ScheduleStatus.NOT_AVAILABLE && (
|
||||
<>
|
||||
<PiXCircleFill
|
||||
size={50}
|
||||
/>
|
||||
<h3 className="text-4xl">
|
||||
Belum tersedia
|
||||
</h3>
|
||||
</>
|
||||
)}
|
||||
{y.status == ScheduleStatus.SCHEDULED && (
|
||||
<>
|
||||
<PiCalendarPlusFill
|
||||
size={50}
|
||||
/>
|
||||
<h3 className="text-4xl">Dijadwalkan</h3>
|
||||
</>
|
||||
)}
|
||||
{y.status == ScheduleStatus.AVAILABLE && (
|
||||
<>
|
||||
<PiCheckCircleFill
|
||||
size={50}
|
||||
/>
|
||||
<h3 className="text-4xl">Tersedia</h3>
|
||||
</>
|
||||
)}
|
||||
{y.status ==
|
||||
ScheduleStatus.PREPARE_TO_DEPART && (
|
||||
<>
|
||||
<PiWarningCircleFill
|
||||
size={50}
|
||||
/>
|
||||
<h3 className="text-4xl">
|
||||
Bersiap Berangkat
|
||||
</h3>
|
||||
</>
|
||||
)}
|
||||
{y.status == ScheduleStatus.CANCELED && (
|
||||
<>
|
||||
<PiXCircleFill
|
||||
size={50}
|
||||
/>
|
||||
<h3 className="text-4xl">Dibatalkan</h3>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="fixed bottom-10 p-4">
|
||||
<div className="fixed bottom-5">
|
||||
<div className="border-2 rounded-md mt-4 h-12 flex">
|
||||
<div className="bg-blue-400 h-full items-center justify-center flex w-40">
|
||||
<h3 className="text-xl text-center text-white">INFORMASI</h3>
|
||||
|
@ -343,6 +373,7 @@ export function Index() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue