5.9 Next.js Building a Car Trader App #5- Pagination with filters for the list of cars

Làm một dữ liệu fixed cho CarCard && dữ liệu động :))

Dữ liệu fixed :)

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 './api/Car';
import  CarCard  from '../components/CarCard';
import Link from 'next/link';
import { getMakes, Make } from './database/getMakes';
import { getModels, Model } from './database/getModels';
import  getPaginatedCars  from './database/getPaginatedCars';
import  getAsString  from '../getAsString';
import CarPagination  from '../components/CarPagination';
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();
  const { query } = useRouter();
  const [serverQuery] = useState(query);
  const { data } = useSWR('/api/cars?' + stringify(query), {
    dedupingInterval: 15000,
    initialData: deepEqual(query, serverQuery) ? { cars, totalPages } : undefined
  });
  const car = {
    id: 4,
    make: 'BMW',
    model: 'x1',
    year: 2012,
    fuelType: 'Diesel',
    kilometers: 565656,
    details: 'Lorem ipsum dolor sit amet',
    price: 24000,
    photoUrl: '/photos/cars/bmw-x1-2012-24999.jpg'
  };
  return (
    <Grid container spacing={3}>
      <Grid item xs={12} sm={5} md={3} lg={2}>
        <Search makes={makes} models={models} />
      </Grid>
      <Grid container item xs={12} sm={7} md={9} lg={10} spacing={3}>
        <Grid item xs={12}>
          <CarPagination totalPages={6} />
        </Grid>
        <Grid  item xs={12} sm={6}>
          <CarCard car={car} />
        </Grid>
        <Grid item xs={12}>
          <CarPagination totalPages={6} />
        </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}
  }
}

C:\Users\Administrator\Desktop\pro\components\CarCard.tsx

import Avatar from '@material-ui/core/Avatar';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import CardHeader from '@material-ui/core/CardHeader';
import CardMedia from '@material-ui/core/CardMedia';
import { red } from '@material-ui/core/colors';
import IconButton from '@material-ui/core/IconButton';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import Link from 'next/link';
import React from 'react';
import { CarModel } from '../../api/Car';
export interface CarCardProps {
  car: CarModel;
}
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[500],
  },
  achorTag: {
      textDecoration: 'none'
  }
}));
export default  function CarCard({ car }: CarCardProps) {
  const classes = useStyles();
  return (
    <Link
      href="/car/[make]/[brand]/[id]"
      as={`/car/${car.make}/${car.model}/${car.id}`}
    >
      <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.make + ' ' + car.model}
            subheader={`£${car.price}`}
          />
          <CardMedia
            className={classes.media}
            image={car.photoUrl}
            title={car.make + ' ' + car.model}
          />
          <CardContent>
            <Typography variant="body2" color="textSecondary" component="p">
              {car.details}
            </Typography>
          </CardContent>
        </Card>
      </a>
    </Link>
  );
}

Dữ liệu dynamic

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 './api/Car';
import  CarCard  from '../components/CarCard';
import Link from 'next/link';
import { getMakes, Make } from './database/getMakes';
import { getModels, Model } from './database/getModels';
import  getPaginatedCars  from './database/getPaginatedCars';
import  getAsString  from '../getAsString';
import CarPagination  from '../components/CarPagination';
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();
  const { query } = useRouter();
  const [serverQuery] = useState(query);
  const { data } = useSWR('/api/cars?' + stringify(query), {
    dedupingInterval: 15000,
    initialData: deepEqual(query, serverQuery) ? { cars, totalPages } : undefined
  });
  const car = {
    id: 4,
    make: 'BMW',
    model: 'x1',
    year: 2012,
    fuelType: 'Diesel',
    kilometers: 565656,
    details: 'Lorem ipsum dolor sit amet',
    price: 24000,
    photoUrl: '/photos/cars/bmw-x1-2012-24999.jpg'
  };
  return (
    <Grid container spacing={3}>
      <Grid item xs={12} sm={5} md={3} lg={2}>
        <Search makes={makes} models={models} />
      </Grid>
      <Grid container item xs={12} sm={7} md={9} lg={10} spacing={3}>
        <Grid item xs={12}>
          <CarPagination totalPages={6} />
        </Grid>
        {(data?.cars || []).map((car) => (
          <Grid key={car.id} item xs={12} sm={6}>
            <CarCard car={car} />
          </Grid>
        ))}
        <Grid item xs={12}>
          <CarPagination totalPages={6} />
        </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}
  }
}

Dữ liệu dynamic effect

Last updated

Was this helpful?