initial commit
This commit is contained in:
77
components/Ask/index.js
Normal file
77
components/Ask/index.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import {askRepository} from "../../repository/ask";
|
||||
import {Image} from "antd";
|
||||
import constraint from "../Constraint";
|
||||
|
||||
const Ask = () => {
|
||||
// const {data: contacts} = askRepository.api.getContacts();
|
||||
const [contacts, setContacts] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
fetchData()
|
||||
}, [])
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const res = await askRepository.api.getContacts()
|
||||
setContacts(res)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
const dataContact = [
|
||||
{
|
||||
title: "Telepon Customer Care",
|
||||
no: contacts?.results?.phone,
|
||||
timetable: contacts?.results?.phone_wording,
|
||||
icon: "/assets/icons/phone.svg",
|
||||
link: `tel:${contacts?.results?.phone}`
|
||||
},
|
||||
{
|
||||
title: "Whatsapp Customer Care",
|
||||
no: contacts?.results?.whatsapp,
|
||||
timetable: contacts?.results?.whatsapp_wording,
|
||||
icon: "/assets/icons/whatsapp.svg",
|
||||
link: `https://wa.me/${contacts?.results?.whatsapp}`
|
||||
},
|
||||
{
|
||||
title: "Email Customer Care",
|
||||
no: contacts?.results?.email,
|
||||
timetable: contacts?.results?.email_wording,
|
||||
icon: "/assets/icons/email.svg",
|
||||
link: `mailto:${contacts?.results?.email}`
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className={'relative pb-10 mt-5 w-full'}>
|
||||
<div className={'text-center'}>
|
||||
<h3 className={'text-lg font-bold z-10 pt-16'}>Tanyakan ke <span className={'text-[#FFB500]'}>Kami</span></h3>
|
||||
<p className={'z-10 px-5'}>Customer Care kami siap membantu Anda jika Anda memiliki pertanyaan atau masalah dalam menggunakan
|
||||
aplikasi ini.</p>
|
||||
</div>
|
||||
<div className={'absolute top-3 left-0 z-0'}>
|
||||
<Image src={'/assets/backgrounds/cloud-left.svg'} alt={'cloud-left'}/>
|
||||
</div>
|
||||
<div className={'absolute top-1 right-0 z-0'}>
|
||||
<Image src={'/assets/backgrounds/cloud-right.svg'} alt={'cloud-right'}/>
|
||||
</div>
|
||||
|
||||
<div className={'flex flex-col gap-4 m-5'}>
|
||||
{dataContact.map((it, index) => (
|
||||
<a key={index} href={it.link} target={'_blank'} className={'flex flex-row justify-between gap-4 bg-white p-5 shadow-lg rounded-lg text-black z-10 hover:cursor-pointer hover:shadow-xl'} rel="noreferrer">
|
||||
<div className={'flex flex-col'}>
|
||||
<span>{it.title}</span>
|
||||
<span className={'font-bold'}>{it.no}</span>
|
||||
<span className={'text-xs text-[#9B9B9B]'}>{it.timetable}</span>
|
||||
</div>
|
||||
<Image src={it.icon} alt={'icon'}width={40} height={40} />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Ask;
|
||||
19
components/BottomSheet/index.js
Normal file
19
components/BottomSheet/index.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import Sheet from "react-modal-sheet";
|
||||
|
||||
const BottomSheet = ({onOpen, onClose, children}) => {
|
||||
return (
|
||||
<Sheet isOpen={onOpen} onClose={onClose} snapPoints={[400]} className={'flex justify-center'}>
|
||||
<Sheet.Container>
|
||||
<Sheet.Header/>
|
||||
<Sheet.Content>
|
||||
{children}
|
||||
</Sheet.Content>
|
||||
</Sheet.Container>
|
||||
|
||||
<Sheet.Backdrop/>
|
||||
</Sheet>
|
||||
)
|
||||
}
|
||||
|
||||
export default BottomSheet;
|
||||
107
components/Constraint/index.js
Normal file
107
components/Constraint/index.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import React, { useState } from 'react';
|
||||
import Image from "next/image";
|
||||
import {Button, Form, Input} from "antd";
|
||||
import Transaction from "../Transaction";
|
||||
import { botsRepository } from '../../repository/bots';
|
||||
|
||||
const Constraint = ({location}) => {
|
||||
const [form] = Form.useForm();
|
||||
const [orderId, setOrderId] = useState('');
|
||||
const [order, setOrder] = useState('');
|
||||
const [orderNotFound, setOrderNotFound] = useState(false);
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
const handleChangeCheckTransaction = (e) => {
|
||||
const value = e.target.value
|
||||
setOrderId(value)
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
setShow(true)
|
||||
if (show) {
|
||||
try {
|
||||
const res = await botsRepository.api.useCheckTransactionByOrderId(orderId);
|
||||
const resultTransaction = res?.data;
|
||||
setOrderNotFound(false);
|
||||
setOrder(resultTransaction);
|
||||
|
||||
} catch (err) {
|
||||
setOrderNotFound(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console?.log(order, "ini ordernya")
|
||||
|
||||
return (
|
||||
<div className={'bg-white px-7 pt-4 pb-8 mt-6'}>
|
||||
<Image src={'/assets/images/logo.svg'} width={100} height={50}/>
|
||||
|
||||
<h3 className={'text-lg font-bold'}>Ada kendala dengan transaksimu?</h3>
|
||||
<p>Cek transaksi dengan Order ID pembayaran:</p>
|
||||
|
||||
<Form form={form} layout={'vertical'}>
|
||||
<Form.Item name="order_id" rules={[
|
||||
{required: true, message: "Silahkan masukan Order ID!"},
|
||||
]}>
|
||||
<Input
|
||||
className={'rounded-lg'}
|
||||
size={'large'}
|
||||
placeholder={'CB-20220924-IaNr'}
|
||||
value={orderId}
|
||||
onChange={handleChangeCheckTransaction} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item shouldUpdate>
|
||||
{() => (
|
||||
<Button
|
||||
disabled={
|
||||
!form.isFieldsTouched(true) ||
|
||||
!!form.getFieldsError().filter(({errors}) => errors.length).length
|
||||
}
|
||||
block
|
||||
className={`${!form.isFieldsTouched(true) ||
|
||||
!!form.getFieldsError().filter(({errors}) => errors.length).length ? 'bg-[#919191]' : 'bg-black'}
|
||||
text-white text-xl h-12 rounded-lg`}
|
||||
onClick={onSubmit}
|
||||
>
|
||||
Cek
|
||||
</Button>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
{orderNotFound || order === undefined ? (
|
||||
<>
|
||||
<h3 className={`font-bold text-xl my-4 ${show ? 'block' : 'hidden'}`}>Status Transaksi</h3>
|
||||
|
||||
<div className={`${show ? 'block' : 'hidden'} bg-[#F7FCFC] border-2 border-[#DFDFDF] h-20 flex items-center gap-2 rounded-lg px-5 mt-2`}>
|
||||
<Image src={'/assets/icons/cariparkir.svg'} width={40} height={40}/>
|
||||
<div className={'flex flex-col'}>
|
||||
<span className={'font-semibold'}>{orderId}</span>
|
||||
<span className={'text-[#FB5060] font-semibold text-sm'}>BELUM ADA TRANSAKSI</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : order ? (
|
||||
<>
|
||||
<h3 className={`font-bold text-xl my-4 ${show ? 'block' : 'hidden'}`}>Status Transaksi</h3>
|
||||
|
||||
<div className={`${show ? 'block' : 'hidden'} bg-[#F7FCFC] border-2 border-[#DFDFDF] h-20 flex items-center gap-2 rounded-lg px-5 mt-2`}>
|
||||
<Image src={'/assets/icons/cariparkir.svg'} width={40} height={40}/>
|
||||
<div className={'flex flex-col'}>
|
||||
<span className={'font-semibold'}>{orderId}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Transaction
|
||||
show={show}
|
||||
orderData={order}
|
||||
location={location}
|
||||
/>
|
||||
</>
|
||||
) : ''}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Constraint;
|
||||
25
components/DownloadApps/index.js
Normal file
25
components/DownloadApps/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import Image from "next/image";
|
||||
|
||||
const DownloadApps = () => {
|
||||
const handleDownload = (type) => {
|
||||
if (type === 'android') {
|
||||
window.open("https://play.google.com/store/apps/details?id=id.sevadigital.cariparkir.consumer&hl=en&gl=US", "_blank");
|
||||
} else {
|
||||
window.open("https://apps.apple.com/id/app/cariparkir-consumer-app/id1327224621", "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={'m-5 text-center z-50'}>
|
||||
<h3 className={'text-lg font-bold z-10'}>Gunakan aplikasi CariParkir untuk mendapatkan harga spesial</h3>
|
||||
|
||||
<div className={'flex flex-row justify-center gap-5'}>
|
||||
<Image className={'hover:cursor-pointer z-10'} src={'/assets/images/app-store.svg'} alt={'app-store'} width={180} height={100} onClick={() => handleDownload('ios')}/>
|
||||
<Image className={'hover:cursor-pointer z-10'} src={'/assets/images/play-store.svg'} alt={'play-store'} width={180} height={100} onClick={() => handleDownload('android')}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DownloadApps;
|
||||
8
components/Layout/DefaultLayout.js
Normal file
8
components/Layout/DefaultLayout.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from "react";
|
||||
import DesktopLayout from "./DesktopLayout/DesktopLayout";
|
||||
|
||||
const DefaultLayout = (props) => {
|
||||
return <DesktopLayout {...props}/>
|
||||
}
|
||||
|
||||
export default DefaultLayout;
|
||||
29
components/Layout/DesktopLayout/DesktopLayout.js
Normal file
29
components/Layout/DesktopLayout/DesktopLayout.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from "react";
|
||||
import ParticlesLayout from "../ParticlesLayout";
|
||||
import {Layout, Image} from "antd";
|
||||
|
||||
const {Content} = Layout;
|
||||
|
||||
const DesktopLayout = ({children, isGradient = false}) => {
|
||||
console.log({isGradient})
|
||||
return <ParticlesLayout>
|
||||
<Layout
|
||||
theme={"light"}
|
||||
className={`relative max-w-2xl mx-auto ${isGradient ? 'bg-[#F5F5F5]' : 'bg-[#FFFFFF]'}`}
|
||||
hasSider={true}>
|
||||
<Content>
|
||||
<div className={'min-h-screen'}>
|
||||
<div className={'z-50'}>{children}</div>
|
||||
{isGradient && (
|
||||
<div className={'absolute bottom-0 z-0'}>
|
||||
<Image className={'z-0 -mb-[7px]'} preview={false}
|
||||
src={'/assets/backgrounds/bg-pattern.png'}/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Content>
|
||||
</Layout>
|
||||
</ParticlesLayout>
|
||||
}
|
||||
|
||||
export default DesktopLayout;
|
||||
61
components/Layout/DesktopLayout/DesktopLayoutHeader.js
Normal file
61
components/Layout/DesktopLayout/DesktopLayoutHeader.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import React, {useState} from 'react';
|
||||
import {Button, Layout, Menu, Popover, Typography} from "antd";
|
||||
import {UserOutlined} from "@ant-design/icons";
|
||||
|
||||
const {Sider, Header, Content, Footer} = Layout;
|
||||
const {Paragraph, Text} = Typography;
|
||||
|
||||
const DesktopLayoutHeader = (props) => {
|
||||
const [clicked, setClicked] = useState(false);
|
||||
|
||||
return (
|
||||
<Header className={"flex items-center justify-end"}>
|
||||
<Popover
|
||||
autoAdjustOverflow={true}
|
||||
placement="bottomRight"
|
||||
content={
|
||||
<Menu
|
||||
type={"line"}
|
||||
inlineIndent={0}
|
||||
theme="light"
|
||||
className={"bg-transparent border-r-0"}
|
||||
mode="inline"
|
||||
>
|
||||
<Menu.Item>
|
||||
<span>Profile</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
// store.authentication.logout();
|
||||
// return history.push("/login");
|
||||
}}
|
||||
>
|
||||
<span>Sign out</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
title={
|
||||
<Text>
|
||||
<span className={"font-semibold"}>info@bangun-kreatif.com</span>
|
||||
<Paragraph type={"secondary-dark"}>
|
||||
Administrator
|
||||
</Paragraph>
|
||||
</Text>
|
||||
}
|
||||
trigger="click"
|
||||
visible={clicked}
|
||||
onVisibleChange={() => setClicked(!clicked)}
|
||||
>
|
||||
<Button
|
||||
size={"default"}
|
||||
style={{}}
|
||||
icon={
|
||||
<UserOutlined className={"text-sm"}/>
|
||||
}
|
||||
/>
|
||||
</Popover>
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
export default DesktopLayoutHeader;
|
||||
48
components/Layout/DesktopLayout/DesktopLayoutMenu.js
Normal file
48
components/Layout/DesktopLayout/DesktopLayoutMenu.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import {Menu} from "antd";
|
||||
import {CalendarOutlined, HomeOutlined, SettingOutlined} from "@ant-design/icons";
|
||||
import Link from 'next/link';
|
||||
|
||||
const DesktopLayoutMenu = (props) => (
|
||||
<Menu
|
||||
defaultOpenKeys={["sub4"]}
|
||||
theme="light"
|
||||
className={"bg-transparent border-r-0 ml-6"}
|
||||
onClick={({keyPath, item}) => {
|
||||
// props.closeLeftDrawer();
|
||||
}}
|
||||
mode="inline"
|
||||
selectedKeys={[]}
|
||||
onSelect={({setKeys, item, selectedKeys}) => {
|
||||
}}
|
||||
overflowedIndicator={0}
|
||||
forceSubMenuRender={true}
|
||||
>
|
||||
<Menu.Item key="home">
|
||||
<Link href={"/home"}>
|
||||
<a>
|
||||
<HomeOutlined/>
|
||||
<span>Home</span>
|
||||
</a>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="about">
|
||||
<Link href={"/about"}>
|
||||
<a>
|
||||
<CalendarOutlined/>
|
||||
<span>About</span>
|
||||
</a>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="setting">
|
||||
<Link href={"/setting"}>
|
||||
<a>
|
||||
<SettingOutlined/>
|
||||
<span>Setting</span>
|
||||
</a>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
export default DesktopLayoutMenu;
|
||||
18
components/Layout/ParticlesLayout.js
Normal file
18
components/Layout/ParticlesLayout.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const ParticlesBg = dynamic(() => import("particles-bg"), { ssr: false });
|
||||
|
||||
const ParticlesLayout = ({children}) => {
|
||||
if(typeof window === "undefined") {
|
||||
return <div>
|
||||
{children}
|
||||
</div>;
|
||||
}
|
||||
|
||||
return <div>
|
||||
{children}
|
||||
<ParticlesBg color={"#ababab"} num={20} type={"cobweb"} bg={true} />
|
||||
</div>
|
||||
}
|
||||
|
||||
export default ParticlesLayout;
|
||||
26
components/Location/index.js
Normal file
26
components/Location/index.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import Image from "next/image";
|
||||
import {Divider} from "antd";
|
||||
|
||||
const Location = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className={'flex flex-col items-center gap-4'}>
|
||||
<Image src={'/assets/images/location.svg'} width={80} height={80}/>
|
||||
|
||||
<div className={'text-center'}>
|
||||
<h1 className={'font-bold'}>LOCKEY Lippo Mall Kemang</h1>
|
||||
<p className={'text-sm text-[#B7BAC2]'}>Jl. Pangeran Antasari No.36, Bangka, Kec. Mampang Prpt.,
|
||||
Kota, Daerah
|
||||
Khusus Ibukota
|
||||
Jakarta
|
||||
12150</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider dashed className={'my-2 border-[#c1c1c1]'} style={{width: '2px 0 0'}}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Location;
|
||||
37
components/StoreProvider.js
Normal file
37
components/StoreProvider.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import {createContext, useContext} from 'react';
|
||||
import {Store} from "../store/store";
|
||||
|
||||
let store;
|
||||
|
||||
export const StoreContext = createContext();
|
||||
|
||||
export function useStore() {
|
||||
const context = useContext(StoreContext)
|
||||
if (context === undefined) {
|
||||
throw new Error('useStore must be used within StoreProvider')
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
export function StoreProvider({children, initialState: initialData}) {
|
||||
const store = initializeStore(initialData);
|
||||
|
||||
return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
|
||||
}
|
||||
|
||||
function initializeStore(initialData = null) {
|
||||
const _store = store ?? new Store()
|
||||
|
||||
// If your page has Next.js data fetching methods that use a Mobx store, it will
|
||||
// get hydrated here, check `pages/ssg.js` and `pages/ssr.js` for more details
|
||||
if (initialData) {
|
||||
_store.hydrate(initialData)
|
||||
}
|
||||
// For SSG and SSR always create a new store
|
||||
if (typeof window === 'undefined') return _store
|
||||
// Create the store once in the client
|
||||
if (!store) store = _store
|
||||
|
||||
return _store
|
||||
}
|
||||
70
components/Transaction/index.js
Normal file
70
components/Transaction/index.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import React, {useEffect, useRef, useState} from 'react';
|
||||
import {Badge, Divider, Tag} from "antd";
|
||||
import Image from "next/image";
|
||||
import {DownCircleOutlined} from "@ant-design/icons";
|
||||
import autoAnimate from "@formkit/auto-animate";
|
||||
import { format } from "date-fns";
|
||||
|
||||
const Transaction = ({show, orderData, location}) => {
|
||||
const [collapse, setCollapse] = useState(false);
|
||||
const parentRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (parentRef.current) {
|
||||
autoAnimate(parentRef.current);
|
||||
}
|
||||
}, [parentRef])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={`${show ? 'block' : 'hidden'} bg-white mt-3 border-[#E5E9F2] shadow rounded-lg`} ref={parentRef}>
|
||||
<div className={'flex justify-between items-center p-3'}>
|
||||
<div className={'flex flex-col'}>
|
||||
<span className={'font-semibold'}>{orderData?.order_id}</span>
|
||||
<span className={'text-[#B7BAC2]'}>{format(new Date(orderData?.date_modified), 'dd/MM/yyyy mm:ss')}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Tag color={'warning'} className={'p-2 rounded'}>{orderData?.status}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!collapse && <Divider className={'m-0'}/>}
|
||||
|
||||
{collapse && (
|
||||
<>
|
||||
<div className={'flex justify-between gap-2 bg-slate-50 border-2 border-x'}>
|
||||
<div className={'flex flex-col pl-3 py-3 gap-2'}>
|
||||
<div className={'flex flex-col'}>
|
||||
<span className={'font-semibold'}>Lokasi</span>
|
||||
<span className={'text-[#515257]'}>{location?.data?.[0]?.name}</span>
|
||||
</div>
|
||||
<div className={'flex flex-col'}>
|
||||
<span className={'font-semibold'}>Total Harga</span>
|
||||
<span className={'text-[#FF6103]'}>Rp.{orderData?.total}</span>
|
||||
</div>
|
||||
{orderData?.payment_method?.toLowerCase() == "gopay" && (
|
||||
<div>
|
||||
<Image src={'/assets/images/gopay.svg'} width={81} height={17}/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={'flex flex-col items-center w-44 pr-3 py-3'}>
|
||||
<span className={'font-semibold'}>Status Parkir</span>
|
||||
<Badge color={'#FF9400'} text={<span className={'text-[#FF9400]'}>In-Location</span>}/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className={'flex items-center gap-2 hover:cursor-pointer p-3'} onClick={() => setCollapse(!collapse)}>
|
||||
<span className={'text-[#96969a] text-sm'}>Lihat Detail</span>
|
||||
<DownCircleOutlined rotate={collapse ? 180 : 0} className={'text-[#96969a]'}/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Transaction;
|
||||
Reference in New Issue
Block a user