emile 3 weeks ago
parent 6b0df34cdd
commit ce99bc2774

Binary file not shown.

@ -1,4 +1,6 @@
from django.shortcuts import render, redirect, get_object_or_404
from addressbook.models import AddressBook, Country, Group, Contact
from osinacore.models import *
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
@ -897,48 +899,33 @@ def add_ticket_update(request, ticket_id):
@staff_login_required
def add_addressbook(request):
customers = CustomerProfile.objects.all().order_by('-id')
business_types = BusinessType.objects.all().order_by('-id')
if request.method == 'POST':
customer_id = request.POST.get('customer')
customer = get_object_or_404(CustomerProfile, id=customer_id)
name = request.POST.get('name')
email = request.POST.get('email')
financial_number = request.POST.get('financial_number')
phone_number = request.POST.get('phone_number')
vat = request.POST.get('vat')
if vat:
vat = True
else:
vat = False
commercial_registration = request.POST.get('commercial_registration')
website = request.POST.get('website')
logo = request.FILES.get('logo')
business_type_id = request.POST.get('type')
business_type = get_object_or_404(BusinessType, id=business_type_id)
countries = Country.objects.all().order_by('name')
groups = Group.objects.all()
business = Business(
customer=customer,
name=name,
email=email,
financial_number=financial_number,
vat=vat,
commercial_registration=commercial_registration,
website=website,
type=business_type,
logo=logo,
phone_number=phone_number,
if request.method == 'POST':
first_name = request.POST.get('first_name')
middle_name = request.POST.get('middle_name')
last_name = request.POST.get('last_name')
country_id = request.POST.get('country') # Optional for now
contact_types = request.POST.getlist('contact_type[]')
contact_values = request.POST.getlist('contact_value[]')
# Create AddressBook instance
address_book = AddressBook.objects.create(
first_name=first_name,
middle_name=middle_name,
last_name=last_name,
country_id=country_id if country_id else None,
)
business.save()
return redirect('businesses')
for type_, value in zip(contact_types, contact_values):
if value:
Contact.objects.create(type=type_, contact=value, addressbook=address_book)
return redirect('addressbook')
context = {
'customers': customers,
'business_types': business_types,
"countries": countries,
"groups": groups,
}
return render(request, 'add_templates/add-business.html', context)
return render(request, 'add_templates/add-addressbook.html', context)

@ -23,7 +23,7 @@ urlpatterns = [
path('tag/<int:tag_id>/', views.edit_tag, name='edittag'),
path('ticket/<int:ticket_id>/status/', views.edit_ticket_status_modal, name='edit-ticket-status-modal'),
path('addressbook/<str:addressbook_id>/', views.edit_addressbook, name='editaddressbook'),
#Mark Points
path('mark_point_working_on/<int:point_id>/<str:task_id>/', views.mark_point_working_on, name='mark_point_working_on'),

@ -1,3 +1,4 @@
from addressbook.models import AddressBook, Country, Contact, Group
from osinacore.models import *
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponseRedirect
@ -662,3 +663,32 @@ def mark_point_completed_task_page(request, point_id, task_id):
return redirect('detailed-task', task_id=task.task_id)
@staff_login_required
def edit_addressbook(request, addressbook_id):
address = get_object_or_404(AddressBook, id=addressbook_id)
countries = Country.objects.all()
if request.method == 'POST':
address.first_name = request.POST.get('first_name')
address.middle_name = request.POST.get('middle_name')
address.last_name = request.POST.get('last_name')
address.country_id = request.POST.get('country')
address.save()
# Delete old contacts
address.contact_set.all().delete()
contact_types = request.POST.getlist('contact_type[]')
contact_values = request.POST.getlist('contact_value[]')
for type_, value in zip(contact_types, contact_values):
if value:
Contact.objects.create(type=type_, contact=value, addressbook=address)
return redirect('addressbook')
return render(request, 'edit_templates/edit-addressbook.html', {
"address": address,
"countries": countries,
})

@ -1,102 +1,68 @@
{% extends "add-edit-main.html" %}
{% extends "main.html" %}
{%load static%}
{% block content %}
<div class="w-full">
<div class="w-full px-5 s:px-9 mb-5">
<div class="w-full h-full shadow-md rounded-md py-5 px-3 bg-white">
<h1 class="text-3xl text-secondosiblue text-center font-semibold">
Add Business
Add Contact
</h1>
<form method="POST" action="{% url 'addaddressbook' %}" enctype="multipart/form-data">
<form method="POST" action="{% url 'addaddressbook' %}">
{% csrf_token %}
<div class="w-full flex flex-col gap-5">
<div class="w-full flex flex-col gap-5 justify-center items-center mt-5">
<div class="w-full">
<label class="text-gray-500">Logo:</label>
<div class="inbox-box border border-gray-300 w-full rounded-md px-3 mt-1">
<div class="flex items-center justify-between">
<input name="logo" required type="file" class="file-input" accept="image/*" hidden />
<span class="file-name text-gray-500 text-base focus:outline-none outline-none">Upload
Logo</span>
<label
class="file-label bg-transparent text-gray-500 border border-white h-14 cursor-pointer flex items-center">
<i class="fa fa-upload" style="font-size: 25px;"></i>
</label>
</div>
</div>
</div>
<div class="w-full">
<label class="text-gray-500">Customer:</label>
<select name="customer" id="business_type"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md text-gray-500 mt-1">
<option value="" selected disabled>Select Customer</option>
{% for customer in customers %}
<option value="{{ customer.id }}">{{ customer.user.first_name }} {{ customer.user.last_name }}</option>
{% endfor %}
</select>
</div>
<div class="w-full">
<label class="text-gray-500">Name:</label>
<input name="name" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Email:</label>
<input name="email" type="email"
<label class="text-gray-500">First Name:</label>
<input name="first_name" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Financial Number:</label>
<input name="financial_number" type="number"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Commercial Registration:</label>
<input name="commercial_registration" type="commercial_registration"
<label class="text-gray-500">Middle Name:</label>
<input name="middle_name" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Mobile Number:</label>
<input name="phone_number" type="number"
<label class="text-gray-500">Last Name:</label>
<input name="last_name" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Website:</label>
<input name="website" type="url"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
<label class="text-gray-500">Country:</label>
<select name="country" class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
<option value="">Select Country</option>
{% for country in countries %}
<option value="{{ country.id }}">{{ country.name }}</option>
{% endfor %}
</select>
</div>
<div class="w-full">
<label class="text-gray-500">Type:</label>
<select name="type" id="business_type"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md text-gray-500 mt-1">
<option value="" selected disabled>Select Business Type</option>
{% for business_type in business_types %}
<option value="{{ business_type.id }}">{{ business_type.name }}</option>
{% endfor %}
</select>
<label class="text-gray-500">Contacts:</label>
<div id="contact-fields" class="flex flex-col gap-3">
<!-- One contact field block (template for duplication) -->
<div class="flex gap-3 contact-block">
<select name="contact_type[]" class="border border-gray-300 rounded-md px-2 py-1">
<option value="Email">Email</option>
<option value="Mobile">Mobile</option>
<option value="Phone">Phone</option>
<option value="Whatsapp">Whatsapp</option>
</select>
<input type="text" name="contact_value[]" placeholder="Enter contact"
class="flex-1 border border-gray-300 rounded-md px-2 py-1" />
<button type="button" class="remove-contact text-red-500"></button>
</div>
</div>
<button type="button" id="add-contact"
class="mt-2 text-osiblue underline hover:text-blue-800">+ Add another contact</button>
</div>
<div class="w-full flex justify-start items-center gap-2 mt-1">
<input name="vat" type="checkbox" >
<label class="text-slate-800">VAT</label>
</div>
<div class="w-full flex justify-center items-center mt-3">
<button type="submit"
class="w-fit py-1 px-5 bg-osiblue rounded-md outline-none text-white border border-osiblue text-xl cursor-pointer hover:bg-white hover:text-osiblue duration-300">Save</button>
class="w-fit py-1 px-3 bg-osiblue rounded-md outline-none text-white border border-osiblue text-xl cursor-pointer hover:bg-white hover:text-osiblue duration-300">Save</button>
</div>
</div>
</form>
@ -106,5 +72,33 @@
<!-------------- JS SCRIPTS --------------->
<script type="text/javascript" src='{% static "js/inputs/upload-input-tag.js" %}'></script>
<script>
document.getElementById('add-contact').addEventListener('click', function () {
const container = document.getElementById('contact-fields');
const newBlock = document.createElement('div');
newBlock.classList.add('flex', 'gap-3', 'contact-block', 'mt-2');
newBlock.innerHTML = `
<select name="contact_type[]" class="border border-gray-300 rounded-md px-2 py-1">
<option value="Email">Email</option>
<option value="Mobile">Mobile</option>
<option value="Phone">Phone</option>
<option value="Whatsapp">Whatsapp</option>
</select>
<input type="text" name="contact_value[]" placeholder="Enter contact"
class="flex-1 border border-gray-300 rounded-md px-2 py-1" />
<button type="button" class="remove-contact text-red-500"></button>
`;
container.appendChild(newBlock);
});
// Handle removing contact blocks
document.addEventListener('click', function (e) {
if (e.target.classList.contains('remove-contact')) {
e.target.closest('.contact-block').remove();
}
});
</script>
{% endblock content %}

@ -0,0 +1,53 @@
{% extends "main.html" %}
{% load static %}
{% block title %}My Projects{% endblock %}
{% block content %}
<div class="w-full xxlg1:w-[75%] bg-white h-fit rounded-md shadow-md p-5">
<div class="w-full flex flex-col gap-4 mt-5">
<div>
<p class="text-gray-500 text-xl">First Name: <span
class="text-slate-800 text-xl font-semibold">{{ address.first_name }}</span></p>
</div>
<div>
<p class="text-gray-500 text-xl">Middle Name: <span
class="text-slate-800 text-xl font-semibold">{{ address.middle_name }}</span></p>
</div>
<div>
<p class="text-gray-500 text-xl">Last Name: <span
class="text-slate-800 text-xl font-semibold">{{ address.last_name }}</span></p>
</div>
<div>
<p class="text-gray-500 text-xl">Country: <span
class="text-slate-800 text-xl font-semibold">{{ address.country.name }}</span></p>
</div>
{% if address.contact_set.all %}
<div>
<p class="text-gray-500 text-xl mb-2">Contacts:</p>
<ul class="list-disc pl-5">
{% for contact in address.contact_set.all %}
<li class="text-slate-800 text-lg">
{{ contact.type }}: {{ contact.contact }}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
<a href="{% url 'editaddressbook' address.id %}">
<button
class="w-full text-base px-3 py-2 bg-fifthosiblue text-white outline-none border border-fifthosiblue rounded-md cursor-pointer hover:bg-white hover:text-fifthosiblue duration-300 mt-5">
Edit Contact
</button>
</a>
<button
class="w-full text-base px-3 py-2 bg-red-500 text-white outline-none border border-red-500 rounded-md cursor-pointer hover:bg-white hover:text-red-500 duration-300 mt-3 deleteCustomerButton"
data-modal-url="">
Delete Contact
</button>
</div>
{% endblock content %}

@ -0,0 +1,106 @@
{% extends "main.html" %}
{% load static %}
{% block content %}
<div class="w-full px-5 s:px-9 mb-5">
<div class="w-full h-full shadow-md rounded-md py-5 px-3 bg-white">
<h1 class="text-3xl text-secondosiblue text-center font-semibold">
Edit Contact
</h1>
<form method="POST" action="{% url 'editaddressbook' address.id %}">
{% csrf_token %}
<div class="w-full flex flex-col gap-5 justify-center items-center mt-5">
<div class="w-full">
<label class="text-gray-500">First Name:</label>
<input name="first_name" type="text" value="{{ address.first_name }}"
class="w-full h-[50px] py-1 px-3 border border-gray-300 rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Middle Name:</label>
<input name="middle_name" type="text" value="{{ address.middle_name }}"
class="w-full h-[50px] py-1 px-3 border border-gray-300 rounded-md mt-1">
</div>
<div class="w-full">
<label class="text-gray-500">Last Name:</label>
<input name="last_name" type="text" value="{{ address.last_name }}"
class="w-full h-[50px] py-1 px-3 border border-gray-300 rounded-md mt-1" required>
</div>
<div class="w-full">
<label class="text-gray-500">Country:</label>
<select name="country"
class="w-full h-[50px] py-1 px-3 border border-gray-300 rounded-md mt-1">
<option value="">Select Country</option>
{% for country in countries %}
<option value="{{ country.id }}"
{% if address.country and country.id == address.country.id %}selected{% endif %}>
{{ country.name }}
</option>
{% endfor %}
</select>
</div>
<!-- Contacts -->
<div class="w-full">
<label class="text-gray-500">Contacts:</label>
<div id="contact-fields" class="flex flex-col gap-3">
{% for contact in address.contact_set.all %}
<div class="flex gap-3 contact-block">
<select name="contact_type[]" class="border border-gray-300 rounded-md px-2 py-1">
{% for type, label in contact.TYPE_CHOICES %}
<option value="{{ type }}"
{% if contact.type == type %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
<input type="text" name="contact_value[]" value="{{ contact.contact }}"
class="flex-1 border border-gray-300 rounded-md px-2 py-1" />
<button type="button" class="remove-contact text-red-500"></button>
</div>
{% endfor %}
</div>
<button type="button" id="add-contact"
class="mt-2 text-osiblue underline hover:text-blue-800">+ Add another contact</button>
</div>
<div class="w-full flex justify-center items-center mt-4">
<button type="submit"
class="w-fit bg-osiblue border border-osiblue rounded-md text-white text-xl px-5 py-1 hover:bg-white hover:text-osiblue duration-300">Save</button>
</div>
</div>
</form>
</div>
</div>
<script>
document.getElementById('add-contact').addEventListener('click', function () {
const container = document.getElementById('contact-fields');
const newBlock = document.createElement('div');
newBlock.classList.add('flex', 'gap-3', 'contact-block', 'mt-2');
newBlock.innerHTML = `
<select name="contact_type[]" class="border border-gray-300 rounded-md px-2 py-1">
<option value="Email">Email</option>
<option value="Mobile">Mobile</option>
<option value="Phone">Phone</option>
<option value="Whatsapp">Whatsapp</option>
</select>
<input type="text" name="contact_value[]" placeholder="Enter contact"
class="flex-1 border border-gray-300 rounded-md px-2 py-1" />
<button type="button" class="remove-contact text-red-500"></button>
`;
container.appendChild(newBlock);
});
document.addEventListener('click', function (e) {
if (e.target.classList.contains('remove-contact')) {
e.target.closest('.contact-block').remove();
}
});
</script>
{% endblock content %}

@ -22,7 +22,7 @@
</div>
</div>
<div class="w-full s:w-fit">
<a href="{% url 'addaddressbook' %}" class="text-blue-500 hover:text-blue-800 hover:underline"></a>
<a href="{% url 'addaddressbook' %}" class="text-blue-500 hover:text-blue-800 hover:underline">
<button
class="w-full s:w-fit text-base px-3 py-2 bg-osiblue text-white outline-none border border-osiblue rounded-md cursor-pointer hover:bg-white hover:text-osiblue duration-300">Add
</button>
@ -61,29 +61,27 @@
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<div class="w-full flex flex-col justify-center items-center gap-3">
<div class="w-[50px] h-[50px] bg-slate-600 rounded-full">
<img src='{{business.logo.url}}' alt="Business Logo"
class="w-full h-full object-cover rounded-full">
</div>
<p class="text-secondosiblue">{{ address.first_name }} {{ address.middle_name }} {{ address.last_name }}</p>
</div>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{address.country.name}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
{% for c in address.contact_set.all %}
<p class="text-secondosiblue">{{c.type}}: {{c.contact}}</p>
{% endfor %}
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{address.type.name}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<a href="{% url 'businessdetails' business.business_id %}">
<a href="{% url 'addressbookdetails' address.id %}">
<div class="cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
@ -91,7 +89,7 @@
</svg>
</div>
</a>
<a href="{% url 'editbusiness' business.business_id %}">
<a href="{% url 'editaddressbook' address.id %}">
<div class="cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
@ -99,7 +97,7 @@
</div>
</a>
<div class="cursor-pointer deleteBusinessButton"
data-modal-url="{% url 'deletebusinessmodal' business.id %}">
data-modal-url="">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[18px] text-red-500 hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>

@ -69,7 +69,7 @@ urlpatterns = [
path('show-points/<str:task_id>/', views.show_points_modal, name='showpoints'),
path('timeline/<str:task_id>/', views.timeline_modal, name='timeline'),
path('reaction-details-modal/', views.reaction_details_modal, name='reactiondetailsmodal'),
path('addressbooks/<str:addressbook_id>/', views.addressbookdetails, name='addressbookdetails'),
#ADMIN CHAT
path('chat-rooms/<int:chat_id>/', views.chat_room, name='adminchatroom'),

@ -1,6 +1,6 @@
from django.shortcuts import render, redirect, get_object_or_404
from addressbook.models import AddressBook
from addressbook.models import AddressBook, Country
from .models import *
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import login as auth_login
@ -859,9 +859,20 @@ def fetch_projects_by_status(request, status=None):
@staff_login_required
def addressbook(request):
Country.objects.get_or_create(name='Lebanon')
addresses = AddressBook.objects.all()
context = {
'addresses' : addresses,
}
return render(request, 'listing_pages/adressbooks.html', context)
@staff_login_required
def addressbookdetails(request, addressbook_id):
address = get_object_or_404(AddressBook, id=addressbook_id)
context = {
'address' : address,
}
return render(request, 'details_templates/addressbook-details.html', context)

Loading…
Cancel
Save