Skip to content
This repository has been archived by the owner on Dec 31, 2023. It is now read-only.

Commit

Permalink
Merge pull request #182 from HutechCJ/feat-api/form-implement
Browse files Browse the repository at this point in the history
Feat api/form implement
  • Loading branch information
Slimaeus committed Sep 13, 2023
2 parents f2da260 + b507433 commit b45832f
Show file tree
Hide file tree
Showing 11 changed files with 414 additions and 40 deletions.
15 changes: 7 additions & 8 deletions apps/cms/@types/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
type AxiosRequestConfig = import('axios').AxiosRequestConfig;

interface IAuthToken {
access_token?: string;
refresh_token?: string;
access_token_expires_in?: number;
access_token_expires_at?: number;
declare global {
namespace NodeJS {
interface ProcessEnv {
GOOGLE_MAP_API_KEY: string
}
}
}

type Nullable<T> = T | null;
export {}
10 changes: 10 additions & 0 deletions apps/cms/@types/util.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type AxiosRequestConfig = import('axios').AxiosRequestConfig

interface IAuthToken {
access_token?: string
refresh_token?: string
access_token_expires_in?: number
access_token_expires_at?: number
}

type Nullable<T> = T | null
234 changes: 208 additions & 26 deletions apps/cms/app/(dash)/orders/[orderId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,213 @@
'use client';
/* eslint-disable react/no-children-prop */
'use client'

import { OrderStatus } from '@/features/order/order.types';
import useGetOrder from '@/features/order/useGetOrder';
import { Box, Stack, Button } from '@mui/material';
import React from 'react';
import { OrderStatus } from '@/features/order/order.types'
import useGetOrder from '@/features/order/useGetOrder'
import {
Box,
Stack,
Button,
Input,
InputLabel,
FormControl,
Container,
Paper,
Typography,
Stepper,
} from '@mui/material'
import LocalShippingIcon from '@mui/icons-material/LocalShipping'
import { useForm } from '@tanstack/react-form'
import React from 'react'
import { GoogleMap, useJsApiLoader } from '@react-google-maps/api'
import _ from 'lodash'
import useGetOrderHubsPath from '@/features/order/useGetOrderHubsPath'

const containerStyle = {
width: '100%',
height: '400px',
}

const center = {
lat: -3.745,
lng: -38.523,
}

function Order({ params }: { params: { orderId: string } }) {
const { data: orderApiRes, isLoading, isError } = useGetOrder(params.orderId);

if (isLoading) {
return 'Loading...';
}

if (!orderApiRes || isError) {
return 'There is an error occurred!';
}

return (
<Box>
<Stack direction="row" spacing={1} sx={{ mb: 1 }}>
<Button>Update</Button>
<Button>Delete</Button>
</Stack>
<div>{orderApiRes.data.id}</div>
<div>Status: {OrderStatus[orderApiRes.data.status]}</div>
</Box>
);
const {
data: orderApiRes,
isLoading: orderLoading,
isError: orderError,
} = useGetOrder(params.orderId)

const {
data: orderHubsPathApiRes,
isLoading: hubsPathLoading,
isError: hubsPathError,
} = useGetOrderHubsPath(params.orderId)

const form = useForm({
// Memoize your default values to prevent re-renders
defaultValues: {
...orderApiRes?.data,
},
onSubmit: async (values) => {
// Do something with form data
console.log(values)
},
})

const { isLoaded } = useJsApiLoader({
id: 'google-map-script',
googleMapsApiKey: '',
})

const [map, setMap] = React.useState(null)

const onLoad = React.useCallback(function callback(map: any) {
// This is just an example of getting and using the map instance!!! don't just blindly copy!
const bounds = new window.google.maps.LatLngBounds(center)
map.fitBounds(bounds)

setMap(map)
}, [])

const onUnmount = React.useCallback(function callback(map: any) {
setMap(null)
}, [])

if (orderLoading) {
return 'Loading...'
}

if (!orderApiRes || orderError) {
return 'There is an error occurred!'
}

return (
<Container maxWidth="xl" sx={{ '& > :not(style)': { m: 2 } }}>
{
// isLoaded && (
// <GoogleMap
// mapContainerStyle={containerStyle}
// center={center}
// zoom={10}
// onLoad={onLoad}
// onUnmount={onUnmount}
// >
// {/* Child components, such as markers, info windows, etc. */}
// <Box
// sx={{
// zIndex: 99,
// }}
// >
// <Typography variant="h1" component="h1">
// Hello
// </Typography>
// </Box>
// </GoogleMap>
// )
}
<Box sx={{
width: "100%"
}}>
{orderHubsPathApiRes && (
<iframe
width="100%"
height="500"
frameBorder="0"
style={{
border: 0,
}}
allowFullScreen
referrerPolicy="no-referrer-when-downgrade"
src={`https://www.google.com/maps/embed/v1/directions?${new URLSearchParams(
{
region: 'VN',
key: `AIzaSyDAW0v16XSZI3GdNte36gFHDynsed4-cz0`,
origin: `${
orderHubsPathApiRes.data.items[0].location
?.latitude ?? 0
},${
orderHubsPathApiRes.data.items[0].location
?.longitude ?? 0
}`,
destination: `${
orderHubsPathApiRes.data.items[1].location
?.latitude ?? 0
},${
orderHubsPathApiRes.data.items[1].location
?.longitude ?? 0
}`,
}
)}`}
></iframe>
)}
</Box>
<form.Provider>
<Paper
sx={{
paddingX: 4,
paddingY: 2,
width: '100%',
}}
>
{Object.keys(orderApiRes.data).map((k) => (
<Box
key={`formField_${k}`}
sx={{
marginY: 2,
}}
>
<form.Field
name={k}
onChange={(value: any) =>
!value
? 'A first name is required'
: value.length < 3
? 'First name must be at least 3 characters'
: undefined
}
onChangeAsyncDebounceMs={500}
onChangeAsync={async (value: any) => {
await new Promise((resolve) =>
setTimeout(resolve, 1000)
)
return (
value.includes('error') &&
'No "error" allowed in first name'
)
}}
children={(field) => {
return (
<FormControl fullWidth>
<InputLabel htmlFor={field.name}>
{_.startCase(field.name)}
</InputLabel>
<Input
name={field.name}
value={field.state.value as any}
onBlur={field.handleBlur}
onChange={(e) =>
field.handleChange(
e.target.value
)
}
/>
{/* <FieldInfo field={field} /> */}
</FormControl>
)
}}
/>
</Box>
))}
</Paper>
<Stack direction="row" spacing={1} sx={{ mb: 1 }}>
<Button>Update</Button>
<Button>Delete</Button>
</Stack>
</form.Provider>
</Container>
)
}

export default Order;
export default Order
12 changes: 12 additions & 0 deletions apps/cms/app/api/maps/directions/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
request.nextUrl.searchParams.append('key', process.env.GOOGLE_MAP_API_KEY)
console.log(request.nextUrl.searchParams)
const url = new URL(
`https://www.google.com/maps/embed/v1/directions?${request.nextUrl.searchParams}`
)
const res = await fetch(url)

return res
}
6 changes: 3 additions & 3 deletions apps/cms/common/utils/string.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export function getPagingQueryString(options: Partial<PagingOptions>): string {
return `?${Object.entries(options)
.map((value) => `${value[0]}=${value[1]}`)
.join('&')}`;
return `?${Object.entries(options)
.map((value) => `${value[0]}=${value[1]}`)
.join('&')}`
}
2 changes: 1 addition & 1 deletion apps/cms/features/example/example.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ExampleApiService extends HttpService {
}

updateExample(id: string, data: any) {
return this.put<Example>(`/examples/${id}`, data);
return this.put(`/examples/${id}`, data);
}

deleteExample(id: string) {
Expand Down
5 changes: 5 additions & 0 deletions apps/cms/features/order/order.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { getPagingQueryString } from '@/common/utils/string';
import { Order } from './order.types';
import HttpService from '@/common/services/http.service';
import { Hub } from '../hub/hub.types';

class OrderApiService extends HttpService {
getOrders(options?: Partial<PagingOptions>) {
Expand All @@ -13,6 +14,10 @@ class OrderApiService extends HttpService {
getOrderById(id: string) {
return this.get<Order>(`/orders/${id}`);
}

getOrderHubPathById(id: string) {
return this.get<Paging<Hub>>(`/orders/${id}/hubs/path`);
}
}

const orderApi = new OrderApiService();
Expand Down
13 changes: 13 additions & 0 deletions apps/cms/features/order/useGetOrderHubsPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client';
import { useQuery } from '@tanstack/react-query';
import orderApi from './order.service';

const useGetOrderHubsPath = (id: string) => {
const queryData = useQuery([`users/get/${id}/hubs/path`], {
queryFn: () => orderApi.getOrderHubPathById(id),
keepPreviousData: true,
});

return queryData;
};
export default useGetOrderHubsPath;
4 changes: 2 additions & 2 deletions apps/cms/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ const nextConfig = {
},
{
source: '/api-test/:path*',
destination: 'https://profio-sv1.azurewebsites.net/api/v1/:path*',
destination: 'https://profioapp.azurewebsites.net/api/v1/:path*',
},
{
source: '/api-dev/:path*',
destination: 'https://profio-sv1.azurewebsites.net/api/v1/:path*',
destination: 'https://profioapp.azurewebsites.net/api/v1/:path*',
},
];
},
Expand Down
Loading

0 comments on commit b45832f

Please sign in to comment.