Updates to the main page

This commit is contained in:
2025-04-22 11:46:55 -05:00
parent 4c0605474c
commit 0e1ddbcf1a
14 changed files with 1493 additions and 60 deletions

View File

@@ -2,6 +2,7 @@ from django import forms
from django.forms import ModelForm
from .models import (
Membership,
CommunityPost,
AddressModel1,
MembershipPerson,
MembershipCommittee,
@@ -38,6 +39,10 @@ class AddressForm(ModelForm):
model = AddressModel1
fields = ["address_1", "address_2", "city", "state", "zip_code"]
class CommunityPostForm(ModelForm):
class Meta:
model = CommunityPost
fields = ['title','category','content']
class PeopleForm(ModelForm):
phone_number = PhoneNumberField(required=False)

View File

@@ -0,0 +1,290 @@
# Generated by Django 5.2 on 2025-04-21 17:42
import datetime
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("schasite", "0009_schaofficer_alter_payments_date"),
]
operations = [
migrations.CreateModel(
name="CommunityParks",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(default=django.utils.timezone.now)),
(
"last_modified",
models.DateTimeField(default=django.utils.timezone.now),
),
("name", models.CharField(max_length=255)),
("distance", models.DecimalField(decimal_places=1, max_digits=3)),
("description", models.CharField(max_length=1024)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="CommunityPost",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(default=django.utils.timezone.now)),
(
"last_modified",
models.DateTimeField(default=django.utils.timezone.now),
),
("title", models.CharField(max_length=255)),
("category", models.CharField(max_length=255)),
("content", models.CharField(max_length=8192)),
("likes", models.IntegerField(default=0)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="CommunitySchools",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(default=django.utils.timezone.now)),
(
"last_modified",
models.DateTimeField(default=django.utils.timezone.now),
),
("name", models.CharField(max_length=255)),
("name_school_url", models.URLField(max_length=256)),
("rating_url", models.URLField(max_length=256)),
("rating", models.DecimalField(decimal_places=2, max_digits=5)),
("distance", models.DecimalField(decimal_places=1, max_digits=3)),
("principal", models.CharField(max_length=255)),
("grades", models.CharField(max_length=255)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="CommunityShoppingAndDining",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(default=django.utils.timezone.now)),
(
"last_modified",
models.DateTimeField(default=django.utils.timezone.now),
),
("name", models.CharField(max_length=255)),
("distance", models.DecimalField(decimal_places=1, max_digits=3)),
("description", models.CharField(max_length=1024)),
],
options={
"abstract": False,
},
),
migrations.AddField(
model_name="addressmodel1",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="addressmodel1",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="calendarevent",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="calendarevent",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="calendareventaddressmodel",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="calendareventaddressmodel",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membership",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membership",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membershipcommittee",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membershipcommittee",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membershipperson",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membershipperson",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membershipservices",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="membershipservices",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="payments",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="payments",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="schaofficer",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="schaofficer",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="usefullinks",
name="created",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name="usefullinks",
name="last_modified",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AlterField(
model_name="payments",
name="date",
field=models.DateField(
default=datetime.datetime(
2025, 4, 21, 17, 42, 47, 893058, tzinfo=datetime.timezone.utc
)
),
),
migrations.CreateModel(
name="CommunityComment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(default=django.utils.timezone.now)),
(
"last_modified",
models.DateTimeField(default=django.utils.timezone.now),
),
("content", models.CharField(max_length=8192)),
("likes", models.IntegerField(default=0)),
(
"post",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="schasite.communitypost",
),
),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="CommunityPostReports",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(default=django.utils.timezone.now)),
(
"last_modified",
models.DateTimeField(default=django.utils.timezone.now),
),
(
"post",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="schasite.communitypost",
),
),
],
options={
"abstract": False,
},
),
]

View File

