Updates with a sign in page

This commit is contained in:
2025-04-25 10:12:16 -05:00
parent 5bd7a37e52
commit b9964b22a9
7 changed files with 187 additions and 25 deletions

View File

@@ -2,6 +2,7 @@ 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): class TimeInfoBase(models.Model):
@@ -181,6 +182,11 @@ class CommunityParks(TimeInfoBase):
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)
### 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): class CommunityPost(TimeInfoBase):
@@ -188,12 +194,20 @@ class CommunityPost(TimeInfoBase):
category = models.CharField(max_length=255) category = models.CharField(max_length=255)
content = models.CharField(max_length=1024*8) content = models.CharField(max_length=1024*8)
likes = models.IntegerField(default=0) likes = models.IntegerField(default=0)
author = models.OneToOneField(CommunityMember, on_delete=models.CASCADE)
class CommunityPostReports(TimeInfoBase): class CommunityPostReports(TimeInfoBase):
# for anyone who reports a post
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE) post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
# user = something 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): class CommunityComment(TimeInfoBase):
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE) post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
content = models.CharField(max_length=1024*8) content = models.CharField(max_length=1024*8)
likes = models.IntegerField(default=0) likes = models.IntegerField(default=0)
author = models.OneToOneField(CommunityMember, on_delete=models.CASCADE)

View File

@@ -16,7 +16,7 @@
<script async defer src="https://tianji.aimloperations.com/tracker.js" data-website-id="cm9qziuid9vr7v6dtdbnx8406"></script> <script async defer src="https://tianji.aimloperations.com/tracker.js" data-website-id="cm9qziuid9vr7v6dtdbnx8406"></script>
</head> </head>
<body> <body>
<p><img src=https://tianji.aimloperations.com/telemetry/cm7w8087y020lddswyhamadj2/cm9u1ehxeajxmv6dtajx4f9yn/badge.svg"></p>
<!-- 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">

View File

@@ -78,34 +78,39 @@
<div class="col-12"> <div class="col-12">
<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="h5 mb-0"><i class="bi bi-activity me-2"></i>Recent Community Activity</h3> <h3 class="h5 mb-0"><i class="bi bi-activity me-2"></i>Your Recently Updated Posts</h3>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="list-group"> <div class="list-group">
{% for recent_post in member_recent_posts %}
<a href="#" class="list-group-item list-group-item-action"> <a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between"> <div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">Annual Picnic Scheduled</h5> <h5 class="mb-1">{{ recent_post.title }}</h5>
<small>3 days ago</small> <small>3 days ago</small>
</div> </div>
<p class="mb-1">The community picnic is scheduled for June 15th. RSVP now!</p> <p class="mb-1">{{ recent_post.content }}</p>
<small>Posted by Sarah Johnson</small> <small>Posted by Sarah Johnson</small>
</a> </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"> <a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between"> <div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">Landscaping Update</h5> <h5 class="mb-1">{{ recent_post.title }}</h5>
<small>1 week ago</small> <small>3 days ago</small>
</div> </div>
<p class="mb-1">New flowers planted in common areas. Come see the improvements!</p> <p class="mb-1">{{ recent_post.content }}</p>
<small>Posted by Robert Wilson</small> <small>Posted by Sarah Johnson</small>
</a>
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">Neighborhood Watch Meeting</h5>
<small>2 weeks ago</small>
</div>
<p class="mb-1">Next meeting scheduled for May 10th at the clubhouse.</p>
<small>Posted by Michael Brown</small>
</a> </a>
{% endfor %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -52,12 +52,12 @@
</div> </div>
<div class="mt-3 text-center"> <div class="mt-3 text-center">
<a href="reset-password.html" class="text-decoration-none">Forgot password?</a> <a href="{% url 'password_reset' %}" class="text-decoration-none">Forgot password?</a>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center text-muted"> <div class="card-footer text-center text-muted">
Not a member? <a href="../../membership.html" class="text-success">Join our community</a> Not a member? <a href="{% url 'signup' %}" class="text-success">Join our community</a>
</div> </div>
</div> </div>
</div> </div>

View 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 %}

