5.xx Thực hành search đã nhận diện được dữ liệu (ok)
Previous5.x Giao diện thực hành search (ok)Next5.2 Next.js Building a Car Trader App #5- Pagination with filters for the list of cars
Last updated
Was this helpful?
Last updated
Was this helpful?
C:\Users\Administrator\Desktop\pro\pages\index.tsx
import { Button, Paper, Select, MenuItem, FormControl, InputLabel, makeStyles, Grid, createStyles, SelectProps } from '@material-ui/core';
import { Field, Form, Formik, FormikProps } from 'formik';
import { GetServerSideProps } from 'next';
import Make from '../interface/Make';
import Model from '../interface/Model';
import getMakes from './database/getMakes';
import getModels from './database/getModels';
import getAsString from '../getAsString';
import { useEffect, useState } from 'react';
import router, { useRouter } from 'next/router';
import useSWR from 'swr';
const useStyles = makeStyles((theme) => createStyles({
paper: {
margin: 'auto',
maxWidth: 500,
padding: theme.spacing(3),
}
}));
export interface SearchProps {
makes: Make[];
models: Model[];
singleColumn?: boolean;
}
const prices = [500, 1000, 5000, 15000, 25000, 50000, 250000];
export interface ModelSelectProps extends SelectProps {
name: string;
models: Model[];
make: string;
initialMake: string;
}
export default function Search({ makes, models, singleColumn }: SearchProps) {
const classes = useStyles();
const { query } = useRouter();
const [initialValues] = useState({
make: getAsString(query.make) || 'all',
model: getAsString(query.model) || 'all',
minPrice: getAsString(query.minPrice) || 'all',
maxPrice: getAsString(query.maxPrice) || 'all',
});
const ModelSelect = ({ initialMake, models, make, ...props }: ModelSelectProps) => {
const { data: newModels } = useSWR < Model[] > ('/api/models?make=' + make, {
dedupingInterval: 60000
});
if (!newModels) return <div>loading...</div>;
return (
<Field as={Select} labelId="model" label="Model" name="model">
<MenuItem value='all'>Model</MenuItem>
{
newModels.map((model)=>(
<MenuItem value={model.model} key={model.model}>{`${model.model} (${model.count})`}</MenuItem>
))
}
</Field>
)
}
return (
<Formik
initialValues={initialValues}
onSubmit={(values) => {
router.push(
{
pathname: '/cars',
query: { ...values, page: 1 },
},
undefined,
{ shallow: true }
);
}}
>
{({values}) => (
<Form className={classes.paper}>
<Paper>
<Grid container spacing={2}>
<Grid item xs={6}>
<FormControl fullWidth variant='outlined'>
<InputLabel id="make">Make</InputLabel>
<Field as={Select} labelId="make" label="Make" name="make">
{
makes?.map((make) => {
return <MenuItem key={make.make} value={make.make}>{make.make + " (" + make.count + " )"}</MenuItem>
})
}
</Field>
</FormControl>
</Grid>
<Grid item xs={6}>
<ModelSelect initialMake={initialValues.make} make={values.make} name="model" models={models} />
</Grid>
<Grid item xs={6}>
<FormControl fullWidth variant='outlined'>
<InputLabel id="minPrice">Min Price</InputLabel>
<Field as={Select} labelId="minPrice" label="Min Price" name="minPrice">
{
prices?.map(price => {
return <MenuItem key={price} value={price}>{price}</MenuItem>
})
}
</Field>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl fullWidth variant='outlined'>
<InputLabel id="maxPrice">Max Price</InputLabel>
<Field as={Select} labelId="maxPrice" label="Max Price" name="maxPrice">
{
prices?.map(price => {
return <MenuItem key={price} value={price}>{price}</MenuItem>
})
}
</Field>
</FormControl>
</Grid>
<Grid item xs={12}>
<Button
type="submit"
variant="contained"
color="primary"
fullWidth
>
Search
</Button>
</Grid>
</Grid>
</Paper>
</Form>
)}
</Formik>
)
}
export const getServerSideProps: GetServerSideProps<SearchProps> = async (ctx) => {
const make = getAsString(ctx.query.make);
const [makes, models] = await Promise.all([getMakes(), getModels(make)]);
return { props: { makes, models } };
}
C:\Users\Administrator\Desktop\pro\pages\cars.tsx
import { Grid, Card, CardHeader, Avatar, IconButton, CardMedia, Typography, makeStyles } from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import CardContent from '@material-ui/core/CardContent';
import deepEqual from 'fast-deep-equal';
import { GetServerSideProps } from 'next';
import { useRouter } from 'next/router';
import { stringify } from 'querystring';
import { useState } from 'react';
import useSWR from 'swr';
import Search from '.';
import CarModel from '../interface/Car';
import Link from 'next/link';
import Pagination from '@material-ui/lab/Pagination';
import Make from '../interface/Make';
import Model from '../interface/Model';
import getMakes from './database/getMakes';
import getModels from './database/getModels';
import getPaginatedCars from './database/getPaginatedCars';
import getAsString from '../getAsString';
export interface CarsListProps {
makes: Make[];
models: Model[];
cars: CarModel[];
totalPages: number;
}
const useStyles = makeStyles((theme) => ({
media: {
height: 0,
paddingTop: '56.25%', // 16:9
},
expand: {
transform: 'rotate(0deg)',
marginLeft: 'auto',
transition: theme.transitions.create('transform', {
duration: theme.transitions.duration.shortest,
}),
},
expandOpen: {
transform: 'rotate(180deg)',
},
avatar: {
backgroundColor: 'red',
},
achorTag: {
textDecoration: 'none'
}
}));
export default function CarsList({makes, models, cars, totalPages}: CarsListProps) {
const classes = useStyles();
return (
<Grid container spacing={3}>
<Grid item xs={12} sm={5} md={3} lg={2}>
<Search singleColumn makes={makes} models={models} />
</Grid>
<Grid container item xs={12} sm={7} md={9} lg={10} spacing={3}>
<Grid item xs={12}>
<Pagination count={10} />
</Grid>
<Grid item xs={12} sm={6}>
<Link
href="#"
as={null}
>
<a className={classes.achorTag}>
<Card>
<CardHeader
avatar={
<Avatar aria-label="recipe" className={classes.avatar}>
R
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={'car.mode'}
subheader={5}
/>
<CardMedia
className={classes.media}
image='photos/cars/volkswagen-eos-2008-14700.jpg'
title={'aaaaaaaaaa'}
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
{'car.details'}
</Typography>
</CardContent>
</Card>
</a>
</Link>
</Grid>
<Grid item xs={12}>
<Pagination count={10} />
</Grid>
</Grid>
</Grid>
);
}
export const getServerSideProps: GetServerSideProps < CarsListProps > = async (ctx) => {
const make = getAsString(ctx.query.make);
const [makes, models, pagination] = await Promise.all([getMakes(),getModels(make),getPaginatedCars(ctx.query)]);
return {
props: {makes, models, cars: pagination.cars, totalPages: pagination.totalPages},
};
};