学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Django3.2 | 39 | QRオーダーシステムの構築 | 提供完了

[38 | 受注表示] << [ホーム] >> [40 | 飲食店モデルのアップデート]

「qrmenu_react/src/apis.js」ファイルに記述を追加します。


記述追加 【QRMenu/qrmenu_react/src/apis.js】123行目

import { toast } from 'react-toastify';

function request(path,  {data = null, token = null, method = "GET" }) {
  return fetch(path, {
    method,
    headers: {
      Authorization: token ? `Token ${token}` : "",
      "Content-Type": "application/json",
    },
    body: method !=="GET" && method !== "DELETE" ? JSON.stringify(data): null,
  })
    .then((response) => {

      //もし成功したら
      if (response.ok) {
        if(method === "DELETE") {
          return true;
        }
        //toast.success("ログイン成功");
        return response.json();
      }
      //失敗
      return response.json().then((json) => {
          //JSONエラー
          if (response.status === 400) {
            //toast.error("氏名もしくはパスワードに間違いがあります。");
            const errors = Object.keys(json).map(
                (k) => `${(json[k].join(" "))}`
            );
            throw new Error(errors.join(" "));
          }
          throw new Error(JSON.stringify(json));
        })
        .catch((e) => {
          if (e.name === "SyntaxError") {
            throw new Error(response.statusText);
          }
          throw new Error(e);
        })
    })

    .catch((e) => {
      //全エラー
      toast(e.message, { type: "error" });
    })
}

export function signIn(username, password) {
  return request("/auth/token/login/", {
    data: {username, password},
    method: "POST",
  })
}

export function register(username, password) {
  return request("/auth/users/", {
    data: {username, password},
    method: "POST",
  })
}

export function fetchPlaces(token) {
  return request("/api/places/", {token});
}

export function addPlace(data, token) {
  return request("/api/places/", {data, token, method: "POST" });
}

export function uploadImage(image) {
  const formData = new FormData();
  formData.append("file", image);
  formData.append("upload_preset", "qrmenu_photos");

  return fetch("https://api.cloudinary.com/v1_1/dov57gocw/image/upload", {
    method: "POST",
    body: formData,
  }).then((response) => {
    return response.json();
  });
}

export function fetchPlace(id, token) {
  return request(`/api/places/${id}`, { token });
}

export function addCategory(data, token) {
  return request("/api/categories/", {data, token, method: "POST"});
}

export function addMenuItems(data, token) {
  return request("/api/menu_items/", {data, token, method: "POST"});
}

export function updateMenuItem(id, data, token) {
  return request(`/api/menu_items/${id}`, { data, token, method: "PATCH"});
}

export function removePlace(id, token) {
  return request(`/api/places/${id}`, {token, method: "DELETE"});
}

export function removeCategory(id, token) {
  return request(`/api/categories/${id}`, {token, method: "DELETE"});
}

export function removeMenuItem(id, token) {
  return request(`/api/menu_items/${id}`, {token, method: "DELETE"});
}

export function updatePlace(id, data, token) {
  return request(`/api/places/${id}`, { data, token, method: "PATCH"})
}

export function createPaymentIntent(data, token) {
  return request("/api/create_payment_intent/", {data, token, method: "POST"});
}

export function fetchOrders(placeId, token) {
  return request(`/api/orders/?place=${placeId}`, { token });
}

export function completeOrder(orderId, data, token) {
  return request(`/api/orders/${orderId}`, {data, token, method: "PATCH"});
}



「src/pages/Orders.js」ファイルを編集します。


記述編集 【Desktop/QRMenu/qrmenu_react/src/pages/Orders.js】

import { IoMdArrowBack } from 'react-icons/io';
import { Row, Col, Button } from 'react-bootstrap';
import { useParams, useHistory } from 'react-router-dom';
import React, { useState, useEffect, useContext } from 'react';

import { fetchOrders, completeOrder } from '../apis';
import AuthContext from '../contexts/AuthContext';
import MainLayout from '../layouts/MainLayout';
import Order from '../components/Order';

const Orders = () => {
    const [orders, setOrders] = useState([]);
    const params = useParams();
    const history = useHistory();
    const auth = useContext(AuthContext);

    const onBack = () => history.push(`/places/${params.id}`);

    const onFetchOrders = async () => {
        const json = await fetchOrders(params.id, auth.token);
        if(json) {
            console.log(json);
            setOrders(json);
        }
    }

    const onCompleteOrder = async (orderId) => {
        const json = await completeOrder(orderId, { status: "completed"}, auth.token );
        if(json) {
            onFetchOrders();
        }
    }

    useEffect(() => {
        onFetchOrders();
        const interval = setInterval(() => {
            onFetchOrders();
        }, 5000);
        return () => clearInterval(interval);
    }, []);

    return (
        <MainLayout>
            <div className="d-flex align-items-center mb-4">
                <Button variant="link" onClick={onBack}>
                    <IoMdArrowBack size={25} color="black" />
                </Button>
                <h3 className="mb-0 ml-2 mr-2">受注リスト</h3>
            </div>

            <Row className="justify-content-center">
                {orders 
                ?.filter((order) => order.status === "processing")
                ?.map((order) => (
                    <Col key={order.id} lg={8}>
                        <Order order={order} />
                    </Col>
                ))}
            </Row>
        </MainLayout>
    );
}

