@ -0,0 +1,19 @@ |
|||||||
|
# Generated by Django 5.1.4 on 2025-01-11 20:13 |
||||||
|
|
||||||
|
import django.db.models.deletion |
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('main', '0003_service_alter_user_bio_alter_user_price_and_more'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='user', |
||||||
|
name='service_offered', |
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='main.service'), |
||||||
|
), |
||||||
|
] |
@ -0,0 +1,29 @@ |
|||||||
|
# Generated by Django 5.1.4 on 2025-01-12 01:26 |
||||||
|
|
||||||
|
import django.db.models.deletion |
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('main', '0004_user_service_offered'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='user', |
||||||
|
name='login_profile', |
||||||
|
field=models.CharField(choices=[('NORMAL', 'Normal User'), ('SERVICE', 'Service Provider'), ('ADMIN', 'Admin User')], default='NORMAL', max_length=15), |
||||||
|
), |
||||||
|
migrations.AlterField( |
||||||
|
model_name='servicerequest', |
||||||
|
name='service', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='service_offered', to='main.service'), |
||||||
|
), |
||||||
|
migrations.AlterField( |
||||||
|
model_name='user', |
||||||
|
name='profile', |
||||||
|
field=models.ImageField(blank=True, null=True, upload_to='profile-images/'), |
||||||
|
), |
||||||
|
] |
@ -1,63 +1,152 @@ |
|||||||
{% extends 'base.html' %} |
{% extends 'base.html' %} |
||||||
|
{% load static %} |
||||||
|
|
||||||
{% block content %} |
{% block content %} |
||||||
<!DOCTYPE html> |
<header class="bg-primary text-white text-center py-5"> |
||||||
<html lang="en"> |
<div class="container"> |
||||||
<head> |
<h1>Welcome to Sahara</h1> |
||||||
<meta charset="UTF-8"> |
<p>Your one-stop platform for elder care services.</p> |
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
</div> |
||||||
<title>Login Form</title> |
</header> |
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
|
||||||
<style> |
<div class="search-bar"> |
||||||
.login-container { |
<input type="text" class="form-control" name=search id=search placeholder="Search Your Caretaker..."> |
||||||
height: 100vh; |
<button class="btn btn-primary ms-1" onclick=sendSearch()>Search</button> |
||||||
display: flex; |
</div> |
||||||
justify-content: center; |
|
||||||
align-items: center; |
<section class="container my-5"> |
||||||
background: #f4f7fc; |
<div class="row"> |
||||||
} |
<div class="col-md-3"> |
||||||
.login-card { |
<div class="category-bar"> |
||||||
padding: 2rem; |
<h4>Services</h4> |
||||||
border-radius: 8px; |
<ul class="list-unstyled"> |
||||||
background: white; |
{% for service in services %} |
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
<li><a href="{% url 'home' %}?category={{ service.id }}" class="category-link">{{ service.name }}</a></li> |
||||||
width: 100%; |
{% endfor %} |
||||||
max-width: 400px; |
</ul> |
||||||
} |
<h4>Price</h4> |
||||||
.login-card h2 { |
<input |
||||||
text-align: center; |
type="number" |
||||||
margin-bottom: 1rem; |
class="form-control" |
||||||
} |
id="basePriceInput" |
||||||
</style> |
value="100" |
||||||
</head> |
min="1" |
||||||
<body> |
step="0.01"> |
||||||
<div class="login-container"> |
<input |
||||||
<div class="login-card"> |
type="range" |
||||||
<h2>Login</h2> |
class="form-range" |
||||||
<form action="#" method="post"> |
min="0.5" |
||||||
{% csrf_token %} |
max="2" |
||||||
<div class="mb-3"> |
step="0.01" |
||||||
<label for="email" class="form-label">Email</label> |
value="1" |
||||||
<input type="text" class="form-control" id="email" name="email" placeholder="Enter your email" required> |
id="ratioSlider"> |
||||||
</div> |
<p class="fs-5"> |
||||||
<div class="mb-3"> |
<strong>Price:</strong> Rs.<span id="price">100.00</span> |
||||||
<label for="password" class="form-label">Password</label> |
(<span id="ratio">1.00</span>x) |
||||||
<input type="password" class="form-control" id="password" name="password" placeholder="Enter your password" required> |
</p> |
||||||
</div> |
</div> |
||||||
<div class="d-flex justify-content-between align-items-center"> |
</div> |
||||||
<div class="form-check"> |
|
||||||
<input type="checkbox" class="form-check-input" id="rememberMe"> |
<div class="col-md-9"> |
||||||
<label class="form-check-label" for="rememberMe">Remember Me</label> |
<h2 class="text-center mb-4">Available Caretakers</h2> |
||||||
|
<div class="row row-cols-1 row-cols-md-3 g-4"> |
||||||
|
|
||||||
|
{% for user in service_providers %} |
||||||
|
<div class="col"> |
||||||
|
<div class="profile-card"> |
||||||
|
{% if user.profile %} |
||||||
|
<img src="{{ user.profile.url }}" alt="{{ user.first_name }} {{ user.last_name }}'s Image" class="img-fluid"> |
||||||
|
{% else %} |
||||||
|
<img src="{% static 'img/dummypic.png' %}" alt="Avatar Image" class="img-fluid"> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
<div class="card-body"> |
||||||
|
<h5 class="card-title">{{ user.first_name|capfirst }} {{ user.last_name|capfirst }}</h5> |
||||||
|
<p class="card-text">Bio: {{ user.bio }}</p> |
||||||
|
<p class="availability">Member Since: {{ user.member_since|date:"F j, Y" }}</p> |
||||||
|
<div class="d-flex align-items-center"> |
||||||
|
<p class="price mb-0">Rs. {{ user.price|floatformat:2 }}</p> |
||||||
|
<!-- Hire button --> |
||||||
|
<button class="btn btn-primary btn-sm ms-auto" data-bs-toggle="modal" data-bs-target="#hireModal" data-name="{{ user.first_name }} {{ user.last_name }}" data-bio="{{ user.bio }}" data-price="{{ user.price|floatformat:2 }}" data-id="{{ user.id }}">Hire</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
</div> |
</div> |
||||||
<a href="#" class="small">Forgot password?</a> |
{% empty %} |
||||||
|
<div class="mx-auto">Oops! No Caretaker Found Currently.</div> |
||||||
|
{% endfor %} |
||||||
|
|
||||||
</div> |
</div> |
||||||
<button type="submit" class="btn btn-primary w-100 mt-3">Login</button> |
</div> |
||||||
</form> |
</div> |
||||||
|
</section> |
||||||
|
|
||||||
|
<!-- Modal --> |
||||||
|
<div class="modal fade" id="hireModal" tabindex="-1" aria-labelledby="hireModalLabel" aria-hidden="true"> |
||||||
|
<div class="modal-dialog"> |
||||||
|
<div class="modal-content"> |
||||||
|
<div class="modal-header"> |
||||||
|
<h5 class="modal-title" id="hireModalLabel">Hire Caretaker</h5> |
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
||||||
|
</div> |
||||||
|
<div class="modal-body"> |
||||||
|
<form id="hireForm"> |
||||||
|
<div class="mb-3"> |
||||||
|
<label for="caretakerName" class="form-label">Caretaker Name</label> |
||||||
|
<input type="text" class="form-control" id="caretakerName" disabled> |
||||||
|
</div> |
||||||
|
<div class="mb-3"> |
||||||
|
<label for="caretakerBio" class="form-label">Bio</label> |
||||||
|
<textarea class="form-control" id="caretakerBio" rows="3" disabled></textarea> |
||||||
|
</div> |
||||||
|
<div class="mb-3"> |
||||||
|
<label for="caretakerPrice" class="form-label">Price</label> |
||||||
|
<input type="text" class="form-control" id="caretakerPrice" disabled> |
||||||
|
</div> |
||||||
|
<div class="mb-3"> |
||||||
|
<label for="caretakerService" class="form-label">Service</label> |
||||||
|
<input type="text" class="form-control" id="caretakerService" disabled> |
||||||
|
</div> |
||||||
|
<button type="submit" class="btn btn-primary">Confirm Hire</button> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
</div> |
</div> |
||||||
</div> |
</div> |
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> |
||||||
</body> |
<script> |
||||||
</html> |
// Handle the modal data population |
||||||
|
const hireModal = document.getElementById('hireModal'); |
||||||
|
hireModal.addEventListener('show.bs.modal', function (event) { |
||||||
|
// Button that triggered the modal |
||||||
|
const button = event.relatedTarget; |
||||||
|
|
||||||
|
// Extract information from data-* attributes |
||||||
|
const name = button.getAttribute('data-name'); |
||||||
|
const bio = button.getAttribute('data-bio'); |
||||||
|
const price = button.getAttribute('data-price'); |
||||||
|
const serviceId = button.getAttribute('data-id'); |
||||||
|
|
||||||
|
// Populate the modal fields |
||||||
|
document.getElementById('caretakerName').value = name; |
||||||
|
document.getElementById('caretakerBio').value = bio; |
||||||
|
document.getElementById('caretakerPrice').value = price; |
||||||
|
// Fetch service name based on service ID (optional, if needed) |
||||||
|
fetch(`/get-service-name/${serviceId}/`) |
||||||
|
.then(response => response.json()) |
||||||
|
.then(data => { |
||||||
|
document.getElementById('caretakerService').value = data.service_name; |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
const sendSearch = () => { |
||||||
|
let url = window.location.href; |
||||||
|
const searchTerm = document.getElementById("search").value; |
||||||
|
url = url.split('?')[0] + "?search=" + encodeURIComponent(searchTerm); |
||||||
|
window.location.href = url; |
||||||
|
} |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
{% endblock %} |
{% endblock %} |
||||||
|
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 113 KiB |
@ -1,7 +1,13 @@ |
|||||||
from django.contrib import admin |
from django.contrib import admin |
||||||
from django.urls import path, include |
from django.urls import path,include |
||||||
|
from django.conf import settings |
||||||
|
from django.conf.urls.static import static |
||||||
|
|
||||||
urlpatterns = [ |
urlpatterns = [ |
||||||
path('admin/', admin.site.urls), |
path('admin/', admin.site.urls), |
||||||
path('', include('main.urls')), |
path('', include('main.urls')), |
||||||
] |
] |
||||||
|
|
||||||
|
|
||||||
|
if settings.DEBUG: |
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) |
@ -0,0 +1,144 @@ |
|||||||
|
body { |
||||||
|
background-color:#ffffff; |
||||||
|
} |
||||||
|
.navbar .navbar-brand { |
||||||
|
margin-right: auto; |
||||||
|
} |
||||||
|
.navbar .nav { |
||||||
|
margin: 0 auto; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.navbar .login { |
||||||
|
margin-left: auto; |
||||||
|
} |
||||||
|
.search-bar { |
||||||
|
margin-top: 20px; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.search-bar input { |
||||||
|
width: 50%; |
||||||
|
border-radius: 50px; |
||||||
|
} |
||||||
|
.profile-card { |
||||||
|
border: 1px solid #ddd; |
||||||
|
border-radius: 10px; |
||||||
|
overflow: hidden; |
||||||
|
transition: transform 0.3s ease, box-shadow 0.3s ease; |
||||||
|
} |
||||||
|
.profile-card:hover { |
||||||
|
transform: translateY(-10px); |
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); |
||||||
|
} |
||||||
|
.profile-card img { |
||||||
|
width: 100%; |
||||||
|
height: 200px; |
||||||
|
object-fit: cover; |
||||||
|
object-position: 10%; |
||||||
|
} |
||||||
|
.profile-card .card-body { |
||||||
|
padding: 15px; |
||||||
|
} |
||||||
|
.profile-card .card-title { |
||||||
|
font-size: 1.25rem; |
||||||
|
font-weight: bold; |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
.profile-card .card-text { |
||||||
|
font-size: 0.9rem; |
||||||
|
color: #555; |
||||||
|
} |
||||||
|
.profile-card .price { |
||||||
|
font-size: 1.1rem; |
||||||
|
font-weight: bold; |
||||||
|
color: #007bff; |
||||||
|
} |
||||||
|
.profile-card .availability { |
||||||
|
font-size: 0.9rem; |
||||||
|
color: #28a745; |
||||||
|
} |
||||||
|
|
||||||
|
.category-bar { |
||||||
|
background-color: #f8f9fa; /* Light background */ |
||||||
|
padding: 20px; |
||||||
|
border-radius: 10px; |
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); /* Subtle shadow */ |
||||||
|
} |
||||||
|
|
||||||
|
.category-bar h4 { |
||||||
|
font-size: 1.25rem; |
||||||
|
font-weight: bold; |
||||||
|
margin-bottom: 15px; |
||||||
|
color: #333; |
||||||
|
} |
||||||
|
|
||||||
|
.category-bar ul { |
||||||
|
padding-left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.category-bar .category-link { |
||||||
|
display: block; |
||||||
|
padding: 10px 15px; |
||||||
|
margin: 5px 0; |
||||||
|
color: #555; |
||||||
|
text-decoration: none; |
||||||
|
border-radius: 5px; |
||||||
|
transition: background-color 0.3s ease, color 0.3s ease; |
||||||
|
} |
||||||
|
|
||||||
|
.category-bar .category-link:hover { |
||||||
|
background-color: #007bff; /* Highlight on hover */ |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
/* odd */ |
||||||
|
.form-container { |
||||||
|
font-family: Arial, sans-serif; |
||||||
|
margin: auto; |
||||||
|
padding: 30px; |
||||||
|
background: rgba(255, 255, 255, 0.9); |
||||||
|
border-radius: 8px; |
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
||||||
|
width: 600px; |
||||||
|
} |
||||||
|
.form-container h2 { |
||||||
|
margin-bottom: 20px; |
||||||
|
} |
||||||
|
.form-group { |
||||||
|
margin-bottom: 15px; |
||||||
|
} |
||||||
|
.form-group label { |
||||||
|
display: block; |
||||||
|
margin-bottom: 5px; |
||||||
|
} |
||||||
|
.form-group input, |
||||||
|
.form-group textarea, |
||||||
|
.form-group select { |
||||||
|
width: 100%; |
||||||
|
padding: 10px; |
||||||
|
border: 1px solid #ccc; |
||||||
|
border-radius: 5px; |
||||||
|
} |
||||||
|
.form-group input[type="file"] { |
||||||
|
padding: 5px; |
||||||
|
} |
||||||
|
.form-group button { |
||||||
|
width: 100%; |
||||||
|
padding: 10px; |
||||||
|
background-color: #007BFF; |
||||||
|
color: #fff; |
||||||
|
border: none; |
||||||
|
border-radius: 5px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
.form-group button:hover { |
||||||
|
background-color: #0056b3; |
||||||
|
} |
||||||
|
.form-wrapper { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
min-height: 100vh; |
||||||
|
background: url('img/backgroung-form.jpg') no-repeat center center/cover; |
||||||
|
} |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 492 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 218 KiB |