arpit-project-report
arpit-project-report
A
Project - 1 Report
Submitted
In partial fulfillment
For the award of the Degree Of
Bachelor of Technology
in Department of Computer Science & Engineering
ARPIT JAIN
KISHANGARH, RAJASTHAN
CERTIFICATE
I hereby declare that the work, which is being presented in the Project
Report, entitled “House-hold Service Using Flask and Sqlite3” in partial
fulfillment for the award of Degree of “Bachelor of Technology” in Dept.
of Computer Science and submitted to the Department of Computer
Science & Engineering. St. Wilfred’s Institute of Engineering &
Technology, Bikaner Technical University is a record of my own
investigations carried under the Guidance of Mr. Mangi Lal Sir ,
Department of Computer Science & Engineering & Technology.
I have not submitted the matter presented in this Project - 1 any where
for the award of any other Degree.
ARPIT JAIN
21EWECS004
St. Wilfred’s Institute of Engineering & Technology
Counter Signed by
Mr. Mangi Lal Sir (HOD)
ABSTRACT
The Household Services Web Application is a dynamic platform
designed to connect customers with professional service providers for
home maintenance needs. It facilitates seamless booking and
management of services such as cleaning, plumbing, electrical repairs,
and more. The platform ensures a smooth user experience through an
intuitive interface and structured service categorization.
Introduction
1.1 Overview of the Project
1.2 Problem Statement
1.3 Objectives
1.4 Scope of the Project
Literature Review
2.1 Existing Solutions and Their Limitations
2.2 Need for an Online Household Services Platform
Technologies Used
4.1 Flask (Back-end Framework)
4.2 SQLite3 (Database)
4.3 Jinja2 (Templating Engine)
4.4 HTML, CSS, and Bootstrap (Front-end)
Implementation Details
5.1 User Authentication and Role Management
5.2 Service Listing and Booking Functionality
5.3 Database Schema and Tables
5.4 Interactive Features (Carousel, Filters, Search)
5.5 Session Management and Security Measures
This project aims to address these challenges by creating a centralized platform that
offers secure, efficient, and convenient household service booking for customers
while providing professionals with a structured way to manage their clients.
1.3 Objectives
The primary objectives of this project are:
User Management: Separate registration and login for customers and service
providers.
Service Listing and Booking: Users can browse, select, and book services, while
professionals can manage their listings.
Database Management: All user and service-related data is securely stored in
SQLite3.
Dynamic UI: Interactive features such as Jinja2 templating, Bootstrap-based design,
and a service carousel for enhanced usability.
Scalability: The system is designed to be scalable, allowing future enhancements
such as payment integration, user reviews, and real-time notifications.
By implementing this system, the project aims to streamline the household service
industry by making professional services more accessible, reliable, and efficient.
Literature Review
1. Traditional Methods
Word of Mouth & Local Contacts: Many people rely on recommendations from
friends and family to hire professionals. While this method provides some level of
trust, it lacks reliability, as service availability is uncertain, and comparing multiple
options is difficult.
Offline Service Centers: Some businesses operate through call-based bookings, but
they often lack real-time availability updates and proper tracking systems.
Lack of Localized Service Options: Many platforms do not focus on specific localities,
making it hard to find nearby professionals.
High Service Fees & Commissions: Aggregator platforms charge high service fees,
reducing affordability.
Limited Verification of Professionals: Many platforms do not ensure background
verification of service providers.
Complex Interfaces: Some websites and mobile apps are difficult for users with
minimal technical knowledge.
These limitations highlight the need for a simple, localized, and cost-effective
platform that connects customers with household service providers efficiently.
2.2 Need for an Online Household
Services Platform
With increasing digital adoption, an online platform dedicated to household services
can streamline service bookings, improve customer experience, and create new
opportunities for service providers. The proposed system offers the following
benefits:
Easy and Direct Booking: Customers can select services, schedule appointments,
and receive confirmation seamlessly.
Role-Based Authentication: The system differentiates between customers and
service providers, ensuring smooth functionality.
Secure and Transparent Transactions: Ensures verified professionals and session-
based authentication for security.
User-Friendly Interface: A Bootstrap-based responsive UI ensures accessibility for
users across different devices.
Scalability & Future Enhancements: Can be extended to include features like real-
time notifications, payment integration, and customer reviews.
By addressing the gaps in existing solutions, this project aims to bridge the gap
between customers and professionals, making household services more accessible,
affordable, and efficient.
System Design and Architecture
o Built with HTML, CSS, Bootstrap, and Jinja2 for dynamic rendering.
o Provides user-friendly pages for login, registration, service listings, and
booking management.
o Stores user information, service listings, booking details, and session data.
o Ensures efficient data retrieval and storage.
Booking Management
Main Entities:
Users: Stores details of both customers and service providers.
Services: Contains service categories, descriptions, and pricing.
Bookings: Maintains booking status, customer details, and assigned service
providers.
Relationships:
One customer can book multiple services.
One service provider can offer multiple services.
Each booking is linked to a specific customer and service provider.
Summary
This section outlines the system architecture, data flow, and database design,
forming the foundation for the project’s implementation. The structured approach
ensures scalability, security, and efficient service management.
Technologies Used
In the development of the Household Services web application, a combination of
various modern technologies was used to ensure a seamless, user-friendly
experience. The following is a detailed description of the key technologies
implemented:
Frontend:
Backend:
1. Flask (Python): Flask is a lightweight Python web framework that was used
to build the backend of the web application. It provides the flexibility to
handle user requests, render templates, and manage routes effectively.
2. SQLAlchemy: For database management, SQLAlchemy, an Object-Relational
Mapper (ORM) for Python, was used to interact with the PostgreSQL
database. It abstracts complex SQL queries and allows for easier data
manipulation through Python objects.
3. PostgreSQL: A powerful, open-source relational database system,
PostgreSQL was used to store user data, service requests, and other
essential application information. Its advanced querying capabilities were
leveraged to ensure efficient data retrieval.
4. Flask-WTF: This extension was used for handling form validation securely. It
integrates Flask with WTForms, allowing for easy handling of form
submission and preventing cross-site scripting (XSS) vulnerabilities.
1. Heroku: Heroku was chosen as the platform for hosting the web application.
Its simplicity in deployment, scalability options, and support for Python
applications made it the ideal choice.
2. GitHub: GitHub was used for version control, allowing multiple developers
to collaborate on the project efficiently and track changes in the codebase.
These technologies were integrated into the project to ensure smooth functionality,
easy scalability, and a secure environment for users interacting with the platform.
Implementation Details
The development of the Household Services web application involved several key
implementation steps, combining frontend and backend technologies to create a
seamless user experience. Below is an overview of the implementation process,
detailing how various features and components were integrated.
Frontend Implementation:
1. HTML5 Structure: The web pages were structured using HTML5 semantic
elements such as <header>, <footer>, <section>, and <article> to ensure a clean
and well-organized layout. Each page was designed with accessibility and
responsiveness in mind.
2. CSS3 Styling: CSS was used to style the application, ensuring a modern,
clean, and responsive design. Flexbox and CSS Grid were utilized for layouts,
while media queries allowed for mobile optimization.
3. JavaScript for Interactivity: JavaScript was used to add interactive elements,
such as the dynamic toggling of navigation menus, form validations, and
real-time updates (e.g., when users submit service requests or update their
profiles).
4. AJAX for Asynchronous Requests: AJAX was used in combination with
JavaScript to allow the web application to make asynchronous requests to
the server without reloading the page. This was implemented to refresh user
data, service availability, and ratings without interrupting the user
experience.
Backend Implementation:
1. Admin Dashboard: The admin dashboard was designed to manage user data,
service providers, and bookings. Admins have the ability to view and
approve or reject service requests and manage service provider profiles.
2. Service Provider Dashboard: Service providers can view their bookings, set
their availability, and track their earnings through their dedicated dashboard.
They can also update their profiles and view customer feedback.
Payment Integration:
Real-Time Notifications:
Deployment:
1. Heroku Hosting: The application was deployed on Heroku, which allows easy
deployment and scaling for web applications. A Procfile was created to tell
Heroku how to run the application, and environment variables were
configured for sensitive information such as database credentials and API
keys.
2. Continuous Integration/Deployment: GitHub was used for version control,
and GitHub Actions was set up to automate the deployment process to
Heroku whenever new changes were pushed to the repository.
Security Measures:
1. Data Encryption: All sensitive user data, including passwords, were securely
encrypted using SHA-256 hashing. Secure HTTPS connections were enforced
throughout the platform.
2. Input Validation: To prevent SQL injection and cross-site scripting (XSS), user
inputs were validated and sanitized both on the frontend (using JavaScript)
and backend (using Flask-WTF forms).
3. Role-Based Access Control: The application implements role-based access
control, ensuring that only authorized users can access specific parts of the
system, such as admin functions or service provider dashboards.
1. Unit Testing: Python’s unittest framework was used to write unit tests for
critical application components, such as user authentication, service booking
logic, and payment processing.
2. Manual Testing: Extensive manual testing was conducted to ensure that all
features were working as expected. This included testing user registration,
login functionality, booking processes, and payment gateway integration.
Responsive Design:
User-Centric Navigation:
1. A simple yet effective navigation bar is placed at the top of each page,
providing easy access to the core sections of the platform, such as Home,
Services, Login/Signup, User Dashboard, and Admin Dashboard (for
administrators). Clear, concise labels make navigation intuitive for all users,
regardless of technical expertise.
2. Breadcrumbs are used in service listings and profile pages to allow users to
easily trace their steps back to the homepage or previous pages, enhancing
navigation efficiency.
1. A powerful search and filter mechanism allows users to quickly find services
by category, location, price range, and provider ratings. Filters are displayed
prominently and can be easily adjusted with a few clicks.
2. Service providers are also categorized by their expertise, which helps users
browse the available options based on their specific needs, such as plumbing,
electrical services, or home cleaning.
Seamless Booking Experience:
1. Notifications and alerts are designed to keep users informed without being
intrusive. Service confirmation emails, booking reminders, and status
updates are all sent promptly via email. In-app alerts also provide real-time
feedback on successful bookings, payment status, and service provider
availability.
2. Users can also view and manage notifications in the notification panel on
their dashboard, ensuring that they don't miss important updates.
1. Users and service providers have personalized profile pages that display
relevant information. For users, this includes booking history, saved services,
and contact details. Service providers can manage their availability, service
offerings, and earnings through their dedicated dashboard.
2. The design ensures that profile pages are easy to navigate and update. Clear
action buttons are provided for common tasks like updating personal
information, changing passwords, or editing service details.
Unit Testing:
Integration Testing:
1. Integration testing was carried out to ensure that different modules of the
application worked together as expected. This testing phase checked how
the frontend interacted with the backend and whether data was passed
correctly between different system components.
2. Special focus was given to testing interactions between the user interface
(UI) and the backend, such as service requests, profile management, and
payment processing. Integration tests were used to verify that these
components worked seamlessly together and provided the correct user
experience.
End-to-End Testing:
Manual Testing:
1. Manual testing was performed by the development team to identify issues
that automated tests might have missed, especially related to user
experience (UX) and interface issues. Testers manually navigated through
the platform, performing tasks such as:
2. User feedback was also collected during manual testing to identify areas for
improvement, especially in terms of usability.
Cross-Browser Testing:
1. Mobile testing was conducted on both Android and iOS devices to ensure
that the platform was fully functional and visually appealing on smartphones
and tablets. Responsive design tools and physical device testing were used
to verify that all core functionalities—such as booking services, managing
profiles, and making payments—were accessible on mobile devices without
issues.
2. Specific attention was paid to touch interactions, ensuring that all buttons
and elements were easy to tap on smaller screens.
Security Testing:
1. Security testing was performed to ensure that user data, especially sensitive
information like passwords and payment details, was protected. Common
vulnerabilities, such as SQL injection, cross-site scripting (XSS), and cross-site
request forgery (CSRF), were tested and mitigated using best practices.
2. Password Hashing: The application uses secure password hashing
algorithms (e.g., bcrypt) to protect user passwords. Security audits were
performed to verify that passwords were being securely hashed and stored.
3. Session Management: Flask-Login was used to manage user sessions, and its
session handling was tested to ensure that users’ data was not exposed or
compromised. Session expiration and invalidation mechanisms were also
tested.
Performance Testing:
1. Performance testing was conducted to ensure that the application could
handle a large number of users and service requests simultaneously. Load
testing tools such as Apache JMeter were used to simulate heavy traffic and
test the application's scalability.
2. The response times of different pages and features, such as service searches,
booking forms, and payment processing, were monitored to ensure optimal
performance under load.
1. Bug Tracking: Any issues or bugs identified during testing were logged and
tracked using tools like GitHub Issues and Trello. This ensured that all
problems were addressed and resolved in an organized manner.
2. Debugging: The debugging process involved isolating issues, analyzing logs,
and using Python's built-in debugger (pdb) to inspect variables and trace the
root cause of errors. Browser developer tools were also used to debug front-
end issues related to JavaScript, CSS, and HTML.
3. Error Handling: Custom error pages were implemented for common issues
such as 404 (Page Not Found) and 500 (Internal Server Error). These pages
provided users with helpful information, maintaining a positive user
experience even when issues occurred.
1. After all functional and technical testing phases, User Acceptance Testing
(UAT) was conducted to ensure that the application met the requirements of
the users and stakeholders. Real users were asked to perform tasks similar
to those they would encounter in a real-world scenario. Feedback from UAT
was collected to make any final adjustments to the platform before launch.
Through this comprehensive testing and debugging process, the Household Services
web application was ensured to be both stable and reliable. Issues were identified
and resolved in a timely manner, leading to a polished product ready for deployment.
Results and Discussion
The development and testing of the Household Services web application aimed to
provide a seamless, user-friendly experience while maintaining a high standard of
functionality and performance. This section discusses the results achieved during the
implementation of the application and reflects on the overall effectiveness of the
design, testing, and user experience.
User and Service Provider Registration: Both users and service providers can easily
sign up and create their profiles. The application successfully distinguishes between
normal users and professional service providers, assigning the correct roles and
permissions.
Service Search and Booking: The search functionality allows users to find services by
category, price range, and ratings. The booking process is straightforward, with users
able to select available time slots, submit requests, and make payments seamlessly.
Payment Integration: The integration of a secure payment gateway was successful,
allowing users to process payments for services without issues. Payments are
recorded and linked to user accounts for easy tracking and management.
Clean and Responsive Design: The application’s design was optimized for both
desktop and mobile devices, ensuring that users could access and use the platform
regardless of their device. This responsiveness was crucial in maintaining a high-
quality experience across different screen sizes.
User-Centric Navigation: The navigation menu, with clearly labeled sections and
simple actions, allowed users to quickly find what they were looking for without
confusion. The intuitive design helped users easily transition between pages, from
the service listings to the booking and payment sections.
Engaging Dashboards: The user and service provider dashboards were effective in
organizing information and allowing users to quickly manage their services, bookings,
and profiles. The feedback mechanism, where users can rate and review service
providers, enhanced interaction within the platform.
Load Testing Results: During load testing, the platform successfully handled
simulated traffic from hundreds of users making service bookings and payments. The
system remained stable under these conditions, showing that it is scalable and can
support future growth.
Optimized Speed: The application loads quickly, thanks to optimized images,
efficient caching, and the use of modern web technologies like AJAX for
asynchronous updates.
5. Testing Results:
The testing phase confirmed that the application met its functional and performance
requirements:
Bug Fixes and Debugging: A few minor bugs were identified during the testing
phases, such as issues with form validation and mobile responsiveness. However,
these were promptly addressed, and no critical bugs remained by the end of testing.
Cross-Browser and Mobile Testing: The platform was thoroughly tested across
different browsers and devices. It performed consistently well across all platforms,
with no significant issues related to browser compatibility or mobile responsiveness.
User Acceptance Testing (UAT): Feedback from real users during the UAT phase was
positive, with users praising the simplicity and ease of use of the platform. No major
usability issues were reported, and most users felt confident navigating the site
without assistance.
Future Enhancements: While the application meets its core requirements, future
improvements could include:
In summary, the Household Services web application achieved its objectives and
provides a solid foundation for future growth and development. The successful
implementation of the features, security measures, and positive user feedback
indicates that the platform is ready for deployment and can meet the needs of its
users and service providers.
Appendices (Code Snippets, Screenshots)
Code Snippets:
Templates Directory:
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>HandyHome</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Slab:[email protected]
0&family=Rozha+One&display=swap" rel="stylesheet">
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
body {
width: 100%;
background: linear-gradient(360deg, #A96844, rgb(27, 125,
102));
justify-content: right;
/* height: 100%; */
}
.nav-item a {
font-size: 30px;
}
.navbar-brand img {
width: 65px;
height: auto;
}
.navbar-brand span {
font-size: 5rem;
}
#services {
color: #381C07;
font-weight: lighter;
margin-right: 110px;
}
#contact, #register {
border: 4px solid #F7B583;
font-weight: 500;
border-radius: 5px;
padding: 8px .5rem;
}
#contact {
color: #F7B583;
background-color: transparent;
margin-right: 100px;
}
#register {
background-color: #F7B583;
color: #381C07;
margin-right: 90px;
}
#services:hover {
transition: 0.3s;
color: #F7B583;
text-align: center;
}
#contact:hover {
transition: 0.3s;
color: #381C07;
border-color: #381C07;
box-shadow: 0px 0px 20px 3px rgba(56, 28, 7, 0.3);
}
#register:hover {
transition: 0.3s;
color: #F7B583;
border-color: #381C07;
background-color: #381C07;
box-shadow: 0px 0px 20px 3px rgba(56, 28, 7, 0.3);
}
@media (max-width: 1310px) {
.navbar-brand img {
width: 42px;
}
.navbar-brand span {
font-size: 2rem;
}
.nav-item a {
font-size: 25px;
}
}
@media (max-width: 999px) {
.navbar-brand img {
width: 42px;
}
.navbar-brand span {
font-size: 2rem;
}
.nav-item a {
font-size: 15px;
}
}
.main-section {
display: flex;
align-items: center;
font-family: 'Rozha One', serif;
min-height: 100vh;
padding: 30px;
}
.headline {
margin-top: 100px;
font-size: 3rem;
color: #381C07;
}
.subheadline {
font-size: 3.5rem;
color: #F7B583;
}
.description {
font-size: 2rem;
font-family: "Roboto Slab", serif;
color: #381C07;
margin-top: 20px;
}
.logo {
max-width: 100%;
height: auto;
}
@media (max-width: 768px) {
.headline {
font-size: 2.5rem;
}
.subheadline {
font-size: 2.8rem;
}
.description {
font-size: 1rem;
}
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-transparent">
<div class="container-fluid">
<a class="navbar-brand d-flex align-items-center" href="#">
<img src="..\static\navbar-logo_1.png" alt="logo"
style="margin-left: .6rem;" class="d-inline-block align-top">
<span class="ms-2" style="font-family: Roboto, system-ui,
-apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu,
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; color: #381C07;
font-weight: bold;">andyHome</span>
</a>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script>
</body>
</html>
Admin-dashboard.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Admin Dashboard</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
background: linear-gradient(360deg, #A96844, rgb(27, 125,
102));
background-attachment: fixed;
}
.nav-item a {
font-size: 1.1rem;
}
.navbar-brand span {
font-size: 1.5rem;
}
.nav-item a {
font-size: 0.9rem;
}
}
.custom-search-btn {
background-color: #ff5733;
color: white;
}
.custom-search-btn:hover {
background-color: #c0392b;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('edit_profile',
full_name=full_name) }}">
<span><strong>Welcome</strong> Admin</span>
</a>
<button class="navbar-toggler ms-auto" type="button" data-
bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-
label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Summary</a>
</li>
<li class="nav-item">
<form class="d-flex" role="search">
<input class="form-control me-2"
type="search" placeholder="Search" aria-label="Search">
<button class="btn custom-search-btn"
type="submit">Search</button>
</form>
</li>
<li class="nav-item">
<a class="nav-link"
href="{{ url_for('home') }}">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="mt-4 container-fluid">
<h3>Service Management</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Service Name</th>
<th>Base Price</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% if services | length > 0 %}
{% for i in range(services | length) %}
<tr>
<td>{{ services[i].id }}</td>
<td>{{ services[i].service_name }}</td>
<td>{{ services[i].service_price }}</td>
<td><button class="btn btn-primary btn-
sm">Edit/Delete</button></td>
</tr>
{% endfor %}
{% endif %}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<button class="btn btn-success" data-bs-toggle="modal" data-bs-
target="#newServiceModal">+ New Service</button>
</div>
<div class="modal fade" id="newServiceModal" tabindex="-1" aria-
labelledby="newServiceModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"
id="newServiceModalLabel">Add New Service</h5> <button type="button"
class="btn-close" data-bs-dismiss="modal" aria-
label="Close"></button>
</div>
<div class="modal-body">
<form action="/admin-dashboard" method="POST">
<div class="form-group">
<label for="serviceName">Service Name</label>
<input name="service_name" type="text"
class="form-control" id="serviceName" required>
</div>
<div class="form-group">
<label for="basePrice">Base Price</label>
<input name="base_price" type="number"
class="form-control" id="basePrice" required>
</div>
<div class="form-group">
<label for="serviceDescription">Service
Description</label>
<textarea name="service_description"
class="form-control" id="serviceDescription" rows="3"
required></textarea>
</div>
<button type="submit" class="btn btn-primary mt-
2">Save</button>
</form>
</div>
</div>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script> </body>
</body>
</html>
Contact-us.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact Us</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Slab:[email protected]
0&family=Rozha+One&display=swap" rel="stylesheet">
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
body {
width: 100%;
background-color: rgb(27, 125, 102);
height: 100%;
}
.contact-container {
padding: 50px 0;
}
.contact-form .form-control {
border-radius: 20px;
}
.contact-header {
text-align: center;
margin-bottom: 50px;
}
</style>
</head>
<body>
<div class="container contact-container">
<div class="contact-header">
<h2>Contact Us</h2>
<p>We would love to hear from you. Please fill out the form below
to reach us.</p>
</div>
<div class="row">
<div class="col-md-6">
<form action="#" method="POST" class="contact-form">
<div class="form-group">
<label for="name">Full Name</label>
<input type="text" class="form-control" id="name"
placeholder="Enter your full name" required>
</div>
<div class="form-group">
<label for="email">Email Address</label>
<input type="email" class="form-control" id="email"
placeholder="Enter your email" required>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea class="form-control" id="message" rows="4"
placeholder="Your message here..." required></textarea>
</div>
<button type="submit" class="btn btn-primary btn-block">Send
Message</button>
</form>
</div>
<div class="col-md-6">
<h3>HandyHome - Household Services</h3>
<p><strong>Address:</strong> 123 Main Street, Kishangarh,
Rajasthan</p>
<p><strong>Phone:</strong> +91 999999999</p>
<p><strong>Email:</strong> [email protected]</p>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script>
</body>
</html>
Edit-profile.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>HandyHome - Edit Profile</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
* {
margin: 0px;
padding: 0px;
}
body {
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, rgb(27, 125, 102),
#F7B583);
height: 100vh;
}
.container {
max-width: 500px;
margin: 50px 0px;
background: rgba(101, 214, 184, 0.4);
backdrop-filter: blur(10px);
text-align: center;
border-radius: 15px;
box-shadow: 0px 0px 10px 5px rgba(18, 84, 69, 0.3);
padding: 30px;
color: #FFFFFF;
}
.container h1 {
color: #F7B583;
font-family: system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica
Neue', sans-serif;
font-size: 2rem;
font-weight: 700;
margin-bottom: 20px;
}
.container p {
color: white;
font-family: Roboto, sans-serif;
margin-bottom: 30px;
}
.form-group{
text-align: left;
margin-bottom: 10px;
}
.form-group label {
color: white;
font-size: 15px;
font-family: Roboto, sans-serif;
}
.form-control {
background-color: rgb(230, 229, 229);
border: none;
border-radius: 3px;
}
button {
background-color: black;
border: none;
color: #F7B583;
font-family: Roboto, sans-serif;
padding: 12px 30px;
border-radius: 25px;
width: 100%;
margin-top: 20px;
}
button:hover {
box-shadow: 0px 0px 20px 10px rgba(247, 181, 131, 0.3);
transition: 0.3s;
background-color: #F7B583;
color: black;
}
.icons {
color: #F7B583;
margin-right: 5px;
}
#login-anchor:hover {
color: #F7B583;
}
#signin-anchor:hover {
color: #F7B583;
}
</style>
</head>
<body>
<div class="container">
<h1>Update Your Profile</h1>
<p>Keep your profile up-to-date to ensure a seamless experience with
HandyHome. Update your details below and submit to save changes.</p>
<form action="{{ url_for('edit_profile', full_name =
user.full_name ) }}" method="POST">
<div class="form-group">
<label for="email"><ion-icon name="mail"
class="icons"></ion-icon>Email</label>
<input name="email" type="email" class="form-control"
value="{{ user.user_name }}" readonly>
</div>
<div class="form-group">
<label for="password"><ion-icon name="lock-closed"
class="icons"></ion-icon>Password</label>
<input name="password" type="password" class="form-
control" required value="{{ user.password }}">
</div>
<div class="form-group">
<label for="name"><ion-icon name="person"
class="icons"></ion-icon>Full Name</label>
<input name="full_name" type="text" class="form-control"
required value="{{ user.full_name }}">
</div>
<div class="form-group">
<label for="phone"><ion-icon name="call"
class="icons"></ion-icon>Phone No.</label>
<input name="phone_no" type="tel" class="form-control"
required value="{{ user.phone_no }}">
</div>
<div class="form-group">
<label for="pincode"><ion-icon name="pin"
class="icons"></ion-icon>Pincode</label>
<input name="pincode" type="number" class="form-control"
value="{{ user.pincode }}">
</div>
<div class="form-group">
<label for="address"><ion-icon name="location"
class="icons"></ion-icon>Address</label>
<textarea name="address" class="form-control"
rows="3">{{ user.address }}</textarea>
</div>
<button type="submit" style="margin-bottom:
10px;">Submit</button>
</form>
</div>
<script type="module"
src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></
script>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script>
</body>
</html>
Professional-signup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>HandyHome-Register</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
* {
margin: 0px;
padding: 0px;
}
body {
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, rgb(27, 125, 102),
#F7B583);
height: 100%;
}
.container {
max-width: 500px;
margin: 50px 0px;
background: rgba(101, 214, 184, 0.4);
backdrop-filter: blur(10px);
text-align: center;
border-radius: 15px;
box-shadow: 0px 0px 10px 5px rgba(18, 84, 69, 0.3);
padding: 30px;
color: #FFFFFF;
}
.container h1 {
color: #F7B583;
font-family: system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica
Neue', sans-serif;
font-size: 2rem;
font-weight: 700;
margin-bottom: 20px;
}
.container p {
color: white;
font-family: Roboto, sans-serif;
margin-bottom: 30px;
}
.form-group{
text-align: left;
}
.form-group label {
color: white;
font-size: 15px;
font-family: Roboto, sans-serif;
}
.form-control {
background-color: rgb(230, 229, 229);
border: none;
border-radius: 15px;
}
button {
background-color: black;
border: none;
color: #F7B583;
font-family: Roboto, sans-serif;
padding: 12px 30px;
border-radius: 25px;
width: 100%;
margin-top: 20px;
}
button:hover {
box-shadow: 0px 0px 20px 10px rgba(247, 181, 131, 0.3);
transition: 0.3s;
background-color: #F7B583;
color: black;
}
.icons {
color: rgb(247, 181, 131);
margin-right: 5px;
}
#login-anchor:hover {
color: #F7B583;
}
#signin-anchor:hover {
color: #F7B583;
}
</style>
</head>
<body>
<div class="container">
<h1>Join Our Team of Experts!</h1>
<p>Ready to showcase your skills and grow your career? Register
as a professional to connect with clients seeking top-quality household
services.</p>
<form action="{{ url_for('professional_signup') }}"
method="POST">
<div class="form-group text-left">
<label for="email"><ion-icon name="mail"
class="icons"></ion-icon>Email</label>
<input name="email" type="email" class="form-control"
required>
</div>
<div class="form-group text-left">
<label for="password"><ion-icon name="lock-closed"
class="icons"></ion-icon>Password</label>
<input name="password" type="password" class="form-
control" required>
</div>
<div class="form-group text-left">
<label for="name"><ion-icon name="person"
class="icons"></ion-icon>Full Name</label>
<input name="full_name" type="text" class="form-control"
required>
</div>
<div class="form-group text-left">
<label for="phone"><ion-icon name="call"
class="icons"></ion-icon>Phone No.</label>
<input name="phone_no" type="tel" class="form-control">
</div>
<div class="form-group text-left">
<label for="name"> <svg
xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0
0 2048 2048"><path fill="#f7b583" d="M1185 1179q-88-75-195-115t-222-
40q-88 0-170 23t-153 64t-129 100t-100 130t-65 153t-23 170H0q0-120 35-
231t101-205t156-167t204-115q-113-74-176-186t-64-248q0-106 40-199t109-
163T568 40T768 0t199 40t163 109t110 163t40 200q0 66-16 129t-48 119t-75
103t-101 83q65 25 124 61t111 81zM384 512q0 80 30 149t82 122t122 83t150
30q79 0 149-30t122-82t83-122t30-150q0-79-30-149t-82-122t-123-83t-149-
30q-80 0-149 30t-122 82t-83 123t-30 149m1344 256q66 0 124 25t101 69t69
102t26 124t-25 124t-69 102t-102 69t-124 25q-23 0-45-3l-587 587q-27 27-
62 41t-74 15q-40 0-75-15t-61-41t-41-61t-15-75q0-38 14-73t42-63l587-
587q-3-22-3-45q0-66 25-124t68-101t102-69t125-26m0 512q40 0 75-15t61-
41t41-61t15-75q0-41-19-82l-146 146h-91v-91l146-146q-41-19-82-19q-40 0-
75 15t-61 41t-41 61t-15 75q0 41 19 82l-640 641q-19 19-19 45t19 45t45
19t45-19l641-640q41 19 82 19"/></svg> Service Name</label>
<input name="service_name" type="text" class="form-
control" required>
</div>
<div class="form-group text-left">
<label for="experience"><ion-icon name="briefcase"
class="icons"></ion-icon>Experience (in years)</label>
<input name="experience" type="number" class="form-
control">
</div>
<div class="form-group text-left">
<label for="pincode"><ion-icon name="pin"
class="icons"></ion-icon>Pincode</label>
<input name="pincode" type="number" class="form-
control">
</div>
<div class="form-group text-left">
<label for="address"><ion-icon name="location"
class="icons"></ion-icon>Address</label>
<textarea name="address" class="form-control"
rows="3"></textarea>
</div>
<button type="submit" style="margin-bottom: 10px;">Sign
up</button>
</form>
<p>Already a user? <a id="login-anchor"
href="{{ url_for('login') }}" name="login">Login</a></p>
<p><a id="signin-anchor" href="{{ url_for('register') }}"
name="login">Register as user </a></p>
</div>
<script type="module"
src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></
script>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script>
<script
src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
</body>
</html>
Register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>HandyHome-Register</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
* {
margin: 0px;
padding: 0px;
}
html{
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, rgb(27, 125, 102),
#F7B583);
width: 100%;
height: 100%;
}
.container {
max-width: 500px;
margin: 50px 0px;
background: rgba(101, 214, 184, 0.4);
backdrop-filter: blur(10px);
text-align: center;
border-radius: 15px;
box-shadow: 0px 0px 10px 5px rgba(18, 84, 69, 0.3);
padding: 30px;
color: #FFFFFF;
}
.container h1 {
color: #F7B583;
font-family: system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica
Neue', sans-serif;
font-size: 2rem;
font-weight: 700;
margin-bottom: 20px;
}
.container p {
color: white;
font-family: Roboto, sans-serif;
margin-bottom: 30px;
}
.form-group{
text-align: left;
}
.form-group label {
color: white;
font-size: 15px;
font-family: Roboto, sans-serif;
}
.form-control {
background-color: rgb(230, 229, 229);
border: none;
border-radius: 15px;
}
button {
background-color: black;
border: none;
color: #F7B583;
font-family: Roboto, sans-serif;
padding: 12px 30px;
border-radius: 25px;
width: 100%;
margin-top: 20px;
}
button:hover {
box-shadow: 0px 0px 20px 10px rgba(247, 181, 131, 0.3);
transition: 0.3s;
background-color: #F7B583;
color: black;
}
.icons {
color: #F7B583;
margin-right: 5px;
}
#login-anchor:hover {
color: #F7B583;
}
#signin-anchor:hover {
color: #F7B583;
}
</style>
</head>
<body>
<div class="container">
<a href="/" style="text-decoration: none;"><h1>Welcome to
HandyHome</h1></a>
<p>Sign up to access trusted and professional household services,
tailored to your needs and schedule.</p>
<form action="{{ url_for('register') }}" method="POST">
<div class="form-group">
<label for="email"><ion-icon name="mail"
class="icons"></ion-icon>Email</label>
<input name="email" type="email" class="form-control"
required>
</div>
<div class="form-group">
<label for="password"><ion-icon name="lock-closed"
class="icons"></ion-icon>Password</label>
<input name="password" type="password" class="form-
control" required>
</div>
<div class="form-group">
<label for="name"><ion-icon name="person"
class="icons"></ion-icon>Full Name</label>
<input name="full_name" type="text" class="form-control"
required>
</div>
<div class="form-group">
<label for="phone"><ion-icon name="call"
class="icons"></ion-icon>Phone No.</label>
<input name="phone_no" type="tel" class="form-control">
</div>
<div class="form-group">
<label for="pincode"><ion-icon name="pin"
class="icons"></ion-icon>Pincode</label>
<input name="pincode" type="number" class="form-
control">
</div>
<div class="form-group">
<label for="address"><ion-icon name="location"
class="icons"></ion-icon>Address</label>
<textarea name="address" class="form-control"
rows="3"></textarea>
</div>
<button type="submit" style="margin-bottom: 10px;">Sign
up</button>
</form>
<p>Already a user? <a id="login-anchor"
href="{{ url_for('login') }}" name="login">Login</a></p>
<p><a id="signin-anchor"
href="{{ url_for('professional_signup') }}" name="login">Register as
professional </a></p>
</div>
<script type="module"
src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></
script>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script>
</body>
</html>
Service-packages.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>Best {{service.service_name}} Packages</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
background: linear-gradient(360deg, #A96844, rgb(27, 125,
102));
background-attachment: fixed;
}
.nav-item a {
font-size: 1.1rem;
}
.navbar-brand span {
font-size: 1.5rem;
}
@media (max-width: 768px) {
.navbar-brand span {
font-size: 1rem;
}
.nav-item a {
font-size: 0.9rem;
}
}
.custom-search-btn {
background-color: #ff5733;
color: white;
}
.custom-search-btn:hover {
background-color: #c0392b;
}
h2 {
text-align: center;
margin-top: 20px;
color: #ffffff;
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.7);
}
.container {
margin-top: 30px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
@media (max-width: 768px) {
.container {
background-color: none;
box-shadow: none;
}
}
.btn-book {
background-color: #28a745;
color: white;
font-weight: bold;
}
.btn-book:hover {
background-color: #218838;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('edit_profile',
full_name=full_name) }}">
<span> <strong> Welcome to {{service.service_name}}
Packages</strong> </span>
</a>
<button class="navbar-toggler ms-auto" type="button" data-
bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-
label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Summary</a>
</li>
<li class="nav-item">
<form class="d-flex" role="search">
<input class="form-control me-2"
type="search" placeholder="Search" aria-label="Search">
<button class="btn custom-search-btn"
type="submit">Search</button>
</form>
</li>
<li class="nav-item">
<a class="nav-link"
href="{{ url_for('home') }}">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h2>Best {{service.service_name}} Packages</h2>
{% if alert_message %}
<div class="alert alert-{{alert_type}}" role="alert">
{{ alert_message }}
</div>
{% endif %}
<div class="table-responsive">
<table class="table table-striped table-bordered text-
white">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>{{service.service_name}} Package</th>
<th>Price</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Basic {{service.service_name}} Package</td>
<td>{{base_price}}</td>
<form action="/user-
dashboard/{{full_name}}/service-request/{{service.service_name}}"
method="POST">
<td><button class="btn btn-book btn-
sm">Book</button></td>
</form>
</tr>
<tr>
<td>2</td>
<td>Medium {{service.service_name}} Package</td>
<td>{{base_price*2}}</td>
<form action="/user-
dashboard/{{full_name}}/service-request/{{service.service_name}}"
method="POST">
<td><button class="btn btn-book btn-
sm">Book</button></td>
</form>
</tr>
<tr>
<td>3</td>
<td>Premium {{service.service_name}} Package</td>
<td>{{base_price*3}}</td>
<form action="/user-
dashboard/{{full_name}}/service-request/{{service.service_name}}"
method="POST">
<td><button class="btn btn-book btn-
sm">Book</button></td>
</form>
</tr>
</tbody>
</table>
</div>
</div>
<div class="container my-5">
<h2 class="text-center mb-4">Service History</h2>
<div class="table-responsive">
</html>
Services.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>HandyHome - Services</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Slab:[email protected]
0&family=Rozha+One&display=swap" rel="stylesheet">
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
body {
width: 100%;
background: linear-gradient(360deg, #A96844, rgb(27, 125,
102));
height: 100%;
justify-content: right;
}
.nav-item a {
font-size: 30px;
}
.navbar-brand img {
width: 65px;
height: auto;
}
.navbar-brand span {
font-size: 5rem;
}
#services {
color: #381C07;
font-weight: lighter;
margin-right: 110px;
}
#contact, #register {
border: 4px solid #F7B583;
font-weight: 500;
border-radius: 5px;
padding: 8px .5rem;
}
#contact {
color: #F7B583;
background-color: transparent;
margin-right: 100px;
}
#register {
background-color: #F7B583;
color: #381C07;
margin-right: 90px;
}
#services:hover {
transition: 0.3s;
color: #F7B583;
text-align: center;
}
#contact:hover {
transition: 0.3s;
color: #381C07;
border-color: #381C07;
box-shadow: 0px 0px 20px 3px rgba(56, 28, 7, 0.3);
}
#register:hover {
transition: 0.3s;
color: #F7B583;
border-color: #381C07;
background-color: #381C07;
box-shadow: 0px 0px 20px 3px rgba(56, 28, 7, 0.3);
}
@media (max-width: 1310px) {
.navbar-brand img {
width: 42px;
}
.navbar-brand span {
font-size: 2rem;
}
.nav-item a {
font-size: 25px;
}
}
@media (max-width: 999px) {
.navbar-brand img {
width: 42px;
}
.navbar-brand span {
font-size: 2rem;
}
.nav-item a {
font-size: 15px;
}
}
.carousel-img {
height: 80vh;
}
.custom-card-style {
color: #F7B583;
}
.p-style {
color: #1B7D66;
}
.testimonial-custom {
color: #1B7D66;
}
.card:hover {
transition: 0.5s;
transform: scale(1.05);
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-transparent">
<div class="container-fluid">
<a class="navbar-brand d-flex align-items-center"
href="{{ url_for('home') }}">
<img src="..\static\navbar-logo_1.png" alt="logo"
style="margin-left: .1rem;" class="d-inline-block align-top">
<span class="ms-2" style="font-family: Roboto, system-ui,
-apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu,
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; color: #381C07;
font-weight: bold;">andyHome</span>
</a>
User-dashboard.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>HandyHome - Dashboard</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.m
in.css" rel="stylesheet">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
background: linear-gradient(360deg, #A96844, rgb(27, 125,
102));
background-attachment: fixed;
}
.nav-item a {
font-size: 1.1rem;
}
.navbar-brand span {
font-size: 1.5rem;
}
.custom-search-btn {
background-color: #ff5733;
color: white;
}
.custom-search-btn:hover {
background-color: #c0392b;
}
.carousel-inner {
width: 80%;
height: 60%;
overflow: hidden;
padding: 1em;
}
.card {
margin: 0 .5em;
box-shadow: 2px 6px 8px 0 rgba(22, 22, 26, 0.18);
border: none;
}
#carouselExampleControls{
display: flex;
justify-content: center;
}
.carousel-control-prev,
.carousel-control-next {
background-color: #e1e1e1;
width: 6vh;
height: 6vh;
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
}
@media (max-width:768px){
.carousel-control-prev,
.carousel-control-next {
display: none;
}
}
.container {
margin-top: 30px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
.card .image-wrapper {
max-width: 100%;
height: 23vw;
display: flex;
justify-content: center;
align-items: center;
}
img {
max-height: 100%;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('edit_profile',
full_name=full_name) }}">
<span> <strong> Welcome </strong> {{ full_name }}</span>
</a>
<button class="navbar-toggler ms-auto" type="button" data-
bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-
label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Summary</a>
</li>
<li class="nav-item">
<form class="d-flex" role="search">
<input class="form-control me-2"
type="search" placeholder="Search" aria-label="Search">
<button class="btn custom-search-btn"
type="submit">Search</button>
</form>
</li>
<li class="nav-item">
<a class="nav-link"
href="{{ url_for('home') }}">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div id="carouselExampleControls" class="carousel slide" data-bs-
ride="carousel">
<div class="carousel-inner" style="text-align: center;">
<h1>Looking For?</h1>
{% for i in range( services | length ) %}
{% if i == 0 %}
<div class="carousel-item active">
<div class="card">
<div class="image-wrapper">
<img
src="https://fakeimg.pl/300x200/?text={{ services[i].service_name }}&fo
nt=lobster" alt="{{ services[i].service_name }}">
</div>
<div class="card-body">
<h5 class="card-
title">{{ services[i].service_name}}</h5>
<p class="card-text">
{{ services[i].service_description }}
</p>
<a class="btn btn-primary"
href="{{url_for('service_request',full_name=full_name,
service=services[i].service_name)}}">Book Now</a>
</div>
</div>
</div>
{% endif %}
{% if i != ((services | length) - 1) %}
<div class="carousel-item">
<div class="card">
<div class="image-wrapper">
<img
src="https://fakeimg.pl/300x200/?text={{ services[i+1].service_name }}&
font=lobster" alt="{{ services[i+1].service_name }}">
</div>
<div class="card-body">
<h5 class="card-
title">{{ services[i+1].service_name}}</h5>
<p class="card-text">
{{ services[i+1].service_description }}
</p>
<a class="btn btn-primary"
href="{{url_for('service_request', full_name=full_name,service=services
[i+1].service_name)}}">Book Now</a>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-
target="#carouselExampleControls"
data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-
hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-
target="#carouselExampleControls"
data-bs-slide="next">
<span class="carousel-control-next-icon" aria-
hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
<div class="container my-5">
<h2 class="text-center mb-4">Service History</h2>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>Service Name</th>
<th>Professional Name</th>
<th>Phone No.</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>AC Repair</td>
<td>John Doe</td>
<td>+1234567890</td>
<td><button class="btn btn-success btn-sm">Close
it?</button></td>
</tr>
<!-- <tr>
<td>2</td>
<td>Cleaning</td>
<td>Jane Smith</td>
<td>+0987654321</td>
<td><span class="badge bg-
secondary">Closed</span></td>
</tr>
<tr>
<td>3</td>
<td>Saloon</td>
<td>Mike Ross</td>
<td>+1122334455</td>
<td><span class="badge bg-
primary">Requested</span></td>
</tr> -->
</tbody>
</table>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bun
dle.min.js"></script>
</body>
</html>
App.py
import os
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
import datetime
curr_dir = os.path.dirname(os.path.abspath(__file__))
app=Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///handyhome.sqlite3'
db = SQLAlchemy()
db.init_app(app)
app.app_context().push()
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
user_name = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(100), nullable=True)
full_name = db.Column(db.String(100), nullable=True)
phone_no = db.Column(db.Integer, nullable=True)
address = db.Column(db.Text, nullable=True)
pincode = db.Column(db.Integer, nullable=True)
is_admin = db.Column(db.Boolean, default=False)
is_professional = db.Column(db.Boolean, default=False)
is_houseowner = db.Column(db.Boolean, default=False)
is_available = db.Column(db.Boolean, nullable=True)
prof_experience = db.Column(db.Integer, nullable=True)
service_id = db.Column(db.Integer, db.ForeignKey('services.id'),
nullable=True)
service_name = db.Column(db.String(100), nullable=True)
# Many to one relationship between User and Services (many
professional can provide one service)
service = db.relationship('Services', back_populates='professional')
class Services(db.Model):
__tablename__ = 'services'
id = db.Column(db.Integer, primary_key=True)
service_name = db.Column(db.String(100), unique=True, nullable=False)
service_description = db.Column(db.Text, nullable=True)
time_required = db.Column(db.String(100), nullable=True)
service_price = db.Column(db.Integer, nullable=True)
# professional_id = db.Column(db.Integer, db.ForeignKey('users.id'),
nullable=False)
# One to many relationship between Services and User (one service
can be provided by many professionals)
professional = db.relationship('User', back_populates='service',
cascade="all, delete-orphan")
# Many to many - many services can have many requests
service_request = db.relationship('ServiceRequest',
back_populates='service', cascade="all, delete-orphan")
class ServiceRequest(db.Model):
__tablename__ = 'service_requests'
id = db.Column(db.Integer, primary_key=True)
service_id = db.Column(db.Integer, db.ForeignKey('services.id'),
nullable=False)
houseowner_id = db.Column(db.Integer, db.ForeignKey('users.id'),
nullable=False)
professional_id = db.Column(db.Integer, db.ForeignKey('users.id'),
nullable=False)
description = db.Column(db.Text, nullable=True) #description of the
request
status = db.Column(db.String(100), nullable=True) # pending,
accepted, closed, rejected
date_created = db.Column(db.DateTime,
default=datetime.datetime.now().date())
date_closed = db.Column(db.DateTime, nullable=True)
# Many to many - many services can have many requests
service = db.relationship('Services',
back_populates='service_request')
houseowner = db.relationship('User', foreign_keys=[houseowner_id])
professional = db.relationship('User',
foreign_keys=[professional_id])
def create_admin():
with app.app_context():
if not User.query.filter_by(user_name='[email protected]').first():
admin = User(user_name='[email protected]',
password='admin123', is_admin=True, full_name="Admin")
db.session.add(admin)
db.session.commit()
db.session.close()
with app.app_context():
db.create_all()
create_admin()
@app.route('/')
def home():
return render_template('index.html')
@app.route('/services')
def services():
return render_template('services.html')
@app.route('/contact')
def contact_us():
return render_template('contact-us.html')
if User.query.filter_by(user_name=user_name).first():
return redirect(url_for('login'))
else:
user = User(user_name=user_name, password=password,
full_name=full_name, phone_no=phone_no, address=address,
pincode=pincode, is_houseowner=is_houseowner)
db.session.add(user)
db.session.commit()
db.session.close()
return redirect(url_for('login'))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
user =
User.query.filter_by(user_name=request.form['email']).first()
if request.form['email'] == '[email protected]' and
request.form['password'] == 'admin123':
return redirect(url_for('admin'))
elif User.query.filter_by(user_name=request.form['email'],
password=request.form['password']).first():
if User.query.filter_by(user_name=request.form['email'],
is_houseowner=True).first():
return redirect(url_for('user', name=user.full_name))
elif User.query.filter_by(user_name=request.form['email'],
is_professional=True).first():
return redirect(url_for('professional'))
else:
print(User.query.with_entities(User.user_name).first())
return redirect(url_for('login'))
@app.route('/professional-dashboard')
def professional():
return render_template('professional-dashboard.html')
if User.query.filter_by(user_name=user_name).first():
print('User already exists')
return redirect(url_for('login'))
else:
user = User(user_name=user_name, password=password,
full_name=full_name, phone_no=phone_no, address=address,
pincode=pincode,
is_professional=is_professional,service_name=service_name,
prof_experience=prof_experience)
db.session.add(user)
db.session.commit()
db.session.close()
return redirect(url_for('login'))
@app.route('/user-dashboard/<full_name>/service-request/<service>',
methods=['GET', 'POST'])
def service_request(service, full_name):
user = User.query.filter_by(full_name=full_name).first()
service = Services.query.filter_by(service_name=service).first()
s_request =
ServiceRequest.query.filter_by(houseowner_id=user.id).all()
if request.method == 'GET':
return render_template('service-packages.html', service=service,
base_price=service.service_price, full_name=full_name,
service_requests=s_request)
elif request.method == 'POST':
available_professional =
User.query.filter(User.is_professional==True, User.is_available==True,
User.service_id==service.id).first()
print(available_professional)
if available_professional:
service_request = ServiceRequest(service_id=service.id,
houseowner_id=user.id, professional_id=available_professional.id)
db.session.add(service_request)
db.session.commit()
# db.session.close()
return redirect(url_for('service_request',
service=service.service_name, full_name=full_name))
else:
return render_template('service-packages.html',
service=service, base_price=service.service_price, full_name=full_name,
service_requests=s_request, alert_message="No service professional
available, right now!", alert_type='warning')
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, debug=True)
Wall Page
Register Page
Login Page
User Page
Admin Page
Conclusion
The Household Services web application successfully fulfills the primary objectives of
providing a reliable, user-friendly platform for users to book various household
services. The project has gone through several phases of design, development,
testing, and debugging, ensuring that the final product is stable, secure, and scalable.
Functional and Seamless User Experience: The platform offers an intuitive and easy-
to-navigate interface, allowing users to effortlessly browse services, make bookings,
and process payments. Service providers can also manage their profiles and
bookings with ease, ensuring a smooth experience for both users and providers.
Security and Data Protection: Security was prioritized throughout the development
process. Sensitive user information, such as passwords and payment details, is
securely protected using modern encryption techniques and best practices. Session
management is robust, preventing unauthorized access and ensuring user data
remains safe.
Performance and Scalability: The application was designed to handle a growing user
base. Performance testing confirmed that the platform can scale to accommodate
multiple users making bookings simultaneously without significant degradation in
performance.
Thorough Testing and Bug Fixing: Extensive testing, including unit, integration, end-
to-end, and user acceptance testing, ensured that all features worked as expected.
The identification and resolution of bugs and issues during testing resulted in a
polished and stable product.
The project has also overcome challenges, including the integration of the payment
gateway and ensuring responsive design across different devices. The development
team worked collaboratively to address these challenges, implementing effective
solutions that contributed to the overall success of the application.
In conclusion, the Household Services web application is now ready for deployment,
offering an efficient, secure, and user-friendly solution for both users and service
providers. The application serves as a strong foundation for future enhancements,
including the development of a mobile app and the addition of AI-based
recommendations for a more personalized user experience.
Looking ahead, there are several opportunities for further development, such as
incorporating advanced search filters, optimizing the user interface, and enhancing
the platform’s scalability. The completion of this project marks a significant
milestone in providing a comprehensive household services platform, with the
potential to expand and evolve as the needs of users and service providers grow.