This frontend connects to the ApartmentRental smart contract, allowing landlords and tenants to interact with the lease agreement.
Read this first: Smart Contract for Apartment Rental & Payments (Solidity)
1. Setup the Project
bash
npx create-react-app apartment-rental-dapp cd apartment-rental-dapp npm install web3 @metamask/detect-provider @chakra-ui/react ethers
2. Key Components
- Connect Wallet (MetaMask)
- Landlord Dashboard (Create lease, refund deposit)
- Tenant Dashboard (Pay rent, terminate lease)
3. Full Frontend Code
App.js
(Main Component)
jsx
import { useState, useEffect } from 'react'; import { ChakraProvider, Button, Box, Heading, Input, Text, VStack, HStack, Alert, AlertIcon } from '@chakra-ui/react'; import Web3 from 'web3'; import ApartmentRentalABI from './ApartmentRentalABI.json'; // Import ABI function App() { const [web3, setWeb3] = useState(null); const [account, setAccount] = useState(''); const [contract, setContract] = useState(null); const [isLandlord, setIsLandlord] = useState(false); const [isTenant, setIsTenant] = useState(false); const [leaseDetails, setLeaseDetails] = useState(null); // Contract Address (Replace with your deployed address) const CONTRACT_ADDRESS = "0x123...YourContractAddress"; // Initialize Web3 and Contract useEffect(() => { const initWeb3 = async () => { if (window.ethereum) { const web3Instance = new Web3(window.ethereum); setWeb3(web3Instance); const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); setAccount(accounts[0]); const contractInstance = new web3Instance.eth.Contract( ApartmentRentalABI, CONTRACT_ADDRESS ); setContract(contractInstance); // Check if user is landlord or tenant const landlord = await contractInstance.methods.landlord().call(); setIsLandlord(accounts[0].toLowerCase() === landlord.toLowerCase()); const tenant = await contractInstance.methods.tenant().call(); setIsTenant(accounts[0].toLowerCase() === tenant.toLowerCase()); // Load lease details if (tenant !== "0x0000000000000000000000000000000000000000") { const details = { rentAmount: await contractInstance.methods.rentAmount().call(), securityDeposit: await contractInstance.methods.securityDeposit().call(), leaseStart: await contractInstance.methods.leaseStart().call(), leaseEnd: await contractInstance.methods.leaseEnd().call(), isActive: await contractInstance.methods.isLeaseActive().call(), }; setLeaseDetails(details); } } else { alert("Please install MetaMask!"); } }; initWeb3(); }, []); // Sign Lease (Tenant) const signLease = async () => { const value = Web3.utils.toWei( (leaseDetails.rentAmount + leaseDetails.securityDeposit).toString(), 'ether' ); await contract.methods.signLease().send({ from: account, value }); alert("Lease signed successfully!"); }; // Pay Rent (ETH) const payRent = async (month) => { const value = Web3.utils.toWei(leaseDetails.rentAmount.toString(), 'ether'); await contract.methods.payRent(month).send({ from: account, value }); alert(`Rent for month ${month} paid!`); }; // Refund Deposit (Landlord) const refundDeposit = async (deductions) => { await contract.methods.refundDeposit(deductions).send({ from: account }); alert("Deposit refunded!"); }; // Terminate Lease const terminateLease = async () => { await contract.methods.terminateLease().send({ from: account }); alert("Lease terminated!"); }; return ( <ChakraProvider> <Box p={8}> <Heading mb={6}>🏠 Decentralized Apartment Rental</Heading> {!account ? ( <Button onClick={() => window.ethereum.request({ method: 'eth_requestAccounts' })}> Connect MetaMask </Button> ) : ( <VStack spacing={6} align="start"> <Text>Connected as: {account}</Text> {isLandlord && ( <Box borderWidth="1px" p={4} borderRadius="md"> <Heading size="md">👔 Landlord Dashboard</Heading> {leaseDetails && leaseDetails.isActive ? ( <Button mt={2} onClick={() => terminateLease()}> Terminate Lease (Penalty: 1 Month Rent) </Button> ) : ( <Button mt={2} onClick={() => refundDeposit(0)}> Refund Deposit </Button> )} </Box> )} {isTenant && leaseDetails && ( <Box borderWidth="1px" p={4} borderRadius="md"> <Heading size="md">👤 Tenant Dashboard</Heading> <Text>Rent: {Web3.utils.fromWei(leaseDetails.rentAmount, 'ether')} ETH/month</Text> <Text>Lease End: {new Date(leaseDetails.leaseEnd * 1000).toLocaleDateString()}</Text> <Button mt={2} onClick={() => payRent(1)}>Pay Rent (ETH)</Button> <Button mt={2} onClick={() => terminateLease()}>Terminate Lease (Lose Deposit)</Button> </Box> )} {!isLandlord && !isTenant && ( <Alert status="info"> <AlertIcon /> You are not the landlord or tenant for this lease. </Alert> )} </VStack> )} </Box> </ChakraProvider> ); } export default App;
4. Contract ABI (ApartmentRentalABI.json
)
Paste the ABI from Remix/your compiled contract:
json
[ { "inputs": [ {"internalType": "uint256","name": "_rentAmount","type": "uint256"}, {"internalType": "uint256","name": "_securityDeposit","type": "uint256"}, {"internalType": "uint256","name": "_leaseDurationMonths","type": "uint256"} ], "stateMutability": "nonpayable", "type": "constructor" }, // ... (Include ALL ABI functions from your contract) ]
5. Key Features
✅ MetaMask Wallet Integration
✅ Landlord & Tenant Views
✅ ETH Payments (Easy to add USDT with payRentERC20
)
✅ Responsive UI with Chakra UI
6. How to Run
bash
npm start
Open http://localhost:3000 and connect MetaMask.