Modals
In this section, we will create the Modals for the frontend application. We use
the Modal
component that we created
earlier.
Create Account Modal
We start with Create Account Modal that will be used to connect to the ZilPay wallet as well as access the smart contract.
It uses Input
and
Button
components. It uses
CheckBox
for selecting the user
role. A button is presented for connecting ZilPay when required.
The createAccountTransition
function is used.
import React, { useEffect, useState } from "react";
import ContextContainer from "../functions/contextContainer";
import createUserTransition from "../functions/createUserTransition";
import Button from "./componentButton";
import Input from "./componentInput";
import Modal from "./componentModal";
import Tick from "./componentTick";
type props = {
showSignUp: boolean;
setShowSignUp(visible: boolean): void;
};
const CreateAccountModal: React.FC<props> = (props) => {
const { showSignUp, setShowSignUp } = props;
const [name, setName] = useState<string | undefined>(undefined);
const [userRole, setUserRole] = useState<string | undefined>("host");
const { zilPay, contract } = ContextContainer.useContainer();
const createUser = async () => {
const role = userRole === "host" ? "1" : "0";
createUserTransition(contract, zilPay, name, role);
};
const connectZilPay = async () => {
await zilPay.wallet.connect();
window.location.reload();
};
useEffect(() => {
setName(undefined);
setUserRole("host");
}, [setShowSignUp]);
return (
<Modal
title="Create Account"
visible={showSignUp}
setVisible={setShowSignUp}
buttonText={"Create Account"}
onClick={createUser}
>
<>
{!zilPay.wallet.isConnect && (
<>
<h4 className="text-xs font-semibold text-gray-500 tracking-wide uppercase py-4">
ZilPay
</h4>
<Button
text={"Connect ZilPay"}
padding
onClick={connectZilPay}
modal
/>
</>
)}
<Input name="Your name" value={name} setValue={setName} />
<h4 className="text-xs font-semibold text-gray-500 tracking-wide uppercase py-4">
Please select one
</h4>
<div className="flex gap-12 mb-8">
<div
className="flex justify-center items-center cursor-pointer"
onClick={() => setUserRole("host")}
>
<p className="text-lg text-gray-800 pr-4">Host</p>
<div
className={`p-1 bg-gray-200 rounded-lg w-8 h-8 hover:scale-95 transform transition-all ${
userRole === "host" ? "" : "hover:bg-gray-300"
}`}
>
<div
className={`w-full h-full rounded transition-colors text-transparent ${
userRole === "host" ? "bg-gray-900 text-gray-200" : ""
}`}
>
{userRole === "host" && <Tick />}
</div>
</div>
</div>
<div
className="flex justify-center items-center cursor-pointer"
onClick={() => setUserRole("renter")}
>
<p className="text-lg text-gray-800 pr-4">Rent</p>
<div
className={`p-1 bg-gray-200 rounded-lg w-8 h-8 hover:scale-95 transform transition-all ${
userRole !== "host" ? "" : "hover:bg-gray-300"
}`}
>
<div
className={`w-full h-full rounded transition-colors text-transparent ${
userRole !== "host" ? "bg-gray-900 text-gray-200" : ""
}`}
>
{userRole !== "host" && <Tick />}
</div>
</div>
</div>
</div>
</>
</Modal>
);
};
export default CreateAccountModal;
/src/components/componentCreateAccountModal.tsx
Create Listing Modal
We now get to the Create Listing Modal that will be used by host users to post new listings.
It uses Input
and
Button
components. It uses
AmenitiesInput
for selecting
the available amenities. A button is presented for connecting ZilPay when
required.
The createListingTransition
function is used.
import React, { useEffect, useState } from "react";
import ContextContainer from "../functions/contextContainer";
import createListingTransition from "../functions/createListingTransition";
import AmenitiesInput from "./componentAmenitiesInput";
import Input from "./componentInput";
import Modal from "./componentModal";
type props = {
showCreateListing: boolean;
setShowCreateListing(visible: boolean): void;
};
const CreateListingModal: React.FC<props> = (props) => {
const { showCreateListing, setShowCreateListing } = props;
const [name, setName] = useState<string | undefined>(undefined);
const [description, setDescription] = useState<string | undefined>(undefined);
const [price, setPrice] = useState<string | undefined>(undefined);
const [rooms, setRooms] = useState<string | undefined>(undefined);
const [bathrooms, setBathrooms] = useState<string | undefined>(undefined);
const [location, setLocation] = useState<string | undefined>(undefined);
const [image, setImage] = useState<string | undefined>(undefined);
const [wifi, setWifi] = useState<boolean>(false);
const [kitchen, setKitchen] = useState<boolean>(false);
const [tv, setTv] = useState<boolean>(false);
const [laundry, setLaundry] = useState<boolean>(false);
const [hvac, setHvac] = useState<boolean>(false);
const { contract, zilPay } = ContextContainer.useContainer();
const createListing = () => {
if (
!name ||
!description ||
!price ||
!rooms ||
!bathrooms ||
!location ||
!image
)
return;
createListingTransition(
contract,
zilPay,
name,
description,
price,
rooms,
bathrooms,
image,
location,
wifi,
kitchen,
tv,
laundry,
hvac,
);
};
useEffect(() => {
setName(undefined);
setDescription(undefined);
setPrice(undefined);
setRooms(undefined);
setBathrooms(undefined);
setLocation(undefined);
setImage(undefined);
setWifi(false);
setKitchen(false);
setTv(false);
setLaundry(false);
setHvac(false);
}, [showCreateListing]);
return (
<Modal
title="Create Listing"
visible={showCreateListing}
setVisible={setShowCreateListing}
buttonText={"Create"}
onClick={createListing}
>
<Input name="Name" value={name} setValue={setName} />
<Input name="Description" value={description} setValue={setDescription} />
<Input name="Rooms" value={rooms} type="number" setValue={setRooms} />
<Input
name="Bathrooms"
value={bathrooms}
type="number"
setValue={setBathrooms}
/>
<Input
name="Price (ZIL)"
unit="per night"
value={price}
type="number"
setValue={setPrice}
/>
<Input name="Image URL" value={image} type="text" setValue={setImage} />
<Input
name="Google Maps Plus Code"
value={location}
type="text"
setValue={setLocation}
/>
<AmenitiesInput
{...{
wifi,
setWifi,
kitchen,
setKitchen,
tv,
setTv,
laundry,
setLaundry,
hvac,
setHvac,
}}
/>
</Modal>
);
};
export default CreateListingModal;
/src/components/componentCreateListingModal.tsx
Manage Listing Modal
We now get to the Create Listing Modal that will be used by host users to post new listings.
It uses Input
and
Button
components. It uses
AmenitiesInput
for selecting
the available amenities. A button is presented for connecting ZilPay when
required.
The deleteListingTransition
, updateListingTransition
, and
claimRentTransition
functions are called as required.
import React, { useEffect, useState } from "react";
import claimRentTransition from "../functions/claimRentTransition";
import ContextContainer from "../functions/contextContainer";
import deleteListingTransition from "../functions/deleteListingTransition";
import updateListingTransition from "../functions/updateListingTransition";
import AmenitiesInput from "./componentAmenitiesInput";
import Button from "./componentButton";
import Input from "./componentInput";
import Modal from "./componentModal";
type props = {
modalListing: any;
showManageListing: boolean;
setShowManageListing(visible: boolean): void;
};
const ManageListingModal: React.FC<props> = (props) => {
const { showManageListing, setShowManageListing, modalListing } = props;
const { id, accumulated_rent } = modalListing;
const [name, setName] = useState<string | undefined>(undefined);
const [description, setDescription] = useState<string | undefined>(undefined);
const [price, setPrice] = useState<string | undefined>(undefined);
const [rooms, setRooms] = useState<string | undefined>(undefined);
const [bathrooms, setBathrooms] = useState<string | undefined>(undefined);
const [location, setLocation] = useState<string | undefined>(undefined);
const [image, setImage] = useState<string | undefined>(undefined);
const [wifi, setWifi] = useState<boolean>(false);
const [kitchen, setKitchen] = useState<boolean>(false);
const [tv, setTv] = useState<boolean>(false);
const [laundry, setLaundry] = useState<boolean>(false);
const [hvac, setHvac] = useState<boolean>(false);
const { contract, zilPay } = ContextContainer.useContainer();
const updateListing = () => {
if (
!name ||
!description ||
!price ||
!rooms ||
!bathrooms ||
!location ||
!image
)
return;
updateListingTransition(
contract,
zilPay,
id,
name,
description,
price,
rooms,
bathrooms,
image,
location,
wifi,
kitchen,
tv,
laundry,
hvac,
);
};
const claimRent = () => {
claimRentTransition(contract, zilPay, id);
setShowManageListing(false);
};
const deleteListing = () => {
deleteListingTransition(contract, zilPay, id);
setShowManageListing(false);
};
useEffect(() => {
setName(modalListing.name);
setDescription(modalListing.description);
setPrice(modalListing.price);
setRooms(modalListing.rooms);
setBathrooms(modalListing.bathrooms);
setLocation(modalListing.location);
setImage(modalListing.image);
setWifi(modalListing.amenities.wifi);
setKitchen(modalListing.amenities.kitchen);
setTv(modalListing.amenities.tv);
setLaundry(modalListing.amenities.laundry);
setHvac(modalListing.amenities.hvac);
}, [showManageListing]);
return (
<Modal
title="Manage Listing"
visible={showManageListing}
setVisible={setShowManageListing}
buttonText={"Update Listing"}
onClick={updateListing}
>
<>
<h4 className="text-sm font-semibold text-gray-500 tracking-wide uppercase py-4">
Accumulated Rent
</h4>
<div className="flex justify-between items-center pb-8">
<p className="text-2xl ">{accumulated_rent}</p>
<Button text={"Claim Rent"} onClick={claimRent} />
</div>
</>
<>
<h4 className="text-sm font-semibold text-gray-500 tracking-wide uppercase py-4">
Delete Listing
</h4>
<Button
text={"Delete Listing"}
onClick={deleteListing}
alert
padding
modal
/>
</>
<Input name="Name" value={name} setValue={setName} />
<Input name="Description" value={description} setValue={setDescription} />
<Input name="Rooms" value={rooms} type="number" setValue={setRooms} />
<Input
name="Bathrooms"
value={bathrooms}
type="number"
setValue={setBathrooms}
/>
<Input
name="Price (ZIL)"
unit="per night"
value={price}
type="number"
setValue={setPrice}
/>
<Input name="Image URL" value={image} type="text" setValue={setImage} />
<Input
name="Google Maps Plus Code"
value={location}
type="text"
setValue={setLocation}
/>
<AmenitiesInput
{...{
wifi,
setWifi,
kitchen,
setKitchen,
tv,
setTv,
laundry,
setLaundry,
hvac,
setHvac,
}}
/>
</Modal>
);
};
export default ManageListingModal;