@@ -3,14 +3,29 @@ from phonenumber_field.modelfields import PhoneNumberField
import datetime
from django.utils import timezone
class TimeInfoBase(models.Model):
created = models.DateTimeField(default=timezone.now)
last_modified = models.DateTimeField(default=timezone.now)
class Meta:
abstract = True
def save(self, *args, **kwargs):
if not kwargs.pop("skip_last_modified", False) and not hasattr(self, "skip_last_modified"):
self.last_modified = timezone.now()
if kwargs.get("update_fields") is not None:
kwargs["update_fields"] = list({*kwargs["update_fields"], "last_modified"})
super().save(*args, **kwargs)
# Create your models here.
class UsefulLinks(models.Model):
class UsefulLinks(TimeInfoBase):
name = models.CharField(max_length=256)
url = models.CharField(max_length=256)
class Membership(models.Model):
class Membership(TimeInfoBase):
children = models.CharField(max_length=256, default="", blank=True, null=True)
def get_address_str(self):
@@ -37,7 +52,7 @@ class Membership(models.Model):
return self.get_address_str() + " | " + self.get_person_1()
class AddressModel1(models.Model):
class AddressModel1(TimeInfoBase):
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
address_1 = models.CharField(max_length=128)
address_2 = models.CharField(max_length=128, blank=True)
@@ -46,7 +61,7 @@ class AddressModel1(models.Model):
zip_code = models.CharField(max_length=5)
class CalendarEvent(models.Model):
class CalendarEvent(TimeInfoBase):
event_name = models.CharField(max_length=256)
start_date = models.DateField(blank=True, null=True)
end_date = models.DateField(blank=True, null=True)
@@ -75,7 +90,7 @@ class CalendarEvent(models.Model):
return not self.has_date()
class CalendarEventAddressModel(models.Model):
class CalendarEventAddressModel(TimeInfoBase):
calendar_event = models.OneToOneField(CalendarEvent, on_delete=models.CASCADE)
address_1 = models.CharField(max_length=128)
address_2 = models.CharField(max_length=128, blank=True)
@@ -89,7 +104,7 @@ class CalendarEventAddressModel(models.Model):
)
class MembershipPerson(models.Model):
class MembershipPerson(TimeInfoBase):
membership = models.ForeignKey(
Membership, on_delete=models.CASCADE, blank=True, null=True
)
@@ -102,7 +117,7 @@ class MembershipPerson(models.Model):
return self.email if self.email else "No email"
class MembershipCommittee(models.Model):
class MembershipCommittee(TimeInfoBase):
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
block_captain = models.BooleanField(default=False, blank=True, null=True)
coordinator = models.BooleanField(default=False, blank=True, null=True)
@@ -119,7 +134,7 @@ class MembershipCommittee(models.Model):
no_preference = models.BooleanField(default=False, blank=True, null=True)
class MembershipServices(models.Model):
class MembershipServices(TimeInfoBase):
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
babysitting = models.BooleanField(default=False, blank=True, null=True)
lawn_mowing = models.BooleanField(default=False, blank=True, null=True)
@@ -131,7 +146,7 @@ class MembershipServices(models.Model):
other_desc = models.CharField(default="", blank=True, null=True, max_length=256)
class Payments(models.Model):
class Payments(TimeInfoBase):
date = models.DateField(default=timezone.now())
status = models.CharField(default="Completed", max_length=256)
email = models.EmailField(blank=True, null=True)
@@ -140,26 +155,45 @@ class Payments(models.Model):
)
class SCHAOfficer(models.Model):
class SCHAOfficer(TimeInfoBase):
name = models.CharField(max_length=255)
position = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
# class CommunitySchools(models.Model):
# name = models.CharField(max_length=255)
# name_school_url = models.URLField(max_length=256)
# rating_url = models.URLField(max_length=256)
# rating = models.DecimalField(max_digits=5, decimal_places=2)
# distance = models.DecimalField(max_digits=3, decimal_places=1)
# principal = models.CharField(max_length=255)
# grades = models.CharField(max_length=255)
### NOT USED YET ###
# class CommunityShoppingAndDining(models.Model):
# name = models.CharField(max_length=255)
# distance = models.DecimalField(max_digits=3, decimal_places=1)
# description = models.CharField(max_length=1024)
class CommunitySchools(TimeInfoBase):
name = models.CharField(max_length=255)
name_school_url = models.URLField(max_length=256)
rating_url = models.URLField(max_length=256)
rating = models.DecimalField(max_digits=5, decimal_places=2)
distance = models.DecimalField(max_digits=3, decimal_places=1)
principal = models.CharField(max_length=255)
grades = models.CharField(max_length=255)
# class CommunityParks(models.Model):
# name = models.CharField(max_length=255)
# distance = models.DecimalField(max_digits=3, decimal_places=1)
# description = models.CharField(max_length=1024)
class CommunityShoppingAndDining(TimeInfoBase):
name = models.CharField(max_length=255)
distance = models.DecimalField(max_digits=3, decimal_places=1)
description = models.CharField(max_length=1024)
class CommunityParks(TimeInfoBase):
name = models.CharField(max_length=255)
distance = models.DecimalField(max_digits=3, decimal_places=1)
description = models.CharField(max_length=1024)
class CommunityPost(TimeInfoBase):
title = models.CharField(max_length=255)
category = models.CharField(max_length=255)
content = models.CharField(max_length=1024*8)
likes = models.IntegerField(default=0)
class CommunityPostReports(TimeInfoBase):
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
# user = something
class CommunityComment(TimeInfoBase):
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
content = models.CharField(max_length=1024*8)
likes = models.IntegerField(default=0)

View File

