base setup

This commit is contained in:
2026-01-07 12:09:20 +05:30
commit 0c275efea1
278 changed files with 11228 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
from django.contrib import admin
from .models import FeedbackModel
admin.site.register(FeedbackModel)

View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class CommunicationsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'at_django_boilerplate.communications'

View File

@@ -0,0 +1,50 @@
# Generated by Django 5.2.6 on 2025-12-29 05:20
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='AppointmentModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('full_name', models.CharField(max_length=255)),
('email', models.EmailField(max_length=254)),
('phone', models.CharField(max_length=20)),
('meeting_with', models.CharField(choices=[('business-consultant', 'Meet to Lawyer'), ('compliance-specialist', 'Meet to CA'), ('incorporation-expert', 'Meet to Secretary')], max_length=50)),
('appointment_datetime', models.DateTimeField()),
('notes', models.TextField(blank=True, null=True)),
('status', models.CharField(choices=[('pending', 'Pending'), ('contacted', 'Contacted'), ('in_process', 'In Process'), ('rescheduled', 'Rescheduled'), ('completed', 'Completed'), ('cancelled', 'Cancelled')], default='pending', max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True)),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='appointments', to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-appointment_datetime'],
},
),
migrations.CreateModel(
name='FeedbackModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('phone', models.CharField(blank=True, max_length=20, null=True)),
('name', models.CharField(blank=True, max_length=255, null=True)),
('subject', models.TextField(blank=True, null=True)),
('message', models.TextField(blank=True, null=True)),
('created_at', models.DateTimeField(default=django.utils.timezone.now)),
('to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='feedbacks', to=settings.AUTH_USER_MODEL)),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='feedback_from', to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.6 on 2026-01-03 06:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('communications', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='feedbackmodel',
name='is_junk',
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 5.2.6 on 2026-01-03 06:18
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('communications', '0002_feedbackmodel_is_junk'),
]
operations = [
migrations.AlterField(
model_name='appointmentmodel',
name='id',
field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='feedbackmodel',
name='id',
field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False),
),
]

View File

