NextJS Templates
Учебное пособие по приложению для бронирования конференц-залов с использованием Back4App, Next.js и Vercel
23 мин
в этом учебном пособии вы создадите bookit , систему бронирования конференц залов, используя next js в качестве фронтенд фреймворка и back4app в качестве бэкенд сервиса вы реализуете аутентификацию пользователей, управление комнатами и функциональность бронирования, а также развернете приложение на vercel 1 предварительные требования чтобы завершить это учебное пособие, вам понадобятся учетная запись back4app (зарегистрируйтесь на back4app https //www back4app com/ ) проект back4app (следуйте за этим руководством https //www back4app com/docs/get started/welcome ) установленный node js на вашем локальном компьютере ( руководство по установке https //nodejs org/ ) базовые знания javascript, next js и rest api (если необходимо, смотрите основы javascript https //www back4app com/docs/javascript guide ) 2 настройка back4app войдите в свою учетную запись back4app и перейдите на панель управления проектом в левой боковой панели нажмите на база данных для доступа к браузеру данных вам нужно будет создать следующие классы для моделирования данных 2 1 создайте класс пользователь email адрес электронной почты для входа password пароль (хэшированный) username необязательное имя пользователя 2 2 создайте room класс в data browser , нажмите создать класс , выберите пользовательский , и назовите класс комната добавьте следующие столбцы имя столбца тип описание имя строка название комнаты описание строка описание комнаты вместимость номер количество людей, которые может вмещать комната удобства массив список удобств (телевизор, wifi и т д ) цена номер цена за час изображение файл url изображения владелец указатель указывает на пользователь класс 2 3 создайте booking класс создайте другой пользовательский класс с именем booking добавьте следующие столбцы название столбца тип описание комната указатель указывает на класс room пользователь указатель указывает на класс user заезд дата дата/время начала бронирования выезд дата дата/время окончания бронирования 3 настройка next js и parse sdk создайте новый проект next js npx create next app bookit app cd bookit app установите parse js sdk npm install parse в файле pages/ app js инициализируйте parse с вашими учетными данными back4app import parse from 'parse'; parse initialize('your app id', 'your javascript key'); parse serverurl = 'https //parseapi back4app com'; function myapp({ component, pageprops }) { return \<component { pageprops} /> } export default myapp; замените 'your app id' и 'your javascript key' на ваши учетные данные приложения back4app 4 реализация аутентификации пользователей 4 1 регистрация пользователя создайте новую страницу pages/signup js с формой регистрации import { usestate } from 'react'; import parse from 'parse'; export default function signup() { const \[email, setemail] = usestate(''); const \[password, setpassword] = usestate(''); const handlesignup = async (e) => { e preventdefault(); const user = new parse user(); user set('username', email); user set('email', email); user set('password', password); try { await user signup(); alert('signup successful!'); } catch (error) { alert('error ' + error message); } }; return ( \<form onsubmit={handlesignup}> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="email" /> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="password" /> \<button type="submit">sign up\</button> \</form> ); } 4 2 вход пользователя создайте pages/login js для входа пользователя import { usestate } from 'react'; import parse from 'parse'; export default function login() { const \[email, setemail] = usestate(''); const \[password, setpassword] = usestate(''); const handlelogin = async (e) => { e preventdefault(); try { await parse user login(email, password); alert('login successful!'); } catch (error) { alert('error ' + error message); } }; return ( \<form onsubmit={handlelogin}> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="email" /> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="password" /> \<button type="submit">login\</button> \</form> ); } 4 3 защищенные маршруты для защищенных маршрутов вы можете использовать api маршруты next js и проверить, аутентифицирован ли пользователь import parse from 'parse'; export default async function handler(req, res) { const user = parse user current(); if (!user) { return res status(401) json({ message 'unauthorized' }); } // proceed with the request } 5 управление комнатами 5 1 отображение доступных комнат создайте pages/index js для отображения доступных комнат import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function home() { const \[rooms, setrooms] = usestate(\[]); useeffect(() => { const fetchrooms = async () => { const room = parse object extend('room'); const query = new parse query(room); const results = await query find(); setrooms(results); }; fetchrooms(); }, \[]); return ( \<div> \<h1>available rooms\</h1> {rooms map(room => ( \<div key={room id}> \<h2>{room get('name')}\</h2> \<img src={room get('image') url()} alt={room get('name')} /> \<p>capacity {room get('capacity')}\</p> \<p>price ${room get('price')} per hour\</p> \</div> ))} \</div> ); } 5 2 добавление комнаты создайте pages/add room js для добавления новых комнат (для авторизованных пользователей) import { usestate } from 'react'; import parse from 'parse'; export default function addroom() { const \[name, setname] = usestate(''); const \[description, setdescription] = usestate(''); const \[capacity, setcapacity] = usestate(0); const \[price, setprice] = usestate(0); const handleaddroom = async (e) => { e preventdefault(); const room = parse object extend('room'); const room = new room(); room set('name', name); room set('description', description); room set('capacity', capacity); room set('price', price); try { await room save(); alert('room added successfully!'); } catch (error) { alert('error ' + error message); } }; return ( \<form onsubmit={handleaddroom}> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="room name" /> \<textarea value={description} onchange={(e) => setdescription(e target value)} placeholder="description">\</textarea> \<input type="number" value={capacity} onchange={(e) => setcapacity(parseint(e target value))} placeholder="capacity" /> \<input type="number" value={price} onchange={(e) => setprice(parseint(e target value))} placeholder="price" /> \<button type="submit">add room\</button> \</form> ); } 5 3 детали комнаты создайте pages/rooms/\[id] js для просмотра подробной информации о комнате import { userouter } from 'next/router'; import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function roomdetails() { const router = userouter(); const { id } = router query; const \[room, setroom] = usestate(null); useeffect(() => { if (!id) return; const fetchroom = async () => { const room = parse object extend('room'); const query = new parse query(room); query equalto('objectid', id); const result = await query first(); setroom(result); }; fetchroom(); }, \[id]); if (!room) return \<div>loading \</div>; return ( \<div> \<h1>{room get('name')}\</h1> \<img src={room get('image') url()} alt={room get('name')} /> \<p>{room get('description')}\</p> \<p>capacity {room get('capacity')}\</p> \<p>price ${room get('price')} per hour\</p> \</div> ); } 6 система бронирования 6 1 бронирование номера добавьте функциональность бронирования в pages/rooms/\[id] js добавив форму бронирования const \[checkin, setcheckin] = usestate(''); const \[checkout, setcheckout] = usestate(''); const handlebooking = async () => { const booking = parse object extend('booking'); const booking = new booking(); booking set('room', room); booking set('user', parse user current()); booking set('checkin', new date(checkin)); booking set('checkout', new date(checkout)); // check for double booking (example logic) const query = new parse query(booking); query equalto('room', room); query greaterthanorequalto('checkin', new date(checkin)); query lessthanorequalto('checkout', new date(checkout)); const overlap = await query first(); if (!overlap) { try { await booking save(); alert('booking successful!'); } catch (error) { alert('error ' + error message); } } else { alert('room is already booked for the selected time range '); } }; 6 2 просмотр и отмена бронирований создайте pages/my bookings js для просмотра и отмены бронирований import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function mybookings() { const \[bookings, setbookings] = usestate(\[]); useeffect(() => { const fetchbookings = async () => { const booking = parse object extend('booking'); const query = new parse query(booking); query equalto('user', parse user current()); const results = await query find(); setbookings(results); }; fetchbookings(); }, \[]); const handlecancel = async (id) => { const booking = bookings find(b => b id === id); if (booking) { await booking destroy(); setbookings(bookings filter(b => b id !== id)); } }; return ( \<div> \<h1>my bookings\</h1> {bookings map(booking => ( \<div key={booking id}> \<p>room {booking get('room') get('name')}\</p> \<p>check in {new date(booking get('checkin')) tolocalestring()}\</p> \<p>check out {new date(booking get('checkout')) tolocalestring()}\</p> \<button onclick={() => handlecancel(booking id)}>cancel booking\</button> \</div> ))} \</div> ); } 7 развертывание на vercel установите vercel cli npm install g vercel разверните ваше приложение next js с помощью vercel следуйте инструкциям, чтобы развернуть ваше приложение на vercel после развертывания ваше приложение будет доступно по публичному url 8 заключение в этом учебном пособии вы создали приложение bookit с использованием next js для фронтенда и back4app в качестве бэкенда вы реализовали аутентификацию пользователей, управление комнатами и функциональность бронирования наконец, вы развернули приложение на vercel теперь вы можете расширить приложение дополнительными функциями, такими как поиск, интеграция платежей или уведомления