@@ -13,25 +13,74 @@
<!-- Custom CSS -->
<link href="{% static 'css/style2.css' %}" rel="stylesheet" type="text/css" />
<script async defer src="https://tianji.aimloperations.com/tracker.js" data-website-id="cm9qziuid9vr7v6dtdbnx8406"></script>
<script type="text/css">
.bg-light {
background-color: #f8f9fa!important;
}
.auth-card {
max-width: 500px;
margin: 0 auto;
}
/* Member Portal */
.member-navbar {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.member-navbar .nav-link {
padding: 0.5rem 1rem;
}
/* Directory */
.directory-table th {
white-space: nowrap;
}
/* Posts */
.post-card {
transition: transform 0.2s ease;
}
.post-card:hover {
transform: translateY(-2px);
}
.post-avatar {
width: 40px;
height: 40px;
}
/* Responsive adjustments */
@media (max-width: 767.98px) {
.member-navbar .navbar-nav {
margin-top: 1rem;
}
.directory-table {
font-size: 0.875rem;
}
}
</script>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-success sticky-top">
<div class="container">
<a class="navbar-brand" href="index.html">Greenwood Estates</a>
<a class="navbar-brand" href="{% url 'index2' %}">Stonehedge Community Homeowners Association</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="index.html"><i class="bi bi-speedometer2 me-1"></i>Dashboard</a>
<a class="nav-link" href="{% url 'dashboard' %}"><i class="bi bi-speedometer2 me-1"></i>Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="directory.html"><i class="bi bi-people me-1"></i>Directory</a>
<a class="nav-link active" href="{% url 'directory' %}"><i class="bi bi-people me-1"></i>Directory</a>
</li>
<li class="nav-item">
<a class="nav-link" href="posts/"><i class="bi bi-chat-square-text me-1"></i>Community Posts</a>
<a class="nav-link" href="{% url 'posts' %}"><i class="bi bi-chat-square-text me-1"></i>Community Posts</a>
</li>
</ul>
<ul class="navbar-nav">
@@ -59,8 +108,8 @@
<div class="container">
<div class="row">
<div class="col-md-6">
<h5 class="text-uppercase">Greenwood Estates HOA</h5>
<p class="text-white-50">1234 Greenwood Lane<br>Anytown, ST 12345</p>
<h5 class="text-uppercase mb-4">Stonehedge Community Homeowners Association</h5>
<p class="text-white-50">1900 Spring Rd. #200<br>Oak Brook, IL 60523</p>
</div>
<div class="col-md-3">
<h5 class="text-uppercase">Quick Links</h5>

View File

@@ -61,7 +61,7 @@
<div class="row">
<div class="col-lg-6 mb-4 mb-lg-0">
<h5 class="text-uppercase mb-4">Stonehedge Community Homeowners Association</h5>
<p class="text-white-50">1234 Greenwood Lane<br>Anytown, ST 12345</p>
<p class="text-white-50">1900 Spring Rd. #200<br>Oak Brook, IL 60523</p>
</div>
<div class="col-lg-4 offset-lg-2 mb-4 mb-lg-0">
<h5 class="text-uppercase mb-4">Quick Links</h5>

View File

@@ -48,37 +48,39 @@
<div class="container">
<h2 class="text-center text-success mb-5">About Our Community</h2>
<div class="row g-4">
<div class="col-md-4">
<div class="col-md-6">
<div class="card h-100 shadow-sm">
<img src="images/amenities.jpg" class="card-img-top" alt="Community Amenities" style="height: 200px; object-fit: cover;">
<div class="card-body">
<h5 class="card-title">Amenities</h5>
<ul class="list-group list-group-flush mb-3">
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Multiple Social Events</li>
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Playground</li>
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Picnic Tables</li>
</ul>
<h5 class="card-title"><a href="{% url 'dues2' %}">Pay Dues</a></h5>
<p class="card-text">Make sure to pay your dues</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="col-md-6">
<div class="card h-100 shadow-sm">
<div class="card-body">
<h5 class="card-title"><a href="{% url 'membership_form2' %}">Join</a></h5>
<p class="card-text">Fill out the membership form and be added to the mailing list</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100 shadow-sm">
<div class="card-body">
<h5 class="card-title"><a href="{% url 'calendar2' %}">Events</a></h5>
<p class="card-text">Checkout out the upcoming and past events!</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100 shadow-sm">
<img src="images/board.jpg" class="card-img-top" alt="HOA Board" style="height: 200px; object-fit: cover;">
<div class="card-body">
<h5 class="card-title"><a href="{% url 'scha_board2' %}">HOA Board</a></h5>
<p class="card-text">Meet our elected board members who volunteer their time to maintain and improve our neighborhood.</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card h-100 shadow-sm">
<img src="images/rules.jpg" class="card-img-top" alt="Community Rules" style="height: 200px; object-fit: cover;">
<div class="card-body">
<h5 class="card-title">Community Rules</h5>
<p class="card-text">Learn about our community guidelines designed to maintain property values and quality of life for all residents.</p>
</div>
</div>
</div>
</div>
</div>
</section>

View File

@@ -46,29 +46,29 @@
<div class="card-body">
<div class="row g-3">
<div class="col-sm-6">
<a href="directory.html" class="btn btn-outline-success w-100 py-3">
<a href="{% url 'directory' %}" class="btn btn-outline-success w-100 py-3">
<i class="bi bi-people display-6 d-block mb-2"></i>
Member Directory
</a>
</div>
<div class="col-sm-6">
<a href="posts/" class="btn btn-outline-success w-100 py-3">
<a href="{% url 'posts' %}" class="btn btn-outline-success w-100 py-3">
<i class="bi bi-chat-square-text display-6 d-block mb-2"></i>
Community Posts
</a>
</div>
<div class="col-sm-6">
<a href="posts/create.html" class="btn btn-outline-success w-100 py-3">
<a href="{% url 'posts_create' %}" class="btn btn-outline-success w-100 py-3">
<i class="bi bi-plus-circle display-6 d-block mb-2"></i>
Create Post
</a>
</div>
<div class="col-sm-6">
<!-- <div class="col-sm-6">
<a href="#" class="btn btn-outline-success w-100 py-3">
<i class="bi bi-calendar-event display-6 d-block mb-2"></i>
View Calendar
</a>
</div>
</div> -->
</div>
</div>
</div>

View File

@@ -13,7 +13,7 @@
<h1 class="display-6">Member Directory</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="index.html">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Directory</li>
</ol>
</nav>

View File

@@ -0,0 +1,166 @@
{% extends 'schasite/authenticated_base.html' %}
{% load static %}
{% block pagetitle %}
<title>Posts | SCHA</title>
{% endblock %}
{% block content %}
<main class="py-5">
<div class="container">
<div class="row mb-4">
<div class="col-12">
<h1 class="display-6">Community Posts</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Community Posts</li>
</ol>
</nav>
</div>
</div>
<div class="row mb-4">
<div class="col-md-8 mb-3 mb-md-0">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-search"></i></span>
<input type="text" class="form-control" placeholder="Search posts...">
<button class="btn btn-success" type="button">Search</button>
</div>
</div>
<div class="col-md-4 text-md-end">
<a href="{% url 'posts_create' %}" class="btn btn-success">
<i class="bi bi-plus-circle me-2"></i>New Post
</a>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<div class="d-flex justify-content-between align-items-center">
<h3 class="h5 mb-0"><i class="bi bi-pin-angle me-2"></i>Pinned Post</h3>
<span class="badge bg-light text-success">Announcement</span>
</div>
</div>
<div class="card-body">
<div class="d-flex mb-3">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h5 class="mb-1">Annual Community Picnic</h5>
<div class="d-flex flex-wrap text-muted small mb-2">
<div class="me-3"><i class="bi bi-person me-1"></i>Sarah Johnson</div>
<div class="me-3"><i class="bi bi-calendar me-1"></i>June 5, 2023</div>
<div><i class="bi bi-chat me-1"></i>12 comments</div>
</div>
</div>
</div>
<p class="card-text">Our annual community picnic is scheduled for Saturday, June 15th from 11am-3pm at the Greenwood Park. This year we'll have a bounce house, face painting, and a pie baking contest. Please RSVP by June 10th so we can plan for food quantities.</p>
<div class="mt-3">
<a href="#" class="btn btn-sm btn-outline-success me-2"><i class="bi bi-hand-thumbs-up me-1"></i>Like (24)</a>
<a href="#" class="btn btn-sm btn-outline-success"><i class="bi bi-chat me-1"></i>Comment</a>
</div>
</div>
</div>
{% for post in posts %}
<div class="card shadow-sm mb-4">
<div class="card-body">
<div class="d-flex mb-3">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h5 class="mb-1"><a href="{% url 'posts_detail' post_id=post.id %}">{{ post.title }}</a></h5>
<div class="d-flex flex-wrap text-muted small mb-2">
<div class="me-3"><i class="bi bi-person me-1"></i>Emily Davis</div>
<div class="me-3"><i class="bi bi-calendar me-1"></i>June 3, 2023</div>
<div><i class="bi bi-chat me-1"></i>8 comments</div>
</div>
</div>
</div>
<p class="card-text">{{ post.content }}</p>
<div class="mt-3">
<a href="#" class="btn btn-sm btn-outline-success me-2"><i class="bi bi-hand-thumbs-up me-1"></i>Like (15)</a>
<a href="#" class="btn btn-sm btn-outline-success"><i class="bi bi-chat me-1"></i>Comment</a>
</div>
</div>
</div>
{% endfor %}
<div class="card shadow-sm mb-4">
<div class="card-body">
<div class="d-flex mb-3">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h5 class="mb-1">Lost Dog - Please Help!</h5>
<div class="d-flex flex-wrap text-muted small mb-2">
<div class="me-3"><i class="bi bi-person me-1"></i>Emily Davis</div>
<div class="me-3"><i class="bi bi-calendar me-1"></i>June 3, 2023</div>
<div><i class="bi bi-chat me-1"></i>8 comments</div>
</div>
</div>
</div>
<p class="card-text">Our golden retriever Max got out of our yard this morning around 9am. He was last seen near the corner of Oak Drive and Maple Street. He's friendly, wearing a blue collar with our contact info. Please call me at 555-456-7890 if you see him!</p>
<div class="mt-3">
<a href="#" class="btn btn-sm btn-outline-success me-2"><i class="bi bi-hand-thumbs-up me-1"></i>Like (15)</a>
<a href="#" class="btn btn-sm btn-outline-success"><i class="bi bi-chat me-1"></i>Comment</a>
</div>
</div>
</div>
<div class="card shadow-sm mb-4">
<div class="card-body">
<div class="d-flex mb-3">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h5 class="mb-1">Yard Sale This Weekend</h5>
<div class="d-flex flex-wrap text-muted small mb-2">
<div class="me-3"><i class="bi bi-person me-1"></i>Michael Brown</div>
<div class="me-3"><i class="bi bi-calendar me-1"></i>June 1, 2023</div>
<div><i class="bi bi-chat me-1"></i>5 comments</div>
</div>
</div>
</div>
<p class="card-text">We're having a yard sale at 321 Elm Avenue this Saturday from 8am-2pm. Lots of household items, kids' clothes, and furniture. Everything must go!</p>
<div class="mt-3">
<a href="#" class="btn btn-sm btn-outline-success me-2"><i class="bi bi-hand-thumbs-up me-1"></i>Like (7)</a>
<a href="#" class="btn btn-sm btn-outline-success"><i class="bi bi-chat me-1"></i>Comment</a>
</div>
</div>
</div>
<nav aria-label="Posts navigation">
<ul class="pagination justify-content-center">
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">Previous</a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item">
<a class="page-link" href="#">Next</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</main>
{% endblock %}
{% block extra_js %}
{% endblock %}

View File

@@ -0,0 +1,124 @@
{% extends 'schasite/authenticated_base.html' %}
{% load static %}
{% block pagetitle %}
<title>Create Post | SCHA</title>
{% endblock %}
{% block content %}
<main class="py-5">
<div class="container">
<div class="row mb-4">
<div class="col-12">
<h1 class="display-6">Create New Post</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'posts' %}">Community Posts</a></li>
<li class="breadcrumb-item active" aria-current="page">Create Post</li>
</ol>
</nav>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-sm">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-pencil me-2"></i>New Community Post</h3>
</div>
<div class="card-body">
<form id="createPostForm" method="POST" action='{% url "posts_create" %}' class="needs-validation" novalidate>
{% csrf_token %}
{% if community_post.errors %}
<div class="alert alert-danger">
<i class="bi bi-info-circle-fill me-2"></i>
<p> Need to fix the following errors</p>
{{ community_post.errors | safe }}
</div>
{% endif %}
<div class="mb-3">
<label for="title" class="form-label">Title*</label>
<input type="text" class="form-control" value='{{ community_post.title.value|default_if_none:"" }}' name="title" id="title" required>
<div class="invalid-feedback">
Please provide a title for your post.
</div>
</div>
<div class="mb-3">
<label for="category" class="form-label">Category*</label>
<select class="form-select" name="category" id="category" required>
<option value='{{ community_post.category.value|default_if_none:"" }}' selected disabled>Select a category</option>
<option>Announcement</option>
<option>Discussion</option>
<option>For Sale</option>
<option>Help Needed</option>
<option>Event</option>
<option>Other</option>
</select>
<div class="invalid-feedback">
Please select a category.
</div>
</div>
<div class="mb-3">
<label for="content" class="form-label">Content*</label>
<textarea class="form-control" value='{{ community_post.content.value|default_if_none:"" }}' name="content" id="content" rows="6" required></textarea>
<div class="invalid-feedback">
Please provide content for your post.
</div>
</div>
<div class="mb-3">
<label for="postImage" class="form-label">Image (optional)</label>
<input class="form-control" type="file" id="postImage" accept="image/*">
<div class="form-text">
Maximum file size: 5MB. Allowed formats: JPG, PNG, GIF.
</div>
</div>
<div class="mb-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="notifyMembers">
<label class="form-check-label" for="notifyMembers">
Notify all members via email about this post
</label>
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="posts_create" class="btn btn-outline-secondary me-md-2">Cancel</a>
<button type="submit" class="btn btn-success">Post to Community</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Form validation
const form = document.getElementById('createPostForm');
form.addEventListener('submit', function(event) {
event.preventDefault();
event.stopPropagation();
if (form.checkValidity()) {
// In a real implementation, this would submit the post
alert('Post created successfully (simulated)');
window.location.href = "../index.html";
}
form.classList.add('was-validated');
}, false);
// Image preview functionality would go here
});
</script>
{% endblock %}

