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

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

Django3.2 | 38 | QRオーダーシステムの構築 | 受注表示

[37 | 受注データ実装] << [ホーム] >> [39 | 提供完了]

オーダーを飲食店側が把握できるよう実装します。


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


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

import { IoMdArrowBack } from 'react-icons/io';
import { AiOutlineDelete, AiOutlineQrcode, AioutlineQrcode } from 'react-icons/ai';
import { RiFileList3Line } from 'react-icons/ri';
import { Row, Col, Button, Modal } from 'react-bootstrap';
import { useParams, useHistory } from 'react-router-dom';
import React, { useEffect, useState, useContext } from 'react';
import styled from 'styled-components';

import {
     fetchPlace, 
     removePlace, 
     removeCategory, 
     removeMenuItem, 
     updatePlace 
    } 
    from '../apis';

import AuthContext from '../contexts/AuthContext';
import MainLayout from '../layouts/MainLayout';
import MenuItemForm from '../containers/MenuItemForm';
import MenuItem from '../components/MenuItem';
import QRCodeModal from '../components/QRCodeModal';

const Panel = styled.div`
    background-color: white;
    padding: 20px;
    border-radius: 5px;
    box-shadow: 1px 1px 10px rgba(0,0,0,0.05);
`;


const Place = () => {
    const [place, setPlace] = useState({});
    const [menuItemFormShow, setMenuItemFormShow] = useState(false);
    const [selectedItem, setSelectedItem] = useState(null);
    const [qrCode, setQrCode] = useState(false);

    const showModal = () => setMenuItemFormShow(true);
    const hideModal = () => setMenuItemFormShow(false);

    const showQRModal = () => setQrCode(true);
    const hideQRModal = () => setQrCode(false);

    const auth = useContext(AuthContext);
    const params = useParams();
    const history = useHistory();

    const onBack = () => history.push("/places");

    const onFetchPlace = async () => {
        const json = await fetchPlace(params.id, auth.token);
        if(json) {
            setPlace(json);
        }
    };

    const onRemovePlace = () => {
        const c = window.confirm("本当に削除してもよろしいですか?")
        if (c) {
            removePlace(params.id, auth.token).then(onBack);
        }
    };

    const onRemoveCategory = (id) => {
        const c = window.confirm("本当に削除してもよろしいですか?")
        if (c) {
            removeCategory(id, auth.token).then(onFetchPlace);
        }
    };

    const onRemoveMenuItem = (id) => {
        const c = window.confirm("本当に削除してもよろしいですか?")
        if (c) {
            removeMenuItem(id, auth.token).then(onFetchPlace);
        }
    };

    const onUpdatePlace = (tables) => {
        updatePlace(place.id, {number_of_tables: tables }, auth.token).then(
            (json) => {
                if (json) {
                    setPlace(json);
                }
            }
        )
    }

    useEffect(() => {
        onFetchPlace();
    }, []);

    return (
        <MainLayout>
            <Row>
                <Col lg={12}>
                    <div className="mb-4">
                        <div className="d-flex justify-content-between align-items-center mb-4">
                            <Button variant="link" onClick={onBack}>
                                <IoMdArrowBack size={25} color="black" />
                            </Button>

                            <h3 className="mb-0 ml-2 mr-2"><img src={place.image} with={50} height={50} /><br/>{place.name}</h3>
                           
                            <Button variant="link" onClick={onRemovePlace}>
                                <AiOutlineDelete size={25} color="red" />

                            </Button>
                        </div>
                        <Button variant="link" onClick={showQRModal} Style=" text-decoration: none;">
                            <AiOutlineQrcode size={25} /><span>QR</span>
                        </Button>
                        <Button variant="link" href={`/places/${params.id}/orders`} Style=" text-decoration: none;">
                            <RiFileList3Line size={25} color="green" /><span Style="color: green; font-size: 0.8rem;">オーダー</span>
                        </Button>                        
                    </div>
                </Col>
                <Col md={4}>
                    <Panel>
                        <MenuItemForm place={place} onDone={onFetchPlace} />
                    </Panel>
                </Col>

                <Col md={8}>
                    {place?.categories?.map((category) => (
                        <div key={category.id} className="mb-5">
                            <div className="d-flex align-items-center mb4">
                            <h4 className="mb-0 mr-2">
                                <b>{category.name}</b>
                            </h4>
                            <Button variant="link" onClick={() => onRemoveCategory(category.id)}>
                                <AiOutlineDelete size={25} color="red" />
                            </Button>
                            </div>
                            <br/>

                            {category.menu_items.map((item) => (
                                <MenuItem 
                                key={item.id} 
                                item={item}
                                onEdit={() => {
                                    setSelectedItem(item);
                                    showModal()
                                }}
                                onRemove={() => onRemoveMenuItem(item.id)} 
                            />
                            ))}

                        </div>
                    ))}
                </Col>


            </Row>

            <Modal show={menuItemFormShow} onHide={hideModal} centerd>
               <Modal.Body>
                <h4 className="text-center">メニューアイテム</h4>
                <MenuItemForm
                    place={place}
                    onDone={() =>{
                        onFetchPlace(); 
                        hideModal()
                    }}
                    item={selectedItem}
                />
                </Modal.Body>
            </Modal>

            <QRCodeModal 
                show={qrCode} 
                onHide={hideQRModal} 
                place={place} 
                centered 
                onUpdatePlace={onUpdatePlace}
            />

        </MainLayout>
    )
};

export default Place;



「qrmenu_react/src/components」フォルダに「Order.js」ファイルを新規作成します。
作成した「src/components/Order.js」ファイルを以下のように編集します。



新規作成 【QRMenu/qrmenu_react/src/components/Order.js】

import { Card } 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 }) => {

    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>
            {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>
            ))}
        </Card.Body>
    </Card>    
    )
}

export default Order;



「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 } 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);
        }
    }
    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?.map((order) => (
                    <Col key={order.id} lg={8}>
                        <Order order={order} />
                    </Col>
                ))}
            </Row>
        </MainLayout>
    );
}

export default Orders;



注文が入ると、自動更新で受注リストに表示されるようになりました。

自動更新受注リスト表示
自動更新受注リスト表示



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


[37 | 受注データ実装] << [ホーム] >> [39 | 提供完了]