aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alphabetlearning/payments/forms.py14
-rw-r--r--alphabetlearning/payments/migrations/0013_alter_emailverification_email.py18
-rw-r--r--alphabetlearning/payments/models.py3
-rw-r--r--alphabetlearning/payments/views.py147
-rw-r--r--alphabetlearning/templates/pages/home.html282
5 files changed, 267 insertions, 197 deletions
diff --git a/alphabetlearning/payments/forms.py b/alphabetlearning/payments/forms.py
new file mode 100644
index 0000000..f69397f
--- /dev/null
+++ b/alphabetlearning/payments/forms.py
@@ -0,0 +1,14 @@
+from django import forms
+from .models import EmailVerification
+
+
+class EmailVerificationForm(forms.ModelForm):
+ class Meta:
+ model = EmailVerification
+ fields = ['email']
+
+ def clean_email(self):
+ email = self.cleaned_data.get('email')
+ if EmailVerification.objects.filter(email=email).exists():
+ raise forms.ValidationError("This email address is already in use.")
+ return email \ No newline at end of file
diff --git a/alphabetlearning/payments/migrations/0013_alter_emailverification_email.py b/alphabetlearning/payments/migrations/0013_alter_emailverification_email.py
new file mode 100644
index 0000000..5d537bb
--- /dev/null
+++ b/alphabetlearning/payments/migrations/0013_alter_emailverification_email.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.4 on 2024-12-05 16:16
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('payments', '0012_rename_pendingemailverification_emailverification'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='emailverification',
+ name='email',
+ field=models.EmailField(max_length=254, unique=True),
+ ),
+ ]
diff --git a/alphabetlearning/payments/models.py b/alphabetlearning/payments/models.py
index 9ea9de2..3a3ba10 100644
--- a/alphabetlearning/payments/models.py
+++ b/alphabetlearning/payments/models.py
@@ -10,7 +10,7 @@ from alphabetlearning.resources.models import Resource
class EmailVerification(models.Model):
- email = models.EmailField()
+ email = models.EmailField(unique=True)
verification_token = models.UUIDField(default=uuid.uuid4, editable=False)
created_at = models.DateTimeField(auto_now_add=True)
is_verified = models.BooleanField(default=False)
@@ -23,7 +23,6 @@ class EmailVerification(models.Model):
def __str__(self):
return f"Email verification for {self.email}"
-
class EmailSignup(models.Model):
email = models.EmailField(unique=True)
date_added = models.DateTimeField(auto_now_add=True)
diff --git a/alphabetlearning/payments/views.py b/alphabetlearning/payments/views.py
index 4b6f79f..dda7900 100644
--- a/alphabetlearning/payments/views.py
+++ b/alphabetlearning/payments/views.py
@@ -18,7 +18,7 @@ from alphabetlearning.payments.models import EmailSignup
from alphabetlearning.payments.models import EmailVerification
from alphabetlearning.resources.models import Resource
from alphabetlearning.users.models import User
-
+from .forms import EmailVerificationForm
from .models import CartItem
from .models import Price
from .models import ShoppingCart
@@ -56,70 +56,101 @@ class SuccessEmailSignupView(TemplateView):
def email_signup_verification(request):
if request.method == "POST":
- email = request.POST.get("email")
-
- # Create pending verification
- pending_verification = EmailVerification.objects.create(
- email=email,
- )
-
- # Generate verification URL
- verification_url = request.build_absolute_uri(
- reverse('payments:verify_email', args=[str(pending_verification.verification_token)])
- )
-
- # Send verification email
- subject = 'Alphabet Learning - Email Verification'
- html_message = f'''
- <html>
- <body>
- <img src="http://localhost:8000/static/images/AL_long_logo_black_grey.png" alt="Alphabet Learning Logo" style="max-width: 200px; margin-bottom: 20px;">
- <p>Hi!</p>
- <p>You recently requested to sign up to the Alphabet Learning contact list.</p>
- <p>Please click the following link to verify your email address within 24 hours:</p>
- <p><a href="{verification_url}">{verification_url}</a></p>
- <p>If you didn't request this, please ignore this email.</p>
- <p>Best regards,</p>
- <p>The Alphabet Learning Team</p>
- </body>
- </html>
+ form = EmailVerificationForm(request.POST)
+ if form.is_valid():
+ # Create pending verification
+ pending_verification = EmailVerification.objects.create(
+ email=form.cleaned_data.get("email"),
+ )
+ # Generate verification URL
+ verification_url:str = request.build_absolute_uri(
+ reverse('payments:verify_email', args=[str(pending_verification.verification_token)])
+ )
+ email = process_verification_emails(verification_url, form.cleaned_data.get("email"), pending_verification, request)
+ return render(request, 'payments/verification_sent.html', {
+ 'email': email
+ })
+ else:
+ email = process_verification_emails(request.POST.get("email"), warn=True)
+ return render(request, 'payments/verification_sent.html', {
+ 'email': email
+ })
+ else:
+ form = EmailVerificationForm()
+ return render(request, "pages/home.html", {"form": form}) # Adjust as necessary
+
+
+def process_verification_emails(email: str, verification_url: str=False, email_verification_obj: EmailVerification=False, warn=False):
+
+ if warn is False:
+ html_warning_message = f'''
+ <p>Please click the following link to verify your email address within 24 hours:</p>
+ <p><a href="{verification_url}">{verification_url}</a></p>
+ <p>If you didn't request this, please ignore this email.</p>
'''
- message = f'''
- Hi!,
-
- You recently requested to sign up to the Alphabet Learning contact list.
-
+ warning_message = f'''
Please click the following link to verify your email address within 24 hours:
{verification_url}
If you didn't request this, please ignore this email.
-
- Best regards,
- The Alphabet Learning Team
'''
- send_mail(
- subject,
- message,
- settings.DEFAULT_FROM_EMAIL,
- [email],
- fail_silently=False,
- html_message=html_message
- )
- admin_message = f'''
- Joanna/Matthew,
-
- {email} has just signed up to the Alphabet Learning contact list. They are awaiting verification.
-
- I will email again if they follow through with the verification.
-
- Best regards,
- The Alphabet Learning Server
+ admin_warn = "They are not already subscribed."
+ else:
+ html_warning_message = f'''
+ <p>You are already subscribed to our list - no further action is required.</p>
'''
+ warning_message = '''
+ You are already subscribed to our list - no further action is required.
+ '''
+ admin_warn = "They have already subscribed so have been told of this fact in their verification email. No further action required."
+
+ # Send verification email
+ subject = 'Alphabet Learning - Email Verification'
+ html_message = f'''
+ <html>
+ <body>
+ <img src="http://localhost:8000/static/images/AL_long_logo_black_grey.png" alt="Alphabet Learning Logo" style="max-width: 200px; margin-bottom: 20px;">
+ <p>Hi!</p>
+ <p>You recently requested to sign up to the Alphabet Learning contact list.</p>
+ {html_warning_message}
+ <p>Best regards,</p>
+ <p>The Alphabet Learning Team</p>
+ </body>
+ </html>
+ '''
+ message = f'''
+ Hi!,
+
+ You recently requested to sign up to the Alphabet Learning contact list.
+
+ {warning_message}
+
+ Best regards,
+ The Alphabet Learning Team
+ '''
+ send_mail(
+ subject,
+ message,
+ settings.DEFAULT_FROM_EMAIL,
+ [email],
+ fail_silently=False,
+ html_message=html_message
+ )
+ admin_message = f'''
+ Joanna/Matthew,
+
+ {email} has just signed up to the Alphabet Learning contact list. They are awaiting verification.
+
+ {admin_warn}
+
+ I will email again if they follow through with the verification.
+
+ Best regards,
+ The Alphabet Learning Server
+ '''
+ mail_admins(subject, admin_message, fail_silently=False)
+ return email
+
- mail_admins(subject, admin_message, fail_silently=False)
- return render(request, 'payments/verification_sent.html', {
- 'email': email
- })
- return render(request, "pages/home.html") # Adjust as necessary
def verify_email(request, token):
try:
pending = EmailVerification.objects.get(
diff --git a/alphabetlearning/templates/pages/home.html b/alphabetlearning/templates/pages/home.html
index bda011c..e0827c1 100644
--- a/alphabetlearning/templates/pages/home.html
+++ b/alphabetlearning/templates/pages/home.html
@@ -1,18 +1,18 @@
{% extends "base.html" %} {% load static %} {% block content %}
-<div class="container text-center">
- <div class="row">
- <div class="px-4 py-5 mt-5 mb-0">
- <h1 class="display-1 fw-bold">Alphabet Learning</h1>
- <p class="display-6 mb-4 mt-4 p-4 rounded" style="color: #919191">
- High quality educational resources focused on simple concepts
- and the first steps in learning.
- </p>
+ <div class="container text-center">
+ <div class="row">
+ <div class="px-4 py-5 mt-5 mb-0">
+ <h1 class="display-1 fw-bold">Alphabet Learning</h1>
+ <p class="display-6 mb-4 mt-4 p-4 rounded" style="color: #919191">
+ High quality educational resources focused on simple concepts
+ and the first steps in learning.
+ </p>
+ </div>
</div>
- </div>
- <hr
- style="
+ <hr
+ style="
border: none;
height: 10px;
background: linear-gradient(
@@ -28,38 +28,46 @@
width: 100%;
margin: 20px 0;
"
- />
+ />
- <div class="row justify-content-center my-5">
- <div class="col-lg-12">
- <h2 class="display-4 font-weight-bolder my-3">Sign up</h2>
- <div>
- <p class="display-6 mb-4" style="color: darkgray">
- To be informed of the site launch and receive FREE resource
- credits, join our new customer mailing list...
- </p>
- </div>
- <form
- method="post"
- action="{% url 'payments:email_signup_verification' %}"
- class="mb-4"
- style="padding: 30px 0"
- >
- {% csrf_token %}
- <div class="my-5">
- <div class="mb-4 text-start">
- <input
- type="email"
- class="sign-up-form-input"
- id="email"
- name="email"
- required
- placeholder="Your email address..."
- />
- </div>
- <button
- type="submit"
- style="
+ <div class="row justify-content-center my-5">
+ <div class="col-lg-12">
+ <h2 class="display-4 font-weight-bolder my-3">Sign up</h2>
+ <div>
+ <p class="display-6 mb-4" style="color: darkgray">
+ To be informed of the site launch and receive FREE resource
+ credits, join our new customer mailing list...
+ </p>
+ </div>
+ <form
+ method="post"
+ action="{% url 'payments:email_signup_verification' %}"
+ class="mb-4"
+ style="padding: 30px 0"
+ >
+ {% csrf_token %}
+ {{ form.non_field_errors }}
+ <div class="my-5">
+ {% if form.email.errors %}
+ <div class="text-start my-2 border border-danger text-danger rounded">
+ <p>
+ {{ form.email.errors }}
+ </p>
+ </div>
+ {% endif %}
+ <div class="mb-4 text-start">
+ <input
+ type="email"
+ class="sign-up-form-input"
+ id="email"
+ name="email"
+ required
+ placeholder="Your email address..."
+ />
+ </div>
+ <button
+ type="submit"
+ style="
background-color: red;
color: white;
border: none;
@@ -68,33 +76,33 @@
font-size: 1.5rem;
font-weight: bold;
"
- >
- Submit
- </button>
- </div>
- <p class="text-muted text-center mt-3">
- <small
+ >
+ Submit
+ </button>
+ </div>
+ <p class="text-muted text-center mt-3">
+ <small
>By joining our list, you agree to our
- <a
- href="{% url 'payments:privacy_policy' %}"
- class="text-decoration-none"
+ <a
+ href="{% url 'payments:privacy_policy' %}"
+ class="text-decoration-none"
>Privacy and Legal Notice</a
- >.</small
- >
+ >.</small
+ >
+ </p>
+ </form>
+ </div>
+ <div class="col-lg-12">
+ <h2 class="display-4 font-weight-bolder my-3">Bonus offer!</h2>
+ <p class="display-6 mb-4" style="color: darkgray">
+ As a thank-you, the first fifty customers who join our mailing
+ list will receive a 50% discount once the site is live.
</p>
- </form>
- </div>
- <div class="col-lg-12">
- <h2 class="display-4 font-weight-bolder my-3">Bonus offer!</h2>
- <p class="display-6 mb-4" style="color: darkgray">
- As a thank-you, the first fifty customers who join our mailing
- list will receive a 50% discount once the site is live.
- </p>
+ </div>
</div>
- </div>
- <hr
- style="
+ <hr
+ style="
border: none;
height: 10px;
background: linear-gradient(
@@ -110,87 +118,87 @@
width: 100%;
margin: 20px 0;
"
- />
+ />
- <div class="row justify-content-center">
- <div class="col-md-4 mb-5 mb-md-0">
- <img
- src="{% static 'images/funnel4.png' %}"
- class="img-fluid rotated-image"
- alt="Funnel 1"
- />
- </div>
- <div class="col-md-4 mb-5 mb-md-0">
- <img
- src="{% static 'images/funnel5.png' %}"
- class="img-fluid rotated-image"
- alt="Funnel 2"
- />
- </div>
- <div class="col-md-4 mb-5 mb-md-0">
- <img
- src="{% static 'images/funnel6.png' %}"
- class="img-fluid rotated-image"
- alt="Funnel 3"
- />
+ <div class="row justify-content-center">
+ <div class="col-md-4 mb-5 mb-md-0">
+ <img
+ src="{% static 'images/funnel4.png' %}"
+ class="img-fluid rotated-image"
+ alt="Funnel 1"
+ />
+ </div>
+ <div class="col-md-4 mb-5 mb-md-0">
+ <img
+ src="{% static 'images/funnel5.png' %}"
+ class="img-fluid rotated-image"
+ alt="Funnel 2"
+ />
+ </div>
+ <div class="col-md-4 mb-5 mb-md-0">
+ <img
+ src="{% static 'images/funnel6.png' %}"
+ class="img-fluid rotated-image"
+ alt="Funnel 3"
+ />
+ </div>
</div>
- </div>
- <div class="row my-5 d-flex align-items-stretch">
- <div class="col-md-12 d-flex">
- <div class="p-4 flex-fill">
- <h2 class="display-4 font-weight-bolder my-3">
- Learning from A to Z
+ <div class="row my-5 d-flex align-items-stretch">
+ <div class="col-md-12 d-flex">
+ <div class="p-4 flex-fill">
+ <h2 class="display-4 font-weight-bolder my-3">
+ Learning from A to Z
+ </h2>
+ <p
+ class="display-6"
+ style="margin-bottom: 20px; color: darkgray"
+ >
+ Focused on early concepts, these resources are designed to
+ be accessible to all learners.
+ </p>
+ </div>
+ </div>
+ <div class="display-4 font-weight-bolder my-5">
+ <h2 class="display-4 font-weight-bolder mb-2">
+ No commitment required
</h2>
- <p
- class="display-6"
- style="margin-bottom: 20px; color: darkgray"
- >
- Focused on early concepts, these resources are designed to
- be accessible to all learners.
+ <p class="display-6" style="margin-bottom: 20px; color: darkgray">
+ Resources will be available to purchase individually without a
+ subscription.
</p>
</div>
</div>
- <div class="display-4 font-weight-bolder my-5">
- <h2 class="display-4 font-weight-bolder mb-2">
- No commitment required
- </h2>
- <p class="display-6" style="margin-bottom: 20px; color: darkgray">
- Resources will be available to purchase individually without a
- subscription.
- </p>
- </div>
- </div>
- <div class="row justify-content-center my-5">
- <div class="col-md-4 mb-5 mb-md-0">
- <img
- src="{% static 'images/funnel1.png' %}"
- class="img-fluid rotated-image"
- alt="Funnel 1"
- />
- </div>
- <div class="col-md-4 mb-5 mb-md-0">
- <img
- src="{% static 'images/funnel2.png' %}"
- class="img-fluid rotated-image"
- alt="Funnel 2"
- />
- </div>
- <div class="col-md-4 mb-5 mb-md-0">
- <img
- src="{% static 'images/funnel3.png' %}"
- class="img-fluid rotated-image"
- alt="Funnel 3"
- />
+ <div class="row justify-content-center my-5">
+ <div class="col-md-4 mb-5 mb-md-0">
+ <img
+ src="{% static 'images/funnel1.png' %}"
+ class="img-fluid rotated-image"
+ alt="Funnel 1"
+ />
+ </div>
+ <div class="col-md-4 mb-5 mb-md-0">
+ <img
+ src="{% static 'images/funnel2.png' %}"
+ class="img-fluid rotated-image"
+ alt="Funnel 2"
+ />
+ </div>
+ <div class="col-md-4 mb-5 mb-md-0">
+ <img
+ src="{% static 'images/funnel3.png' %}"
+ class="img-fluid rotated-image"
+ alt="Funnel 3"
+ />
+ </div>
</div>
+ <p
+ class="display-6 mb-4 mt-4 p-4 col-12 rounded text-center"
+ style="color: darkgray"
+ >
+ Alphabet Learning is currently in active <br/>development and will be
+ launched in Spring 2025.
+ </p>
</div>
- <p
- class="display-6 mb-4 mt-4 p-4 col-12 rounded text-center"
- style="color: darkgray"
- >
- Alphabet Learning is currently in active <br />development and will be
- launched in Spring 2025.
- </p>
-</div>
{% endblock content %}