export default Orders;



OrderのStatusを「Processing」から「Completed」に変更すると、受注リストから消えるようになりました。

StatusをCompletedに変更
StatusをCompletedに変更


受注リストから消える
受注リストから消える



「src/pages/Orders.js」ファイルに記述を追加します。


記述追加 【Desktop/QRMenu/qrmenu_react/src/pages/Orders.js】56行目

import { IoMdArrowBack } from 'react-icons/io';
import { Row, Col, Button } from 'react-bootstrap';
import { useParams, useHistory } from 'react-router-dom';
import React, { useState, useEffect, useContext } from 'react';

import { fetchOrders, completeOrder } from '../apis';
import AuthContext from '../contexts/AuthContext';
import MainLayout from '../layouts/MainLayout';
import Order from '../components/Order';

const Orders = () => {
    const [orders, setOrders] = useState([]);
    const params = useParams();
    const history = useHistory();
    const auth = useContext(AuthContext);

    const onBack = () => history.push(`/places/${params.id}`);

    const onFetchOrders = async () => {
        const json = await fetchOrders(params.id, auth.token);
        if(json) {
            console.log(json);
            setOrders(json);
        }
    }

    const onCompleteOrder = async (orderId) => {
        const json = await completeOrder(orderId, { status: "completed"}, auth.token );
        if(json) {
            onFetchOrders();
        }
    }

    useEffect(() => {
        onFetchOrders();
        const interval = setInterval(() => {
            onFetchOrders();
        }, 5000);
        return () => clearInterval(interval);
    }, []);

    return (
        <MainLayout>
            <div className="d-flex align-items-center mb-4">
                <Button variant="link" onClick={onBack}>
                    <IoMdArrowBack size={25} color="black" />
                </Button>
                <h3 className="mb-0 ml-2 mr-2">受注リスト</h3>
            </div>

            <Row className="justify-content-center">
                {orders 
                ?.filter((order) => order.status === "processing")
                ?.map((order) => (
                    <Col key={order.id} lg={8}>
                        <Order order={order} onComplete={() => onCompleteOrder(order.id)} />
                    </Col>
                ))}
            </Row>
        </MainLayout>
    );
}

export default Orders;



「src/components/Order.js」ファイルの記述を編集します。


記述編集 【Desktop/QRMenu/qrmenu_react/src/components/Order.js】

import { Card, Button } from 'react-bootstrap';
import React from 'react';
import { FaTimes } from 'react-icons/fa';
import styled from 'styled-components';

const ItemQuantity = styled.span`

    border-radius: 50%;
    box-shadow: 1px 1px 8px rgba(0,0,0,0.2);
    width: 30px;
    height: 30px;
    padding: 8px 9px 8px 9px;

    }
`;

const Order = ({ order, onComplete }) => {

    return (
        <Card className="mb-3">
            <Card.Header className="d-flex justify-content-between">
                <span>{`オーダーNo.${order.id} [ 客席#${order.table} ]`}</span>
                <span><b>{order.amount.toLocaleString()}円</b></span>
            </Card.Header>

        <Card.Body className="d-flex justify-content-between">
            <div>
                {JSON.parse(order.detail).map((item) => (
                    <div className="mb-2">
                        <ItemQuantity><FaTimes size={10} color="black" />{item.quantity}</ItemQuantity>
                        <img 
                            src={item.image} 
                            width={30}
                            height={30}
                            style={{ borderRadius: 3, margin: "0 10px"}} 
                        />
                        <span>{item.name}</span>
                    </div>
                ))}
            </div>

            <div>
                {onComplete ? (
                        <Button variant="standard" size="md" onClick={onComplete}>
                            完了
                        </Button>
                    ) : null }
            </div>
        </Card.Body>
    </Card>    
    )
}

export default Order;



完了ボタンを押すとStatusがCompletedになり、受注リストから消えるようになりました。

完了ボタンでCompleted
完了ボタンでCompleted



↓↓クリックして頂けると励みになります。


[38 | 受注表示] << [ホーム] >> [40 | 飲食店モデルのアップデート]