@@ -0,0 +1,63 @@
from django.db import models
from django.utils import timezone
from at_django_boilerplate.utils.mixins import UUIDMixin
class FeedbackModel(UUIDMixin):
user = models.ForeignKey('accounts.CustomUser',related_name='feedback_from',null=True,blank=True,on_delete=models.DO_NOTHING)
email = models.EmailField(null=True,blank=True)
phone = models.CharField(max_length=20, null=True, blank=True) # Corrected
name = models.CharField(max_length=255, blank=True, null=True)
to = models.ForeignKey('accounts.CustomUser',related_name='feedbacks',null=True,blank=True,on_delete=models.DO_NOTHING)
is_junk = models.BooleanField(default= False)
subject = models.TextField(null=True,blank=True)
message = models.TextField(null=True,blank=True)
created_at = models.DateTimeField(default=timezone.now)
# communications/models.py
class AppointmentModel(UUIDMixin):
MEETING_CHOICES = (
('business-consultant', 'Meet to Lawyer'),
('compliance-specialist', 'Meet to CA'),
('incorporation-expert', 'Meet to Secretary'),
)
STATUS_CHOICES = (
('pending', 'Pending'),
('contacted', 'Contacted'),
('in_process', 'In Process'),
('rescheduled', 'Rescheduled'),
('completed', 'Completed'),
('cancelled', 'Cancelled'),
)
user = models.ForeignKey(
'accounts.CustomUser',
related_name='appointments',
null=True,
blank=True,
on_delete=models.DO_NOTHING
)
full_name = models.CharField(max_length=255)
email = models.EmailField()
phone = models.CharField(max_length=20)
meeting_with = models.CharField(max_length=50, choices=MEETING_CHOICES)
appointment_datetime = models.DateTimeField()
notes = models.TextField(blank=True, null=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"APP-{self.pk:06d} - {self.full_name}"
class Meta:
ordering = ['-appointment_datetime']

View File

@@ -0,0 +1,437 @@
{% extends 'public_base.html' %}
{% load static %}
{% block title %}Book an Appointment - RegisterYourStartup.com{% endblock %}
{% block meta_description %}Schedule a consultation with our business experts. Book an appointment for personalized guidance on incorporation, compliance, and business growth strategies.{% endblock %}
{% block content %}
<style>
/* Glassmorphism Effect */
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Custom Scrollbar */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: #6b7280; border-radius: 4px; }
/* Smooth animations */
.hover-lift { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.hover-lift:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); }
/* Gradient text */
.gradient-text { background: linear-gradient(90deg, #4f46e5, #7c3aed); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
/* Appointment Form Styles */
:root {
--bg-color: #f8fafc;
--text-color: #1f2937;
--accent-color: #4f46e5;
--input-border: #4f46e5;
--button-bg: #4f46e5;
--button-text: #ffffff;
--card-bg: #ffffff;
}
.appointment-form-section {
background-color: var(--bg-color);
color: var(--text-color);
padding: 3rem 1rem;
min-height: 100vh;
display: flex;
align-items: center;
}
.appointment-form-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
gap: 3rem;
justify-content: center;
align-items: flex-start;
}
.appointment-form-wrapper {
flex: 1;
min-width: 400px;
background: var(--card-bg);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.appointment-form-wrapper label {
color: var(--text-color);
font-weight: 600;
display: block;
margin-bottom: 0.5rem;
}
.appointment-form-wrapper input,
.appointment-form-wrapper textarea,
.appointment-form-wrapper select {
border: 1px solid var(--input-border);
border-radius: 8px;
padding: 0.75rem;
width: 100%;
margin-bottom: 1rem;
background: var(--card-bg);
color: var(--text-color);
font-size: 1rem;
transition: all 0.3s ease;
}
.appointment-form-wrapper input:focus,
.appointment-form-wrapper textarea:focus,
.appointment-form-wrapper select:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.appointment-form-wrapper input::placeholder,
.appointment-form-wrapper textarea::placeholder {
color: #9ca3af;
}
.appointment-form-wrapper .btn-submit {
background: linear-gradient(90deg, #4f46e5, #7c3aed);
color: var(--button-text);
font-weight: bold;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
width: 100%;
font-size: 1.1rem;
}
.appointment-form-wrapper .btn-submit:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(79, 70, 229, 0.3);
}
.benefits-wrapper {
flex: 1;
min-width: 400px;
}
.appointment-heading {
font-size: 3.5rem;
font-weight: bold;
color: var(--text-color);
margin-bottom: 1rem;
line-height: 1.1;
}
.appointment-subheading {
font-size: 1.2rem;
color: var(--text-color);
margin-bottom: 2rem;
max-width: 500px;
}
@media (max-width: 768px) {
.appointment-form-container {
flex-direction: column;
align-items: center;
}
.appointment-heading {
font-size: 2.5rem;
text-align: center;
}
.appointment-form-wrapper,
.benefits-wrapper {
min-width: 100%;
}
}
.error {
color: #dc2626;
font-size: 0.875rem;
margin-top: -0.5rem;
margin-bottom: 1rem;
display: block;
}
/* Benefits Section */
.benefits-section {
background: linear-gradient(135deg, #4f46e5, #7c3aed);
color: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.benefit-item {
margin-bottom: 1.5rem;
display: flex;
align-items: flex-start;
}
.benefit-icon {
margin-right: 15px;
font-size: 1.2rem;
background: rgba(255, 255, 255, 0.2);
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.benefit-title {
font-weight: 600;
margin-bottom: 5px;
font-size: 1.1rem;
}
.benefit-description {
color: rgba(255, 255, 255, 0.9);
line-height: 1.4;
}
.success-message {
background: #d1fae5;
color: #065f46;
padding: 1.5rem;
border-radius: 12px;
border: 1px solid #a7f3d0;
margin-bottom: 2rem;
text-align: center;
font-size: 1.1rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}
</style>
<!-- Hero Section -->
<section class="py-16 md:py-24 bg-[#B6C3FD]">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row items-center">
<div class="md:w-1/2 mb-10 md:mb-0">
<h1 class="pt-10 text-4xl md:text-5xl font-extrabold text-gray-900 mb-4 leading-tight">
Book an <span class="gradient-text">Appointment</span>
</h1>
<p class="text-lg text-gray-700 mb-8 max-w-xl">
Schedule a consultation with our business experts. Get personalized guidance on incorporation, compliance, and growth strategies tailored to your needs.
</p>
<div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
<a href="#appointment-form" class="bg-indigo-600 text-white px-8 py-3 rounded-full font-medium hover:bg-indigo-700 transition text-center">Book Now</a>
</div>
</div>
<div class="md:w-1/2 flex justify-center relative">
<div class="w-80 h-80 bg-gradient-to-br from-indigo-200 to-purple-200 rounded-full flex items-center justify-center">
<i class="fas fa-calendar-check text-6xl text-indigo-600"></i>
</div>
<div class="absolute -top-4 -right-4 w-40 h-40 bg-gradient-to-br from-pink-200 to-orange-200 rounded-full opacity-70"></div>
<div class="absolute -bottom-4 -left-4 w-32 h-32 bg-gradient-to-br from-green-200 to-blue-200 rounded-full opacity-70"></div>
</div>
</div>
</div>
</section>
<!-- Appointment Form Section -->
<section id="appointment-form" class="appointment-form-section">
<div class="appointment-form-container">
<!-- Django Messages (Success / Error) -->
{% if messages %}
<div class="w-full max-w-4xl mx-auto mb-8">
{% for message in messages %}
<div class="success-message">
{{ message|safe }}
</div>
{% endfor %}
</div>
{% endif %}
<!-- Left: Appointment Form -->
<div class="appointment-form-wrapper">
<h2 class="text-2xl font-bold mb-6 text-center" style="color: var(--text-color);">Schedule Your Consultation</h2>
<form method="post" class="vertical-form">
{% csrf_token %}
<!-- All your form fields unchanged -->
<div class="form-group">
<label for="fullName">Full Name</label>
<input id="fullName" name="fullName" class="form-control" placeholder="Enter your full name" required type="text">
<span id="fullName-error" class="error"></span>
</div>
<div class="form-group">
<label for="email">Email</label>
<input id="email" name="email" class="form-control" placeholder="Enter your email" required type="email">
<span id="email-error" class="error"></span>
</div>
<div class="form-group">
<label for="phone">Phone Number</label>
<input id="phone" name="phone" class="form-control" placeholder="Enter your phone number" required type="tel">
<span id="phone-error" class="error"></span>
</div>
<div class="form-group">
<label for="meetingWith">Meet with</label>
<select id="meetingWith" name="meetingWith" required>
<option value="">Select an expert</option>
<option value="business-consultant">Lawyer (Business Consultation)</option>
<option value="compliance-specialist">Chartered Accountant (CA)</option>
<option value="incorporation-expert">Company Secretary</option>
</select>
<span id="meetingWith-error" class="error"></span>
</div>
<div class="form-group">
<label for="appointmentDateTime">Appointment Date & Time</label>
<input type="datetime-local" id="appointmentDateTime" name="appointmentDateTime" required>
<span id="appointmentDateTime-error" class="error"></span>
</div>
<div class="form-group">
<label for="notes">Notes (Optional)</label>
<textarea id="notes" name="notes" rows="4" class="form-control" placeholder="Any specific questions or topics you'd like to discuss?"></textarea>
</div>
<input class="btn btn-submit" type="submit" value="BOOK APPOINTMENT">
</form>
</div>
<!-- Right: Benefits -->
<div class="benefits-wrapper">
<h1 class="appointment-heading">
Book an appointment with us
</h1>
<p class="appointment-subheading">
Fill out the form to connect with us. During this session, our experts will:
</p>
<div id="benefits" class="benefits-section">
<div class="benefit-item">
<div class="benefit-icon">+</div>
<div>
<div class="benefit-title">Walk you through our services</div>
<p class="benefit-description">We provide solutions tailored to your business needs</p>
</div>
</div>
<div class="benefit-item">
<div class="benefit-icon">+</div>
<div>
<div class="benefit-title">Answer your specific questions</div>
<p class="benefit-description">Get actionable insights for your business</p>
</div>
</div>
<div class="benefit-item">
<div class="benefit-icon">+</div>
<div>
<div class="benefit-title">Expert Guidance</div>
<p class="benefit-description">Receive personalized advice from specialists in incorporation, compliance, and business growth</p>
</div>
</div>
<div class="benefit-item">
<div class="benefit-icon">+</div>
<div>
<div class="benefit-title">Time-Saving Efficiency</div>
<p class="benefit-description">Streamlined consultations help you get clear answers quickly</p>
</div>
</div>
<div class="benefit-item">
<div class="benefit-icon">+</div>
<div>
<div class="benefit-title">Comprehensive Support</div>
<p class="benefit-description">From starting a business to managing operations globally, we've got you covered</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-16 bg-gradient-to-r from-indigo-500 to-purple-600">
<div class="container mx-auto px-4 text-center">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">Ready to Grow Your Business?</h2>
<p class="text-indigo-100 text-lg mb-8 max-w-2xl mx-auto">Book a consultation today and let our expert team guide you through seamless business setup and expansion</p>
<div class="flex flex-col sm:flex-row justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<a href="{% url 'contact_us_form' %}" class="bg-white text-indigo-600 px-8 py-3 rounded-full font-medium hover:bg-indigo-50 transition">Contact Us</a>
<a href="tel:+9192204-33466" class="border border-white text-white px-8 py-3 rounded-full font-medium hover:bg-white hover:text-indigo-600 transition">Call: +91 92204-33466</a>
</div>
</div>
</section>
<script>
// Client-side form validation
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('form');
const fullNameInput = document.getElementById('fullName');
const emailInput = document.getElementById('email');
const phoneInput = document.getElementById('phone');
const meetingWithInput = document.getElementById('meetingWith');
const appointmentDateTimeInput = document.getElementById('appointmentDateTime');
form.addEventListener('submit', function(e) {
let isValid = true;
// Clear previous errors
document.querySelectorAll('.error').forEach(error => error.textContent = '');
// Validate full name
if (!fullNameInput.value.trim()) {
document.getElementById('fullName-error').textContent = 'Full name is required';
isValid = false;
}
// Validate email
if (!emailInput.value.trim()) {
document.getElementById('email-error').textContent = 'Email is required';
isValid = false;
} else {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(emailInput.value)) {
document.getElementById('email-error').textContent = 'Please enter a valid email address';
isValid = false;
}
}
// Validate phone
if (!phoneInput.value.trim()) {
document.getElementById('phone-error').textContent = 'Phone number is required';
isValid = false;
}
// Validate meeting with
if (!meetingWithInput.value) {
document.getElementById('meetingWith-error').textContent = 'Please select who you want to meet with';
isValid = false;
}
// Validate appointment date & time
if (!appointmentDateTimeInput.value) {
document.getElementById('appointmentDateTime-error').textContent = 'Please select appointment date and time';
isValid = false;
} else {
const selectedDateTime = new Date(appointmentDateTimeInput.value);
const now = new Date();
if (selectedDateTime <= now) {
document.getElementById('appointmentDateTime-error').textContent = 'Please select a future date and time';
isValid = false;
}
}
if (!isValid) {
e.preventDefault();
}
});
});
</script>
{% endblock %}

View File

@@ -0,0 +1,518 @@
{% extends 'public_base.html' %}
{% load crispy_forms_tags %}
{% block title %}Contact Us - RegisterYourStartup.com{% endblock %}
{% block meta_description %}Get in touch with RegisterYourStartup.com. Contact our global offices in India, UAE, USA, UK, Saudi Arabia, Malaysia, Singapore, Indonesia, Kenya, and Bangalore.{% endblock %}
{% block content %}
<style>
/* Glassmorphism Effect */
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Custom Scrollbar */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: #6b7280; border-radius: 4px; }
/* Smooth animations */
.hover-lift { transition: transform 0.3s ease, box-shadow 0.3s ease; }
.hover-lift:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); }
/* Gradient text */
.gradient-text { background: linear-gradient(90deg, #4f46e5, #7c3aed); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
/* Contact Form Styles - Using template colors */
:root {
--bg-color: #f8fafc;
--text-color: #1f2937;
--accent-color: #4f46e5;
--input-border: #4f46e5;
--button-bg: #4f46e5;
--button-text: #ffffff;
--card-bg: #ffffff;
}
.contact-form-section {
background-color: var(--bg-color);
color: var(--text-color);
padding: 3rem 1rem;
min-height: 100vh;
display: flex;
align-items: center;
}
.contact-form-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
gap: 3rem;
justify-content: center;
align-items: flex-start;
}
.contact-form-wrapper {
flex: 1;
min-width: 400px;
background: var(--card-bg);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.contact-form-wrapper label {
color: var(--text-color);
font-weight: 600;
display: block;
margin-bottom: 0.5rem;
}
.contact-form-wrapper input,
.contact-form-wrapper textarea {
border: 1px solid var(--input-border);
border-radius: 8px;
padding: 0.75rem;
width: 100%;
margin-bottom: 1rem;
background: var(--card-bg);
color: var(--text-color);
font-size: 1rem;
transition: all 0.3s ease;
}
.contact-form-wrapper input:focus,
.contact-form-wrapper textarea:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.contact-form-wrapper input::placeholder,
.contact-form-wrapper textarea::placeholder {
color: #9ca3af;
}
.contact-form-wrapper .btn-submit {
background: linear-gradient(90deg, #4f46e5, #7c3aed);
color: var(--button-text);
font-weight: bold;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
width: 100%;
font-size: 1.1rem;
}
.contact-form-wrapper .btn-submit:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(79, 70, 229, 0.3);
}
.contact-info-wrapper {
flex: 1;
min-width: 400px;
}
.contact-heading {
font-size: 3.5rem;
font-weight: bold;
color: var(--text-color);
margin-bottom: 1rem;
line-height: 1.1;
}
.contact-subheading {
font-size: 1.2rem;
color: var(--text-color);
margin-bottom: 2rem;
max-width: 500px;
}
@media (max-width: 768px) {
.contact-form-container {
flex-direction: column;
align-items: center;
}
.contact-heading {
font-size: 2.5rem;
text-align: center;
}
.contact-form-wrapper,
.contact-info-wrapper {
min-width: 100%;
}
}
.error {
color: #dc2626;
font-size: 0.875rem;
margin-top: -0.5rem;
margin-bottom: 1rem;
display: block;
}
/* Offices Grid */
.offices-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.office-card {
background: var(--card-bg);
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-left: 4px solid var(--accent-color);
transition: all 0.3s ease;
}
.office-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.office-card h3 {
color: var(--text-color);
margin-bottom: 1rem;
font-size: 1.2rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.office-card h3 i {
color: var(--accent-color);
}
.office-card p {
margin: 0.5rem 0;
color: #6b7280;
line-height: 1.4;
}
.contact-details {
background: var(--card-bg);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 2rem;
}
.contact-item {
display: flex;
align-items: flex-start;
margin-bottom: 1.5rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid #e5e7eb;
}
.contact-item:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.contact-icon {
background: linear-gradient(90deg, #4f46e5, #7c3aed);
color: white;
width: 40px;
height: 40px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
flex-shrink: 0;
}
.contact-content h4 {
color: var(--text-color);
margin-bottom: 0.5rem;
font-size: 1.1rem;
}
.contact-content p {
color: #6b7280;
margin: 0.25rem 0;
line-height: 1.4;
}
.section-title {
color: var(--text-color);
font-size: 2rem;
font-weight: bold;
margin-bottom: 2rem;
text-align: center;
}
</style>
<!-- Hero Section -->
<section class="py-16 md:py-24 bg-[#B6C3FD]">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row items-center">
<div class="md:w-1/2 mb-10 md:mb-0">
<h1 class=" pt-10 text-4xl md:text-5xl font-extrabold text-gray-900 mb-4 leading-tight">
Contact <span class="gradient-text">Us</span>
</h1>
<p class="text-lg text-gray-700 mb-8 max-w-xl">
Get in touch with our global team of experts. We're here to help you with business incorporation, compliance, and expansion worldwide.
</p>
<div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
<a href="#offices" class="border border-indigo-600 text-indigo-600 px-8 py-3 rounded-full font-medium hover:bg-indigo-50 transition text-center">Our Offices</a>
</div>
</div>
<div class="md:w-1/2 flex justify-center relative">
<div class="w-80 h-80 bg-gradient-to-br from-indigo-200 to-purple-200 rounded-full flex items-center justify-center">
<i class="fas fa-envelope text-6xl text-indigo-600"></i>
</div>
<div class="absolute -top-4 -right-4 w-40 h-40 bg-gradient-to-br from-pink-200 to-orange-200 rounded-full opacity-70"></div>
<div class="absolute -bottom-4 -left-4 w-32 h-32 bg-gradient-to-br from-green-200 to-blue-200 rounded-full opacity-70"></div>
</div>
</div>
</div>
</section>
<!-- Contact Form Section -->
<section id="contact-form" class="contact-form-section">
<div class="contact-form-container">
<!-- Left: Contact Form -->
<div class="contact-form-wrapper">
<h2 class="text-2xl font-bold mb-6 text-center" style="color: var(--text-color);">Get In Touch</h2>
{% if messages %}
{% for message in messages %}
<div class="alert alert-success w-100 text-center mt-4 mb-4" style="background: #d1fae5; color: #065f46; padding: 1.2rem; border-radius: 8px; border: 1px solid #a7f3d0; font-size: 1.1rem;">
{{ message|safe }}
</div>
{% endfor %}
{% endif %}
<form method="post" class="vertical-form">
{% csrf_token %}
<label class="form-label" for="name">Your Name</label>
<input id="name" name="name" class="form-control" placeholder="Enter your full name" required type="text"
{% if user.is_authenticated %}value="{{ user.get_full_name }}"{% endif %}>
<span id="name-error" class="error"></span>
<label class="form-label" for="subject">Subject</label>
<input id="subject" name="subject" class="form-control" placeholder="Enter your subject" required type="text">
<span id="subject-error" class="error"></span>
<label class="form-label" for="message">Message</label>
<textarea id="message" name="message" rows="6" class="form-control" placeholder="Enter your message" required></textarea>
<span id="message-error" class="error"></span>
{% if not user.is_authenticated %}
<label class="form-label" for="email">Email</label>
<input id="email" name="email" class="form-control" placeholder="Enter your email" required type="email">
<span id="email-error" class="error"></span>
<label class="form-label" for="phone">Phone (Optional)</label>
<input id="phone" name="phone" class="form-control" placeholder="Enter your phone number" type="tel">
<span id="phone-error" class="error"></span>
{% endif %}
<input class="btn btn-submit" type="submit" value="Send Message">
</form>
<!-- ✅ Success message below the form -->
{% if feedback_submitted %}
<div class="alert alert-success w-100 text-center mt-4" style="background: #d1fae5; color: #065f46; padding: 1rem; border-radius: 8px; border: 1px solid #a7f3d0;">
Thank you for your feedback! We will get back to you shortly. Please use Ticket ID: <strong>{{ ticket_id }}</strong> for future reference.
</div>
{% endif %}
</div>
<!-- Right: Contact Info -->
<div class="contact-info-wrapper">
<h1 class="contact-heading">Contact us</h1>
<p class="contact-subheading">
It is very important for us to keep in touch with you, so we are always ready to answer any questions that interest you. Shoot!
</p>
<!-- Contact Details -->
<div class="contact-details">
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-building"></i>
</div>
<div class="contact-content">
<h4>HEAD OFFICE</h4>
<p><strong>ADDRESS:</strong></p>
<p>D - 878, LGF, New Friends Colony,</p>
<p>New Delhi - 110025, India</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-phone"></i>
</div>
<div class="contact-content">
<h4>PHONE NUMBERS</h4>
<p><strong>Customer Care:</strong> +91 92204 33466</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fas fa-envelope"></i>
</div>
<div class="contact-content">
<h4>EMAIL</h4>
<p>info@registeryourstartup.com</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Global Offices Section -->
<section id="offices" class="py-16 bg-gray-50">
<div class="container mx-auto px-4">
<h2 class="section-title">Our Global Offices</h2>
<div class="offices-grid">
<!-- UAE Office -->
<div class="office-card">
<h3><i class="fas fa-building"></i> U.A.E Office</h3>
<p><strong>Visalite Global FZCO</strong></p>
<p>Scality Office No 63, Building No 9WC 523</p>
<p>PO Box 491, Dubai Airport Freezone</p>
<p>Dubai, UAE</p>
</div>
<!-- USA Office -->
<div class="office-card">
<h3><i class="fas fa-flag-usa"></i> U.S. Office</h3>
<p>3240 E-State Street, Hamilton</p>
<p>New Jersey 08619</p>
<p>United States</p>
</div>
<!-- UK Office -->
<div class="office-card">
<h3><i class="fas fa-landmark"></i> U.K. Office</h3>
<p>8 Alexandra Road, Worthing</p>
<p>West Sussex BN 11 2DX</p>
<p>United Kingdom</p>
</div>
<!-- Saudi Arabia Office -->
<div class="office-card">
<h3><i class="fas fa-mosque"></i> Saudi Arabia Office</h3>
<p>Building No. 4219, Al Izdihar Street</p>
<p>Unit No. 4301, Riyadh 12486</p>
<p>Saudi Arabia</p>
</div>
<!-- Malaysia Office -->
<div class="office-card">
<h3><i class="fas fa-university"></i> Malaysia Office</h3>
<p>Landmark, Suite 1705, Level 17</p>
<p>12 Jalan Ngee Heng</p>
<p>80000 Johor Bahru, Johor</p>
<p>Malaysia</p>
</div>
<!-- Singapore Office -->
<div class="office-card">
<h3><i class="fas fa-city"></i> Singapore Office</h3>
<p>3 Shenton Way, #09-07</p>
<p>Shenton House</p>
<p>Singapore 068805</p>
</div>
<!-- Indonesia Office -->
<div class="office-card">
<h3><i class="fas fa-torii-gate"></i> Indonesia Office</h3>
<p>Cyber 2 Tower, Rasuna Said</p>
<p>Kuningan, Jakarta</p>
<p><strong>Phone:</strong> +62 812-863-18349</p>
</div>
<!-- Kenya Office -->
<div class="office-card">
<h3><i class="fas fa-globe-africa"></i> Kenya Office</h3>
<p>#7 Vakaria Investment</p>
<p>Mombasa Road, Nairobi</p>
<p>Kenya</p>
</div>
<!-- Bangalore Office -->
<div class="office-card">
<h3><i class="fas fa-laptop-code"></i> Bangalore Office</h3>
<p>Bizcon Services Toyama Bizhub</p>
<p>Second Floor, Near Manyata Tech Park</p>
<p>Thannisandra Main Road</p>
<p>Bangalore 560077, India</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-16 bg-gradient-to-r from-indigo-500 to-purple-600">
<div class="container mx-auto px-4 text-center">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">Ready to Start Your Business Journey?</h2>
<p class="text-indigo-100 text-lg mb-8 max-w-2xl mx-auto">Contact us today and let our expert team guide you through seamless business setup and expansion</p>
<div class="flex flex-col sm:flex-row justify-center space-y-4 sm:space-y-0 sm:space-x-4">
<a href="#contact-form" class="bg-white text-indigo-600 px-8 py-3 rounded-full font-medium hover:bg-indigo-50 transition">Send Message</a>
<a href="{% url 'book_appointment' %}" class="border border-white text-white px-8 py-3 rounded-full font-medium hover:bg-white hover:text-indigo-600 transition">Book Appointment</a>
</div>
</div>
</section>
<script>
// Form validation
document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('form');
const subjectInput = document.getElementById('subject');
const messageInput = document.getElementById('message');
const emailInput = document.getElementById('email');
const phoneInput = document.getElementById('phone');
form.addEventListener('submit', function(e) {
let isValid = true;
// Clear previous errors
document.querySelectorAll('.error').forEach(error => error.textContent = '');
// Validate subject
if (!subjectInput.value.trim()) {
document.getElementById('subject-error').textContent = 'Subject is required';
isValid = false;
}
// Validate message
if (!messageInput.value.trim()) {
document.getElementById('message-error').textContent = 'Message is required';
isValid = false;
}
// Validate email if present
if (emailInput && !emailInput.value.trim()) {
document.getElementById('email-error').textContent = 'Email is required';
isValid = false;
} else if (emailInput && emailInput.value.trim()) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(emailInput.value)) {
document.getElementById('email-error').textContent = 'Please enter a valid email address';
isValid = false;
}
}
if (!isValid) {
e.preventDefault();
}
});
});
</script>
{% endblock %}

View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@@ -0,0 +1,7 @@
from django.urls import path
from . import views
urlpatterns = [
path('contact/', views.ContactView.as_view(), name='contact_us_form'),
path('book-appointment/', views.AppointmentView.as_view(), name='book_appointment'),
]

View File

@@ -0,0 +1,190 @@
from django.shortcuts import render, redirect
from django.core.mail import send_mail
from django.conf import settings
from django.views.generic import View
from django.contrib import messages
from django.utils import timezone # Ensure this is imported
from at_django_boilerplate.accounts.models import CustomUser
from at_django_boilerplate.communications.models import FeedbackModel, AppointmentModel
from at_django_boilerplate.backend_admin.models import SEOConfiguration
class ContactView(View):
template_name = 'contact_us_form.html'
def get(self, request, *args, **kwargs):
seo = SEOConfiguration.objects.first()
context = {
'user': request.user,
'meta_title': seo.contact_meta_title if seo else "Contact Us - RegisterYourStartup",
'meta_description': seo.contact_meta_description if seo else "Get in touch with our team."
}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
custom_user = None
if request.user.is_authenticated:
try:
custom_user = request.user
except CustomUser.DoesNotExist:
pass
subject = request.POST.get('subject')
message = request.POST.get('message')
name = request.POST.get('name')
email = ''
phone = ''
full_name = name or "Anonymous User"
if custom_user:
email = custom_user.get_decrypted_email()
phone = custom_user.get_decrypted_contact_number()
full_name = custom_user.get_full_name() or name or "Authenticated User"
else:
email = request.POST.get('email')
phone = request.POST.get('phone')
# Save feedback
feedback = FeedbackModel(
user=custom_user,
name=full_name,
email=email,
phone=phone,
subject=subject,
message=message
)
feedback.save()
ticket_id = feedback.id
# Prepare and send email
email_message = f'''
Ticket ID:\t{ticket_id}
Name:\t{full_name}
Email:\t{email}
Contact Number:\t{phone or 'Not provided'}
Subject:\t{subject}
Message:\t{message}
'''
try:
send_mail(
subject='You have a new message on RegisterYourStartup',
message=email_message,
from_email=settings.EMAIL_HOST_USER,
recipient_list=[settings.EMAIL_HOST_USER],
fail_silently=False,
)
except Exception as e:
print("Email sending failed:", e)
messages.success(
request,
f"Thank you, <strong>{full_name.split()[0] if full_name.split() else 'there'}</strong>! "
f"Your message has been sent successfully. "
f"Your Ticket ID is <strong>{ticket_id}</strong>. We will get back to you shortly."
)
return redirect('contact_us_form')
class AppointmentView(View):
template_name = 'book_appointment.html'
def get(self, request, *args, **kwargs):
seo = SEOConfiguration.objects.first()
context = {
'meta_title': seo.appointment_meta_title if seo and seo.appointment_meta_title else "Book an Appointment - RegisterYourStartup.com",
'meta_description': seo.appointment_meta_description if seo and seo.appointment_meta_description else "Schedule a consultation with our business experts.",
}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
custom_user = None
if request.user.is_authenticated:
try:
custom_user = request.user
except CustomUser.DoesNotExist:
pass
full_name = request.POST.get('fullName')
email = request.POST.get('email')
phone = request.POST.get('phone')
meeting_with = request.POST.get('meetingWith')
appointment_datetime_str = request.POST.get('appointmentDateTime')
notes = request.POST.get('notes', '')
# Basic server-side validation
if not all([full_name, email, phone, meeting_with, appointment_datetime_str]):
messages.error(request, "All required fields must be filled.")
return redirect('book_appointment')
try:
# Parse the datetime-local input (format: YYYY-MM-DDTHH:MM)
# Replace 'T' with space to make it compatible with fromisoformat
naive_datetime = timezone.datetime.fromisoformat(
appointment_datetime_str.replace('T', ' ')
)
# Convert to timezone-aware datetime
appointment_datetime = timezone.make_aware(naive_datetime)
if appointment_datetime <= timezone.now():
messages.error(request, "Appointment time must be in the future.")
return redirect('book_appointment')
except ValueError:
messages.error(request, "Invalid date/time format.")
return redirect('book_appointment')
# Save appointment
appointment = AppointmentModel(
user=custom_user,
full_name=full_name,
email=email,
phone=phone,
meeting_with=meeting_with,
appointment_datetime=appointment_datetime,
notes=notes
)
appointment.save()
ticket_id = f"APP-{appointment.pk:06d}"
# Send email notification to admin
email_subject = f"New Appointment Booking - {ticket_id}"
email_message = f"""
New Appointment Request
Ticket ID: {ticket_id}
Name: {full_name}
Email: {email}
Phone: {phone}
Meet With: {appointment.get_meeting_with_display()}
Date & Time: {appointment_datetime.strftime('%d %B %Y, %I:%M %p')}
Notes: {notes or 'No additional notes'}
Please confirm or follow up with the user.
"""
try:
send_mail(
subject=email_subject,
message=email_message,
from_email=settings.EMAIL_HOST_USER,
recipient_list=[settings.EMAIL_HOST_USER],
fail_silently=False,
)
except Exception as e:
print("Appointment email failed:", e)
# Success message via Django messages (shown on redirect)
messages.success(
request,
f"Thank you, <strong>{full_name.split()[0] if full_name.split() else 'there'}</strong>! "
f"Your appointment has been booked successfully. "
f"Your Ticket ID is <strong>{ticket_id}</strong>. We will contact you shortly to confirm."
)
# Redirect to same page to show success message and prevent resubmission
return redirect('book_appointment')