diff --git a/sahara/db.sqlite3 b/sahara/db.sqlite3
index 33e0fb4..3638b51 100644
Binary files a/sahara/db.sqlite3 and b/sahara/db.sqlite3 differ
diff --git a/sahara/main/__pycache__/models.cpython-312.pyc b/sahara/main/__pycache__/models.cpython-312.pyc
index eb99c66..6bcbb4c 100644
Binary files a/sahara/main/__pycache__/models.cpython-312.pyc and b/sahara/main/__pycache__/models.cpython-312.pyc differ
diff --git a/sahara/main/__pycache__/urls.cpython-312.pyc b/sahara/main/__pycache__/urls.cpython-312.pyc
index 2496d92..92ca9d0 100644
Binary files a/sahara/main/__pycache__/urls.cpython-312.pyc and b/sahara/main/__pycache__/urls.cpython-312.pyc differ
diff --git a/sahara/main/__pycache__/views.cpython-312.pyc b/sahara/main/__pycache__/views.cpython-312.pyc
index a00c760..75dc713 100644
Binary files a/sahara/main/__pycache__/views.cpython-312.pyc and b/sahara/main/__pycache__/views.cpython-312.pyc differ
diff --git a/sahara/main/migrations/0006_servicerequest_phone_number.py b/sahara/main/migrations/0006_servicerequest_phone_number.py
new file mode 100644
index 0000000..8a38a9c
--- /dev/null
+++ b/sahara/main/migrations/0006_servicerequest_phone_number.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.4 on 2025-01-12 03:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0005_user_login_profile_alter_servicerequest_service_and_more'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='servicerequest',
+ name='phone_number',
+ field=models.CharField(blank=True, max_length=15, null=True),
+ ),
+ ]
diff --git a/sahara/main/migrations/0007_remove_servicerequest_phone_number_user_phone_number.py b/sahara/main/migrations/0007_remove_servicerequest_phone_number_user_phone_number.py
new file mode 100644
index 0000000..5636c37
--- /dev/null
+++ b/sahara/main/migrations/0007_remove_servicerequest_phone_number_user_phone_number.py
@@ -0,0 +1,22 @@
+# Generated by Django 5.1.4 on 2025-01-12 03:41
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0006_servicerequest_phone_number'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='servicerequest',
+ name='phone_number',
+ ),
+ migrations.AddField(
+ model_name='user',
+ name='phone_number',
+ field=models.CharField(blank=True, max_length=15, null=True),
+ ),
+ ]
diff --git a/sahara/main/migrations/0008_alter_servicerequest_is_approved.py b/sahara/main/migrations/0008_alter_servicerequest_is_approved.py
new file mode 100644
index 0000000..131dc80
--- /dev/null
+++ b/sahara/main/migrations/0008_alter_servicerequest_is_approved.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.4 on 2025-01-12 10:38
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0007_remove_servicerequest_phone_number_user_phone_number'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='servicerequest',
+ name='is_approved',
+ field=models.BooleanField(blank=True, null=True),
+ ),
+ ]
diff --git a/sahara/main/migrations/0009_alter_servicerequest_is_approved.py b/sahara/main/migrations/0009_alter_servicerequest_is_approved.py
new file mode 100644
index 0000000..87d76a0
--- /dev/null
+++ b/sahara/main/migrations/0009_alter_servicerequest_is_approved.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.4 on 2025-01-12 10:38
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0008_alter_servicerequest_is_approved'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='servicerequest',
+ name='is_approved',
+ field=models.BooleanField(blank=True, default=False, null=True),
+ ),
+ ]
diff --git a/sahara/main/migrations/__pycache__/0006_servicerequest_phone_number.cpython-312.pyc b/sahara/main/migrations/__pycache__/0006_servicerequest_phone_number.cpython-312.pyc
new file mode 100644
index 0000000..eccbadf
Binary files /dev/null and b/sahara/main/migrations/__pycache__/0006_servicerequest_phone_number.cpython-312.pyc differ
diff --git a/sahara/main/migrations/__pycache__/0007_remove_servicerequest_phone_number_user_phone_number.cpython-312.pyc b/sahara/main/migrations/__pycache__/0007_remove_servicerequest_phone_number_user_phone_number.cpython-312.pyc
new file mode 100644
index 0000000..68786f7
Binary files /dev/null and b/sahara/main/migrations/__pycache__/0007_remove_servicerequest_phone_number_user_phone_number.cpython-312.pyc differ
diff --git a/sahara/main/migrations/__pycache__/0008_alter_servicerequest_is_approved.cpython-312.pyc b/sahara/main/migrations/__pycache__/0008_alter_servicerequest_is_approved.cpython-312.pyc
new file mode 100644
index 0000000..e0a972c
Binary files /dev/null and b/sahara/main/migrations/__pycache__/0008_alter_servicerequest_is_approved.cpython-312.pyc differ
diff --git a/sahara/main/migrations/__pycache__/0009_alter_servicerequest_is_approved.cpython-312.pyc b/sahara/main/migrations/__pycache__/0009_alter_servicerequest_is_approved.cpython-312.pyc
new file mode 100644
index 0000000..8a8f8c2
Binary files /dev/null and b/sahara/main/migrations/__pycache__/0009_alter_servicerequest_is_approved.cpython-312.pyc differ
diff --git a/sahara/main/models.py b/sahara/main/models.py
index 257ba59..1eeaf3e 100644
--- a/sahara/main/models.py
+++ b/sahara/main/models.py
@@ -55,7 +55,6 @@ class UserManager(BaseUserManager):
return self.create_user(first_name, last_name, email, password, **extra_fields)
def send_verification_email(self, user):
- # Generate the token and the uid for the verification URL
token = default_token_generator.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk))
verification_url = f"{settings.FRONTEND_URL}/verify-email/{uid}/{token}/"
@@ -93,6 +92,7 @@ class User(AbstractBaseUser, PermissionsMixin):
bio = models.CharField(max_length=200, blank=True, null=True)
member_since = models.DateTimeField(auto_now_add=True)
updated_on = models.DateField(auto_now=True)
+ phone_number = models.CharField(max_length=15, blank=True, null=True)
service_offered = models.ForeignKey(Service, on_delete=models.CASCADE,blank=True,null=True)
login_profile = models.CharField(
max_length=15,
@@ -112,6 +112,11 @@ class User(AbstractBaseUser, PermissionsMixin):
def get_short_name(self):
return self.first_name
+ @property
+ def url(self):
+ if self.profile_picture:
+ return self.profile_picture.url
+ return None
class ServiceRequest(models.Model):
client = models.ForeignKey(User,on_delete=models.CASCADE,related_name="client")
@@ -119,11 +124,12 @@ class ServiceRequest(models.Model):
agreed_price = models.DecimalField(max_digits=999,decimal_places=2 , default=0)
service_hour = models.PositiveIntegerField(default=1)
agreed_on = models.DateField(auto_now_add=True)
- is_approved = models.DateTimeField(blank=True, null=True)
+ is_approved = models.BooleanField(blank=True, null=True,default=False)
remarks = models.TextField(blank=True, null=True)
is_completed = models.BooleanField(default=False)
completed_date = models.DateTimeField(null=True,blank=True)
service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name="service_offered")
+
def __str__(self):
return self.service.name
diff --git a/sahara/main/templates/main/home.html b/sahara/main/templates/main/home.html
index 0a76e01..d6e46da 100644
--- a/sahara/main/templates/main/home.html
+++ b/sahara/main/templates/main/home.html
@@ -5,7 +5,7 @@
Welcome to Sahara
-
Your one-stop platform for elder care services.
+
Your one-stop platform for elder cure serviecs.
@@ -24,26 +24,6 @@
{{ service.name }}
{% endfor %}
- Price
-
-
-
- Price: Rs.100.00
- (1.00 x)
-
@@ -67,7 +47,7 @@
Rs. {{ user.price|floatformat:2 }}
-
Hire
+
Hire
@@ -90,24 +70,44 @@
@@ -127,26 +127,68 @@
const bio = button.getAttribute('data-bio');
const price = button.getAttribute('data-price');
const serviceId = button.getAttribute('data-id');
+ const contact = button.getAttribute('data-contact');
+ const email = button.getAttribute('data-email');
+ const id = 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;
- });
+ document.getElementById('caretakeremail').value = email;
+ document.getElementById('caretakercontact').value = contact;
+ document.getElementById('caretakerid').value = id;
});
+
+
+const sendRequest = async () => {
+ try {
+ const price = document.getElementById('caretakerPrice').value;
+ const serviceHour = document.getElementById('serviceHour').value;
+ const serviceProviderId = document.getElementById('caretakerid').value;
+ const caretakerservice = document.getElementById('caretakerservice').value;
+
+ const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
+ const hireUrl = "{% url 'hire' %}";
+ const initiatorId = "{{ request.user.id }}";
+
+ const response = await fetch(hireUrl, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json; charset=UTF-8",
+ "X-CSRFToken": csrfToken,
+ },
+ body: JSON.stringify({
+ price: price,
+ initiator: initiatorId,
+ serviceProvider: serviceProviderId,
+ serviceHour: serviceHour,
+ caretakerservice: caretakerservice,
+ })
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(errorText);
+ }
+
+ const data = await response.json();
+ console.log('Request was successful:', data);
+ window.location.href = window.location.href;
+
+ } catch (error) {
+ console.error('There was an error with the request:', error.message);
+ alert('There was an error with your request: ' + error.message);
+ }
+};
+
+
const sendSearch = () => {
let url = window.location.href;
const searchTerm = document.getElementById("search").value;
url = url.split('?')[0] + "?search=" + encodeURIComponent(searchTerm);
window.location.href = url;
}
-
{% endblock %}
diff --git a/sahara/main/templates/main/profile.html b/sahara/main/templates/main/profile.html
new file mode 100644
index 0000000..d078f42
--- /dev/null
+++ b/sahara/main/templates/main/profile.html
@@ -0,0 +1,126 @@
+{% extends 'base.html' %}
+{% load static %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
Contact Information
+
Email: {{ user.email }}
+
Phone: (+977) {{ user.phone_number }}
+
Address: {{ user.address }}
+
+
+
+
+
+ {% if request.user == user %}
+
+
+
Pending/Active Requests
+
+
+ {% for req in pending_requests %}
+
+ {{ req.service_offered }} request from {{ req.client.first_name|capfirst }} {{ req.client.last_name|capfirst }}
+ Accept
+
+ {% empty %}
+
+ Hurray! There are no Pending Requests till now.
+
+ {% endfor %}
+
+
+
+
+
+
+
Completed/Active Requests
+
+
+ {% for service in current %}
+
+ {{ service.service_offered }} request from {{ service.client.first_name|capfirst }} {{ service.client.last_name|capfirst }}
+ Complete
+
+ {% empty %}
+
+ There are no active tasks right now.
+
+ {% endfor %}
+
+
+
+ {% endif %}
+
+{% endblock %}
+
diff --git a/sahara/main/templates/main/services1.html b/sahara/main/templates/main/services1.html
new file mode 100644
index 0000000..66c7f1b
--- /dev/null
+++ b/sahara/main/templates/main/services1.html
@@ -0,0 +1,164 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+
+
+ Services
+
+
+ Our Services
+
+
+
I am a tech-savvy individual with a Bachelor's degree in Software Development, seeking employment as a mobile game developer. I am passionate about consistently advancing my knowledge and skills. I have attended multiple seminars and boot camps on coding and game development.
+
+
+
+
+ What We Offer
+
+
+
I am a tech-savvy individual with a Bachelor's degree in Software Development, seeking employment as a mobile game developer. I am passionate about consistently advancing my knowledge and skills. I have attended multiple seminars and boot camps on coding and game development.
+
+
+
+
+ Our Web App Provides
+
+
+
+
Feature 1
+
Detail about the first feature of the web app.
+
+
+
+
Feature 2
+
Detail about the second feature of the web app.
+
+
+
+
Feature 3
+
Detail about the third feature of the web app.
+
+
+
+
Feature 4
+
Detail about the fourth feature of the web app.
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/sahara/main/urls.py b/sahara/main/urls.py
index 82d2a3a..c6bf744 100644
--- a/sahara/main/urls.py
+++ b/sahara/main/urls.py
@@ -5,7 +5,9 @@ urlpatterns = [
path('', views.home, name="home"),
path('register/', views.register, name='register'),
path('activate///', views.activate_account, name='activate_account'),
- # path('verify-email///', views.verify_email, name='verify_email'),
path('login/', views.user_login, name='login'),
path('logout/', views.user_logout, name='logout'),
+ path('hire/', views.hire_view, name='hire'),
+ path('services/',views.services,name='services'),
+ path('profiles/',views.profie_View, name="profiles")
]
\ No newline at end of file
diff --git a/sahara/main/views.py b/sahara/main/views.py
index 67d52db..be646c3 100644
--- a/sahara/main/views.py
+++ b/sahara/main/views.py
@@ -1,35 +1,49 @@
-from django.shortcuts import render, redirect,HttpResponse,get_list_or_404
+from django.shortcuts import render, redirect,HttpResponse,get_object_or_404
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from django.contrib.auth.decorators import login_required
from django.contrib import messages
-from .models import User,Service
+from .models import User,Service,ServiceRequest
from .forms import UserRegistrationForm
import logging
+import json
+from django.http import JsonResponse
+from django.views.decorators.csrf import csrf_protect
logger = logging.getLogger('main')
def home(request):
- category = request.GET.get('category')
- services = Service.objects.all()
- if category:
- try:
- service = Service.objects.get(id=category)
- service_providers = User.objects.filter(service_offered=service)
- except Service.DoesNotExist:
- service_providers = []
- else:
- service_providers = User.objects.filter(service_offered__isnull=False)
-
- context = {
- 'service_providers': service_providers,
- 'services': services
- }
+ if(request.method == "GET"):
+ category = request.GET.get('category')
+ search = request.GET.get('search')
+ services = Service.objects.all()
+ if category:
+ try:
+ service = Service.objects.get(id=category)
+ service_providers = User.objects.filter(service_offered=service)
+ except Service.DoesNotExist:
+ service_providers = []
+ elif search:
+ try:
+ service_providers = User.objects.filter(first_name__startswith=search)
+ except Service.DoesNotExist:
+ service_providers = []
+ else:
+ service_providers = User.objects.filter(service_offered__isnull=False)
+ context = {
+ 'service_providers': service_providers,
+ 'services': services
+ }
- return render(request, "main/home.html", context)
+ return render(request, "main/home.html", context)
+ print(request.POST)
+ return HttpResponse("tjisfjsa")
def register(request):
+ if request.user.is_authenticated:
+ messages.warning(request,"You are already logged in. Please Logout first to register ")
+ return redirect('home')
if request.method == 'POST' and request.FILES:
form = UserRegistrationForm(request.POST,request.FILES, instance=request.user)
if form.is_valid():
@@ -38,7 +52,7 @@ def register(request):
user.save()
try:
- user.send_verification_email()
+ user.send_verification_email(user)
messages.success(request, 'Registration successful! Please check your email to activate your account.')
except Exception as e:
logger.error(f"Error sending verification email: {e}")
@@ -67,24 +81,29 @@ def activate_account(request, uidb64, token):
return redirect('register')
def user_login(request):
- print(request.user.is_authenticated)
if request.user.is_authenticated:
+ messages.info(request, f'You are already logged in as {request.user}')
return redirect('home')
else:
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
- user = authenticate(request, email = email, password = password)
+
+ # Authenticate the user using the email and password
+ user = authenticate(request, email=email, password=password)
+
if user is not None:
- form = login(request, user)
- messages.success(request, f' welcome {user} !!')
+ # Log the user in
+ login(request, user)
+ messages.success(request, f'Welcome {user}!')
return redirect('home')
- else:
- messages.info(request, f'Something went wrong')
+ else:
+ # If authentication fails
+ messages.error(request, 'Invalid email or password. Please try again.')
- messages.info(request, f'You are Already Logged in as {request.user}')
- return render(request, 'main/login.html', {'title':'log in'})
-
+ # Handle GET request by initializing a blank form
+ form = None # Optionally, you can replace this with your login form
+ return render(request, 'main/login.html', {'form': form})
@login_required
def user_logout(request):
@@ -92,7 +111,70 @@ def user_logout(request):
messages.success(request, 'You have been logged out.')
return redirect('login')
-# def verify_email(request, uidb64, token):
-# # This view is redundant if it does the same as activate_account
-# # Consider removing or assigning a different purpose
-# pass
\ No newline at end of file
+def services(request):
+ return render(request,'main/services1.html')
+
+@login_required
+@csrf_protect
+def hire_view(request):
+ if request.method == 'POST':
+ try:
+ data = json.loads(request.body)
+ price = data.get('price')
+ initiator_id = data.get('initiator')
+ service_provider_id = data.get('serviceProvider')
+ service_hour = data.get('serviceHour')
+ caretakerservice_id = data.get('caretakerservice')
+
+ # Validate required fields
+ if not price or not initiator_id or not service_provider_id or not service_hour or not caretakerservice_id:
+ return JsonResponse({'error': 'Missing required fields'}, status=400)
+
+ # Validate initiator
+ if str(request.user.id) != str(initiator_id):
+ return JsonResponse({'error': 'Unauthorized initiator'}, status=401)
+
+ # Retrieve service provider and service
+ service_provider = get_object_or_404(User, id=service_provider_id)
+ service = get_object_or_404(Service, id=caretakerservice_id)
+
+ # Create and save the service request
+ service_request = ServiceRequest(
+ agreed_price=price,
+ service_provider=service_provider,
+ client=request.user,
+ service_hour=service_hour,
+ service=service
+ )
+ service_request.save()
+
+ messages.success(request, 'Request submitted successfully!')
+ return JsonResponse({'success': 'Request submitted successfully!'}, status=201)
+
+ except json.JSONDecodeError:
+ messages.error(request, 'Invalid JSON format')
+ return JsonResponse({'error': 'Invalid JSON format'}, status=400)
+ except User.DoesNotExist:
+ messages.error(request, 'Service provider does not exist')
+ return JsonResponse({'error': 'Service provider does not exist'}, status=404)
+ except Service.DoesNotExist:
+ messages.error(request, 'Service does not exist')
+ return JsonResponse({'error': 'Service does not exist'}, status=404)
+ except Exception as e:
+ messages.error(request, f'An error occurred: {str(e)}')
+ return JsonResponse({'error': 'An error occurred'}, status=500)
+ else:
+ messages.error(request, 'Invalid request method')
+ return JsonResponse({'error': 'Invalid request method'}, status=405)
+
+def profie_View(request,pk):
+ if request.method == "GET":
+ user = get_object_or_404(User,id=pk)
+ pending_requests = ServiceRequest.objects.filter(service_provider=user, is_approved=False)
+ current = ServiceRequest.objects.filter(service_provider=user, is_approved=True)
+ completed = ServiceRequest.objects.filter(service_provider=user, is_completed=True)
+ context = {'user':user,
+ 'pending_requests':pending_requests,
+ 'completed_orders' : completed
+ }
+ return render(request,'main/profile.html', context)
\ No newline at end of file
diff --git a/sahara/static/css/styles.css b/sahara/static/css/styles.css
index db25951..abc2fab 100644
--- a/sahara/static/css/styles.css
+++ b/sahara/static/css/styles.css
@@ -141,4 +141,60 @@ body {
align-items: center;
min-height: 100vh;
background: url('img/backgroung-form.jpg') no-repeat center center/cover;
+}
+
+/* status for history */
+.status-badge {
+ font-size: 0.9em;
+ padding: 0.25em 0.6em;
+ border-radius: 10px;
+ margin-left: 10px;
+}
+.status-active {
+ background-color: #28a745;
+ color: white;
+}
+.status-inactive {
+ background-color: #dc3545;
+ color: white;
+}
+
+footer {
+ margin-top: 50px;
+}
+/* darken */
+header {
+ position: relative;
+ background: url('../img/background.jpg') no-repeat center center/cover;
+ height: 300px;
+ width: 100%;
+}
+
+header::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5); /* Dark overlay */
+ z-index: 1; /* Make sure the overlay is above the image but below the text */
+}
+
+header .container {
+ position: relative;
+ z-index: 2; /* Ensure the text appears above the overlay */
+}
+
+header h1 {
+ font-size: 2.5rem; /* Larger text for better visibility */
+ font-weight: bold;
+ color: #fff; /* White text for contrast */
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7); /* Adding shadow to make text pop */
+}
+
+header p {
+ font-size: 1.2rem;
+ color: #fff; /* White text for contrast */
+ text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7); /* Subtle shadow for better legibility */
}
\ No newline at end of file
diff --git a/sahara/static/css/styles.css_1 b/sahara/static/css/styles.css_1
new file mode 100644
index 0000000..db25951
--- /dev/null
+++ b/sahara/static/css/styles.css_1
@@ -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;
+}
\ No newline at end of file
diff --git a/sahara/static/img/background.jpg b/sahara/static/img/background.jpg
new file mode 100644
index 0000000..8c8422c
Binary files /dev/null and b/sahara/static/img/background.jpg differ
diff --git a/sahara/static/img/dummy pic.png b/sahara/static/img/dummy pic.png
new file mode 100644
index 0000000..fd85231
Binary files /dev/null and b/sahara/static/img/dummy pic.png differ
diff --git a/sahara/static/img/grandmother.png b/sahara/static/img/grandmother.png
new file mode 100644
index 0000000..d557b39
Binary files /dev/null and b/sahara/static/img/grandmother.png differ
diff --git a/sahara/static/profile-images/pic1.jpg b/sahara/static/profile-images/pic1.jpg
new file mode 100644
index 0000000..bfbb2b8
Binary files /dev/null and b/sahara/static/profile-images/pic1.jpg differ
diff --git a/sahara/templates/base.html b/sahara/templates/base.html
index 4df818a..d4d4829 100644
--- a/sahara/templates/base.html
+++ b/sahara/templates/base.html
@@ -10,30 +10,42 @@
-
+
+
{% for message in messages %}