View File

@@ -0,0 +1,328 @@
{% extends 'schasite/authenticated_base.html' %}
{% load static %}
{% block pagetitle %}
<title>Posts | SCHA</title>
<script type="text/css">
.post-detail .card-header {
padding: 1rem 1.25rem;
}
.comment-list {
max-height: 500px;
overflow-y: auto;
padding-right: 0.5rem;
}
.comment-list::-webkit-scrollbar {
width: 8px;
}
.comment-list::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.comment-list::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 10px;
}
.comment-list::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
/* Responsive adjustments */
@media (max-width: 767.98px) {
.comment-list {
max-height: none;
}
.post-detail .card-header h3 {
font-size: 1.1rem;
}
}
/* Interaction buttons */
.btn-outline-success:hover .bi-hand-thumbs-up,
.text-success .bi-hand-thumbs-up {
fill: currentColor;
}
</script>
{% endblock %}
{% block content %}
<main class="py-5">
<div class="container">
<div class="row mb-4">
<div class="col-12">
<h1 class="display-6">Community Post</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="../../index.html">Home</a></li>
<li class="breadcrumb-item"><a href="../index.html">Community Posts</a></li>
<li class="breadcrumb-item active" aria-current="page">Post Details</li>
</ol>
</nav>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Main Post Card -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<div class="d-flex justify-content-between align-items-center">
<h3 class="h5 mb-0">Annual Community Picnic</h3>
<span class="badge bg-light text-success">Announcement</span>
</div>
</div>
<div class="card-body">
<div class="d-flex mb-4">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="bi bi-person-fill text-success fs-4"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h5 class="mb-1">Sarah Johnson</h5>
<div class="d-flex flex-wrap text-muted small">
<div class="me-3"><i class="bi bi-calendar me-1"></i>Posted on June 5, 2023</div>
<div><i class="bi bi-chat me-1"></i>12 comments</div>
</div>
</div>
</div>
<div class="mb-4">
<img src="../../../images/events/picnic.jpg" alt="Community picnic" class="img-fluid rounded mb-3">
<p>Our annual community picnic is scheduled for <strong>Saturday, June 15th from 11am-3pm</strong> at the Greenwood Park. This is always one of our most popular events, bringing together neighbors of all ages for a day of fun and community building.</p>
<h5 class="mt-4">Event Details</h5>
<ul>
<li><strong>Date:</strong> June 15, 2024</li>
<li><strong>Time:</strong> 11:00 AM - 3:00 PM</li>
<li><strong>Location:</strong> Greenwood Community Park</li>
<li><strong>Address:</strong> 1234 Greenwood Lane, Anytown, ST</li>
<li><strong>RSVP Deadline:</strong> June 10, 2024</li>
</ul>
<h5 class="mt-4">What to Expect</h5>
<p>This year we're excited to offer:</p>
<ul>
<li>Bounce house and playground activities for kids</li>
<li>Face painting and balloon animals</li>
<li>Pie baking contest (sign up below!)</li>
<li>Potluck lunch (main dishes provided by HOA)</li>
<li>Live acoustic music from 1-3pm</li>
</ul>
<div class="alert alert-success mt-4">
<h5><i class="bi bi-info-circle me-2"></i>Volunteers Needed</h5>
<p>We're looking for volunteers to help with setup (10-11am), food service (11:30am-1:30pm), and cleanup (3-4pm). Please email me if you can help!</p>
</div>
</div>
<div class="d-flex justify-content-between align-items-center">
<div>
<button class="btn btn-sm btn-outline-success me-2">
<i class="bi bi-hand-thumbs-up me-1"></i>Like (24)
</button>
<button class="btn btn-sm btn-outline-success">
<i class="bi bi-share me-1"></i>Share
</button>
</div>
<div>
<a href="#" class="text-decoration-none text-success small">
<i class="bi bi-flag me-1"></i>Report
</a>
</div>
</div>
</div>
</div>
<!-- Comments Section -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-chat-square-text me-2"></i>Comments (12)</h3>
</div>
<div class="card-body">
<!-- Comment Form -->
<div class="mb-4">
<form>
<div class="mb-3">
<label for="commentText" class="form-label">Add a comment</label>
<textarea class="form-control" id="commentText" rows="3" placeholder="Share your thoughts..."></textarea>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-success">Post Comment</button>
</div>
</form>
</div>
<hr>
<!-- Comment List -->
<div class="comment-list">
<!-- Comment 1 -->
<div class="d-flex mb-4">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<h6 class="mb-0">Robert Wilson</h6>
<small class="text-muted">June 5, 2023 at 2:30 PM</small>
</div>
<p class="mb-2">Looking forward to it! I'll bring my famous potato salad. Can I sign up to help with setup?</p>
<div>
<a href="#" class="text-decoration-none text-success small me-3">
<i class="bi bi-hand-thumbs-up me-1"></i>Like (5)
</a>
<a href="#" class="text-decoration-none text-success small">
<i class="bi bi-reply me-1"></i>Reply
</a>
</div>
<!-- Reply -->
<div class="d-flex mt-3">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 32px; height: 32px;">
<i class="bi bi-person-fill text-success small"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<h6 class="mb-0">Sarah Johnson</h6>
<small class="text-muted">June 5, 2023 at 3:15 PM</small>
</div>
<p class="mb-2">That would be great Robert! I'll put you down for setup crew.</p>
<div>
<a href="#" class="text-decoration-none text-success small me-3">
<i class="bi bi-hand-thumbs-up me-1"></i>Like (2)
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Comment 2 -->
<div class="d-flex mb-4">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<h6 class="mb-0">Emily Davis</h6>
<small class="text-muted">June 6, 2023 at 9:45 AM</small>
</div>
<p class="mb-2">I'd love to enter the pie contest! Are there any category restrictions?</p>
<div>
<a href="#" class="text-decoration-none text-success small me-3">
<i class="bi bi-hand-thumbs-up me-1"></i>Like (3)
</a>
<a href="#" class="text-decoration-none text-success small">
<i class="bi bi-reply me-1"></i>Reply
</a>
</div>
</div>
</div>
<!-- Comment 3 -->
<div class="d-flex">
<div class="flex-shrink-0">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-person-fill text-success"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<h6 class="mb-0">Michael Brown</h6>
<small class="text-muted">June 6, 2023 at 11:20 AM</small>
</div>
<p class="mb-2">I'll bring my guitar and play during the music time if that's okay!</p>
<div>
<a href="#" class="text-decoration-none text-success small me-3">
<i class="bi bi-hand-thumbs-up me-1"></i>Like (8)
</a>
<a href="#" class="text-decoration-none text-success small">
<i class="bi bi-reply me-1"></i>Reply
</a>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer text-center">
<a href="#" class="text-decoration-none">Load more comments</a>
</div>
</div>
<!-- Related Posts -->
<div class="card shadow-sm">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-collection me-2"></i>Related Posts</h3>
</div>
<div class="card-body">
<div class="list-group list-group-flush">
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Summer Pool Schedule</h6>
<small class="text-muted">May 28, 2023</small>
</div>
<p class="mb-1 small">Pool hours and rules for the summer season</p>
<small class="text-muted">Posted by Michael Brown</small>
</a>
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Neighborhood Yard Sale</h6>
<small class="text-muted">May 15, 2023</small>
</div>
<p class="mb-1 small">Community-wide yard sale August 3-4</p>
<small class="text-muted">Posted by Emily Davis</small>
</a>
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Landscaping Updates</h6>
<small class="text-muted">April 30, 2023</small>
</div>
<p class="mb-1 small">New plants and improvements in common areas</p>
<small class="text-muted">Posted by Robert Wilson</small>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Like button functionality
document.querySelectorAll('.bi-hand-thumbs-up').forEach(icon => {
icon.addEventListener('click', function() {
// In a real implementation, this would track likes
this.classList.toggle('text-success');
});
});
// Comment submission
const commentForm = document.querySelector('.comment-list').previousElementSibling.querySelector('form');
commentForm.addEventListener('submit', function(e) {
e.preventDefault();
const commentText = document.getElementById('commentText').value;
if (commentText.trim() !== '') {
// In a real implementation, this would submit the comment
alert('Comment posted successfully (simulated)');
document.getElementById('commentText').value = '';
}
});
});
</script>
{% endblock %}

View File

@@ -0,0 +1,396 @@
{% extends 'schasite/authenticated_base.html' %}
{% load static %}
{% block pagetitle %}
<title>Profile | SCHA</title>
<script type="text/css">
.profile-avatar {
width: 120px;
height: 120px;
margin: 0 auto 1rem;
}
.dues-history table {
font-size: 0.875rem;
}
.dues-history th,
.dues-history td {
padding: 0.5rem;
}
.list-group-item-action:hover {
background-color: rgba(25, 135, 84, 0.05);
}
/* Communication Preferences */
#preferencesForm .form-check {
margin-bottom: 0.5rem;
}
/* Responsive adjustments */
@media (max-width: 991.98px) {
.profile-avatar {
width: 80px;
height: 80px;
}
}
@media (max-width: 767.98px) {
.profile-avatar {
width: 100px;
height: 100px;
}
}
</script>
{% endblock %}
{% block content %}
<main class="py-5">
<div class="container">
<div class="row mb-4">
<div class="col-12">
<h1 class="display-6">My Profile</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="../index.html">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Profile</li>
</ol>
</nav>
</div>
</div>
<div class="row g-4">
<!-- Left Column -->
<div class="col-lg-4">
<!-- Member Card -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-person-badge me-2"></i>Profile</h3>
</div>
<div class="card-body text-center">
<div class="mb-3">
<div class="bg-success bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center mx-auto" style="width: 120px; height: 120px;">
<i class="bi bi-person-fill text-success fs-1"></i>
</div>
</div>
<h4 class="card-title">John Doe</h4>
<p class="text-muted">Member since: January 15, 2020</p>
<hr>
<button class="btn btn-outline-success btn-sm mb-3">
<i class="bi bi-pencil me-1"></i>Edit Profile
</button>
<button class="btn btn-outline-success btn-sm mb-3">
<i class="bi bi-lock me-1"></i>Change Password
</button>
</div>
</div>
<!-- Dues Payment History -->
<div class="card shadow-sm">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-credit-card me-2"></i>Dues Payment History</h3>
</div>
<div class="card-body">
<div class="alert alert-success">
<i class="bi bi-check-circle-fill me-2"></i>
<strong>Current Status:</strong> Paid through December 2024
</div>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Date</th>
<th>Amount</th>
<th>Method</th>
<th>Receipt</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jan 10, 2024</td>
<td>$600.00</td>
<td>Credit Card</td>
<td><a href="#" class="text-success">View</a></td>
</tr>
<tr>
<td>Jan 5, 2023</td>
<td>$550.00</td>
<td>Bank Transfer</td>
<td><a href="#" class="text-success">View</a></td>
</tr>
<tr>
<td>Jan 8, 2022</td>
<td>$525.00</td>
<td>Check</td>
<td><a href="#" class="text-success">View</a></td>
</tr>
<tr>
<td>Jan 12, 2021</td>
<td>$500.00</td>
<td>Credit Card</td>
<td><a href="#" class="text-success">View</a></td>
</tr>
<tr>
<td>Jan 15, 2020</td>
<td>$500.00</td>
<td>Check</td>
<td><a href="#" class="text-success">View</a></td>
</tr>
</tbody>
</table>
</div>
<div class="text-center mt-2">
<a href="#" class="btn btn-sm btn-success">
<i class="bi bi-printer me-1"></i>Print Full History
</a>
</div>
</div>
</div>
</div>
<!-- Right Column -->
<div class="col-lg-8">
<!-- Member Details -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<div class="d-flex justify-content-between align-items-center">
<h3 class="h5 mb-0"><i class="bi bi-house-heart me-2"></i>Member Details</h3>
<button class="btn btn-sm btn-light" id="editDetailsBtn">
<i class="bi bi-pencil me-1"></i>Edit
</button>
</div>
</div>
<div class="card-body">
<form id="memberDetailsForm">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">First Name</label>
<input type="text" class="form-control" value="John" disabled>
</div>
<div class="col-md-6">
<label class="form-label">Last Name</label>
<input type="text" class="form-control" value="Doe" disabled>
</div>
<div class="col-md-6">
<label class="form-label">Email</label>
<input type="email" class="form-control" value="john.doe@example.com" disabled>
</div>
<div class="col-md-6">
<label class="form-label">Phone</label>
<input type="tel" class="form-control" value="(555) 123-4567" disabled>
</div>
<div class="col-12">
<label class="form-label">Street Address</label>
<input type="text" class="form-control" value="123 Oak Drive" disabled>
</div>
<div class="col-md-4">
<label class="form-label">City</label>
<input type="text" class="form-control" value="Anytown" disabled>
</div>
<div class="col-md-4">
<label class="form-label">State</label>
<input type="text" class="form-control" value="ST" disabled>
</div>
<div class="col-md-4">
<label class="form-label">ZIP Code</label>
<input type="text" class="form-control" value="12345" disabled>
</div>
<div class="col-12 mt-3" id="saveDetailsBtn" style="display: none;">
<button type="submit" class="btn btn-success me-2">Save Changes</button>
<button type="button" class="btn btn-outline-secondary" id="cancelEditBtn">Cancel</button>
</div>
</div>
</form>
</div>
</div>
<!-- My Posts -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-pencil-square me-2"></i>My Posts</h3>
</div>
<div class="card-body">
<div class="list-group list-group-flush">
<a href="../posts/detail.html" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Looking for lawn service recommendations</h6>
<small class="text-muted">May 28, 2024</small>
</div>
<p class="mb-1 small">Does anyone have a landscaper they would recommend for weekly mowing?</p>
<small><span class="badge bg-success bg-opacity-10 text-success">Discussion</span> • 5 comments</small>
</a>
<a href="../posts/detail.html" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Lost cat - gray tabby</h6>
<small class="text-muted">April 15, 2024</small>
</div>
<p class="mb-1 small">Our cat Mittens got out last night near Oak Drive. Please contact if seen!</p>
<small><span class="badge bg-success bg-opacity-10 text-success">Help Needed</span> • 12 comments</small>
</a>
<a href="../posts/detail.html" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Garage sale this weekend</h6>
<small class="text-muted">March 30, 2024</small>
</div>
<p class="mb-1 small">We're having a garage sale Saturday 8am-2pm with furniture, tools, and more.</p>
<small><span class="badge bg-success bg-opacity-10 text-success">For Sale</span> • 3 comments</small>
</a>
</div>
<div class="text-center mt-3">
<a href="../posts/" class="btn btn-sm btn-outline-success">View All My Posts</a>
</div>
</div>
</div>
<!-- My Comments -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-chat-left-text me-2"></i>Posts I've Commented On</h3>
</div>
<div class="card-body">
<div class="list-group list-group-flush">
<a href="../posts/detail.html" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Annual Community Picnic</h6>
<small class="text-muted">June 5, 2024</small>
</div>
<p class="mb-1 small"><strong>My comment:</strong> "Looking forward to it! I'll bring potato salad."</p>
<small><span class="badge bg-success bg-opacity-10 text-success">Announcement</span> • 24 comments total</small>
</a>
<a href="../posts/detail.html" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Pool opening delayed</h6>
<small class="text-muted">May 20, 2024</small>
</div>
<p class="mb-1 small"><strong>My comment:</strong> "Thanks for the update. Any estimate on opening date?"</p>
<small><span class="badge bg-success bg-opacity-10 text-success">Announcement</span> • 8 comments total</small>
</a>
<a href="../posts/detail.html" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">Neighborhood watch meeting</h6>
<small class="text-muted">April 10, 2024</small>
</div>
<p class="mb-1 small"><strong>My comment:</strong> "I can help organize the next meeting."</p>
<small><span class="badge bg-success bg-opacity-10 text-success">Event</span> • 15 comments total</small>
</a>
</div>
<div class="text-center mt-3">
<a href="../posts/" class="btn btn-sm btn-outline-success">View All My Comments</a>
</div>
</div>
</div>
<!-- Communication Preferences -->
<div class="card shadow-sm">
<div class="card-header bg-success text-white">
<h3 class="h5 mb-0"><i class="bi bi-envelope me-2"></i>Communication Preferences</h3>
</div>
<div class="card-body">
<form id="preferencesForm">
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="emailNotifications" checked>
<label class="form-check-label" for="emailNotifications">
Receive email notifications
</label>
</div>
</div>
<div class="mb-3">
<h6 class="mb-2">Notification Types:</h6>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="postReplies" checked>
<label class="form-check-label" for="postReplies">
When someone replies to my posts
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="commentReplies" checked>
<label class="form-check-label" for="commentReplies">
When someone replies to my comments
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="communityAnnouncements" checked>
<label class="form-check-label" for="communityAnnouncements">
Community announcements
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="eventReminders">
<label class="form-check-label" for="eventReminders">
Event reminders
</label>
</div>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="showInDirectory" checked>
<label class="form-check-label" for="showInDirectory">
Include my contact information in the member directory
</label>
</div>
<div class="form-text">
Uncheck to hide your email and phone number from other members
</div>
</div>
<div class="mt-4">
<button type="submit" class="btn btn-success">Save Preferences</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Edit details toggle
const editBtn = document.getElementById('editDetailsBtn');
const cancelBtn = document.getElementById('cancelEditBtn');
const saveBtn = document.getElementById('saveDetailsBtn');
const formInputs = document.querySelectorAll('#memberDetailsForm input');
editBtn.addEventListener('click', function() {
formInputs.forEach(input => {
input.disabled = false;
});
saveBtn.style.display = 'block';
editBtn.style.display = 'none';
});
cancelBtn.addEventListener('click', function() {
formInputs.forEach(input => {
input.disabled = true;
});
saveBtn.style.display = 'none';
editBtn.style.display = 'block';
});
// Form submissions
document.getElementById('memberDetailsForm').addEventListener('submit', function(e) {
e.preventDefault();
// In a real implementation, this would save the changes
alert('Profile details updated successfully (simulated)');
formInputs.forEach(input => {
input.disabled = true;
});
saveBtn.style.display = 'none';
editBtn.style.display = 'block';
});
document.getElementById('preferencesForm').addEventListener('submit', function(e) {
e.preventDefault();
// In a real implementation, this would save preferences
alert('Communication preferences saved (simulated)');
});
});
</script>
{% endblock %}

View File

@@ -10,6 +10,10 @@ if settings.DEBUG:
path('password_reset/',views.password_reset, name="password_reset"),
path('directory/',views.member_directory, name="directory"),
path('dashboard/',views.member_dashboard, name="dashboard"),
path('posts/',views.member_posts, name="posts"),
path('posts_create/',views.member_posts_create, name="posts_create"),
path('posts/<int:post_id>',views.member_posts_detail, name="posts_detail"),
path('profile/',views.profile, name="profile"),
]
else:
@@ -42,3 +46,4 @@ urlpatterns = authenticated_views + [
]

View File

@@ -1,11 +1,13 @@
from django.shortcuts import render, redirect
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership, CommunityPost
from .forms import (
ChildrenForm,
CommunityPostForm,
AddressForm,
PeopleForm,
CommitteeForm,
ServicesForm,
) # , CaptchaForm
from django.db import transaction, IntegrityError
@@ -489,4 +491,36 @@ def member_dashboard(request):
if request.method == "POST":
raise NotImplementedError()
else:
return render(request, "schasite/member_dashboard.html",{})
return render(request, "schasite/member_dashboard.html",{})
def member_posts(request):
if request.method == "POST":
raise NotImplementedError()
else:
posts = CommunityPost.objects.all()[:5]
return render(request, "schasite/member_posts.html",{"posts":posts})
def member_posts_create(request):
if request.method == "POST":
community_post_form = CommunityPostForm(request.POST)
if community_post_form.is_valid():
community_post_form.save()
return render(request, "schasite/member_posts.html",{})
else:
print(f'Error creating the post: {community_post_form.errors}')
return render(request, "schasite/member_posts_create.html",{"community_post": community_post_form})
else:
return render(request, "schasite/member_posts_create.html",{"community_post": CommunityPostForm()})
def member_posts_detail(request, post_id):
if request.method == "POST":
raise NotImplementedError()
else:
return render(request, "schasite/member_posts_detail.html",{})
def profile(request):
if request.method == "POST":
raise NotImplementedError()
else:
return render(request, "schasite/profile.html",{})