Free CRM Part 2: Client Notes, Dark Mode, Adding Customers
We have a lot of stuff to add to our free CRM software.
Small businesses are counting on us! Small businesses don't want to pay monstrous fees!
Mr. Big Boss the head honcho called. He said he wants improvements! This is what he requested:
To improve the view with a dark mode, we can use Bulma's dark mode support or add custom CSS to toggle between light and dark themes. There should be a button to toggle the Dark Mode on or off. And it should work across pages.
Here is the new base.html. Notice the JavaScript code for toggling Dark Mode.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CRM</title>
<link rel="stylesheet" >
<style>
body.dark-mode {
background-color: #121212;
color: #e0e0e0;
}
body.dark-mode .navbar, body.dark-mode .table {
background-color: #1f1f1f;
color: #e0e0e0;
}
body.dark-mode .input, body.dark-mode .textarea {
background-color: #2e2e2e;
color: #e0e0e0;
}
.toggle-dark-mode {
cursor: pointer;
padding: 5px;
background-color: #2e2e2e;
color: #e0e0e0;
border-radius: 5px;
}
</style>
</head>
<body>
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="/">CRM</a>
<span class="toggle-dark-mode" onclick="toggleDarkMode()">Toggle Dark Mode</span>
</div>
</nav>
<section class="section">
<div class="container">
{% block content %}
{% endblock %}
</div>
</section>
<script>
function toggleDarkMode() {
document.body.classList.toggle('dark-mode');
localStorage.setItem('dark-mode', document.body.classList.contains('dark-mode'));
}
document.addEventListener('DOMContentLoaded', () => {
if (localStorage.getItem('dark-mode') === 'true') {
document.body.classList.add('dark-mode');
}
});
</script>
</body>
</html>
Next we can update the customer_list.html template.
{% extends "crm/base.html" %}
{% block content %}
<h1 class="title">Customer List</h1>
<a class="button is-primary" href="{% url 'add_customer' %}">Add Customer</a>
<table class="table is-fullwidth">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Address</th>
</tr>
</thead>
<tbody>
{% for customer in customers %}
<tr>
<td>{{ customer.name }}</td>
<td>{{ customer.email }}</td>
<td>{{ customer.phone }}</td>
<td>{{ customer.address }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
Now we have a nice Dark Mode toggle button to help our eyesight at night time. This can be toggled on the top left.
In order to add notes, we simply edit our model. We create a new class Note. I want to add notes for every customer. I also want to see previous notes. If any of you have used SalesForce you can imagine what this might look like.
Lets edit models.py to include our new class Note.
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=255)
email = models.EmailField(unique=True)
phone = models.CharField(max_length=20, blank=True)
address = models.TextField(blank=True)
def __str__(self):
return self.name
class Note(models.Model):
customer = models.ForeignKey(Customer, related_name='notes', on_delete=models.CASCADE)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Note for {self.customer.name} at {self.created_at}"
Create and apply migrations in order to update the database. If we have a new class, we need to update the database.
python manage.py makemigrations crm
python manage.py migrate
Create a file crm/forms.py for our new Notes class.
from django import forms
from .models import Customer, Note
class CustomerForm(forms.ModelForm):
class Meta:
model = Customer
fields = ['name', 'email', 'phone', 'address']
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ['text']
Update views.py. While we are here, we need to work on adding customers. This will take input from a form.
领英推荐
# crm/views.py
from django.shortcuts import render, redirect, get_object_or_404
from .models import Customer, Note
from .forms import CustomerForm, NoteForm
def customer_list(request):
customers = Customer.objects.all()
return render(request, 'crm/customer_list.html', {'customers': customers})
def add_customer(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
form.save()
return redirect('customer_list')
else:
form = CustomerForm()
return render(request, 'crm/add_customer.html', {'form': form})
def customer_detail(request, pk):
customer = get_object_or_404(Customer, pk=pk)
notes = customer.notes.all()
if request.method == 'POST':
form = NoteForm(request.POST)
if form.is_valid():
note = form.save(commit=False)
note.customer = customer
note.save()
return redirect('customer_detail', pk=customer.pk)
else:
form = NoteForm()
return render(request, 'crm/customer_detail.html', {'customer': customer, 'notes': notes, 'form': form})
Update crm/urls.py to have the proper urls. We need an url for adding customers and an url for viewing details.
# crm/urls.py
from django.urls import path
from .views import customer_list, add_customer, customer_detail
urlpatterns = [
path('', customer_list, name='customer_list'),
path('add/', add_customer, name='add_customer'),
path('<int:pk>/', customer_detail, name='customer_detail'),
]
Now we should add new files to our templates. Here is add_customer.html.
{% extends "crm/base.html" %}
{% block content %}
<h1 class="title">Add Customer</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button is-primary">Add Customer</button>
</form>
{% endblock %}
And customer_detail.html. This page is for viewing those notes.
{% extends "crm/base.html" %}
{% block content %}
<h1 class="title">{{ customer.name }}</h1>
<p>Email: {{ customer.email }}</p>
<p>Phone: {{ customer.phone }}</p>
<p>Address: {{ customer.address }}</p>
<h2 class="subtitle">Notes</h2>
<ul>
{% for note in notes %}
<li>{{ note.created_at }}: {{ note.text }}</li>
{% endfor %}
</ul>
<h2 class="subtitle">Add Note</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button is-primary">Add Note</button>
</form>
{% endblock %}
Lets see how it looks. Now this is notes page is viewed over at https://127.0.0.1:8000/1/
I will need to have to edit this a bit so that we can arrive at the proper page. So admire this nice note taking form and lets re-visit customer_list.html.
Edit customer_list.html to tie everything we did today together.
{% extends "crm/base.html" %}
{% block content %}
<h1 class="title">Customer List</h1>
<table class="table is-fullwidth">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Address</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for customer in customers %}
<tr>
<td><a href="{% url 'customer_detail' customer.pk %}">{{ customer.name }}</a></td>
<td>{{ customer.email }}</td>
<td>{{ customer.phone }}</td>
<td>{{ customer.address }}</td>
<td><a href="{% url 'customer_detail' customer.pk %}">View</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<a class="button is-primary" href="{% url 'add_customer' %}">Add Customer</a>
{% endblock %}
Now re-load the main page and lets see what happens. It's going to look great.
Ah now I see the view option that takes us to respective notes, and the Add Customer button. Very nice! Also, we can add new customers. I think the new sales department is going to have a great time using this software.
I've added the source code for this free CRM. If you have suggestions let me know about them so i can apply new features. -Henry