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

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

Django3.2 | 42 | QRオーダーシステムの構築 | UI設定ページ

[41 | UIの更新] << [ホーム] >> [43 | UI設定フォーム]

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



新規作成 【QRMenu/qrmenu_react/src/pages/MenuSettings.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 } from 'react';

import { fetchPlace } from '../apis';
import MainLayout from '../layouts/MainLayout';
import MenuList from '../components/MenuList';

const MenuSettings = ()=> {
    const [place, setPlace] = useState({});

    const params = useParams();
    const history = useHistory();

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

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

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

    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 mr-2 ml-2">メニュー設定</h3>
            </div>

            <Row>
                <Col md={8}>
                    <MenuList place={place} font={place.font} color={place.color} onOrder={() => []}/>
                </Col>
            </Row>
        </MainLayout>
    )
}

export default MenuSettings;



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


記述編集 【Desktop/QRMenu/qrmenu_react/src/router/App.js】

import { BrowserRouter, Switch, Route } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import React from 'react';

import { AuthProvider } from '../contexts/AuthContext';
import PrivateRoute from './PrivateRoute';

import Home from '../pages/Home';
import Login from '../pages/Login';
import Register from '../pages/Register';
import Places from '../pages/Places';
import Place from '../pages/Place';
import Menu from '../pages/Menu';
import Orders from '../pages/Orders';
import MenuSettings from '../pages/MenuSettings';

function App() {
  return (
    <AuthProvider>
    <BrowserRouter>
      <Switch>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route exact path='/login'>
          <Login />
        </Route>
        <Route exact path='/menu/:id/:table'>
          <Menu />
        </Route>
        <Route exact path='/register'>
          <Register />
        </Route>
        
        <PrivateRoute exact path='/places/:id'>
          <Place />
        </PrivateRoute>                  
        <PrivateRoute exact path='/places'>
          <Places />
        </PrivateRoute>
        <PrivateRoute exact path='/places/:id/orders'>
          <Orders />
        </PrivateRoute>
        <PrivateRoute exact path='/places/:id/settings'>
          <MenuSettings />
        </PrivateRoute>            
      </Switch>
    </BrowserRouter>
    <ToastContainer />
    </AuthProvider>
  )
}

export default App;



「src/components/MenuList.js」ファイルの記述を変更します。


記述変更 【Desktop/QRMenu/qrmenu_react/src/components/MenuList.js】20行目

import React from 'react';
import styled from 'styled-components';
import MenuItem from './MenuItem';

const Place = styled.div`
    text-align: center;
    img {
        border-radius: 5px;
        margin-bottom: 20px;
        margin-top: 20px;
    }
`;

const Container = styled.div`
b, p {
    ${({ font }) => font && `font-family: ${font};`}
}
`;

const MenuList = ({ place, shoppingCart = {}, onOrder, font = "", color = "" }) => {
    return (
        <Container font={font}>
        <Place>
            <img src={place.image} with={100} height={100} />
            <h3><b>{place.name}</b></h3>
        </Place>
        {place?.categories
            ?.filter(
                (category) => category.menu_items.filter((i) => i.is_available).length
            )
            .map((category) => (
                <div key={category.id} className="mt-5">
                    <h4 className="mb-4">
                        <b>{category.name}</b>
                    </h4>
                    {category.menu_items
                        .filter((item) => item.is_available)
                        .map((item) => (
                            <MenuItem 
                                key={item.id} 
                                item={{
                                    ...item,
                                    quantity: shoppingCart[item.id]?.quantity,
                                }}
                                onOrder={onOrder} 
                                color={color}
                            />
                           
                        ))
                    }
                </div>
            ))
        }
        </Container>
    )
};

export default MenuList;



ブラウザを確認します。
http://localhost:3000/places/5/settings


設定ページが表示されるようになりました。

設定ページ表示
設定ページ表示



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


記述編集 【Desktop/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 { FiSettings } from 'react-icons/fi';
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>
                        <Button variant="link" href={`/places/${params.id}/settings`} Style=" text-decoration: none;">
                            <FiSettings size={25} color="#4b0082" /><span Style="color: #4b0082; 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;



設定ページのリンクができました。

設定ページリンク
設定ページリンク



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


[41 | UIの更新] << [ホーム] >> [43 | UI設定フォーム]