View File

@@ -8,6 +8,7 @@ if settings.DEBUG:
path('login/',views.login, name="login"), path('login/',views.login, name="login"),
path('set_password/',views.set_password, name="set_password"), path('set_password/',views.set_password, name="set_password"),
path('password_reset/',views.password_reset, name="password_reset"), path('password_reset/',views.password_reset, name="password_reset"),
path('signup/',views.signup, name="signup"),
path('directory/',views.member_directory, name="directory"), path('directory/',views.member_directory, name="directory"),
path('dashboard/',views.member_dashboard, name="dashboard"), path('dashboard/',views.member_dashboard, name="dashboard"),
path('posts/',views.member_posts, name="posts"), path('posts/',views.member_posts, name="posts"),

View File

@@ -1,5 +1,6 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership, CommunityPost
from .forms import ( from .forms import (
ChildrenForm, ChildrenForm,
CommunityPostForm, CommunityPostForm,
@@ -15,6 +16,8 @@ from django.db import transaction, IntegrityError
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
""" """
@@ -472,13 +475,25 @@ 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): def login(request):
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() 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: else:
return render(request, "schasite/signin.html",{}) return render(request, "schasite/signin.html",{})
def logout(request):
if request.method == "POST":
logout(request)
return redirect('index2')
def password_reset(request): def password_reset(request):
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() raise NotImplementedError()
@@ -488,29 +503,48 @@ def password_reset(request):
def set_password(request): def set_password(request):
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() raise NotImplementedError()
return redirect('login')
else: else:
return render(request, "schasite/set_password.html",{}) 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): def member_directory(request):
if request.method == "POST": if request.method == "POST":
# these should be filters
raise NotImplementedError() raise NotImplementedError()
else: else:
return render(request, "schasite/member_directory.html",{}) members = MembershipPerson.objects.all()
return render(request, "schasite/member_directory.html",{'members':members})
@login_required(login_url="/login")
def member_dashboard(request): def member_dashboard(request):
current_member = CommunityMember.objects.get(user=request.user)
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() raise NotImplementedError()
else: else:
return render(request, "schasite/member_dashboard.html",{}) 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): def member_posts(request):
current_member = CommunityMember.objects.get(user=request.user)
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() raise NotImplementedError()
else: else:
posts = CommunityPost.objects.all()[:5] posts = CommunityPost.objects.all()[:5]
return render(request, "schasite/member_posts.html",{"posts":posts}) return render(request, "schasite/member_posts.html",{"posts":posts})
@login_required(login_url="/login")
def member_posts_create(request): def member_posts_create(request):
current_member = CommunityMember.objects.get(user=request.user)
if request.method == "POST": if request.method == "POST":
community_post_form = CommunityPostForm(request.POST) community_post_form = CommunityPostForm(request.POST)
if community_post_form.is_valid(): if community_post_form.is_valid():
@@ -523,13 +557,17 @@ def member_posts_create(request):
else: else:
return render(request, "schasite/member_posts_create.html",{"community_post": CommunityPostForm()}) return render(request, "schasite/member_posts_create.html",{"community_post": CommunityPostForm()})
@login_required(login_url="/login")
def member_posts_detail(request, post_id): def member_posts_detail(request, post_id):
current_member = CommunityMember.objects.get(user=request.user)
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() raise NotImplementedError()
else: else:
return render(request, "schasite/member_posts_detail.html",{}) return render(request, "schasite/member_posts_detail.html",{})
#@login_required(login_url="/login")
def profile(request): def profile(request):
#current_member = CommunityMember.objects.get(user=request.user)
if request.method == "POST": if request.method == "POST":
raise NotImplementedError() raise NotImplementedError()
else: else: