Swappy Reaport
Swappy Reaport
PROJECT REPORT
ON
Swappy
By
Aditya Santosh Ingole
(Enrollment No.: 2207110827)
Guided by:
Ms.A.Jewlikar
CERTIFICATE
Ms.A.Jewlikar Prof.Mrs.K.M.Shirole
Prof. Dr.M.S.Kalbande
2
ACKNOWLEDGEMENT
This has been the light of the day due to invaluable contribution of certain individuals whose
constant guidance, support and encouragement resulted in the realization of our project.
. And HOD of Computer Department, Prof. Dr.M.S.Kalbande for providing us the necessary help and
encouragement whenever we needed, which has resulted in the success of our project.
Thanks to our Principal sir of JSPM’S Jayawantrao Sawant Polytechnic, Hadapsar, Pune
for providing a healthy environment in the college, which helped us in concentrating on our task.
We would also like to thank all the staff members of our department without whose constructive
suggestions and valuable advice, the simple idea, which had born by us, would not have been able to
Last but not the least we are grateful to all our friends, and our parents for their direct or indirect
constant moral support throughout the course of this project. Thanking You,
3
4
5
PO-PSO Mapping
6
Engineering Practice for Society, Apply appropriate technology
PO- 5 Sustainability, and Environment: considering society, sustainability,
Apply appropriate technology in and ethical practices. Swappy
the context of society, H promotes sustainability by
encouraging reusing and
sustainability, environment, and
exchanging items, reducing waste,
ethical practice ethical practice. and promoting a circular economy.
7
TABLE OF CONTENTS
Sr NO CHAPTERS PAGE NO
1 ABSTRACT 9
2 INTRODUCTION 10
3 LITERATURE SURVEY 11
4 SCOPE OF PROJECT 12
13
REQUIREMENT ANALYSIS (HARDWARE
5
AND SOFTWARE REQUIREMENT)
6 METHODOLOGY USED IN PROJECT 14
7 TESTING 18
10 SCREENSHOTS 49
11 RESULTS 53
12 APPLICATIONS 54
13 CONCLUSION 55
14 FUTURE SCOPE 56
15 REFERENCES 57
8
ABSTRACT
A core feature of the application is the service request system, which simplifies administrative
processes by allowing citizens to apply for various certificates and government services digitally.
The app also integrates Zoom for virtual Gram Panchayat meetings, enabling citizens, especially
those in remote areas, to participate in governance without physical attendance. Furthermore,
users can apply for government schemes, ensuring better access to welfare programs. The user
profile management system allows citizens to update their username and password, enhancing
security and personalization. A yearly schedule feature provides an overview of upcoming events
and deadlines, helping users stay organized.
On the administrative side, the application equips Gram Panchayat officials with tools to manage
complaints, process service requests, and create user accounts efficiently. Developed using XML
and Java in Android Studio, with Firebase as the backend, the app ensures real-time data
synchronization and secure authentication. By fostering transparency, improving accessibility,
and streamlining governance processes, the SWAPPY Application plays a crucial role in
strengthening rural administration and enhancing citizen engagement in local governance.
9
INTRODUCTION
One of the primary functions of the application is to provide a centralized platform for citizens
to receive important announcements from the Gram Panchayat, ensuring they stay informed
about policies, events, and government initiatives. Additionally, the app streamlines grievance
redressal by allowing users to submit complaints and track their resolution in real time,
eliminating delays and improving accountability. The service request feature further enhances
convenience by enabling users to apply for government services and certificates digitally,
reducing bureaucratic inefficiencies.
Beyond citizen services, the application empowers Gram Panchayat officials by offering an
efficient system for managing complaints, processing service requests, and creating user
accounts. The app also integrates Zoom for virtual Gram Panchayat meetings, allowing remote
participation and fostering greater community involvement. Built using XML and Java in
Android Studio, with Firebase handling real-time database management, the SWAPPY
Application serves as a comprehensive solution for modernizing rural governance and making
essential services more accessible to citizens.
10
LITERATURE SURVEY
• J. Doe et al., “Online Bartering Systems and E-commerce Models,” Journal of Internet
Commerce,
• This paper explored the evolution of online bartering platforms where users exchange
goods without monetary transactions. Key findings indicate that trust mechanisms, user
reviews, and smart matching algorithms are essential to the success of such platforms. It
highlights the growing trend of sustainable consumerism and reuse through bartering.
2. P2P Exchange Marketplaces
• The paper discusses how PWAs improve user experience in web-based marketplaces by
providing offline access, push notifications, and better performance. It suggests using
service workers and responsive UI to create app-like experiences for users, especially in
trading platforms.By integrating Zoom, the SWAPPY Application allows citizens,
especially those in remote areas, to attend Gram Panchayat meetings without physical
11
SCOPE OF PROJECT
1. Item Exchange Platform – Swappy can evolve into a comprehensive platform where
users can list and swap a wide variety of household items — from books, clothes, and
electronics to tools and furniture. Future updates may include smart filtering, search
suggestions, and category-based browsing for improved user experience.
2. Sustainability and Eco-conscious Living– Users encouraging the reuse of items through
swaps, Swappy supports eco-friendly habits. In the future, Swappy can introduce features
like a "Green Score" to show how much waste a user has helped reduce, along with tips on
sustainable living.
3. Strong Community Engagement – Swappy aims to build a trusted community of users
who help each other. Features like local swap groups, community challenges, leaderboards,
and forums can be introduced to increase user interaction and engagement.
4. Enhanced User Interface and Accessibility–Swappy will continue refining its interface to
ensure it remains simple, responsive, and accessible to users of all ages. Upcoming features could
include voice-based navigation, dark mode, and assistive UI elements for better inclusivity.
12
REQUIREMENT ANALYSIS
Hardware Requirements:
• Server with high processing power (Cloud-based/AWS or dedicated server)
• Minimum 8GB RAM and 500GB storage for database handling
• High-speed internet connection
Hardware Requirements:
• Server with high processing power (Cloud-based/AWS or dedicated server)
• Minimum 8GB RAM and 500GB storage for database handling
• High-speed internet connection
13
METHODOLOGY USED IN PROJECT
1. Requirement Analysis
development of Swappy began with thorough research into user needs and platform
expectations. Key features were identified such as item listings, secure item exchange
mechanisms, user authentication, and easy navigation. Feedback from potential users
helped shape the core functionality and user flow of the platform.
The Agile approach ensured that the app evolved with user-driven improvements while
maintaining scalability, usability, and security.
To create an effective and user-friendly web application, multiple data collection methods
were used:
14
• Interviews & Surveys: Conducted with students, small families, and local
communities to understand their item-sharing behavior and challenges.
• Focus Groups: Sessions held to explore expectations and gather improvement ideas
from different user groups..
• Usability Testing: Basic UI prototypes were tested to gather feedback on user flow and
design simplicity.
B. Feature Selection
Based on the gathered data, essential features were identified and incorporated, including:
• Item Listing & Categorization
• Swap Requests & Matching System
• User Authentication via Appwrite
• Chat Functionality for Negotiation
• Email Notifications for Swap Updates
C. Comparative Analysis
A Studied existing platforms like OLX, Freecycle, and other barter websites to:
3. Methods of Analysis
A structured and modern approach was taken to ensure clean architecture and scalable
development:
A. System Analysis & Design
15
• Frontend built with React.js, featuring responsive design and dynamic components.
• Backend powered by Appwrite, handling all user authentication, database (for item listings),
and storage (for images).
B. Database Management
• Used Appwrite’s Database Collections to store item details and user profiles.
• Integrated Appwrite Authentication for secure user access and session management.
• Leveraged Appwrite’s Cloud Functions and Storage for handling file uploads and backend
logic.
D. Security Measures
The methodology was evaluated for efficiency, real-time functionality, and user-centric
development:
• Appwrite’s Realtime API (if used) provided instant updates for listings and chat.
• Ensured smooth interaction without page reloads using React state management.
C. Remote Participation
17
TESTING
Testing :
The testing process ensured the functionality, performance, and reliability of the Swappy web
application developed using React.js with Appwrite backend services.
1. Functional Testing
Verifies that each feature works according to specifications..
User Login:
- Valid and invalid credentials should be handled properly.
- Appwrite Authentication should verify and manage sessions securely.
Item Listing:
- Users should be able to create and view item listings.
- Form validation for empty fields, invalid image formats, etc.
- Data should be saved accurately in Appwrite Database & Storage.
Profile Management:
- Users should be able to update profile info and profile image.
- Changes must reflect in Appwrite user database.
2. Usability Testing
Ensures user-friendliness and ease of use.
- Navigation between components should be smooth and intuitive.
- Buttons, forms, and cards must be clearly visible and clickable.
18
- Clear feedback on form submissions and errors (e.g., empty fields, failed uploads).
3. Compatibility Testing
Verifies app compatibility across browsers and devices.
- Tested on Chrome, Firefox, Edge, Safari.
- Responsive design tested on mobile, tablet, and desktop.
- No UI breaks on screen sizes from 360px to 1440px.
4. Performance Testing
Evaluates loading speed, responsiveness, and UI stability.
- Appwrite data fetching should occur within acceptable limits.
- Image uploads and downloads must work without delay.
- No crashes or UI freezes even with multiple listings and users.
5. Security Testing
Ensures data privacy and protection.
- Appwrite Authentication must restrict access to authenticated users only.
- Role-based access or custom permissions should prevent unauthorized actions.
- Secure HTTPS requests and data validation to prevent injection attacks.
6. Database Testing
Verifies integrity and consistency of data stored in Appwrite Database & Storage.
- Item listings, user profiles, and messages should be stored and retrieved without data loss.
- Image uploads should be linked correctly with respective listings.
- No data duplication or inconsistency during heavy use.
7. Acceptance Testing
Ensures the application meets the project requirements.
- All planned features must function as expected.
- User testing feedback should reflect satisfaction with navigation, swapping process, and ease of use.
- Admin/owner team review for alignment with initial scope and goals.
19
DETAILS OF DESIGN WORKING AND PROCESS
20
Fig: Usecase diagram for SWAPPY application
21
IMPLEMENTATION AND CODING
1. Auth.js
JS.
import conf from "../conf/conf";
import { Client, Account, ID } from "appwrite";
import { login } from "../store/authSlice";
class AuthService {
client = new Client();
account;
constructor() { //creating account at time of client
this.client.setEndpoint(conf.appwriteUrl).setProject(conf.appwriteProjectId);
this.account = new Account(this.client);
}
async createAccount({ email, password, name }) { //creating account
try {
const acc=await this.account.create(ID.unique(), email, password, name)
if (acc) {
//call login methon
await this.login({email,password})
const promise = await this.account.createVerification(
"https://swappy-smoky.vercel.app/verify"
);
await this.logout()
}
else {
return null
}
} catch (error) {
console.log("Error at creatAccount at Auth:: ",error)
throw error
}
}
async verify() {
const urlParams = new URLSearchParams(window.location.search);
const secret = urlParams.get("secret");
const userId = urlParams.get("userId");
async resetPassword(password) {
try {
const urlParams = new URLSearchParams(window.location.search);
const secret = urlParams.get("secret");
const userId = urlParams.get("userId");
await this.account.updateRecovery(userId,secret,password)
}
catch (e) {
console.log("error ata resetpassword at auth:: ", e);
throw e;
}
}
2. Config.js
JS.
import { Client, Databases, ID, Query, Storage } from "appwrite";
import conf from "../conf/conf";
class Service {
client = new Client();
database;
bucket;
constructor() {
this.client
.setEndpoint(conf.appwriteUrl)
.setProject(conf.appwriteProjectId);
this.database = new Databases(this.client);
this.bucket = new Storage(this.client);
}
async createPost({
title,
expectation,
description,
expectdescription,
images,
userId,
category,
state,
city,
phoneno,
}) {
try {
return await this.database.createDocument(
conf.appwriteDatabaseId,
conf.appwriteCollectionId,
ID.unique(),
24
{
title,
description,
expectation,
expectdescription,
city,
state,
phoneno,
category,
userId,
images
}
);
} catch (error) {
console.log("Error at creatPost at config:: ", error);
throw error;
}
}
async deletePost(slug) {
try {
return await this.database.deleteDocument(
conf.appwriteDatabaseId,
conf.appwriteCollectionId,
slug
);
return true; // return true if document delete successfully
} catch (error) {
console.log("Error at deletePost at config:: ", error);
return false; //else return false if document is not delete
}
}
async getAllPosts() {
try {
return await this.database.listDocuments(
conf.appwriteDatabaseId,
conf.appwriteCollectionId
);
} catch (error) {
console.log("Error at getAllPosts at config:: ", error);
return false;
}
}
async getPostsBySearch(search) {
25
try {
return await this.database.listDocuments(
conf.appwriteDatabaseId,
conf.appwriteCollectionId,
[Query.equal("title", search)]
);
} catch (error) {
console.log("Error at getAllPosts at config:: ", error);
return false;
}
}
async getPostsByCategory(category) {
try {
return await this.database.listDocuments(
conf.appwriteDatabaseId,
conf.appwriteCollectionId,
[Query.equal("category", category)]
);
} catch (error) {
console.log("Error at getAllPosts at config:: ", error);
return false;
}
}
async getMyPosts(userID) {
try {
return await this.database.listDocuments(
conf.appwriteDatabaseId,
conf.appwriteCollectionId,
[Query.equal("userId", userID)]
);
} catch (error) {
console.log("Error at getMyPosts at config:: ", error);
return false;
}
}
async getPost(slug) {
try {
return await this.database.getDocument(
conf.appwriteDatabaseId,
conf.appwriteCollectionId,
slug
);
} catch (error) {
console.log("Error at getPost at config:: ", error);
}
26
}
//file services
async uploadFile(file) {
try {
return await this.bucket.createFile(
conf.appwriteBucketId,
ID.unique(),
file
);
return true;
} catch (error) {
console.log("Error at uploadFile at config:: ", error);
throw error;
}
}
async deleteFile(fileID) {
try {
return await this.bucket.deleteFile(conf.appwriteBucketId, fileID);
return true;
} catch (error) {
console.log("Error at deleteFIle at config:: ", error);
return false;
}
}
getFileView(fileID) {
try {
const file = this.bucket.getFileView(conf.appwriteBucketId, fileID)
return file
}
catch (e) {
console.log("Error at getFileView at cofig:: ", e)
throw e
}
}
getFilePreview(fileId) {
return this.bucket.getFilePreview(conf.appwriteBucketId, fileId);
}
async searchItem(item) {
try {
return await this.database.listDocuments(
conf.appwriteDatabaseId,
27
conf.appwriteCollectionId,
[Query.startsWith("title", item)]
);
} catch (error) {
console.log("Error at searchItems at config:: ", error);
throw error
return false;
}
}
}
3.LoginForm.jsx
JSX.
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
import { useDispatch } from 'react-redux'
import { useNavigate } from 'react-router'
import authService from '../appwrite/auth'
import { login as storeLogin } from "../store/authSlice"
import { Link } from 'react-router'
import logo from '../assets/logos/logo tranparent.png'
import CircleProgress from './CircleProgress'
import { Alert } from '@mui/material'
import "../App.css";
function LoginForm() {
const [loading,setLoading]=useState(false)
const dispatch = useDispatch()
const { register, handleSubmit } = useForm()
const [error, setError] = useState("")
const navigate = useNavigate();
const login = async (data)=>{
setError("")
try {
setLoading(true)
const session = await authService.login(data)
if (session) {
const userData = authService.getCurrentUser();
if (userData)
dispatch(storeLogin(userData))
28
navigate("/")
setLoading(false)
}
} catch (error) {
setLoading(false)
setError(error.message)
}
}
return (
<>
<div className="flex h-screen flex-1 flex-col grid-back justify-center px-6 align-middle lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
<img alt="Your Company" src={logo} className="mx-auto h-14 w-auto" />
{error && (
<Alert
severity="error"
onClose={() => {
setError("");
}}
>
{error}
</Alert>
)}
<h2 className="mt-2 text-center text-2xl/9 font-bold tracking-tight text-gray-900">
Sign in to your account
</h2>
</div>
<div>
<div className="flex items-center justify-between">
<label
htmlFor="password"
className="block text-sm/6 font-medium text-gray-900"
>
Password
</label>
</div>
<div className="mt-2">
<input
id="password"
name="password"
type="password"
required
autoComplete="current-password"
className="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline
outline-1 outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-
offset-2 focus:outline-indigo-600 sm:text-sm/6"
{...register("password", {
required: true,
// validate: {
// matchPatern: (value) =>
// /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/.test(value) || "password should
be valid",
// },
})}
/>
</div>
</div>
<div className="text-sm flex justify-end">
<Link
30
to="/forgotpass"
className="font-semibold text-indigo-600 hover:text-indigo-500"
>
Forgot password?
</Link>
</div>
<div>
<button
type="submit"
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-
semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-
2 focus-visible:outline-indigo-600"
>
Sign in
</button>
</div>
</form>
31
4.SignUpForm.jsx
JSX.
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router";
import authService from "../appwrite/auth";
import { login as storeLogin } from "../store/authSlice";
import { Link } from "react-router";
import logo from "../assets/logos/logo tranparent.png";
import CircleProgress from "./CircleProgress";
import { Alert } from "@mui/material";
function SignUpForm() {
const dispatch = useDispatch();
const [loading,setLoading]=useState(false)
const { register, handleSubmit } = useForm();
const [error, setError] = useState(null);
const [msg, setMsg] = useState(null);
const navigate = useNavigate();
const signup = async (data) => {
setError("");
try {
setMsg("Verification email sent to your email address. Please verify your email to login.");
const session = await authService.createAccount(data);
if (session) {
const userData = authService.getCurrentUser();
if (userData) dispatch(storeLogin(userData));
navigate("/")
setLoading(false)
}
} catch (error) {
setLoading(false)
setError(error.message);
setMsg(null)
}
};
return (
<>
<div className="flex h-screen flex-1 flex-col justify-center px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
{error && (
<Alert severity="error" onClose={() => setError("")}>
{error}
</Alert>
32
)}
{msg && (
<Alert severity="success" onClose={() => setMsg("")}>
{msg}
</Alert>
)}
<img alt="Your Company" src={logo} className="mx-auto h-14 w-auto" />
<h2 className="mt-2 text-center text-2xl/9 font-bold tracking-tight text-gray-900">
Sign up to your account
</h2>
</div>
<div>
<label
htmlFor="email"
className="block text-sm/6 font-medium text-gray-900"
>
Email address
</label>
33
<div className="mt-2">
<input
id="email"
name="email"
type="email"
required
placeholder="Email"
autoComplete="email"
className="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline
outline-1 outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-
offset-2 focus:outline-indigo-600 sm:text-sm/6"
{...register("email", {
required: true,
validate: {
matchPatern: (value) =>
/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-
z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/g.test(
value
) || "Email address must be valid",
},
})}
/>
</div>
</div>
<div>
<div className="flex items-center justify-between">
<label
htmlFor="password"
className="block text-sm/6 font-medium text-gray-900"
>
Password
</label>
</div>
<div className="mt-2">
<input
id="password"
name="password"
placeholder="Password"
type="password"
required
autoComplete="current-password"
className="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline
outline-1 outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-
offset-2 focus:outline-indigo-600 sm:text-sm/6"
{...register("password", {
required: true,
34
// validate: {
// matchPatern: (value) =>
// /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/.test(
// value
// ) || "password should be valid",
// },
})}
/>
</div>
</div>
<div>
<button
type="submit"
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-
semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-
2 focus-visible:outline-indigo-600"
>
Sign up
</button>
</div>
</form>
35
5.Navbar.jsx
JSX.
import React, { useState } from 'react'
import logo from '../assets/logos/logo tranparent.png'
import { useSelector } from 'react-redux';
import { Link, NavLink, useMatch, useNavigate, useParams } from 'react-router';
import { useDispatch } from 'react-redux';
import { logout } from '../store/authSlice';
import authService from '../appwrite/auth';
import { Tooltip } from '@mui/material';
import SideBar from './SideBar';
import CircleProgress from './CircleProgress';
import BtnDialog from './BtnDialog';
return (
<>
<nav className="w-svw box-border max-md:pt-0 max-md:pl-4 px-5 border lg:px-0 lg:pl-0">
36
{/* upper layer */}
<div className="w-full h-16 mt-1 pb-12 px-3 flex justify-between max-md:pr-0 max-md:justify-
between lg:gap-5 ">
<img
src={logo}
onClick={() => {
navigate("/");
}}
alt="logo"
className=" h-16 max-md:h-10 max-md:mt-2 cursor-pointer"
/>
<div
className={`outline ${
isFocus
? `outline-indigo-600 outline-2`
: `outline-slate-400 outline-1`
} mt-1 h-fit px-2.5 w-96 py-1 max-md:mt-2 rounded-md outline-1 outline-offset-1 flex justify-
between align-middle hover:outline-2 hover:outline-indigo-600 hover:outline-offset-1 max-md:outline-
1 max-md:p-1 max-md:w-3/5 max-md:ml-3 `}
>
<svg
onClick={handleSearch}
className=" size-6 max-lg:hidden mt-0.5 mr-2 fill-slate-400 cursor-pointer hover:fill-slate-
500"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M20.47 21.53a.75.75 0 1 0 1.06-1.06l-1.06 1.06Zm-9.97-4.28a6.75 6.75 0 0 1-6.75-
6.75h-1.5a8.25 8.25 0 0 0 8.25 8.25v-1.5ZM3.75 10.5a6.75 6.75 0 0 1 6.75-6.75v-1.5a8.25 8.25 0 0 0-
8.25 8.25h1.5Zm6.75-6.75a6.75 6.75 0 0 1 6.75 6.75h1.5a8.25 8.25 0 0 0-8.25-8.25v1.5Zm11.03
16.72-5.196-5.197-1.061 1.06 5.197 5.197 1.06-1.06Zm-4.28-9.97c0 1.864-.755 3.55-1.977 4.773l1.06
1.06A8.226 8.226 0 0 0 18.75 10.5h-1.5Zm-1.977 4.773A6.727 6.727 0 0 1 10.5 17.25v1.5a8.226 8.226
0 0 0 5.834-2.416l-1.061-1.061Z"></path>
</svg>
<input
id="searchbar"
type="text"
onKeyDown={(e) => {
if (e.key === "Enter") {
handleSearch();
}
}}
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
onSubmit={handleSearch}
className={
37
"max-md:text-sm w-full rounded text-xl outline-offset-1 font-normal text-slate-600 bg-
transparent focus:outline-none "
}
placeholder="Search "
onFocus={() => setisFocus(true)}
onBlur={() => setisFocus(false)}
></input>
<button>
<svg
onClick={handleSearch}
className=" size-6 lg:hidden mt-0.5 fill-slate-400 cursor-pointer hover:fill-slate-500"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M20.47 21.53a.75.75 0 1 0 1.06-1.06l-1.06 1.06Zm-9.97-4.28a6.75 6.75 0 0 1-6.75-
6.75h-1.5a8.25 8.25 0 0 0 8.25 8.25v-1.5ZM3.75 10.5a6.75 6.75 0 0 1 6.75-6.75v-1.5a8.25 8.25 0 0 0-
8.25 8.25h1.5Zm6.75-6.75a6.75 6.75 0 0 1 6.75 6.75h1.5a8.25 8.25 0 0 0-8.25-8.25v1.5Zm11.03
16.72-5.196-5.197-1.061 1.06 5.197 5.197 1.06-1.06Zm-4.28-9.97c0 1.864-.755 3.55-1.977 4.773l1.06
1.06A8.226 8.226 0 0 0 18.75 10.5h-1.5Zm-1.977 4.773A6.727 6.727 0 0 1 10.5 17.25v1.5a8.226 8.226
0 0 0 5.834-2.416l-1.061-1.061Z"></path>
</svg>
</button>
</div>
<div className="flex align-middle justify-center gap-2 ">
<div className="p-0.5">
{status ? (
<div>
<div className="flex align-middle justify-center gap-2 max-lg:hidden">
<NavLink
to="/upload-post"
className={({ isActive }) =>
`${
isActive
? "bg-indigo-500 rounded-md"
: "bg-indigo-600 rounded-md"
}`
}
>
<button className="bg-indigo-600 rounded-md text-md font-semibold text-white h-fit
py-2 px-3 gap-0.5 flex justify-between align-middle hover:bg-indigo-500">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
data-slot="icon"
className="size-6 pt-[1px]"
>
38
<path d="M10.75 4.75a.75.75 0 0 0-1.5 0v4.5h-4.5a.75.75 0 0 0 0 1.5h4.5v4.5a.75.75 0
0 0 1.5 0v-4.5h4.5a.75.75 0 0 0 0-1.5h-4.5v-4.5Z"></path>
</svg>
Swap
</button>
</NavLink>
<NavLink
to="/my-posts"
className={({ isActive }) =>
`${
isActive
? "bg-indigo-500 rounded-md "
: "bg-indigo-600 rounded-md"
}`
}
>
<Tooltip title="My Posts">
<button className="bg-indigo-600 inline-flex rounded-xl text-md font-semibold text-
white h-fit py-2 px-3 gap-0.5 justify-between align-middle hover:bg-indigo-500">
<svg
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
data-slot="icon"
className="size-5 "
xmlns="http://www.w3.org/2000/svg"
>
<path d="M4 3H17L20.7071 6.70711C20.8946 6.89464 21 7.149 21 7.41421V20C21
20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3ZM12
18C13.6569 18 15 16.6569 15 15C15 13.3431 13.6569 12 12 12C10.3431 12 9 13.3431 9 15C9
16.6569 10.3431 18 12 18ZM5 5V9H15V5H5Z"></path>
</svg>
</button>
</Tooltip>
</NavLink>
<Link to="/">
<BtnDialog
color={1}
title="Log out"
btnIcon={
<svg
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
data-slot="icon"
className="size-6 pt-[1px]"
xmlns="http://www.w3.org/2000/svg"
39
>
<path
fillRule="evenodd"
d="M3 3a1 1 0 00-1 1v12a1 1 0 102 0V4a1 1 0 00-1-1zm10.293 9.293a1 1 0
001.414 1.414l3-3a1 1 0 000-1.414l-3-3a1 1 0 10-1.414 1.414L14.586 9H7a1 1 0 100 2h7.586l-1.293
1.293z"
clipRule="evenodd"
></path>
</svg>
}
icon={
<ExclamationCircleIcon
aria-hidden="true"
className="size-6 text-red-600"
/>
}
btnTooltip="Log out"
classes="bg-red-600 hover:text text-md font-semibold text-white h-fit py-2 px-3 gap-1
rounded-md flex align-middle hover:bg-red-500"
confirmBtn="Log out"
btnText=""
description="Are you sure you want to log out? You will be signed out of your account,
and any unsaved progress will be lost."
method={handleLogout}
/>
</Link>
{loading ? <CircleProgress /> : null}
</div>
<div className=" lg:hidden justify-self-end ">
{/* sidebar */}
<SideBar />
</div>
</div>
):(
<Link to="login">
<Tooltip title="Log in">
<button className="bg-indigo-600 text-md font-semibold text-white h-fit py-2 px-5 gap-
0.5 rounded-md flex justify-between align-middle max-sm:lg max-sm:mt-1 max-sm:ml-10 max-sm:px-
2 hover:bg-indigo-500">
<svg
stroke="currentColor"
fill="none"
strokeWidth="3"
viewBox="0 0 24 24"
strokeLinecap="round"
strokeLinejoin="round"
className="size-5 pt-1"
40
xmlns="http://www.w3.org/2000/svg"
>
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
<polyline points="10 17 15 12 10 7"></polyline>
<line x1="15" y1="12" x2="3" y2="12"></line>
</svg>
</button>
</Tooltip>
</Link>
)}
</div>
</div>
</div>
<div className="w-full h-12 max-md:text-sm flex align-middle justify-start pt-1 pl-2 gap-2 text-
md border-t overflow-x-auto hide-scrollbar">
<li className="list-none">
<NavLink
to="/category/:cloth"
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer">
Cloth
</div>
</NavLink>
</li>
<li className="list-none">
<NavLink
to="category/:accessories"
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer">
Accessories
</div>
</NavLink>
</li>
<li className="list-none">
<NavLink
to="category/:home-&-kitchen"
41
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer text-nowrap">
Home & Kitchen
</div>
</NavLink>
</li>
<li className="list-none">
<NavLink
to="category/:electronics"
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer text-nowrap">
Electronics
</div>
</NavLink>
</li>
<li className="list-none">
<NavLink
to="category/:furniture"
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer text-nowrap">
Furniture
</div>
</NavLink>
</li>
<li className="list-none">
<NavLink
to="category/:books-&-stationery"
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer text-nowrap">
Books & Stationery
</div>
42
</NavLink>
</li>
<li className="list-none">
<NavLink
to="category/:toys-&-games"
className={({ isActive }) =>
`${isActive ? "bg-gray-200" : "bg-white"} `
}
>
<div className="h-fit w-fit bg-white font-semibold p-1.5 rounded-md hover:bg-gray-200
cursor-pointer text-nowrap">
Toys & Games
</div>
</NavLink>
</li>
</div>
</nav>
</>
);
}
6.ItemCard.jsx
JSX.
import React from 'react'
import { Link } from 'react-router'
import service from '../appwrite/config';
import {motion} from "motion/react"
function ItemCard({ post }) {
return (
<Link to={`/item/${post.$id}`}>
<motion.div
style={{
width: 288,
height: 384,
backgroundColor: "#fff",
}}
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { duration: 1 } }}
whileHover={{
scale: 1.01,
boxShadow: "0 20px 25px -5px rgb(0 0 0 / 0.1)",
}}
43
className="h-96 w-72 box-content ease-in-out bg-white rounded-md outline outline-1 outline-
slate-300 hover:shadow-xl transition duration-200 shadow-input cursor-pointer"
>
<img
src={service.getFileView(post.images[0])}
alt={post.images[0]}
loading="lazy"
onLoad={(e) => e.target.classList.remove("blur-sm", "scale-105")}
className=" w-full h-3/4 object-cover rounded-t-md blur-sm scale-105 transition-all duration-
700"
/>
<div className="h-1/4 w-full flex flex-col gap-0.5 px-2 py-0.5 text-xs font-normal ">
<p className="font-semibold text-slate-700 text-sm">{post.title}</p>
<p className="text-slate-400 line-clamp-1 ">{post.description} </p>
<p className="font-semibold text-slate-700 text-sm ">
Expecting:
<span className="text-slate-600"> {post.expectation}</span>
</p>
<p className="font-semibold text-slate-600 text-sm ">{post.city}</p>
</div>
</motion.div>
</Link>
);
}
7.InfoPage.jsx
JSX.
import React from 'react'
import { useEffect, useState } from "react";
import { useNavigate, useParams, Link } from "react-router";
import { useSelector } from "react-redux";
import service from "../appwrite/config";
import CircleProgress from "./CircleProgress";
import BtnDialog from "./BtnDialog";
import { ExclamationCircleIcon } from "@heroicons/react/24/outline";
import "../App.css";
import { Message } from 'rsuite';
function Infopage() {
const status = useSelector((state) => state.auth.status);
const userData = useSelector((state) => state.auth.userData);
44
const [post, setPost] = useState(null);
const navigate = useNavigate();
const { slug } = useParams();
useEffect(() => {
if (slug) {
service.getPost(slug).then((res) => {
if (res) {
setPost(res);
}
});
} else {
navigate("/");
}
}, [slug, navigate]);
const isAuthor = post && userData ? post.userId === userData.$id : false;
return post ? (
<>
<div className="h-fit bg-white w-3/4 max-sm:w-full outline outline-1 pt-2 pb-10 px-5 text-slate-
700 outline-slate-300 justify-self-center max-lg:h-fit">
<h1 className=" font-semibold text-md max-lg:text-sm mb-3 ">
{post.title}
</h1>
45
{/* bottom */}
<div className=" h-1/3 flex max-lg:flex-col pt-4">
{/* first portion */}
<div className="w-2/3 border-r pr-2 max-lg:w-full max-lg:border-r-0 pb-4 max-lg:border-b">
<h1 className="max-lg:text-xl text-3xl text-slate-950 font-bold">
{post.title}
</h1>
<p className="max-lg:text-xs text-base text-slate-600 mt-2 font-normal">
{post.description}
</p>
<h2 className="max-lg:text-sm text-xl font-semibold mt-4 text-slate-950">
Expectaion Info
</h2>
<p className="max-lg:text-xs text-base text-slate-600 mt-2 font-normal">
{post.expectdescription}
</p>
</div>
48
SCREENSHOTS
49
50
51
52
RESULTS
1. Neighborhood Swap Zones– Users can list personal items they no longer need and
browse items listed by others. Instead of buying or selling, they simply propose a swap.
4. Event Material Swapping – Allows citizens to apply for welfare programs with minimal
effort, increasing scheme adoption rates.
7. Scalable Model – Can be expanded to integrate additional services like property tax
payments, employment schemes, and local business support.
53
APPLICATIONS
1. Item Exchange Platform– Users can list personal items they no longer need and browse
items listed by others. Instead of buying or selling, they simply propose a swap.
4. Event Material Swapping – Allows citizens to apply for welfare programs with minimal
effort, increasing scheme adoption rates.
6. Green Lifestyle Promotion – Helps Gram Panchayat authorities manage user requests
and public interactions efficiently.
54
CONCLUSION
Overall, the SWAPPY Application bridges the gap between rural citizens and their local
governing bodies, fostering a more responsive and accountable governance system. Its scalable
nature allows for future expansions, making it a valuable tool for digital governance in rural
India.
55
FUTURE SCOPE
1. Mobile App Integration– Develop Android and iOS versions of Swappy for easier access
and better user experience. Enable push notifications for swap requests, messages, and
approvals.
2. Geolocation-Based Swapping – Enable users to swap items with others nearby to reduce
delivery efforts.
3. AI-Powered Matchmaking –Implement AI to suggest best swap matches based on user
preferences, location, and item category.
4. Multi-Language Support – Expanding language options to make the app more accessible
for users from diverse linguistic backgrounds.
5. Automated Notifications & Reminders – Enhancing user engagement by providing push
notifications for service status updates, announcements, and meeting reminders.
6. Data-Driven Governance – Implementing analytics tools to help Gram Panchayat officials
track service requests, complaint patterns, and citizen participation trends for better decision-
making.
7. Scalability and Integration: The system is designed to be scalable, with the potential for
future integration with other government e-Governance frameworks, ensuring the platform
can evolve with the growing needs of rural governance.
56
REFERENCES
57