Updates with a sign in page
This commit is contained in:
@@ -2,6 +2,7 @@ from django.db import models
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
import datetime
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
class TimeInfoBase(models.Model):
|
||||
|
||||
@@ -181,6 +182,11 @@ class CommunityParks(TimeInfoBase):
|
||||
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):
|
||||
@@ -188,12 +194,20 @@ class CommunityPost(TimeInfoBase):
|
||||
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)
|
||||
# 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):
|
||||
post = models.ForeignKey(CommunityPost, on_delete=models.CASCADE)
|
||||
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)
|
||||
@@ -16,7 +16,7 @@
|
||||
<script async defer src="https://tianji.aimloperations.com/tracker.js" data-website-id="cm9qziuid9vr7v6dtdbnx8406"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p><img src=https://tianji.aimloperations.com/telemetry/cm7w8087y020lddswyhamadj2/cm9u1ehxeajxmv6dtajx4f9yn/badge.svg"></p>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-success sticky-top">
|
||||
<div class="container">
|
||||
|
||||
@@ -78,34 +78,39 @@
|
||||
<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>Recent Community Activity</h3>
|
||||
<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">Annual Picnic Scheduled</h5>
|
||||
<h5 class="mb-1">{{ recent_post.title }}</h5>
|
||||
<small>3 days ago</small>
|
||||
</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>
|
||||
</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">Landscaping Update</h5>
|
||||
<small>1 week ago</small>
|
||||
<h5 class="mb-1">{{ recent_post.title }}</h5>
|
||||
<small>3 days ago</small>
|
||||
</div>
|
||||
<p class="mb-1">New flowers planted in common areas. Come see the improvements!</p>
|
||||
<small>Posted by Robert Wilson</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>
|
||||
<p class="mb-1">{{ recent_post.content }}</p>
|
||||
<small>Posted by Sarah Johnson</small>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -52,12 +52,12 @@
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
104
schasite/templates/schasite/signup.html
Normal file
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 %}
|
||||
@@ -8,6 +8,7 @@ if settings.DEBUG:
|
||||
path('login/',views.login, name="login"),
|
||||
path('set_password/',views.set_password, name="set_password"),
|
||||
path('password_reset/',views.password_reset, name="password_reset"),
|
||||
path('signup/',views.signup, name="signup"),
|
||||
path('directory/',views.member_directory, name="directory"),
|
||||
path('dashboard/',views.member_dashboard, name="dashboard"),
|
||||
path('posts/',views.member_posts, name="posts"),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership
|
||||
|
||||
from .models import UsefulLinks, CalendarEvent, MembershipPerson, Payments, SCHAOfficer, Membership, CommunityPost
|
||||
from .forms import (
|
||||
ChildrenForm,
|
||||
CommunityPostForm,
|
||||
@@ -15,6 +16,8 @@ from django.db import transaction, IntegrityError
|
||||
from django.conf import settings # new
|
||||
from django.http.response import JsonResponse, HttpResponse
|
||||
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
|
||||
|
||||
"""
|
||||
@@ -472,13 +475,25 @@ def membership_form(request):
|
||||
def scha_board(request):
|
||||
return render(request, "schasite/scha_board.html", {})
|
||||
|
||||
|
||||
def login(request):
|
||||
|
||||
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:
|
||||
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()
|
||||
@@ -488,29 +503,48 @@ def password_reset(request):
|
||||
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:
|
||||
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):
|
||||
current_member = CommunityMember.objects.get(user=request.user)
|
||||
if request.method == "POST":
|
||||
raise NotImplementedError()
|
||||
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):
|
||||
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():
|
||||
@@ -523,13 +557,17 @@ def member_posts_create(request):
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user