Compare commits
11 Commits
b9aee578c3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b97d5ac792 | |||
| fc64549c00 | |||
| b9964b22a9 | |||
| 5bd7a37e52 | |||
| 627bff8074 | |||
| 992750dc55 | |||
| 0e1ddbcf1a | |||
| 4c0605474c | |||
| 77ccc5c2fe | |||
| 636cf3d45d | |||
| b1e372ff9d |
@@ -53,7 +53,7 @@ MIDDLEWARE = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = "scha.urls"
|
ROOT_URLCONF = "scha.urls"
|
||||||
|
CSRF_TRUSTED_ORIGINS = ["https://schawheaton.aimloperations.com","https://www.schawheaton.aimloperations.com", "https://www.schawheaton.com", "https://schawheaton.com"]
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from schasite.views import stripe_cancelled, stripe_success, stripe_webhook
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("schasite/", include("schasite.urls")),
|
path("schasite/", include("schasite.urls")),
|
||||||
|
path("", include("schasite.urls")),
|
||||||
path("success/", stripe_success),
|
path("success/", stripe_success),
|
||||||
path("cancelled/", stripe_cancelled),
|
path("cancelled/", stripe_cancelled),
|
||||||
path("webhook/", stripe_webhook),
|
path("webhook/", stripe_webhook),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from django import forms
|
|||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from .models import (
|
from .models import (
|
||||||
Membership,
|
Membership,
|
||||||
|
CommunityPost,
|
||||||
AddressModel1,
|
AddressModel1,
|
||||||
MembershipPerson,
|
MembershipPerson,
|
||||||
MembershipCommittee,
|
MembershipCommittee,
|
||||||
@@ -10,21 +11,20 @@ from .models import (
|
|||||||
from phonenumber_field.formfields import PhoneNumberField
|
from phonenumber_field.formfields import PhoneNumberField
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
# from django_recaptcha.fields import ReCaptchaField
|
from django_recaptcha.fields import ReCaptchaField
|
||||||
# from django.conf import settings
|
from django.conf import settings
|
||||||
# from django_recaptcha.widgets import ReCaptchaV3
|
from django_recaptcha.widgets import ReCaptchaV3
|
||||||
|
|
||||||
# class CaptchaForm(forms.Form):
|
class CaptchaForm(forms.Form):
|
||||||
# captcha = ReCaptchaField(
|
captcha = ReCaptchaField(
|
||||||
# public_key=settings.RECAPTCHA_PUBLIC_KEY,
|
public_key=settings.RECAPTCHA_PUBLIC_KEY,
|
||||||
# private_key=settings.RECAPTCHA_PRIVATE_KEY,
|
private_key=settings.RECAPTCHA_PRIVATE_KEY,
|
||||||
# widget=ReCaptchaV3(
|
widget=ReCaptchaV3(
|
||||||
# attrs={
|
attrs={
|
||||||
# 'required_score':0.85,
|
'required_score':0.85,
|
||||||
# }
|
}
|
||||||
# ),
|
),
|
||||||
|
)
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
class ChildrenForm(ModelForm):
|
class ChildrenForm(ModelForm):
|
||||||
@@ -38,6 +38,10 @@ class AddressForm(ModelForm):
|
|||||||
model = AddressModel1
|
model = AddressModel1
|
||||||
fields = ["address_1", "address_2", "city", "state", "zip_code"]
|
fields = ["address_1", "address_2", "city", "state", "zip_code"]
|
||||||
|
|
||||||
|
class CommunityPostForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = CommunityPost
|
||||||
|
fields = ['title','category','content']
|
||||||
|
|
||||||
class PeopleForm(ModelForm):
|
class PeopleForm(ModelForm):
|
||||||
phone_number = PhoneNumberField(required=False)
|
phone_number = PhoneNumberField(required=False)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -2,15 +2,31 @@ from django.db import models
|
|||||||
from phonenumber_field.modelfields import PhoneNumberField
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
import datetime
|
import datetime
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
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.
|
# Create your models here.
|
||||||
class UsefulLinks(models.Model):
|
class UsefulLinks(TimeInfoBase):
|
||||||
name = models.CharField(max_length=256)
|
name = models.CharField(max_length=256)
|
||||||
url = 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)
|
children = models.CharField(max_length=256, default="", blank=True, null=True)
|
||||||
|
|
||||||
def get_address_str(self):
|
def get_address_str(self):
|
||||||
@@ -37,7 +53,7 @@ class Membership(models.Model):
|
|||||||
return self.get_address_str() + " | " + self.get_person_1()
|
return self.get_address_str() + " | " + self.get_person_1()
|
||||||
|
|
||||||
|
|
||||||
class AddressModel1(models.Model):
|
class AddressModel1(TimeInfoBase):
|
||||||
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
||||||
address_1 = models.CharField(max_length=128)
|
address_1 = models.CharField(max_length=128)
|
||||||
address_2 = models.CharField(max_length=128, blank=True)
|
address_2 = models.CharField(max_length=128, blank=True)
|
||||||
@@ -46,7 +62,7 @@ class AddressModel1(models.Model):
|
|||||||
zip_code = models.CharField(max_length=5)
|
zip_code = models.CharField(max_length=5)
|
||||||
|
|
||||||
|
|
||||||
class CalendarEvent(models.Model):
|
class CalendarEvent(TimeInfoBase):
|
||||||
event_name = models.CharField(max_length=256)
|
event_name = models.CharField(max_length=256)
|
||||||
start_date = models.DateField(blank=True, null=True)
|
start_date = models.DateField(blank=True, null=True)
|
||||||
end_date = models.DateField(blank=True, null=True)
|
end_date = models.DateField(blank=True, null=True)
|
||||||
@@ -54,7 +70,7 @@ class CalendarEvent(models.Model):
|
|||||||
coordinator_email = models.EmailField(max_length=256, blank=True, null=True)
|
coordinator_email = models.EmailField(max_length=256, blank=True, null=True)
|
||||||
event_link_name = models.CharField(max_length=64, blank=True, null=True)
|
event_link_name = models.CharField(max_length=64, blank=True, null=True)
|
||||||
event_url = models.URLField(max_length=256, blank=True, null=True)
|
event_url = models.URLField(max_length=256, blank=True, null=True)
|
||||||
description= models.CharField(max_length=1024, default="")
|
#description= models.CharField(max_length=1024, default="")
|
||||||
|
|
||||||
def has_date(self):
|
def has_date(self):
|
||||||
return not self.start_date is None
|
return not self.start_date is None
|
||||||
@@ -75,7 +91,7 @@ class CalendarEvent(models.Model):
|
|||||||
return not self.has_date()
|
return not self.has_date()
|
||||||
|
|
||||||
|
|
||||||
class CalendarEventAddressModel(models.Model):
|
class CalendarEventAddressModel(TimeInfoBase):
|
||||||
calendar_event = models.OneToOneField(CalendarEvent, on_delete=models.CASCADE)
|
calendar_event = models.OneToOneField(CalendarEvent, on_delete=models.CASCADE)
|
||||||
address_1 = models.CharField(max_length=128)
|
address_1 = models.CharField(max_length=128)
|
||||||
address_2 = models.CharField(max_length=128, blank=True)
|
address_2 = models.CharField(max_length=128, blank=True)
|
||||||
@@ -89,7 +105,7 @@ class CalendarEventAddressModel(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MembershipPerson(models.Model):
|
class MembershipPerson(TimeInfoBase):
|
||||||
membership = models.ForeignKey(
|
membership = models.ForeignKey(
|
||||||
Membership, on_delete=models.CASCADE, blank=True, null=True
|
Membership, on_delete=models.CASCADE, blank=True, null=True
|
||||||
)
|
)
|
||||||
@@ -102,7 +118,7 @@ class MembershipPerson(models.Model):
|
|||||||
return self.email if self.email else "No email"
|
return self.email if self.email else "No email"
|
||||||
|
|
||||||
|
|
||||||
class MembershipCommittee(models.Model):
|
class MembershipCommittee(TimeInfoBase):
|
||||||
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
||||||
block_captain = models.BooleanField(default=False, blank=True, null=True)
|
block_captain = models.BooleanField(default=False, blank=True, null=True)
|
||||||
coordinator = models.BooleanField(default=False, blank=True, null=True)
|
coordinator = models.BooleanField(default=False, blank=True, null=True)
|
||||||
@@ -119,7 +135,7 @@ class MembershipCommittee(models.Model):
|
|||||||
no_preference = models.BooleanField(default=False, blank=True, null=True)
|
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)
|
membership = models.OneToOneField(Membership, on_delete=models.CASCADE)
|
||||||
babysitting = models.BooleanField(default=False, blank=True, null=True)
|
babysitting = models.BooleanField(default=False, blank=True, null=True)
|
||||||
lawn_mowing = models.BooleanField(default=False, blank=True, null=True)
|
lawn_mowing = models.BooleanField(default=False, blank=True, null=True)
|
||||||
@@ -131,7 +147,7 @@ class MembershipServices(models.Model):
|
|||||||
other_desc = models.CharField(default="", blank=True, null=True, max_length=256)
|
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())
|
date = models.DateField(default=timezone.now())
|
||||||
status = models.CharField(default="Completed", max_length=256)
|
status = models.CharField(default="Completed", max_length=256)
|
||||||
email = models.EmailField(blank=True, null=True)
|
email = models.EmailField(blank=True, null=True)
|
||||||
@@ -140,26 +156,58 @@ class Payments(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SCHAOfficer(models.Model):
|
class SCHAOfficer(TimeInfoBase):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
position = models.CharField(max_length=255)
|
position = models.CharField(max_length=255)
|
||||||
email = models.EmailField(max_length=255)
|
email = models.EmailField(max_length=255)
|
||||||
|
|
||||||
# class CommunitySchools(models.Model):
|
### NOT USED YET ###
|
||||||
# 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 CommunityShoppingAndDining(models.Model):
|
class CommunitySchools(TimeInfoBase):
|
||||||
# name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
# distance = models.DecimalField(max_digits=3, decimal_places=1)
|
name_school_url = models.URLField(max_length=256)
|
||||||
# description = models.CharField(max_length=1024)
|
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):
|
class CommunityShoppingAndDining(TimeInfoBase):
|
||||||
# name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
# distance = models.DecimalField(max_digits=3, decimal_places=1)
|
distance = models.DecimalField(max_digits=3, decimal_places=1)
|
||||||
# description = models.CharField(max_length=1024)
|
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)
|
||||||
|
|
||||||
|
### Member only models
|
||||||
|
|
||||||
|
class CommunityMember(TimeInfoBase):
|
||||||
|
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||||
|
membership_person = models.OneToOneField(MembershipPerson, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
author = models.OneToOneField(CommunityMember, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
class CommunityPostReports(TimeInfoBase):
|
||||||
|
# for anyone who reports a post
|
||||||
|
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
|
||||||
|
reporter = models.OneToOneField(CommunityMember, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
class CommunityPostLikes(TimeInfoBase):
|
||||||
|
# for anyone who likes a post
|
||||||
|
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
|
||||||
|
reporter = models.OneToOneField(CommunityMember, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
class CommunityComment(TimeInfoBase):
|
||||||
|
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
|
||||||
|
content = models.CharField(max_length=1024*8)
|
||||||
|
likes = models.IntegerField(default=0)
|
||||||
|
author = models.OneToOneField(CommunityMember, on_delete=models.CASCADE)
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
padding-top: 56px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
|
|||||||
BIN
schasite/static/images/District_200.png
Normal file
|
After Width: | Height: | Size: 474 KiB |
BIN
schasite/static/images/brighton.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
schasite/static/images/danada.jpeg
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
schasite/static/images/downtown_naperville.jpeg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
schasite/static/images/downtown_wheaton.jpeg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
schasite/static/images/seven_gables.jpg
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
schasite/static/images/wheaton_farmers_market.jpeg
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -11,7 +11,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-lg-6 mb-4 mb-lg-0">
|
<div class="col-lg-6 mb-4 mb-lg-0">
|
||||||
<img src="../images/schools.jpg" alt="Local Schools" class="img-fluid rounded shadow">
|
<img src="{% static 'images/District_200.png' %}" alt="Local Schools" class="img-fluid rounded shadow">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<h2 class="text-success mb-4">Excellent Schools Serving Our Community</h2>
|
<h2 class="text-success mb-4">Excellent Schools Serving Our Community</h2>
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
<strong>Grades:</strong> 9-12<br>
|
<strong>Grades:</strong> 9-12<br>
|
||||||
<strong>Enrollment:</strong> 698<br>
|
<strong>Enrollment:</strong> 698<br>
|
||||||
<strong>Distance:</strong> 2.7 miles from community entrance<br>
|
<strong>Distance:</strong> 2.7 miles from community entrance<br>
|
||||||
<strong>Principal:</strong> TBD</p>
|
<strong>Principal:</strong> Raeann Huhn </p>
|
||||||
<a href="https://www.sfhscollegeprep.org/" target="_blank" class="btn btn-sm btn-outline-success">Visit Website</a>
|
<a href="https://www.sfhscollegeprep.org/" target="_blank" class="btn btn-sm btn-outline-success">Visit Website</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
<strong>Grades:</strong> 9-12<br>
|
<strong>Grades:</strong> 9-12<br>
|
||||||
<strong>Enrollment:</strong> 1265<br>
|
<strong>Enrollment:</strong> 1265<br>
|
||||||
<strong>Distance:</strong> 5.9 miles from community entrance<br>
|
<strong>Distance:</strong> 5.9 miles from community entrance<br>
|
||||||
<strong>Principal:</strong> TBD</p>
|
<strong>Principal:</strong> Sheri Costello </p>
|
||||||
<a href="http://www.cusd200.org/Domain/140" target="_blank" class="btn btn-sm btn-outline-success">Visit Website</a>
|
<a href="http://www.cusd200.org/Domain/140" target="_blank" class="btn btn-sm btn-outline-success">Visit Website</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-lg-6 order-lg-2 mb-4 mb-lg-0">
|
<div class="col-lg-6 order-lg-2 mb-4 mb-lg-0">
|
||||||
<img src="../images/history.jpg" alt="Community History" class="img-fluid rounded shadow">
|
<img src="{% static 'images/header.gif' %}" alt="Community History" class="img-fluid rounded shadow">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 order-lg-1">
|
<div class="col-lg-6 order-lg-1">
|
||||||
<h2 class="text-success mb-4">Our Rich History</h2>
|
<h2 class="text-success mb-4">Our Rich History</h2>
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card h-100 shadow-sm">
|
<div class="card h-100 shadow-sm">
|
||||||
<img src="../images/greenwood-mall.jpg" class="card-img-top" alt="Greenwood Mall">
|
<img src="{% static 'images/danada.jpeg' %}" class="card-img-top" alt="Greenwood Mall">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Danada</h5>
|
<h5 class="card-title">Danada</h5>
|
||||||
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>1.0 miles from community</p>
|
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>1.0 miles from community</p>
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card h-100 shadow-sm">
|
<div class="card h-100 shadow-sm">
|
||||||
<img src="../images/farmers-market.jpg" class="card-img-top" alt="Farmers Market">
|
<img src="{% static 'images/downtown_wheaton.jpeg' %}" class="card-img-top" alt="Farmers Market">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Downtown Wheaton</h5>
|
<h5 class="card-title">Downtown Wheaton</h5>
|
||||||
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>2.7 miles from community</p>
|
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>2.7 miles from community</p>
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card h-100 shadow-sm">
|
<div class="card h-100 shadow-sm">
|
||||||
<img src="../images/farmers-market.jpg" class="card-img-top" alt="Farmers Market">
|
<img src="{% static 'images/wheaton_farmers_market.jpeg' %}" class="card-img-top" alt="Farmers Market">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Wheaton Farmersmarket</h5>
|
<h5 class="card-title">Wheaton Farmersmarket</h5>
|
||||||
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>2.8 miles from community</p>
|
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>2.8 miles from community</p>
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card h-100 shadow-sm">
|
<div class="card h-100 shadow-sm">
|
||||||
<img src="../images/dining-district.jpg" class="card-img-top" alt="Dining District">
|
<img src="{% static 'images/downtown_naperville.jpeg' %}" class="card-img-top" alt="Dining District">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Downtown Naperville</h5>
|
<h5 class="card-title">Downtown Naperville</h5>
|
||||||
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>6.2 miles from community</p>
|
<p class="card-text"><i class="bi bi-geo-alt-fill text-success me-2"></i>6.2 miles from community</p>
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
<div class="card shadow-sm h-100">
|
<div class="card shadow-sm h-100">
|
||||||
<div class="row g-0 h-100">
|
<div class="row g-0 h-100">
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<img src="../images/community-park.jpg" class="img-fluid rounded-start h-100" alt="Community Park" style="object-fit: cover;">
|
<img src="{% static 'images/brighton.jpg' %}" class="img-fluid rounded-start h-100" alt="Community Park" style="object-fit: cover;">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -249,7 +249,7 @@
|
|||||||
<div class="card shadow-sm h-100">
|
<div class="card shadow-sm h-100">
|
||||||
<div class="row g-0 h-100">
|
<div class="row g-0 h-100">
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<img src="../images/nature-preserve.jpg" class="img-fluid rounded-start h-100" alt="Nature Preserve" style="object-fit: cover;">
|
<img src="{% static 'images/seven_gables.jpg' %}" class="img-fluid rounded-start h-100" alt="Nature Preserve" style="object-fit: cover;">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -260,8 +260,8 @@
|
|||||||
<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>Playground</li>
|
||||||
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Baseball Field</li>
|
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Baseball Field</li>
|
||||||
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Tennis Court</li>
|
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Tennis Court</li>
|
||||||
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>BasketballCourt</li>
|
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Basketball Court</li>
|
||||||
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Picninc Tables</li>
|
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Picnic Tables</li>
|
||||||
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Dogs Allowed</li>
|
<li class="list-group-item"><i class="bi bi-check text-success me-2"></i>Dogs Allowed</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="card-text"><small class="text-muted">Open daily from 8am to sunset</small></p>
|
<p class="card-text"><small class="text-muted">Open daily from 8am to sunset</small></p>
|
||||||
|
|||||||
174
schasite/templates/schasite/authenticated_base.html
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
{% load static %}
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
{% block pagetitle %}
|
||||||
|
{% endblock %}
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<!-- Bootstrap Icons -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||||
|
<!-- 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="{% 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="{% url 'dashboard' %}"><i class="bi bi-speedometer2 me-1"></i>Dashboard</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<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="{% url 'posts' %}"><i class="bi bi-chat-square-text me-1"></i>Community Posts</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown">
|
||||||
|
<i class="bi bi-person-circle me-1"></i>John D.
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end">
|
||||||
|
<li><a class="dropdown-item" href="#"><i class="bi bi-person me-2"></i>Profile</a></li>
|
||||||
|
<li><a class="dropdown-item" href="#"><i class="bi bi-gear me-2"></i>Settings</a></li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li><a class="dropdown-item" href="../../auth/login.html"><i class="bi bi-box-arrow-right me-2"></i>Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="bg-dark text-white pt-4 pb-3">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<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>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><a href="index.html" class="text-white-50">Dashboard</a></li>
|
||||||
|
<li><a href="directory.html" class="text-white-50">Directory</a></li>
|
||||||
|
<li><a href="posts/" class="text-white-50">Community Posts</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<h5 class="text-uppercase">Account</h5>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><a href="#" class="text-white-50">Profile</a></li>
|
||||||
|
<li><a href="#" class="text-white-50">Settings</a></li>
|
||||||
|
<li><a href="../../auth/login.html" class="text-white-50">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="my-3">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 text-center">
|
||||||
|
<p class="mb-0 small">© 2023 Greenwood Estates HOA. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- Bootstrap JS -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Directory Script -->
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Search functionality
|
||||||
|
const searchInput = document.getElementById('directorySearch');
|
||||||
|
const tableRows = document.querySelectorAll('tbody tr');
|
||||||
|
|
||||||
|
searchInput.addEventListener('input', function() {
|
||||||
|
const searchTerm = this.value.toLowerCase();
|
||||||
|
|
||||||
|
tableRows.forEach(row => {
|
||||||
|
const rowText = row.textContent.toLowerCase();
|
||||||
|
if (rowText.includes(searchTerm)) {
|
||||||
|
row.style.display = '';
|
||||||
|
} else {
|
||||||
|
row.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter functionality
|
||||||
|
const filterSelect = document.getElementById('directoryFilter');
|
||||||
|
|
||||||
|
filterSelect.addEventListener('change', function() {
|
||||||
|
const filterValue = this.value;
|
||||||
|
// In a real implementation, this would filter the directory
|
||||||
|
console.log('Filter by:', filterValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -12,8 +12,11 @@
|
|||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||||
<!-- Custom CSS -->
|
<!-- Custom CSS -->
|
||||||
<link href="{% static 'css/style2.css' %}" rel="stylesheet" type="text/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>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-success sticky-top">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-success sticky-top">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -59,7 +62,6 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6 mb-4 mb-lg-0">
|
<div class="col-lg-6 mb-4 mb-lg-0">
|
||||||
<h5 class="text-uppercase mb-4">Stonehedge Community Homeowners Association</h5>
|
<h5 class="text-uppercase mb-4">Stonehedge Community Homeowners Association</h5>
|
||||||
<p class="text-white-50">1234 Greenwood Lane<br>Anytown, ST 12345</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4 offset-lg-2 mb-4 mb-lg-0">
|
<div class="col-lg-4 offset-lg-2 mb-4 mb-lg-0">
|
||||||
<h5 class="text-uppercase mb-4">Quick Links</h5>
|
<h5 class="text-uppercase mb-4">Quick Links</h5>
|
||||||
@@ -76,7 +78,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr class="my-4 text-white-50">
|
<hr class="my-4 text-white-50">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div id="footer">© Stonehedge Community Homeowners Association 2010-<script>document.write( new Date().getFullYear() );</script>. All rights reserved
|
<div id="footer">
|
||||||
|
<p>© Stonehedge Community Homeowners Association 2010-<script>document.write( new Date().getFullYear() );</script>. All rights reserved </p>
|
||||||
|
<p> Developed by <a href="https://aimloperations.com">AI ML Operations, LLC</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -87,4 +91,4 @@
|
|||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -109,9 +109,8 @@
|
|||||||
<i class="bi bi-credit-card text-success display-4 mb-3"></i>
|
<i class="bi bi-credit-card text-success display-4 mb-3"></i>
|
||||||
<h4 class="text-success">Credit/Debit Card</h4>
|
<h4 class="text-success">Credit/Debit Card</h4>
|
||||||
<p class="card-text">Pay securely with Visa, Mastercard, American Express, or Discover.</p>
|
<p class="card-text">Pay securely with Visa, Mastercard, American Express, or Discover.</p>
|
||||||
<a href="https://buy.stripe.com/test_14k6rE7jD3hQ2SQ144" class="btn btn-success mt-3" target="_blank" id="submitBtn">
|
|
||||||
Pay with Card
|
<button class="btn btn-success mt-3" id="submitBtn">Pay Dues</button>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -192,39 +191,6 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
<!-- Stripe Integration Script (example) -->
|
<!-- Stripe Integration Script (example) -->
|
||||||
<script>
|
<script src="https://js.stripe.com/v3/"></script>
|
||||||
// This would be replaced with your actual Stripe integration code
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Example: Track outbound links to Stripe
|
|
||||||
const stripeLinks = document.querySelectorAll('a[href*="stripe.com"]');
|
|
||||||
stripeLinks.forEach(link => {
|
|
||||||
link.addEventListener('click', function(e) {
|
|
||||||
// You could add analytics tracking here
|
|
||||||
console.log('Redirecting to Stripe payment');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Example: Dynamic balance loading (would connect to your backend)
|
|
||||||
function loadAccountBalance() {
|
|
||||||
// In a real implementation, this would fetch from your database
|
|
||||||
// This is just a placeholder example
|
|
||||||
return {
|
|
||||||
member: "John Doe (Lot #42)",
|
|
||||||
balance: "$600.00",
|
|
||||||
dueDate: "January 15, 2024",
|
|
||||||
lastPayment: "$600.00 on January 10, 2023"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the account info section (example)
|
|
||||||
const accountInfo = loadAccountBalance();
|
|
||||||
document.querySelector('.bg-light p:nth-child(1)').innerHTML =
|
|
||||||
`<strong>Member:</strong> ${accountInfo.member}`;
|
|
||||||
document.querySelector('.bg-light p:nth-child(2)').innerHTML =
|
|
||||||
`<strong>Current Balance:</strong> ${accountInfo.balance} (Due ${accountInfo.dueDate})`;
|
|
||||||
document.querySelector('.bg-light p:nth-child(3)').innerHTML =
|
|
||||||
`<strong>Last Payment:</strong> ${accountInfo.lastPayment}`;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<script src="{% static 'main.js' %}"></script>
|
<script src="{% static 'main.js' %}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends 'schasite/base.html' %}
|
{% extends 'schasite/base2.html' %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
{% block pagetitle %}
|
{% block pagetitle %}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{% extends 'schasite/base.html' %}
|
{% extends 'schasite/base2.html' %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
{% block pagetitle %}
|
{% block pagetitle %}
|
||||||
|
|||||||
@@ -3,21 +3,42 @@
|
|||||||
|
|
||||||
{% block pagetitle %}
|
{% block pagetitle %}
|
||||||
<title>Stonehedge Community Homeowners Association</title>
|
<title>Stonehedge Community Homeowners Association</title>
|
||||||
|
<style type="text/css">
|
||||||
|
.hero-section {
|
||||||
|
background: url({% static 'images/header.gif' %});
|
||||||
|
height: 60vh;
|
||||||
|
display: flex;
|
||||||
|
background-repeat:no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<section id="home" class="py-5 bg-success bg-opacity-10">
|
<section id="home" class="py-5 bg-success bg-opacity-10">
|
||||||
|
|
||||||
<div class="container py-5">
|
<div class="container py-5">
|
||||||
|
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-lg-8 mb-4 mb-lg-0">
|
<div class="col-lg-8 mb-4 mb-lg-0">
|
||||||
<h1 class="display-4 fw-bold mb-3">Welcome to Stonehedge Community Homeowners Association</h1>
|
|
||||||
|
<h1 class="display-4 fw-bold mb-3">Welcome to Stonehedge Community Homeowners Association</h1>
|
||||||
<p class="lead mb-4">A premier community dedicated to maintaining beautiful homes, safe neighborhoods, and a high quality of life for all residents.</p>
|
<p class="lead mb-4">A premier community dedicated to maintaining beautiful homes, safe neighborhoods, and a high quality of life for all residents.</p>
|
||||||
<a href="{% url 'about_us2' %}" class="btn btn-success btn-lg px-4">Learn More</a>
|
<a href="{% url 'about_us2' %}" class="btn btn-success btn-lg px-4">Learn More</a>
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
</div>
|
||||||
<img src='{% static "images/bricks.jpg" %}' alt="Stonehedge Community Homeowners Association" class="img-fluid rounded-circle shadow">
|
|
||||||
</div>
|
|
||||||
|
<!-- <div class="col-lg-4">
|
||||||
|
<img src="{% static 'images/header.gif' %}" alt="Stonehedge Community Homeowners Association" class="img-fluid rounded-circle shadow">
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -27,112 +48,39 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="text-center text-success mb-5">About Our Community</h2>
|
<h2 class="text-center text-success mb-5">About Our Community</h2>
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<div class="col-md-4">
|
|
||||||
|
<div class="col-md-6">
|
||||||
<div class="card h-100 shadow-sm">
|
<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">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Amenities</h5>
|
<h5 class="card-title"><a href="{% url 'dues2' %}">Pay Dues</a></h5>
|
||||||
<p class="card-text">Our community features a swimming pool, playground, walking trails, and clubhouse available for resident use.</p>
|
<p class="card-text">Make sure to pay your dues</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-6">
|
||||||
<div class="card h-100 shadow-sm">
|
<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">
|
<div class="card-body">
|
||||||
<h5 class="card-title">HOA Board</h5>
|
<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">
|
||||||
|
<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>
|
<p class="card-text">Meet our elected board members who volunteer their time to maintain and improve our neighborhood.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
|
||||||
|
|
||||||
<!-- News Section -->
|
|
||||||
<section id="news" class="py-5 bg-success bg-opacity-10">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="text-center text-success mb-5">Community News & Events</h2>
|
|
||||||
<div class="row g-4">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div class="card h-100 shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Annual Community Picnic</h5>
|
|
||||||
<p class="card-text">Join us on June 15th for our annual community picnic at the clubhouse. Food, games, and fun for the whole family!</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer bg-transparent border-0">
|
|
||||||
<a href="#" class="btn btn-outline-success">RSVP Now</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div class="card h-100 shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title">Landscaping Updates</h5>
|
|
||||||
<p class="card-text">New landscaping will be installed in common areas beginning next month. Expect temporary parking restrictions.</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer bg-transparent border-0">
|
|
||||||
<a href="#" class="btn btn-outline-success">View Schedule</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center mt-4">
|
|
||||||
<a href="#" class="btn btn-success px-4">View All News</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Documents Section -->
|
|
||||||
<section id="documents" class="py-5">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="text-center text-success mb-5">Community Documents</h2>
|
|
||||||
<div class="row g-4">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card h-100 shadow-sm">
|
|
||||||
<div class="card-header bg-success text-white">
|
|
||||||
<h5 class="mb-0">Governing Documents</h5>
|
|
||||||
</div>
|
|
||||||
<div class="list-group list-group-flush">
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">CC&Rs</a>
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">Bylaws</a>
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">Articles of Incorporation</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card h-100 shadow-sm">
|
|
||||||
<div class="card-header bg-success text-white">
|
|
||||||
<h5 class="mb-0">Meeting Minutes</h5>
|
|
||||||
</div>
|
|
||||||
<div class="list-group list-group-flush">
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">2023 Meetings</a>
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">2022 Meetings</a>
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">Archive</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card h-100 shadow-sm">
|
|
||||||
<div class="card-header bg-success text-white">
|
|
||||||
<h5 class="mb-0">Forms</h5>
|
|
||||||
</div>
|
|
||||||
<div class="list-group list-group-flush">
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">Architectural Request</a>
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">Complaint Form</a>
|
|
||||||
<a href="#" class="list-group-item list-group-item-action">Resale Certificate Request</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
123
schasite/templates/schasite/member_dashboard.html
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
{% extends 'schasite/authenticated_base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block pagetitle %}
|
||||||
|
<title>Dashboard | 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">Member Dashboard</h1>
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">Home</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-4">
|
||||||
|
<!-- Welcome Card -->
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card shadow-sm h-100">
|
||||||
|
<div class="card-header bg-success text-white">
|
||||||
|
<h3 class="h5 mb-0"><i class="bi bi-house-door me-2"></i>Welcome</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title">Hello, John Doe!</h4>
|
||||||
|
<p class="card-text">Welcome to your Greenwood Estates member portal. From here you can access community resources, connect with neighbors, and stay informed.</p>
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<i class="bi bi-info-circle-fill me-2"></i>
|
||||||
|
Your membership is active through December 31, 2024.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Links -->
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card shadow-sm h-100">
|
||||||
|
<div class="card-header bg-success text-white">
|
||||||
|
<h3 class="h5 mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<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="{% 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="{% 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">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<!-- Recent Activity -->
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-success text-white">
|
||||||
|
<h3 class="h5 mb-0"><i class="bi bi-activity me-2"></i>Your Recently Updated Posts</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="list-group">
|
||||||
|
{% for recent_post in member_recent_posts %}
|
||||||
|
<a href="#" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1">{{ recent_post.title }}</h5>
|
||||||
|
<small>3 days ago</small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1">{{ recent_post.content }}</p>
|
||||||
|
<small>Posted by Sarah Johnson</small>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-success text-white">
|
||||||
|
<h3 class="h5 mb-0"><i class="bi bi-activity me-2"></i>Recent Community Posts</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="list-group">
|
||||||
|
{% for recent_post in recent_posts %}
|
||||||
|
<a href="#" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1">{{ recent_post.title }}</h5>
|
||||||
|
<small>3 days ago</small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1">{{ recent_post.content }}</p>
|
||||||
|
<small>Posted by Sarah Johnson</small>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extra_js %}
|
||||||
|
{% endblock %}
|
||||||
229
schasite/templates/schasite/member_directory.html
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
{% extends 'schasite/authenticated_base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block pagetitle %}
|
||||||
|
<title>Directory | 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">Member Directory</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">Directory</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-md-6 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 members..." id="directorySearch">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">Filter</span>
|
||||||
|
<select class="form-select" id="directoryFilter">
|
||||||
|
<option selected>All Members</option>
|
||||||
|
<option>Committee Members</option>
|
||||||
|
<option>Board Members</option>
|
||||||
|
<option>By Street</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<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-people-fill me-2"></i>Community Members</h3>
|
||||||
|
<span class="badge bg-light text-success">142 Members</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover mb-0">
|
||||||
|
<thead class="table-success">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Address</th>
|
||||||
|
<th>Contact</th>
|
||||||
|
<th>Committees</th>
|
||||||
|
<th>Services</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<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">
|
||||||
|
<h6 class="mb-0">John & Sarah Smith</h6>
|
||||||
|
<small class="text-muted">Lot #42</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>123 Oak Drive</td>
|
||||||
|
<td>
|
||||||
|
<a href="mailto:john.smith@example.com" class="text-decoration-none"><i class="bi bi-envelope me-1"></i>Email</a><br>
|
||||||
|
<a href="tel:5551234567" class="text-decoration-none"><i class="bi bi-telephone me-1"></i>555-123-4567</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success mb-1">Social Committee</span>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success">Welcoming</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-info bg-opacity-10 text-info">Pet Care</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<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">
|
||||||
|
<h6 class="mb-0">Robert Wilson</h6>
|
||||||
|
<small class="text-muted">Lot #18</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>456 Maple Street</td>
|
||||||
|
<td>
|
||||||
|
<a href="mailto:rwilson@example.com" class="text-decoration-none"><i class="bi bi-envelope me-1"></i>Email</a><br>
|
||||||
|
<a href="tel:5559876543" class="text-decoration-none"><i class="bi bi-telephone me-1"></i>555-987-6543</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success mb-1">Architectural</span>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success">Board</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-info bg-opacity-10 text-info">Lawn Mowing</span>
|
||||||
|
<span class="badge bg-info bg-opacity-10 text-info">Snow Shoveling</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<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">
|
||||||
|
<h6 class="mb-0">Emily Davis</h6>
|
||||||
|
<small class="text-muted">Lot #75</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>789 Pine Road</td>
|
||||||
|
<td>
|
||||||
|
<a href="mailto:emily.d@example.com" class="text-decoration-none"><i class="bi bi-envelope me-1"></i>Email</a><br>
|
||||||
|
<a href="tel:5554567890" class="text-decoration-none"><i class="bi bi-telephone me-1"></i>555-456-7890</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success mb-1">Communications</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-info bg-opacity-10 text-info">Babysitting</span>
|
||||||
|
<span class="badge bg-info bg-opacity-10 text-info">House Sitting</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<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">
|
||||||
|
<h6 class="mb-0">Michael & Lisa Brown</h6>
|
||||||
|
<small class="text-muted">Lot #33</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>321 Elm Avenue</td>
|
||||||
|
<td>
|
||||||
|
<a href="mailto:mbrown@example.com" class="text-decoration-none"><i class="bi bi-envelope me-1"></i>Email</a><br>
|
||||||
|
<a href="tel:5557890123" class="text-decoration-none"><i class="bi bi-telephone me-1"></i>555-789-0123</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success mb-1">Landscape</span>
|
||||||
|
<span class="badge bg-success bg-opacity-10 text-success">Safety</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-info bg-opacity-10 text-info">Other (Handyman)</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<nav aria-label="Directory navigation">
|
||||||
|
<ul class="pagination justify-content-center mb-0">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extra_js %}
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Search functionality
|
||||||
|
const searchInput = document.getElementById('directorySearch');
|
||||||
|
const tableRows = document.querySelectorAll('tbody tr');
|
||||||
|
|
||||||
|
searchInput.addEventListener('input', function() {
|
||||||
|
const searchTerm = this.value.toLowerCase();
|
||||||
|
|
||||||
|
tableRows.forEach(row => {
|
||||||
|
const rowText = row.textContent.toLowerCase();
|
||||||
|
if (rowText.includes(searchTerm)) {
|
||||||
|
row.style.display = '';
|
||||||
|
} else {
|
||||||
|
row.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter functionality
|
||||||
|
const filterSelect = document.getElementById('directoryFilter');
|
||||||
|
|
||||||
|
filterSelect.addEventListener('change', function() {
|
||||||
|
const filterValue = this.value;
|
||||||
|
// In a real implementation, this would filter the directory
|
||||||
|
console.log('Filter by:', filterValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
166
schasite/templates/schasite/member_posts.html
Normal 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 %}
|
||||||
124
schasite/templates/schasite/member_posts_create.html
Normal 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 %}
|
||||||
328
schasite/templates/schasite/member_posts_detail.html
Normal 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 %}
|
||||||
@@ -74,7 +74,8 @@
|
|||||||
<h2 class="h4 mb-0">New Member Information</h2>
|
<h2 class="h4 mb-0">New Member Information</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="membershipForm" class="needs-validation" novalidate>
|
<form id="membershipForm" method="POST" action='{% url "membership_form2" %}' class="needs-validation" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
<!-- Household Information -->
|
<!-- Household Information -->
|
||||||
<fieldset class="mb-4">
|
<fieldset class="mb-4">
|
||||||
<legend class="h5 text-success border-bottom pb-2">Household Information</legend>
|
<legend class="h5 text-success border-bottom pb-2">Household Information</legend>
|
||||||
@@ -83,30 +84,27 @@
|
|||||||
<div class="row g-3 mb-4">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="streetAddress" class="form-label">Street Address*</label>
|
<label for="streetAddress" class="form-label">Street Address*</label>
|
||||||
<input type="text" class="form-control" id="streetAddress" required>
|
<input type="text" class="form-control" id="streetAddress" name="streetAddress" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide your street address.
|
Please provide your street address.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="unit" class="form-label">Unit/Apt #</label>
|
<label for="unit" class="form-label">Unit/Apt #</label>
|
||||||
<input type="text" class="form-control" id="unit">
|
<input type="text" class="form-control" id="unit" name="unit">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="city" class="form-label">City*</label>
|
<label for="city" class="form-label">City*</label>
|
||||||
<input type="text" class="form-control" id="city" required>
|
<input type="text" class="form-control" id="city" name="city" value="Wheaton" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide your city.
|
Please provide your city.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="state" class="form-label">State*</label>
|
<label for="state" class="form-label">State*</label>
|
||||||
<select class="form-select" id="state" required>
|
<select class="form-select" id="state" name="state" value="Illinois" required>
|
||||||
<option value="" selected disabled>Choose...</option>
|
<option value="" selected disabled>Choose...</option>
|
||||||
<option>Alabama</option>
|
<option>IL</option>
|
||||||
<option>Alaska</option>
|
|
||||||
<!-- Add all states -->
|
|
||||||
<option>Wyoming</option>
|
|
||||||
</select>
|
</select>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please select your state.
|
Please select your state.
|
||||||
@@ -114,7 +112,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="zipCode" class="form-label">ZIP Code*</label>
|
<label for="zipCode" class="form-label">ZIP Code*</label>
|
||||||
<input type="text" class="form-control" id="zipCode" required>
|
<input type="text" class="form-control" id="zipCode" value="zipCode" value="60189" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide your ZIP code.
|
Please provide your ZIP code.
|
||||||
</div>
|
</div>
|
||||||
@@ -128,28 +126,28 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="firstName1" class="form-label">First Name*</label>
|
<label for="firstName1" class="form-label">First Name*</label>
|
||||||
<input type="text" class="form-control" id="firstName1" required>
|
<input type="text" class="form-control" id="firstName1" name="firstName1" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide first name.
|
Please provide first name.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="lastName1" class="form-label">Last Name*</label>
|
<label for="lastName1" class="form-label">Last Name*</label>
|
||||||
<input type="text" class="form-control" id="lastName1" required>
|
<input type="text" class="form-control" id="lastName1" name="lastName1" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide last name.
|
Please provide last name.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="email1" class="form-label">Email*</label>
|
<label for="email1" class="form-label">Email*</label>
|
||||||
<input type="email" class="form-control" id="email1" required>
|
<input type="email" class="form-control" id="email1" name="email1" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide a valid email.
|
Please provide a valid email.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="phone1" class="form-label">Phone*</label>
|
<label for="phone1" class="form-label">Phone*</label>
|
||||||
<input type="tel" class="form-control" id="phone1" required>
|
<input type="tel" class="form-control" id="phone1" name="phone1" required>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please provide phone number.
|
Please provide phone number.
|
||||||
</div>
|
</div>
|
||||||
@@ -174,19 +172,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="firstName2" class="form-label">First Name</label>
|
<label for="firstName2" class="form-label">First Name</label>
|
||||||
<input type="text" class="form-control" id="firstName2">
|
<input type="text" class="form-control" id="firstName2" name="firstName2">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="lastName2" class="form-label">Last Name</label>
|
<label for="lastName2" class="form-label">Last Name</label>
|
||||||
<input type="text" class="form-control" id="lastName2">
|
<input type="text" class="form-control" id="lastName2" name="lastName2">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="email2" class="form-label">Email</label>
|
<label for="email2" class="form-label">Email</label>
|
||||||
<input type="email" class="form-control" id="email2">
|
<input type="email" class="form-control" id="email2" name="email2">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="phone2" class="form-label">Phone</label>
|
<label for="phone2" class="form-label">Phone</label>
|
||||||
<input type="tel" class="form-control" id="phone2">
|
<input type="tel" class="form-control" id="phone2" name="phone2">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -199,50 +197,82 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="socialCommittee">
|
<input class="form-check-input" type="checkbox" id="block_captain" for="block_captain" name="block_captain">
|
||||||
<label class="form-check-label" for="socialCommittee">
|
<label class="form-check-label" id="block_captain">
|
||||||
Social & Events Committee
|
BlockCaptain
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="landscapeCommittee">
|
<input class="form-check-input" type="checkbox" id="coordinator" for="coordinator" name="coordinator">
|
||||||
<label class="form-check-label" for="landscapeCommittee">
|
<label class="form-check-label" id="coordinator">
|
||||||
Landscape & Maintenance Committee
|
Coordinator
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="safetyCommittee">
|
<input class="form-check-input" type="checkbox" id="egg_hunt" for="egg_hunt" name="egg_hunt">
|
||||||
<label class="form-check-label" for="safetyCommittee">
|
<label class="form-check-label" id="egg_hunt">
|
||||||
Safety & Neighborhood Watch
|
Easter Egg Hunt
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="spring_garage_sale" for="spring_garage_sale" name="spring_garage_sale">
|
||||||
|
<label class="form-check-label" id="spring_garage_sale">
|
||||||
|
Spring Garage Sale
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="golf_outing" for="golf_outing" name="golf_outing">
|
||||||
|
<label class="form-check-label" id="golf_outing">
|
||||||
|
Golf Outing
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="ice_cream_social" for="ice_cream_social" name="ice_cream_social">
|
||||||
|
<label class="form-check-label" id="ice_cream_social">
|
||||||
|
Ice Creame Social
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="architecturalCommittee">
|
<input class="form-check-input" type="checkbox" id="fall_garage_sale" for="fall_garage_sale" name="fall_garage_sale">
|
||||||
<label class="form-check-label" for="architecturalCommittee">
|
<label class="form-check-label" id="fall_garage_sale">
|
||||||
Architectural Review Committee
|
Fall Garage Sale
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="communicationsCommittee">
|
<input class="form-check-input" type="checkbox" id="halloween_party" for="halloween_party" name="halloween_party">
|
||||||
<label class="form-check-label" for="communicationsCommittee">
|
<label class="form-check-label" id="halloween_party">
|
||||||
Communications Committee
|
Halloween Party
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="welcomingCommittee">
|
<input class="form-check-input" type="checkbox" id="santa_visit" for="santa_visit" name="santa_visit">
|
||||||
<label class="form-check-label" for="welcomingCommittee">
|
<label class="form-check-label" id="santa_visit">
|
||||||
Welcoming Committee
|
Santa Visits
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="civic_affair" for="civic_affair" name="civic_affair">
|
||||||
|
<label class="form-check-label" id="civic_affair">
|
||||||
|
Civic Affairs Journalist
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="phone_directory" for="phone_directory" name="phone_directory">
|
||||||
|
<label class="form-check-label" id="phone_directory">
|
||||||
|
Annual Phone Director
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="no_preference" for="no_preference" name="no_preference">
|
||||||
|
<label class="form-check-label" id="no_preference">
|
||||||
|
No Preference
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3">
|
|
||||||
<label for="otherCommitteeInterest" class="form-label">Other interests or skills you'd like to contribute:</label>
|
|
||||||
<textarea class="form-control" id="otherCommitteeInterest" rows="2"></textarea>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<!-- Services Section -->
|
<!-- Services Section -->
|
||||||
@@ -253,44 +283,54 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="babysitting">
|
<input class="form-check-input" type="checkbox" id="babysitting" for="babysitting" name="babysitting">
|
||||||
<label class="form-check-label" for="babysitting">
|
<label class="form-check-label" for="babysitting">
|
||||||
Babysitting
|
Babysitting
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="lawnMowing">
|
<input class="form-check-input" type="checkbox" id="lawn_mowing" for="lawn_mowing" name="lawn_mowing">
|
||||||
<label class="form-check-label" for="lawnMowing">
|
<label class="form-check-label" for="lawn_mowing">
|
||||||
Lawn Mowing
|
Lawn Mowing
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="snowShoveling">
|
<input class="form-check-input" type="checkbox" id="snow_shoveling" for="snow_shoveling" name="snow_shoveling">
|
||||||
<label class="form-check-label" for="snowShoveling">
|
<label class="form-check-label" for="snow_shoveling">
|
||||||
Snow Shoveling
|
Snow Shoveling
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="leaf_raking" for="leaf_raking" name="leaf_raking">
|
||||||
|
<label class="form-check-label" for="leaf_raking">
|
||||||
|
Lead Raking
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="houseSitting">
|
<input class="form-check-input" type="checkbox" id="house_sitting" for="house_sitting" name="house_sitting">
|
||||||
<label class="form-check-label" for="houseSitting">
|
<label class="form-check-label" for="house_sitting">
|
||||||
House Sitting
|
House Sitting
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="petCare">
|
<input class="form-check-input" type="checkbox" id="petsitting" for="petsitting" name="petsitting">
|
||||||
<label class="form-check-label" for="petCare">
|
<label class="form-check-label" for="petsitting">
|
||||||
Pet Care
|
Pet Sitting
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
<input class="form-check-input" type="checkbox" id="otherService">
|
<input class="form-check-input" type="checkbox" id="other" for="other" name="other">
|
||||||
<label class="form-check-label" for="otherService">
|
<label class="form-check-label" for="other">
|
||||||
Other (please specify)
|
Other (please specify)
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<label for="other_desc" class="form-label">Other interests or skills you'd like to contribute:</label>
|
||||||
|
<textarea class="form-control" id="other_desc" for="other_desc" name="other_desc" rows="2"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3" id="otherServiceSpecify" style="display: none;">
|
<div class="mt-3" id="otherServiceSpecify" style="display: none;">
|
||||||
@@ -299,20 +339,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<!-- Terms & Submit -->
|
|
||||||
<div class="mb-3">
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="checkbox" id="agreeTerms" required>
|
|
||||||
<label class="form-check-label" for="agreeTerms">
|
|
||||||
I agree to the <a href="#" data-bs-toggle="modal" data-bs-target="#termsModal">Terms and Conditions</a>*
|
|
||||||
</label>
|
|
||||||
<div class="invalid-feedback">
|
|
||||||
You must agree before submitting.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||||
|
{% if captchaForm %}
|
||||||
|
{{ captchaForm }}
|
||||||
|
{% endif %}
|
||||||
<button class="btn btn-outline-secondary me-md-2" type="reset">Reset Form</button>
|
<button class="btn btn-outline-secondary me-md-2" type="reset">Reset Form</button>
|
||||||
<button class="btn btn-success" type="submit">Submit Membership</button>
|
<button class="btn btn-success" type="submit">Submit Membership</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -324,35 +354,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Terms Modal -->
|
|
||||||
<div class="modal fade" id="termsModal" tabindex="-1" aria-labelledby="termsModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-lg">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="termsModalLabel">Membership Terms and Conditions</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<h6>Greenwood Estates HOA Membership Agreement</h6>
|
|
||||||
<p>By joining the Greenwood Estates Homeowners Association, you agree to:</p>
|
|
||||||
<ol>
|
|
||||||
<li>Abide by the community covenants, conditions, and restrictions (CC&Rs)</li>
|
|
||||||
<li>Pay annual membership dues in a timely manner</li>
|
|
||||||
<li>Participate in community standards and guidelines</li>
|
|
||||||
<li>Receive communications from the HOA board and committees</li>
|
|
||||||
<li>Have your contact information shared with other members for community purposes</li>
|
|
||||||
</ol>
|
|
||||||
<p>Your membership helps maintain our community's quality and property values. The HOA board reserves the right to approve or deny membership applications.</p>
|
|
||||||
<h6>Privacy Policy</h6>
|
|
||||||
<p>Your personal information will be used solely for HOA communications and operations. We do not sell or share member information with third parties except as required for community management.</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-success" data-bs-dismiss="modal">I Understand</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
47
schasite/templates/schasite/password_reset.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{% extends 'schasite/base2.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block pagetitle %}
|
||||||
|
<title>Password Reset | SCHA</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-success text-white text-center">
|
||||||
|
<h2><i class="bi bi-key me-2"></i>Reset Password</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form id="resetForm" class="needs-validation" novalidate>
|
||||||
|
<div class="mb-4 text-center">
|
||||||
|
<p>Enter your email address and we'll send you a link to reset your password.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="resetEmail" class="form-label">Email Address</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-envelope"></i></span>
|
||||||
|
<input type="email" class="form-control" id="resetEmail" required>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Please provide a valid email address.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button type="submit" class="btn btn-success">
|
||||||
|
<i class="bi bi-send me-2"></i>Send Reset Link
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer text-center">
|
||||||
|
<a href="login.html" class="text-decoration-none"><i class="bi bi-arrow-left me-1"></i>Back to Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
396
schasite/templates/schasite/profile.html
Normal 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 %}
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<h3 class="text-success mb-3">2025-2026 Stonehedge Community Homeowners Association Board</h3>
|
<h3 class="text-success mb-3">2025-2026 Stonehedge Community Homeowners Association Board</h3>
|
||||||
<p>The Stonehedge Community Homeowners Association is governed by a volunteer board of directors elected by the community members. Board members serve two-year terms and are responsible for overseeing the community's operations, finances, and enforcement of covenants.</p>
|
<p>The Stonehedge Community Homeowners Association is governed by a volunteer board of directors elected by the community members. Board members serve two-year terms and are responsible for overseeing the community's operations, finances, and enforcement of covenants.</p>
|
||||||
<p>Board meetings are held monthly and are open to all residents. <a href="../index.html#documents">View meeting schedule</a>.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,7 +62,7 @@
|
|||||||
<h4 class="mb-0">{{ officer.position }}</h4>
|
<h4 class="mb-0">{{ officer.position }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<img src="../images/board/john-smith.jpg" alt="John Smith" class="rounded-circle mb-3" width="150" height="150">
|
<!--<img src="../images/board/john-smith.jpg" alt="John Smith" class="rounded-circle mb-3" width="150" height="150">-->
|
||||||
<h5 class="card-title">{{ officer.name }}</h5>
|
<h5 class="card-title">{{ officer.name }}</h5>
|
||||||
<!-- <p class="text-muted">Term: 2022-2024</p>
|
<!-- <p class="text-muted">Term: 2022-2024</p>
|
||||||
<p class="card-text">John has lived in Greenwood Estates since 2015 and brings 20 years of financial management experience to the board.</p> -->
|
<p class="card-text">John has lived in Greenwood Estates since 2015 and brings 20 years of financial management experience to the board.</p> -->
|
||||||
@@ -85,7 +84,7 @@
|
|||||||
<h4 class="mb-0">TBD</h4>
|
<h4 class="mb-0">TBD</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<img src="../images/board/john-smith.jpg" alt="John Smith" class="rounded-circle mb-3" width="150" height="150">
|
<!--<img src="../images/board/john-smith.jpg" alt="John Smith" class="rounded-circle mb-3" width="150" height="150">-->
|
||||||
<h5 class="card-title">TBD</h5>
|
<h5 class="card-title">TBD</h5>
|
||||||
<p class="text-muted">TBD</p>
|
<p class="text-muted">TBD</p>
|
||||||
<p class="card-text">TBD</p>
|
<p class="card-text">TBD</p>
|
||||||
@@ -97,53 +96,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
<!-- Committees Section -->
|
|
||||||
<div class="row mt-5">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<div class="card-header bg-success text-white">
|
|
||||||
<h3 class="mb-0">HOA Committees</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4 mb-4">
|
|
||||||
<div class="card h-100">
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title text-success">Architectural Review</h5>
|
|
||||||
<p class="card-text">Reviews all exterior modification requests to ensure compliance with community standards.</p>
|
|
||||||
<p><strong>Chair:</strong> Robert Wilson</p>
|
|
||||||
<a href="mailto:architecture@greenwoodestates.org" class="btn btn-sm btn-outline-success">Contact Committee</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4 mb-4">
|
|
||||||
<div class="card h-100">
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title text-success">Social & Events</h5>
|
|
||||||
<p class="card-text">Plans community events, holiday celebrations, and social gatherings.</p>
|
|
||||||
<p><strong>Chair:</strong> Lisa Martinez</p>
|
|
||||||
<a href="mailto:events@greenwoodestates.org" class="btn btn-sm btn-outline-success">Contact Committee</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4 mb-4">
|
|
||||||
<div class="card h-100">
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title text-success">Landscape & Maintenance</h5>
|
|
||||||
<p class="card-text">Oversees common area maintenance and landscaping improvements.</p>
|
|
||||||
<p><strong>Chair:</strong> David Thompson</p>
|
|
||||||
<a href="mailto:landscape@greenwoodestates.org" class="btn btn-sm btn-outline-success">Contact Committee</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center mt-3">
|
|
||||||
<a href="#" class="btn btn-success">Learn About Committee Opportunities</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
127
schasite/templates/schasite/set_password.html
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{% extends 'schasite/base2.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block pagetitle %}
|
||||||
|
<title>Set Password | SCHA</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-success text-white text-center">
|
||||||
|
<h2><i class="bi bi-key me-2"></i>Set New Password</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form id="passwordForm" class="needs-validation" novalidate>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="newPassword" class="form-label">New Password</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-lock"></i></span>
|
||||||
|
<input type="password" class="form-control" id="newPassword" required
|
||||||
|
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}">
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="toggleNewPassword">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Password must contain at least 8 characters with uppercase, lowercase, and a number.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-text">
|
||||||
|
<small>Must be at least 8 characters with uppercase, lowercase, and a number.</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="confirmPassword" class="form-label">Confirm Password</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-lock"></i></span>
|
||||||
|
<input type="password" class="form-control" id="confirmPassword" required>
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="toggleConfirmPassword">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Passwords must match.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button type="submit" class="btn btn-success">
|
||||||
|
<i class="bi bi-check-circle me-2"></i>Set Password
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer text-center">
|
||||||
|
<a href="login.html" class="text-decoration-none"><i class="bi bi-arrow-left me-1"></i>Back to Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extra_js %}
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Toggle password visibility
|
||||||
|
const toggleNewPassword = document.getElementById('toggleNewPassword');
|
||||||
|
const newPasswordInput = document.getElementById('newPassword');
|
||||||
|
const toggleConfirmPassword = document.getElementById('toggleConfirmPassword');
|
||||||
|
const confirmPasswordInput = document.getElementById('confirmPassword');
|
||||||
|
|
||||||
|
toggleNewPassword.addEventListener('click', function() {
|
||||||
|
const type = newPasswordInput.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||||
|
newPasswordInput.setAttribute('type', type);
|
||||||
|
this.innerHTML = type === 'password' ? '<i class="bi bi-eye"></i>' : '<i class="bi bi-eye-slash"></i>';
|
||||||
|
});
|
||||||
|
|
||||||
|
toggleConfirmPassword.addEventListener('click', function() {
|
||||||
|
const type = confirmPasswordInput.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||||
|
confirmPasswordInput.setAttribute('type', type);
|
||||||
|
this.innerHTML = type === 'password' ? '<i class="bi bi-eye"></i>' : '<i class="bi bi-eye-slash"></i>';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form validation
|
||||||
|
const form = document.getElementById('passwordForm');
|
||||||
|
|
||||||
|
form.addEventListener('submit', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Check if passwords match
|
||||||
|
if (newPasswordInput.value !== confirmPasswordInput.value) {
|
||||||
|
confirmPasswordInput.setCustomValidity("Passwords must match");
|
||||||
|
} else {
|
||||||
|
confirmPasswordInput.setCustomValidity("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form.checkValidity()) {
|
||||||
|
// In a real implementation, this would update the password
|
||||||
|
alert('Password successfully updated (simulated)');
|
||||||
|
window.location.href = "login.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
form.classList.add('was-validated');
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Live password validation
|
||||||
|
newPasswordInput.addEventListener('input', function() {
|
||||||
|
if (this.value !== confirmPasswordInput.value) {
|
||||||
|
confirmPasswordInput.setCustomValidity("Passwords must match");
|
||||||
|
} else {
|
||||||
|
confirmPasswordInput.setCustomValidity("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
confirmPasswordInput.addEventListener('input', function() {
|
||||||
|
if (this.value !== newPasswordInput.value) {
|
||||||
|
this.setCustomValidity("Passwords must match");
|
||||||
|
} else {
|
||||||
|
this.setCustomValidity("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
66
schasite/templates/schasite/signin.html
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
{% extends 'schasite/base2.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block pagetitle %}
|
||||||
|
<title>Login | SCHA</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-success text-white text-center">
|
||||||
|
<h2><i class="bi bi-shield-lock me-2"></i>Member Login</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form id="loginForm" class="needs-validation" novalidate>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="loginEmail" class="form-label">Email Address</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-envelope"></i></span>
|
||||||
|
<input type="email" class="form-control" id="loginEmail" required>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Please provide a valid email address.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="loginPassword" class="form-label">Password</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-key"></i></span>
|
||||||
|
<input type="password" class="form-control" id="loginPassword" required>
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Please enter your password.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 form-check">
|
||||||
|
<input type="checkbox" class="form-check-input" id="rememberMe">
|
||||||
|
<label class="form-check-label" for="rememberMe">Remember me</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button type="submit" class="btn btn-success">
|
||||||
|
<i class="bi bi-box-arrow-in-right me-2"></i>Sign In
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 text-center">
|
||||||
|
<a href="{% url 'password_reset' %}" class="text-decoration-none">Forgot password?</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer text-center text-muted">
|
||||||
|
Not a member? <a href="{% url 'signup' %}" class="text-success">Join our community</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
104
schasite/templates/schasite/signup.html
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
{% extends 'schasite/base2.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block pagetitle %}
|
||||||
|
<title>Login | SCHA</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-success text-white text-center">
|
||||||
|
<h2><i class="bi bi-shield-lock me-2"></i>Member Signup</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form id="loginForm" class="needs-validation" novalidate>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<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">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Last Name</label>
|
||||||
|
<input type="text" class="form-control" value="Doe">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Email</label>
|
||||||
|
<input type="email" class="form-control" value="john.doe@example.com">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Phone</label>
|
||||||
|
<input type="tel" class="form-control" value="(555) 123-4567">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<label class="form-label">Street Address</label>
|
||||||
|
<input type="text" class="form-control" value="123 Oak Drive">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label">City</label>
|
||||||
|
<input type="text" class="form-control" value="Anytown">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label">State</label>
|
||||||
|
<input type="text" class="form-control" value="ST">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label">ZIP Code</label>
|
||||||
|
<input type="text" class="form-control" value="12345" >
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="loginPassword" class="form-label">Password</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-key"></i></span>
|
||||||
|
<input type="password" class="form-control" id="loginPassword" required>
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Please enter your password.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="loginPassword" class="form-label">Confirm Password</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-key"></i></span>
|
||||||
|
<input type="password" class="form-control" id="loginPassword" required>
|
||||||
|
<button class="btn btn-outline-secondary" type="button" id="togglePassword">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
Please confirm your password. </div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button type="submit" class="btn btn-success">
|
||||||
|
<i class="bi bi-box-arrow-in-right me-2"></i>Sign Up
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 text-center">
|
||||||
|
<a href="{% url 'login' %}" class="text-decoration-none">Back to Log In</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
<div class="col-lg-10">
|
<div class="col-lg-10">
|
||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
<div class="card-header bg-success text-white">
|
<div class="card-header bg-success text-white">
|
||||||
<h3 class="mb-0"><i class="bi bi-exclamation-triangle me-2"></i>Useful Links</h3>
|
<h3 class="mb-0">Useful Links</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
|||||||
@@ -1,26 +1,50 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.conf import settings
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path("", views.index, name="index"),
|
if settings.DEBUG:
|
||||||
path("useful_links", views.useful_links, name="useful_links"),
|
authenticated_views = [
|
||||||
path("about_us", views.about_us, name="about_us"),
|
path('login/',views.login, name="login"),
|
||||||
path("calendar", views.calendar, name="calendar"),
|
path('set_password/',views.set_password, name="set_password"),
|
||||||
path("newsletters", views.newsletters, name="newsletters"),
|
path('password_reset/',views.password_reset, name="password_reset"),
|
||||||
path("dues", views.dues, name="dues"),
|
path('signup/',views.signup, name="signup"),
|
||||||
path("membership_form", views.membership_form, name="membership_form"),
|
path('directory/',views.member_directory, name="directory"),
|
||||||
path("scha_board", views.scha_board, name="scha_board"),
|
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:
|
||||||
|
authenticated_views = []
|
||||||
|
|
||||||
|
urlpatterns = authenticated_views + [
|
||||||
|
# path("", views.index, name="index"),
|
||||||
|
# path("useful_links", views.useful_links, name="useful_links"),
|
||||||
|
# path("about_us", views.about_us, name="about_us"),
|
||||||
|
# path("calendar", views.calendar, name="calendar"),
|
||||||
|
# path("newsletters", views.newsletters, name="newsletters"),
|
||||||
|
# path("dues", views.dues, name="dues"),
|
||||||
|
# path("membership_form", views.membership_form, name="membership_form"),
|
||||||
|
# path("scha_board", views.scha_board, name="scha_board"),
|
||||||
# updated UI urls
|
# updated UI urls
|
||||||
path("index2", views.index2, name="index2"),
|
path("", views.index2, name="index2"),
|
||||||
path("about_us2", views.about_us2, name="about_us2"),
|
path("about_us", views.about_us2, name="about_us2"),
|
||||||
path("calendar2", views.calendar2, name="calendar2"),
|
path("calendar", views.calendar2, name="calendar2"),
|
||||||
path("newsletters2", views.newsletters2, name="newsletters2"),
|
path("newsletters", views.newsletters2, name="newsletters2"),
|
||||||
path("dues2", views.dues2, name="dues2"),
|
path("dues", views.dues2, name="dues2"),
|
||||||
path("membership_form2", views.membership_form2, name="membership_form2"),
|
path("membership_form", views.membership_form2, name="membership_form2"),
|
||||||
path("scha_board2", views.scha_board2, name="scha_board2"),
|
path("scha_board", views.scha_board2, name="scha_board2"),
|
||||||
path("useful_links2", views.useful_links2, name="useful_links2"),
|
path("useful_links", views.useful_links2, name="useful_links2"),
|
||||||
# stripe specific urls below
|
# stripe specific urls below
|
||||||
path("config/", views.stripe_config),
|
path("config/", views.stripe_config),
|
||||||
path("create-checkout-session/", views.create_checkout_session),
|
path("create-checkout-session/", views.create_checkout_session),
|
||||||
|
|
||||||
|
# authenticated views
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer
|
|
||||||
|
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership, CommunityPost
|
||||||
from .forms import (
|
from .forms import (
|
||||||
ChildrenForm,
|
ChildrenForm,
|
||||||
|
CommunityPostForm,
|
||||||
AddressForm,
|
AddressForm,
|
||||||
PeopleForm,
|
PeopleForm,
|
||||||
CommitteeForm,
|
CommitteeForm,
|
||||||
ServicesForm,
|
ServicesForm,
|
||||||
) # , CaptchaForm
|
CaptchaForm
|
||||||
|
)
|
||||||
from django.db import transaction, IntegrityError
|
from django.db import transaction, IntegrityError
|
||||||
|
|
||||||
# Stripe required imports
|
# Stripe required imports
|
||||||
from django.conf import settings # new
|
from django.conf import settings # new
|
||||||
from django.http.response import JsonResponse, HttpResponse
|
from django.http.response import JsonResponse, HttpResponse
|
||||||
from django.views.decorators.csrf import csrf_exempt # new
|
from django.views.decorators.csrf import csrf_exempt # new
|
||||||
|
from django.contrib.auth import logout, authenticate, login
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
import stripe
|
import stripe
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
print(__name__)
|
||||||
"""
|
"""
|
||||||
Strip Stuff
|
Strip Stuff
|
||||||
Tutorial: https://testdriven.io/blog/django-stripe-tutorial/
|
Tutorial: https://testdriven.io/blog/django-stripe-tutorial/
|
||||||
@@ -34,28 +43,27 @@ def stripe_config(request):
|
|||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def create_checkout_session(request):
|
def create_checkout_session(request):
|
||||||
if request.method == "GET":
|
if request.method == 'GET':
|
||||||
domain_url = "http://localhost:8000/"
|
domain_url ="https://www.schawheaton.com/"
|
||||||
stripe.api_key = settings.STRIPE_SECRET_KEY
|
stripe.api_key = settings.STRIPE_SECRET_KEY
|
||||||
try:
|
try:
|
||||||
checkout_session = stripe.checkout.Session.create(
|
checkout_session = stripe.checkout.Session.create(
|
||||||
success_url=domain_url + "success?session_id={CHECKOUT_SESSION_ID}",
|
success_url = domain_url+'success?session_id={CHECKOUT_SESSION_ID}',
|
||||||
cancel_url=domain_url + "cancelled/",
|
cancel_url = domain_url+'cancelled/',
|
||||||
payment_method_types=["card"],
|
payment_method_types=['card'],
|
||||||
mode="payment",
|
mode="payment",
|
||||||
line_items=[
|
line_items = [{
|
||||||
{
|
# 'name':'SCHA Dues',
|
||||||
# 'name':'SCHA Dues',
|
'quantity': 1,
|
||||||
"quantity": 1,
|
# 'currency': 'usd',
|
||||||
# 'currency': 'usd',
|
'price':'price_1P5KBtIbGKYTLTtMJ0Rh1jMu',
|
||||||
"price": "price_1OxZLfDV0RPXOyxG5ipjhUXk",
|
#'price_1P5K7uIbGKYTLTtMFNxbkA8X'
|
||||||
}
|
#'price_1OxZLfDV0RPXOyxG5ipjhUXk',
|
||||||
],
|
}]
|
||||||
)
|
)
|
||||||
return JsonResponse({"sessionId": checkout_session["id"]})
|
return JsonResponse({'sessionId': checkout_session['id']})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return JsonResponse({"error": str(e)})
|
return JsonResponse({'error': str(e)})
|
||||||
|
|
||||||
|
|
||||||
def stripe_success(request):
|
def stripe_success(request):
|
||||||
return render(request, "schasite/dues_success.html", {})
|
return render(request, "schasite/dues_success.html", {})
|
||||||
@@ -70,11 +78,13 @@ def stripe_webhook(request):
|
|||||||
stripe.api_key = settings.STRIPE_SECRET_KEY
|
stripe.api_key = settings.STRIPE_SECRET_KEY
|
||||||
endpoint_secret = settings.STRIPE_ENDPOINT_SECRET
|
endpoint_secret = settings.STRIPE_ENDPOINT_SECRET
|
||||||
payload = request.body
|
payload = request.body
|
||||||
sig_header = request.META["HTTP_STRIPE_SIGNATURE"]
|
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
|
||||||
event = None
|
event = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
|
event = stripe.Webhook.construct_event(
|
||||||
|
payload, sig_header, endpoint_secret
|
||||||
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
# Invalid payload
|
# Invalid payload
|
||||||
return HttpResponse(status=400)
|
return HttpResponse(status=400)
|
||||||
@@ -83,17 +93,18 @@ def stripe_webhook(request):
|
|||||||
return HttpResponse(status=400)
|
return HttpResponse(status=400)
|
||||||
|
|
||||||
# Handle the checkout.session.completed event
|
# Handle the checkout.session.completed event
|
||||||
if event["type"] == "checkout.session.completed":
|
if event['type'] == 'checkout.session.completed':
|
||||||
email = None
|
email = None
|
||||||
try:
|
try:
|
||||||
email = event["data"]["object"]["customer_details"]["email"]
|
email = event['data']['object']['customer_details']['email']
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
person = MembershipPerson.objects.filter(
|
person = MembershipPerson.objects.filter(email=email).first() # just take the first
|
||||||
email=email
|
|
||||||
).first() # just take the first
|
|
||||||
|
|
||||||
payment = Payments.objects.create(email=email, person=person)
|
payment = Payments.objects.create(
|
||||||
|
email=email,
|
||||||
|
person = person
|
||||||
|
)
|
||||||
# try to link to a member
|
# try to link to a member
|
||||||
payment.save()
|
payment.save()
|
||||||
# TODO: run some custom code here
|
# TODO: run some custom code here
|
||||||
@@ -141,24 +152,23 @@ def calendar2(request):
|
|||||||
|
|
||||||
|
|
||||||
def scha_board2(request):
|
def scha_board2(request):
|
||||||
def get_officer(position_name):
|
def get_officers(position_name) -> list[SCHAOfficer]:
|
||||||
try:
|
try:
|
||||||
return SCHAOfficer.objects.get(position=position_name)
|
return SCHAOfficer.objects.filter(position=position_name)
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
officers = [
|
officers = []
|
||||||
get_officer("President"),
|
for position in ["President","1st Vice President",
|
||||||
get_officer("1st Vice President"),
|
"2nd Vice President",
|
||||||
get_officer("2nd Vice President"),
|
"Treasurer",
|
||||||
get_officer("Treasurer"),
|
"Secretary",
|
||||||
get_officer("Secretary"),
|
"Website",
|
||||||
get_officer("Website"),
|
"Membership",
|
||||||
get_officer("Membership"),
|
"Directory",
|
||||||
get_officer("Directory"),
|
"Facebook",
|
||||||
get_officer("Facebook"),
|
"Eblasts"]:
|
||||||
get_officer("Eblasts"),
|
officers += get_officers(position)
|
||||||
]
|
|
||||||
|
|
||||||
return render(request, "schasite/scha_board2.html", {"officers": officers})
|
return render(request, "schasite/scha_board2.html", {"officers": officers})
|
||||||
|
|
||||||
@@ -178,77 +188,130 @@ def membership_form2(request):
|
|||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
# before we pass in the data we want to sanitize the phone numbers
|
# before we pass in the data we want to sanitize the phone numbers
|
||||||
post_data = request.POST.copy()
|
address_data = {
|
||||||
post_data.update(
|
"address_1": request.POST.get("streetAddress", ""),
|
||||||
{
|
"address_2": request.POST.get("unit", ""),
|
||||||
"person1-phone_number": sanitize_phone_number(
|
"city": request.POST.get("city", "60189"),
|
||||||
post_data["person1-phone_number"]
|
"state": request.POST.get("state", "IL"),
|
||||||
)
|
"zip_code": request.POST.get("zipCode", "60189"),
|
||||||
}
|
}
|
||||||
)
|
logging.debug(address_data)
|
||||||
post_data.update(
|
addressForm = AddressForm(address_data)
|
||||||
{
|
logging.debug(f"is addressForm valid: {addressForm.is_valid()}")
|
||||||
"person2-phone_number": sanitize_phone_number(
|
if not addressForm.is_valid():
|
||||||
post_data["person2-phone_number"]
|
logging.error(f"addressForm Errors: {addressForm.errors}")
|
||||||
)
|
|
||||||
}
|
services_data = {
|
||||||
)
|
"babysitting": True if request.POST.get("babysitting", "") == "on" else False,
|
||||||
membershipForm = ChildrenForm(post_data)
|
"lawn_mowing": True if request.POST.get("lawn_mowing", "") == "on" else False,
|
||||||
addressForm = AddressForm(post_data)
|
"snow_shoveling": True if request.POST.get("snow_shoveling", "") == "on" else False,
|
||||||
peopleForm1 = PeopleForm(post_data, prefix="person1")
|
"leaf_raking": True if request.POST.get("leaf_raking", "") == "on" else False,
|
||||||
peopleForm2 = PeopleForm(post_data, prefix="person2")
|
"petsitting": True if request.POST.get("petsitting", "") == "on" else False,
|
||||||
servicesForm = ServicesForm(post_data)
|
"house_sitting": True if request.POST.get("house_sitting", "") == "on" else False,
|
||||||
committeeForm = CommitteeForm(post_data)
|
"other": True if request.POST.get("other", "") == "on" else False,
|
||||||
# captchaForm = CaptchaForm(post_data)
|
"other_desc": True if request.POST.get("other_desc", "") == "on" else False,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
committee_data = {
|
||||||
|
"block_captain": True if request.POST.get("block_captain", "") == "on" else False,
|
||||||
|
"coordinator": True if request.POST.get("coordinator", "") == "on" else False,
|
||||||
|
"egg_hunt": True if request.POST.get("egg_hunt", "") == "on" else False,
|
||||||
|
"spring_garage_sale": True if request.POST.get("spring_garage_sale", "") == "on" else False,
|
||||||
|
"golf_outing": True if request.POST.get("golf_outing", "") == "on" else False,
|
||||||
|
"ice_cream_social": True if request.POST.get("ice_cream_social", "") == "on" else False,
|
||||||
|
"fall_garage_sale": True if request.POST.get("fall_garage_sale", "") == "on" else False,
|
||||||
|
"halloween_party": True if request.POST.get("halloween_party", "") == "on" else False,
|
||||||
|
"santa_visit": True if request.POST.get("santa_visit", "") == "on" else False,
|
||||||
|
"website": True if request.POST.get("website", "") == "on" else False,
|
||||||
|
"civic_affair": True if request.POST.get("civic_affair", "") == "on" else False,
|
||||||
|
"phone_directory": True if request.POST.get("phone_directory", "") == "on" else False,
|
||||||
|
"no_preference": True if request.POST.get("no_preference", "") == "on" else False,
|
||||||
|
}
|
||||||
|
|
||||||
|
servicesForm = ServicesForm(services_data)
|
||||||
|
committeeForm = CommitteeForm(committee_data)
|
||||||
|
person1_data = {
|
||||||
|
"first_name": request.POST.get("firstName1"),
|
||||||
|
"last_name": request.POST.get("lastName1"),
|
||||||
|
"email": request.POST.get("email1"),
|
||||||
|
"phone_number": sanitize_phone_number(request.POST.get("phone1")),
|
||||||
|
}
|
||||||
|
person2_data = {
|
||||||
|
"frist_name": request.POST.get("firstName2"),
|
||||||
|
"last_name": request.POST.get("lastName2"),
|
||||||
|
"email": request.POST.get("email2"),
|
||||||
|
"phone_number": sanitize_phone_number(request.POST.get("phone2")),
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
peopleForm1 = PeopleForm(person1_data)
|
||||||
|
peopleForm2 = PeopleForm(person2_data)
|
||||||
|
|
||||||
|
|
||||||
|
logging.debug("Validating the captcha form")
|
||||||
|
logging.debug(request.POST.get("captcha",""))
|
||||||
|
captchaForm = CaptchaForm({
|
||||||
|
"captcha": request.POST.get("captcha","")
|
||||||
|
})
|
||||||
|
logging.debug(f"Captch form is: {captchaForm.is_valid()}")
|
||||||
|
|
||||||
|
|
||||||
|
logging.debug(f"peopleForm1 form is: {peopleForm1.is_valid()}")
|
||||||
|
logging.debug(f"peopleForm2 form is: {peopleForm2.is_valid()}")
|
||||||
|
logging.debug(f"servicesForm form is: {servicesForm.is_valid()}")
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
membershipForm.is_valid()
|
addressForm.is_valid()
|
||||||
and addressForm.is_valid()
|
|
||||||
and committeeForm.is_valid()
|
and committeeForm.is_valid()
|
||||||
and (peopleForm1.is_valid() or peopleForm2.is_valid())
|
and (peopleForm1.is_valid() or peopleForm2.is_valid())
|
||||||
and servicesForm.is_valid()
|
and servicesForm.is_valid()
|
||||||
): # and captchaForm.is_valid():
|
and captchaForm.is_valid()
|
||||||
|
):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
membershipForm = ChildrenForm({**post_data})
|
logging.debug("starting to save")
|
||||||
membership = membershipForm.save(commit=False)
|
try:
|
||||||
membership.save()
|
membership = Membership.objects.create()
|
||||||
|
|
||||||
if peopleForm1.is_valid():
|
if peopleForm1.is_valid():
|
||||||
people1_obj = peopleForm1.save(commit=False)
|
people1_obj = peopleForm1.save(commit=False)
|
||||||
people1_obj.membership = membership
|
people1_obj.membership = membership
|
||||||
people1_obj.save()
|
people1_obj.save()
|
||||||
|
|
||||||
if peopleForm2.is_valid():
|
if peopleForm2.is_valid():
|
||||||
people2_obj = peopleForm2.save(commit=False)
|
people2_obj = peopleForm2.save(commit=False)
|
||||||
people2_obj.membership = membership
|
people2_obj.membership = membership
|
||||||
people2_obj.save()
|
people2_obj.save()
|
||||||
|
|
||||||
committee_obj = committeeForm.save(commit=False)
|
committee_obj = committeeForm.save(commit=False)
|
||||||
committee_obj.membership = membership
|
committee_obj.membership = membership
|
||||||
committee_obj.save()
|
committee_obj.save()
|
||||||
|
|
||||||
services_obj = servicesForm.save(commit=False)
|
services_obj = servicesForm.save(commit=False)
|
||||||
services_obj.membership = membership
|
services_obj.membership = membership
|
||||||
services_obj.save()
|
services_obj.save()
|
||||||
|
|
||||||
address_obj = addressForm.save(commit=False)
|
address_obj = addressForm.save(commit=False)
|
||||||
address_obj.membership = membership
|
address_obj.membership = membership
|
||||||
address_obj.save()
|
address_obj.save()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
|
||||||
return redirect("index")
|
return redirect("index2")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
logging.warning("Some field is not valid")
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"schasite/membership_form2.html",
|
"schasite/membership_form2.html",
|
||||||
{
|
{
|
||||||
"membershipForm": ChildrenForm,
|
|
||||||
"peopleForm1": peopleForm1,
|
"peopleForm1": peopleForm1,
|
||||||
"peopleForm2": peopleForm2,
|
"peopleForm2": peopleForm2,
|
||||||
"addressForm": addressForm,
|
"addressForm": addressForm,
|
||||||
"committeeForm": committeeForm,
|
"committeeForm": committeeForm,
|
||||||
"servicesForm": servicesForm,
|
"servicesForm": servicesForm,
|
||||||
# 'captchaForm': captchaForm,
|
'captchaForm': captchaForm,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -256,12 +319,11 @@ def membership_form2(request):
|
|||||||
request,
|
request,
|
||||||
"schasite/membership_form2.html",
|
"schasite/membership_form2.html",
|
||||||
{
|
{
|
||||||
"membershipForm": ChildrenForm(),
|
|
||||||
"peopleForm1": PeopleForm(prefix="person1"),
|
"peopleForm1": PeopleForm(prefix="person1"),
|
||||||
"peopleForm2": PeopleForm(prefix="person2"),
|
"peopleForm2": PeopleForm(prefix="person2"),
|
||||||
"committeeForm": CommitteeForm(),
|
"committeeForm": CommitteeForm(),
|
||||||
"servicesForm": ServicesForm(),
|
"servicesForm": ServicesForm(),
|
||||||
# 'captchaForm': CaptchaForm(),
|
'captchaForm': CaptchaForm(),
|
||||||
"addressForm": AddressForm(
|
"addressForm": AddressForm(
|
||||||
initial={
|
initial={
|
||||||
"city": "Wheaton",
|
"city": "Wheaton",
|
||||||
@@ -415,3 +477,102 @@ def membership_form(request):
|
|||||||
|
|
||||||
def scha_board(request):
|
def scha_board(request):
|
||||||
return render(request, "schasite/scha_board.html", {})
|
return render(request, "schasite/scha_board.html", {})
|
||||||
|
|
||||||
|
|
||||||
|
def login(request):
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
username = request.POST["username"]
|
||||||
|
password = request.POST["password"]
|
||||||
|
user = authenticate(request, username=username, password=password)
|
||||||
|
if user is not None:
|
||||||
|
return redirect('dashboard')
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/signin.html",{'error_msg': "Invalid username/password"})
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/signin.html",{})
|
||||||
|
|
||||||
|
def logout(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
logout(request)
|
||||||
|
return redirect('index2')
|
||||||
|
|
||||||
|
|
||||||
|
def password_reset(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/password_reset.html",{})
|
||||||
|
|
||||||
|
def set_password(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
return redirect('login')
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/set_password.html",{})
|
||||||
|
|
||||||
|
def signup(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
return redirect('login')
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/signup.html",{})
|
||||||
|
|
||||||
|
@login_required(login_url="/login")
|
||||||
|
def member_directory(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
# these should be filters
|
||||||
|
raise NotImplementedError()
|
||||||
|
else:
|
||||||
|
members = MembershipPerson.objects.all()
|
||||||
|
return render(request, "schasite/member_directory.html",{'members':members})
|
||||||
|
|
||||||
|
@login_required(login_url="/login")
|
||||||
|
def member_dashboard(request):
|
||||||
|
current_member = CommunityMember.objects.get(user=request.user)
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
else:
|
||||||
|
recent_posts = CommunityPost.objects.all()[:5]
|
||||||
|
member_recent_posts = CommunityPost.objects.filter(author=current_member)[:5]
|
||||||
|
return render(request, "schasite/member_dashboard.html",{"recent_posts":recent_posts, "member_recent_posts": member_recent_posts, "current_member": current_member})
|
||||||
|
|
||||||
|
@login_required(login_url="/login")
|
||||||
|
def member_posts(request):
|
||||||
|
current_member = CommunityMember.objects.get(user=request.user)
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
else:
|
||||||
|
posts = CommunityPost.objects.all()[:5]
|
||||||
|
return render(request, "schasite/member_posts.html",{"posts":posts})
|
||||||
|
|
||||||
|
@login_required(login_url="/login")
|
||||||
|
def member_posts_create(request):
|
||||||
|
current_member = CommunityMember.objects.get(user=request.user)
|
||||||
|
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()})
|
||||||
|
|
||||||
|
@login_required(login_url="/login")
|
||||||
|
def member_posts_detail(request, post_id):
|
||||||
|
current_member = CommunityMember.objects.get(user=request.user)
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/member_posts_detail.html",{})
|
||||||
|
|
||||||
|
#@login_required(login_url="/login")
|
||||||
|
def profile(request):
|
||||||
|
#current_member = CommunityMember.objects.get(user=request.user)
|
||||||
|
if request.method == "POST":
|
||||||
|
raise NotImplementedError()
|
||||||
|
else:
|
||||||
|
return render(request, "schasite/profile.html",{})
|
||||||
|
|||||||