New changes.

main
nataly 1 year ago
parent 7784d927af
commit 40f0d93824

@ -6,5 +6,6 @@ urlpatterns = [
path('product', views.add_product, name='addproduct'),
path('service', views.add_service, name='addservice'),
path('order', views.add_order, name='addorder'),
path('invoice/<int:order_id>/', views.add_invoice_pdf, name='addinvoice'),
]

@ -173,7 +173,7 @@ def add_invoice_pdf(request, order_id):
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"'
return response
return response

@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2024-04-24 12:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('billing', '0041_orderitem_active'),
]
operations = [
migrations.AddField(
model_name='order',
name='due_date',
field=models.DateField(blank=True, null=True),
),
]

@ -40,6 +40,7 @@ class Order(models.Model):
business = models.ForeignKey(Business, on_delete=models.SET_NULL, null=True, blank=True)
status = models.CharField(max_length=200, choices=STATUS, default='None')
order_id = models.CharField(max_length=100, null=True, blank=True)
due_date = models.DateField(null=True, blank=True)
@property
def get_cart_total(self):
orderitems = self.orderitem_set.all()

@ -34,8 +34,7 @@
<div class="w-full">
<label class="text-gray-500">Business:</label>
<select name="business" id="businessSelectTag"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md text-gray-500 mt-1"
required>
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md text-gray-500 mt-1">
<option selected disabled>Select Customer First</option>
</select>
</div>

@ -86,7 +86,7 @@
{% if order.status == 'Pending' and not order.invoice %}
<a href="{% url 'addinvoice' order.id %}">
<a href="{% url 'addinvoice' order.id %}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-[18px] text-blue-500">
<path fill-rule="evenodd" d="M5.625 1.5H9a3.75 3.75 0 0 1 3.75 3.75v1.875c0 1.036.84 1.875 1.875 1.875H16.5a3.75 3.75 0 0 1 3.75 3.75v7.875c0 1.035-.84 1.875-1.875 1.875H5.625a1.875 1.875 0 0 1-1.875-1.875V3.375c0-1.036.84-1.875 1.875-1.875ZM12.75 12a.75.75 0 0 0-1.5 0v2.25H9a.75.75 0 0 0 0 1.5h2.25V18a.75.75 0 0 0 1.5 0v-2.25H15a.75.75 0 0 0 0-1.5h-2.25V12Z" clip-rule="evenodd" />
<path d="M14.25 5.25a5.23 5.23 0 0 0-1.279-3.434 9.768 9.768 0 0 1 6.963 6.963A5.23 5.23 0 0 0 16.5 7.5h-1.875a.375.375 0 0 1-.375-.375V5.25Z" />

@ -14,7 +14,6 @@ urlpatterns = [
# DETAILS
path('invoice-details/<int:order_id>/', views.invoice_details, name='invoicedetails'),
path('fetch-customer-items/<int:customer_id>/', views.fetch_customer_items, name='fetch_customer_items'),
path('fetch-customer-businesses/<int:customer_id>/', views.fetch_customer_businesses, name='fetch_customer_businesses'),
]

@ -85,3 +85,4 @@ def fetch_customer_businesses(request, customer_id):
business_data = None
return JsonResponse({'businesses': business_data})

@ -0,0 +1,61 @@
{% extends "customer_main.html" %}
{%load static%}
{% block content %}
<div class="w-full px-5 s:px-9 flex flex-col gap-3">
<div class="w-full bg-white rounded-md h-fit shadow-md p-5">
<h1 class="text-3xl text-secondosiblue text-center font-semibold">
Open Ticket
</h1>
<form class="w-full flex flex-col gap-5 justify-center items-center mt-5" method="POST" action="">
{% csrf_token %}
<div class="w-full">
<label class="text-gray-500">Ticket Title:</label>
<input required name="title" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
</div>
<div class="w-full">
<label class="text-gray-500">What is this regarding?</label>
<select class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
<option value="">General Accounting</option>
</select>
</div>
<div class="w-full">
<label class="text-gray-500">Desceription:</label>
<textarea required name="description"
class="w-full py-1 px-3 border border-gray-300 outline-none rounded-md mt-1 resize-none"
rows="8"></textarea>
</div>
<div class="w-full">
<label class="text-gray-500">Attach Files:</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="" type="file" class="file-input" hidden multiple />
<span class="file-name text-gray-500 text-base focus:outline-none outline-none">Upload
Document(s)</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 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>
</div>
</form>
</div>
</div>
<!-------------- JS SCRIPTS --------------->
<script type="text/javascript" src='{% static "js/upload-input-tag.js" %}'></script>
{% endblock %}

@ -0,0 +1,175 @@
{% extends "customer_main.html" %}
{%load static%}
{% block content %}
<div class="w-full px-5 s:px-9 flex flex-col gap-3">
<div class="w-full bg-white rounded-md h-fit shadow-md p-5">
<div class="w-full h-fit flex flex-col gap-2 bg-gray-100 shadow-md rounded-md px-3 py-3">
<p class="text-secondosiblue text-xl">Ticket: <span class="font-semibold">#2226663535</span></p>
<div class="flex justify-start items-center gap-1">
<div class="w-[16px] h-[16px] rounded-full bg-red-200 border border-red-500 shadow-md"></div>
<p class="text-secondosiblue font-light">Closed by Linode at 20-4-24 16:30</p>
</div>
</div>
<div class="w-full flex flex-col gap-8 mt-5 s:mt-10">
<!-- REPLY 1 -->
<div class="flex gap-3">
<div>
<div class="w-[45px] s:w-[60px] h-[45px] s:h-[60px] rounded-full shadow-md border border-gray-100">
<img src="{% static 'images/ositcom_logos/full-logo.png' %}"
class="w-full h-full rounded-full object-cover">
</div>
</div>
<div class="w-full replyContainer shadow-md">
<div
class="w-full bg-gray-100 flex justify-between items-center gap-3 px-3 py-3 cursor-pointer rounded-t-md toggleReply">
<p class="text-secondosiblue font-light text-sm s:text-base"><span class="font-semibold">Ositcom
Ltd</span>
commented 2024-04-17 12:19</p>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowUp">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowDown hidden">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</div>
<div class="w-full bg-white p-5 flex flex-col gap-3 reply">
<p class="text-gray-500 font-light leading-8 text-[15px]">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non purus consectetur
magna sodales fringilla. Suspendisse non imperdiet metus. Curabitur feugiat tristique
varius. Curabitur fermentum sapien nisi, sed suscipit odio luctus sed. Mauris pretium risus
a tincidunt facilisis. Aliquam quis odio in mi aliquet scelerisque et ut urna. Ut ultrices
turpis odio, id hendrerit lectus dignissim in. Donec at tortor quis dui auctor sodales porta
et purus. Aliquam at nunc sit amet tortor lacinia porttitor. Proin auctor, eros ac
sollicitudin iaculis, felis quam vulputate ante, eu varius dolor arcu non enim. Vestibulum
ornare dapibus risus, id eleifend ipsum. Aliquam metus urna, bibendum quis cursus vitae,
placerat sit amet felis. Aliquam tellus ex, pretium id gravida id, vulputate et velit.
Phasellus leo felis, lobortis ut dolor eget, viverra aliquet ligula. Aliquam molestie ac
eros et fermentum.
</p>
</div>
</div>
</div>
<!-- CUSTOMER SUPPORT REPLY 2 -->
<div class="flex gap-3">
<div>
<div class="w-[45px] s:w-[60px] h-[45px] s:h-[60px] rounded-full shadow-md border border-gray-100">
<img src="{% static 'images/netcommerce-logo.png' %}"
class="w-full h-full rounded-full object-cover">
</div>
</div>
<div class="w-full replyContainer shadow-md">
<div
class="w-full bg-gray-100 flex justify-between items-center gap-3 px-3 py-3 cursor-pointer rounded-t-md toggleReply">
<p class="text-secondosiblue font-light text-sm s:text-base"><span
class="font-semibold">Scott</span>
Customer Support commented 2024-04-17 12:19</p>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowUp">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowDown hidden">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</div>
<div class="w-full bg-white flex flex-col gap-5 p-5 reply">
<p class="text-gray-500 font-light leading-8 text-[15px]">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non purus consectetur
magna sodales fringilla. Suspendisse non imperdiet metus. Curabitur feugiat tristique
varius. Curabitur fermentum sapien nisi, sed suscipit odio luctus sed. Mauris pretium risus
a tincidunt facilisis. Aliquam quis odio in mi aliquet scelerisque et ut urna. Ut ultrices
turpis odio, id hendrerit lectus dignissim in. Donec at tortor quis dui auctor sodales porta
et purus.
</p>
<div class="w-full border-t border-gray-200 pt-5 flex justify-start items-center gap-3">
<a class="text-secondosiblue font-light cursor-pointer hover:text-gray-500 duration-300">How
did I do?</a>
<div class="flex justify-start items-center gap-2">
<div class="w-fit h-fit rounded-full border-4 border-secondosiblue">
<img src="{% static 'images/icons/happy-icon.png' %}" class="w-[30px] h-[30px] rounded-full cursor-pointer hover:scale-105 duration-300 transition-transform">
</div>
<div class="w-fit h-fit rounded-full">
<img src="{% static 'images/icons/neutral-icon.png' %}" class="w-[30px] h-[30px] rounded-full cursor-pointer hover:scale-105 duration-300 transition-transform">
</div>
<div class="w-fit h-fit rounded-full">
<img src="{% static 'images/icons/unhappy-icon.png' %}" class="w-[30px] h-[30px] rounded-full cursor-pointer hover:scale-105 duration-300 transition-transform">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- REPLYING SECTION -->
<div class="flex gap-3">
<div>
<div class="w-[45px] s:w-[60px] h-[45px] s:h-[60px] rounded-full shadow-md border border-gray-100">
<img src="{% static 'images/ositcom_logos/full-logo.png' %}"
class="w-full h-full rounded-full object-cover">
</div>
</div>
<div class="w-full flex flex-col gap-3">
<textarea
class="w-full bg-white px-3 py-3 border border-gray-200 rounded-md outline-none text-gray-500 resize-none"
rows="8" placeholder="Reply to Ositcom Ltd..."></textarea>
<div class="w-full flex flex-col s:flex-row justify-end items-center gap-3">
<div class="w-full s:w-[50px] h-[50px] rounded-md bg-gray-50 shadow-md border border-gray-100 flex justify-center items-center p-2 cursor-pointer relative hover:scale-105 duration-300 transition-transform">
<input type="file" name="file" id="fileInput" class="opacity-0">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 text-secondosiblue z-10 absolute pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />
</svg>
</div>
<button
class="w-full s:w-fit bg-secondosiblue border border-secondosiblue text-white rounded-md cursor-pointer hover:bg-white hover:text-secondosiblue duration-300 px-9 py-3">
Send
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!---------------------- JS SCRIPTS -------------------->
<script type="text/javascript" src="{% static 'js/customer_dashboard/ticket-details.js' %}"></script>
{% endblock %}

@ -0,0 +1,117 @@
{% extends "customer_main.html" %}
{%load static%}
{% block modules_section %}
<!-- This block is intentionally left empty to exclude the modules section -->
{% endblock modules_section %}
{% block content %}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<p id="invoiceId" class="hidden">{{invoice.id}}</p>
<div class="w-full px-5 s:px-9 flex flex-col gap-5 mt-5 font-poppinsLight">
<div class="w-full h-fit bg-white rounded-md shadow-md">
<div class="grid grid-cols-1 xxlg1:grid-cols-2">
<div
class="w-full flex flex-col items-center justify-between rounded-lb-none xxlg1:rounded-l-md h-full rounded-tl-md rounded-tr-md xxlg1:rounded-tr-none gap-10 overflow-hidden relative bg-gradient-to-b from-gray-400 via-gray-500 to-blue-950">
<div
class="absolute top-0 left-32 w-[400px] h-[400px] bg-slate-800 filter blur-xl opacity-70 animate-blob animation-delay-2000">
</div>
<div
class="absolute top-20 right-0 w-[400px] h-[400px] bg-osiblue filter blur-xl opacity-70 animate-blob animation-delay-2000">
</div>
<div
class="absolute bottom-0 left-10 w-[400px] h-[400px] bg-blue-900 filter blur-xl opacity-70 animate-blob animation-delay-2000">
</div>
<div
class="absolute bottom-0 right-36 w-[400px] h-[400px] bg-gray-400 filter blur-xl opacity-70 animate-blob animation-delay-2000">
</div>
<div></div>
<!-- INVOICE DETAILS -->
<div class="w-[90%] s:w-[85%] xll:w-[75%] h-fit flex flex-col gap-5 justify-center items-center py-9 bg-white rounded-md z-10 shadow-md duration-300">
<img src="{% static 'images/ositcom_logos/full-logo.png' %}" class="w-[120px]">
<div class="w-full bg-osiblue py-3 px-3 flex justify-between items-center text-white mt-5">
<p>Due Date: <span class="font-semibold">{{invoice.order.due_date}}</span></p>
<p>Invoice <span class="font-semibold">${{invoice.invoice_number}}</span></p>
</div>
<div class="w-full p-5">
<p class="font-poppinsBold text-secondosiblue text-[17px]">Bill To:</p>
<p class="text-secondosiblue font-light">{{invoice.order.customer.user.first_name}} {{invoice.order.customer.user.last_name}}</p>
<p class="text-secondosiblue font-light">{{invoice.order.customer.mobile_number}}</p>
<p class="text-secondosiblue font-light">{{invoice.order.customer.user.email}}</p>
</div>
<div class="w-full bg-osiblue py-3 px-3 flex justify-start items-center text-white">
<p>Invoice Items</p>
</div>
<div class="w-full flex flex-col gap-5 p-5">
<ul class="text-secondosiblue font-light list-disc px-5">
{% for item in invoice.order.orderitem_set.all %}
<li>{{item.item.title}}</li>
{% endfor %}
</ul>
<div class="w-full flex justify-end items-center text-secondosiblue text-xl">
<p>Total: <span class="font-semibold">${{invoice.order.get_cart_total}}</span></p>
</div>
</div>
</div>
<div class="w-full bg-white border-bl-none xxlg1:border-bl-md px-5 py-3 z-10 flex flex-col justify-center items-center border border-gray-100">
<p class="text-secondosiblue font-poppinsLight text-sm">Payment Powered By</p>
<img src="{% static 'images/netcommerce-logo.png' %}" class="w-[120px]">
</div>
</div>
<!-- EMBEDDED PAYMENT FORM -->
<div class="p-5 relative min-h-[200px] xxlg1:h-full">
<div class="w-full h-full absolute flex justify-center items-center bg-black bg-opacity-30 z-10 inset-0 rounded-rt-none rounded-b-md xxlg1:rounded-r-md rounded-bl-md xxlg1:rounded-bl-none hidden"
id="paymentLoader">
<div role="status">
<svg aria-hidden="true"
class="w-14 h-14 text-white animate-spin dark:text-gray-600 fill-secondosiblue"
viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor" />
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill" />
</svg>
</div>
</div>
<div id="paymentContent">
</div>
</div>
</div>
</div>
</div>
<!---------------------- JS SCRIPTS -------------------->
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script src="https://creditlibanais-netcommerce.gateway.mastercard.com/static/checkout/checkout.min.js"></script>
<!-- TO CALL THE INITIATE CHECKOUT PAGE -->
<script type="text/javascript" src='{% static "js/customer_dashboard/invoice-payment.js" %}'></script>
{% endblock %}

@ -13,21 +13,22 @@
<tr>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Due Date
ID
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Title
Due Date
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Description
Items
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Status
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Amount
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
@ -38,35 +39,58 @@
<!-- TABLE BODY -->
<tbody class="bg-white divide-y divide-gray-200">
{% for invoice in invoices %}
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">20-2-2024</p>
<p class="text-secondosiblue">{{invoice.invoice_number}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">Invoice 1</p>
<p class="text-secondosiblue">{{invoice.order.due_date}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">Invoice description section</p>
<div class="w-full h-full flex justify-center items-center">
<ul class="text-secondosiblue font-light list-disc px-5">
{% for item in invoice.order.orderitem_set.all %}
<li>{{item.item.title}}</li>
{% endfor %}
</ul>
</div>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300 bg-yellow-500">
<p class="text-white">Pending</p>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300 {% if invoice.order.status == 'Pending' %}bg-yellow-500{% endif %} {% if invoice.order.status == 'Completed' %}bg-green-700{% endif %}">
<p class="text-white">{{invoice.order.status}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">200</p>
<p class="text-secondosiblue">${{invoice.order.get_cart_total}}</p>
</td>
<td class="px-6 py-4">
<div class="w-full flex justify-center items-center">
<button class="flex justify-center items-center gap-2 px-3 py-1 rounded-md bg-osiblue text-white border border-osiblue cursor-pointer hover:bg-white hover:text-osiblue duration-300">
Pay Now
<div class="w-full flex justify-center items-center gap-3">
<button
class="w-fit px-3 py-2 rounded-md bg-gray-100 border border-gray-100 shadow-md cursor-pointer hover:scale-105 duration-300 transition-transform">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="w-4 h-4 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round"
d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
</svg>
</button>
{% if not invoice.order.status == 'Completed' %}
<a href="{% url 'invoicepayment' invoice.id %}">
<button
class="flex justify-center items-center gap-2 px-3 py-1 rounded-md bg-osiblue text-white border border-osiblue cursor-pointer hover:bg-white hover:text-osiblue duration-300">
Pay Now
</button>
</a>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

@ -41,17 +41,17 @@
{% for order in orders %}
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">{{order.order_id}}</p>
<p class="text-secondosiblue">{{order.order_id}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
{% for item in order.orderitem_set.all %}
<p class="text-slate-800">{{item.item.title}}</p>
<p class="text-secondosiblue">{{item.item.title}}</p>
{% endfor %}
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">${{order.get_cart_total}}</p>
<p class="text-secondosiblue">${{order.get_cart_total}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300 bg-green-700">

@ -0,0 +1,95 @@
{% extends "customer_main.html" %}
{%load static%}
{% block content %}
<div class="w-full px-5 s:px-9 flex flex-col gap-3">
<div class="w-full bg-white rounded-md h-fit shadow-md p-5">
<h1 class="text-secondosiblue text-[30px]">My Tickets</h1>
<div class="w-full flex flex-col gap-3 mt-4">
<div class="w-full bg-gray-200 rounded-md shadow-md h-fit p-3 flex items-center justify-between gap-5">
<div class="flex items-center gap-5 text-[17px]">
<p class="text-secondosiblue font-semibold cursor-pointer">Open Ticktes</p>
<p class="text-gray-500 cursor-pointer">Closed Ticktes</p>
</div>
<a href="{% url 'customeraddticket' %}">
<button class="w-fit px-5 py-2 bg-osiblue border border-osiblue text-white rounded-md cursor-pointer hover:bg-white hover:text-secondosiblue duration-300">
Open Ticket
</button>
</a>
</div>
<div class="overflow-x-auto border border-gray-300 rounded-md">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Subject
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Ticket ID
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Regarding
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Date Created
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 border-r border-gray-300 uppercase whitespace-nowrap">
Last Updated
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
Updated By
</th>
</tr>
</thead>
<!-- TABLE BODY -->
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<a href="{% url 'innercustomerticket' %}">
<p class="text-secondosiblue cursor-pointer hover:text-gray-500 duration-300">My Account Balance</p>
</a>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">22666766</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Django</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-2024</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-2024</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<p class="text-secondosiblue">Ositcom Ltd</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %}

@ -15,8 +15,10 @@
<div class="w-full px-5 s:px-9 flex flex-col gap-5 mt-5 font-poppinsLight">
<div class="w-full h-fit bg-white rounded-md shadow-md">
<div class="grid grid-cols-1 xxlg1:grid-cols-2">
<!-- ITEM DETAILS -->
<div
class="w-full flex flex-col items-center justify-center rounded-l-md h-full p-9 gap-8 overflow-hidden relative bg-gradient-to-b from-gray-400 via-gray-500 to-blue-950">
class="w-full flex flex-col items-center justify-between rounded-tl-md rounded-lb-none xxlg1:rounded-l-md h-full rounded-tr-md xxlg1:rounded-tr-none gap-8 overflow-hidden relative bg-gradient-to-b from-gray-400 via-gray-500 to-blue-950">
<div
class="absolute top-0 left-32 w-[400px] h-[400px] bg-slate-800 filter blur-xl opacity-70 animate-blob animation-delay-2000">
</div>
@ -31,28 +33,46 @@
</div>
<div class="hidden s:flex z-10">
<img src="{% static 'images/ositcom_logos/full-logo-white.png' %}" class="w-[150px]">
</div>
<div></div>
<div class="w-full s:w-fit flex flex-col justify-center items-center gap-5 text-center border border-white border-opacity-10 rounded-md py-10 px-10 s:px-20 shadow-md bg-white z-10">
<p class="text-secondosiblue font-poppinsExtraBold uppercase text-xl s:text-2xl">{{item.title}}</p>
<p class="text-secondosiblue text-xl s:text-2xl">${{item.amount}}</p>
<div class="z-10 flex flex-col justify-center items-center gap-8 p-5 w-full s:w-fit">
<div class="hidden s:flex z-10">
<img src="{% static 'images/ositcom_logos/full-logo-white.png' %}" class="w-[150px]">
</div>
<select class="w-full s:w-[300px] bg-white border border-gray-200 rounded-md px-3 py-3 text-secondosiblue outline-none flex justify-center items-center text-center cursor-pointer" id="cycle">
{% for cycle in cycles %}
<option value="{{cycle.id}}">{{cycle.months}} {% if cycle.months == 1 %}month {% else %}months{% endif %}</option>
{% endfor %}
</select>
<div class="w-full s:w-fit flex flex-col justify-center items-center gap-5 text-center border border-white border-opacity-10 rounded-md py-10 px-10 s:px-20 shadow-md bg-white z-10">
<p class="text-secondosiblue font-poppinsExtraBold uppercase text-xl s:text-2xl">{{item.title}}</p>
<p class="text-secondosiblue text-xl s:text-2xl">$<span id="cyclePrice"></span></p>
<select class="w-full s:w-[300px] bg-white border border-gray-200 rounded-md px-3 py-3 text-secondosiblue outline-none flex justify-center items-center text-center cursor-pointer" id="cycle">
{% for cycle in cycles %}
<option value="{{cycle.id}}" data-cycle-price="{{cycle.cycle_price}}">{{cycle.months}} {% if cycle.months == 1 %}month {% else %}months{% endif %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="w-full bg-white border-bl-none xxlg1:border-bl-md px-5 py-3 z-10 flex flex-col justify-center items-center border border-gray-100">
<p class="text-secondosiblue font-poppinsLight text-sm">Payment Powered By</p>
<img src="{% static 'images/netcommerce-logo.png' %}" class="w-[120px]">
</div>
</div>
<!-- EMBEDDED PAYMENT FORM -->
<div class="p-5">
<div id="paymentContent">
<div class="p-5 relative min-h-[200px] xxlg1:h-full">
<div class="w-full h-full absolute flex justify-center items-center bg-black bg-opacity-30 z-10 inset-0 rounded-rt-none rounded-b-md xxlg1:rounded-r-md rounded-bl-md xxlg1:rounded-bl-none hidden" id="paymentLoader">
<div role="status">
<svg aria-hidden="true" class="w-14 h-14 text-white animate-spin dark:text-gray-600 fill-secondosiblue" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
</svg>
</div>
</div>
<div id="paymentContent">
</div>
</div>
</div>
@ -60,8 +80,8 @@
</div>
<!---------------------- JS SCRIPTS -------------------->
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
@ -69,7 +89,12 @@
<script src="https://creditlibanais-netcommerce.gateway.mastercard.com/static/checkout/checkout.min.js"></script>
<!-- TO CALL THE INITIATE CHECKOUT PAGE -->
<script type="text/javascript" src='{% static "js/customer_dashboard/payment.js" %}'></script>
<!-- TO CHANGE THE PRICE BASED ON THE CHOSEN CYCLE FROM THE SELECT TAG -->
<script type="text/javascript" src='{% static "js/customer_dashboard/payment-pricing.js" %}'></script>
{% endblock %}

@ -3,14 +3,22 @@ from . import views
urlpatterns = [
# LISTING
path('redirect-osimenu/', views.redirect_osimenu, name='redirectosimenu'),
path('redirect-osicard/', views.redirect_osicard, name='redirectosicard'),
# ADD
path('customer-add-ticket/', views.customer_add_ticket, name='customeraddticket'),
# LISTING
path('my-invoices/', views.customer_invoices, name='customerinvoices'),
path('products/', views.all_products, name='products'),
path('my-orders/', views.customer_orders, name='customerorders'),
path('my-tickets/', views.customer_tickets, name='customertickets'),
# DETAILS
path('inner-customer-ticket/', views.inner_customer_ticket, name='innercustomerticket'),
# PRODUCTS URL
@ -27,4 +35,7 @@ urlpatterns = [
path('payment/osimenu-basic/', views.buy_free_osimenu, name='buyfreeosimenu'),
path('payment/osicard-basic/', views.buy_free_osicard, name='buyfreeosicard'),
path('invoice-payment/<int:invoice_id>/', views.invoice_payment, name='invoicepayment'),
path('initiate_invoice_checkout/', views.initiate_invoice_checkout, name='initiateinvoicecheckout'),
]

@ -27,13 +27,27 @@ def redirect_osicard(request):
# ADD
@customer_login_required
def customer_invoices(request, *args, **kwargs):
def customer_add_ticket(request, *args, **kwargs):
context = {
}
return render(request, 'add_templates/customer-add-ticket.html', context)
# LISTING
@customer_login_required
def customer_invoices(request, *args, **kwargs):
invoices = Invoice.objects.filter(order__customer = request.user.customerprofile)
context = {
'invoices' : invoices,
}
return render(request, 'listing_pages/customer-invoices.html', context)
@ -61,6 +75,27 @@ def customer_orders(request, *args, **kwargs):
return render(request, 'listing_pages/customer-orders.html', context)
@customer_login_required
def customer_tickets(request, *args, **kwargs):
context = {
}
return render(request, 'listing_pages/customer-tickets.html', context)
# DETAILS
def inner_customer_ticket(request, *args, **kwargs):
context = {
}
return render(request, 'details_templates/inner-customer-ticket.html', context)
@ -128,10 +163,13 @@ def dedicated_servers_plans(request, *args, **kwargs):
def payment(request, item_id):
item = get_object_or_404(Item, id=item_id)
cycles = RecurringCycle.objects.filter(item = item)
selected_cycle = None
context = {
'item' : item,
'cycles' : cycles,
'selected_cycle': selected_cycle,
}
return render(request, 'payment.html', context)
@ -356,4 +394,70 @@ def buy_free_osicard(request):
response = requests.post(api_url, json=api_data)
print(response)
return redirect('customerorders')
return redirect('customerorders')
@customer_login_required
def invoice_payment(request, invoice_id):
invoice = get_object_or_404(Invoice, id = invoice_id)
context = {
'invoice' : invoice,
}
return render(request, 'invoice-payment.html', context)
@customer_login_required
def initiate_invoice_checkout(request):
api_username = 'merchant.TEST06127800'
api_password = '37846250a67c70e7fe9f82cf6ca81f93'
merchant_id = 'TEST06127800'
merchant_name = 'Ositcom Sal'
customer = request.user.customerprofile
data = json.loads(request.body)
invoice_id = data.get('invoice_id')
invoice = get_object_or_404(Invoice, id=invoice_id)
order = invoice.order
order_id = order.order_id
price = order.get_cart_total
payload = {
'apiOperation': 'INITIATE_CHECKOUT',
'apiUsername': api_username,
'apiPassword': api_password,
'merchant': merchant_id,
'interaction.operation': 'PURCHASE',
'interaction.merchant.name': merchant_name,
'order.id': order_id,
'order.amount': price,
'order.currency': 'USD',
'order.description': 'description_of_order',
'order.notificationUrl' : 'https://newosina.osinode.com/webhooks/',
'interaction.returnUrl' : f"https://newosina.osinode.com/check-order-status/{merchant_id}/{order_id}/"
}
try:
response = requests.post('https://creditlibanais-netcommerce.gateway.mastercard.com/api/nvp/version/78', data=payload)
print('Response Content:', response.text)
if response.status_code == 200:
response_data = response.text
parsed_data = dict(item.split('=') for item in response_data.split('&'))
session_id = parsed_data.get('session.id')
return JsonResponse({'session_id': session_id}, status=200)
else:
print('Response Status Code:', response.status_code)
return JsonResponse({'error': 'Failed to initiate checkout'}, status=500)
except Exception as e:
print('Exception:', e)
return JsonResponse({'error': 'Internal Server Error'}, status=500)

Binary file not shown.

@ -27,7 +27,7 @@ urlpatterns = [
path('reference/', views.add_reference_modal, name='addreferencemodal'),
path('tag/', views.add_tag_modal, name='addtagmodal'),
path('reaction/<int:status_id>/<str:emoji>/', views.add_reaction, name='add_reaction'),
path('add-ticket/', views.add_ticket, name='addticket'),
]

@ -593,7 +593,17 @@ def add_reaction(request, status_id, emoji):
# If the user hasn't reacted yet, create a new reaction
new_reaction = Reaction.objects.create(status=status, emoji=emoji, user=user)
return JsonResponse({'message': 'Reaction added successfully.'})
@staff_login_required
def add_ticket(request, *args, **kwargs):
context = {
}
return render(request, 'add_templates/add-ticket.html', context)

@ -0,0 +1,62 @@
{% extends "add-edit-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">
Add Ticket
</h1>
<form class="w-full flex flex-col gap-5 justify-center items-center mt-5" method="POST" action="">
{% csrf_token %}
<div class="w-full">
<label class="text-gray-500">Ticket Title:</label>
<input required name="title" type="text"
class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
</div>
<div class="w-full">
<label class="text-gray-500">What is this regarding?</label>
<select class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-1">
<option value="">General Accounting</option>
</select>
</div>
<div class="w-full">
<label class="text-gray-500">Desceription:</label>
<textarea required name="description"
class="w-full py-1 px-3 border border-gray-300 outline-none rounded-md mt-1 resize-none"
rows="8"></textarea>
</div>
<div class="w-full">
<label class="text-gray-500">Attach Files:</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="" type="file" class="file-input" hidden multiple />
<span class="file-name text-gray-500 text-base focus:outline-none outline-none">Upload
Document(s)</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 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>
</div>
</form>
</div>
</div>
<!-------------- JS SCRIPTS --------------->
<script type="text/javascript" src='{% static "js/upload-input-tag.js" %}'></script>
{% endblock %}

@ -59,37 +59,32 @@
<!-- TICKETS -->
<div class="w-full h-fit bg-white rounded-md shadow-md p-5">
<h1 class="text-secondosiblue text-[25px]">Tickets</h1>
<div class="overflow-x-auto border border-gray-300 rounded-md mt-3">
<div class="overflow-x-auto border border-gray-300 rounded-md">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Client
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Last Update
Subject
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Last Reply
Ticket ID
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Subject
Regarding
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Department
Date Created
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Status
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 border-r border-gray-300 uppercase whitespace-nowrap">
Last Updated
</th>
<th scope="col" class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
Actions
Updated By
</th>
</tr>
</thead>
@ -98,40 +93,29 @@
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Emile Elliye</p>
<a href="{% url 'innercustomerticket' %}">
<p class="text-secondosiblue cursor-pointer hover:text-gray-500 duration-300">My Account Balance</p>
</a>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-1-2024</p>
<p class="text-secondosiblue">22666766</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-2024</p>
<p class="text-secondosiblue">Django</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Add Customer Template</p>
<p class="text-secondosiblue">20-2-2024</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Informatique</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300 bg-green-700">
<p class="text-white">Closed</p>
<p class="text-secondosiblue">20-2-2024</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<a href="">
<div class="text-[15px] text-blue-500 cursor-pointer">
<i class="fa fa-edit"></i>
</div>
</a>
<div class="text-[15px] text-red-500 cursor-pointer">
<i class="fa fa-trash"></i>
</div>
</div>
<p class="text-secondosiblue">Ositcom Ltd</p>
</td>
</tr>
</tbody>
@ -197,6 +181,64 @@
</table>
</div>
</div>
<div class="w-full h-fit bg-white rounded-md shadow-md p-5">
<h1 class="text-secondosiblue text-[25px]">Other Ways to Get Help</h1>
<div class="w-full grid grid-cols-1 s:grid-cols-2 gap-5 mt-5">
<div class="flex flex-col gap-3 justify-center items-center bg-gray-50 border border-gray-100 shadow-md rounded-md px-5 py-10">
<div class="w-[70px] h-[70px] rounded-full bg-white border border-gray-100 flex justify-center items-center p-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m6.75 12H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
</svg>
</div>
<p class="font-poppinsBold text-secondosiblue text-center text-xl">Guides & Tutorials</p>
<p class="text-gray-500 font-light text-center">View Osina guides and tutorials for all experience levels.</p>
</div>
<div class="flex flex-col gap-3 justify-center items-center bg-gray-50 border border-gray-100 shadow-md rounded-md px-5 py-10">
<div class="w-[70px] h-[70px] rounded-full bg-white border border-gray-100 flex justify-center items-center p-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />
</svg>
</div>
<p class="font-poppinsBold text-secondosiblue text-center text-xl">Community Q&A</p>
<p class="text-gray-500 font-light text-center">Ask questions, find answers, and connect with other members of the Ositcom community.</p>
</div>
<div class="flex flex-col gap-3 justify-center items-center bg-gray-50 border border-gray-100 shadow-md rounded-md px-5 py-10">
<div class="w-[70px] h-[70px] rounded-full bg-white border border-gray-100 flex justify-center items-center p-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="M7.5 14.25v2.25m3-4.5v4.5m3-6.75v6.75m3-9v9M6 20.25h12A2.25 2.25 0 0 0 20.25 18V6A2.25 2.25 0 0 0 18 3.75H6A2.25 2.25 0 0 0 3.75 6v12A2.25 2.25 0 0 0 6 20.25Z" />
</svg>
</div>
<p class="font-poppinsBold text-secondosiblue text-center text-xl">Ositcom Status Page</p>
<p class="text-gray-500 font-light text-center">Get Updates on Ositcom incidents and maintenance.</p>
</div>
<div class="flex flex-col gap-3 justify-center items-center bg-gray-50 border border-gray-100 shadow-md rounded-md px-5 py-10">
<div class="w-[70px] h-[70px] rounded-full bg-white border border-gray-100 flex justify-center items-center p-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 9v.906a2.25 2.25 0 0 1-1.183 1.981l-6.478 3.488M2.25 9v.906a2.25 2.25 0 0 0 1.183 1.981l6.478 3.488m8.839 2.51-4.66-2.51m0 0-1.023-.55a2.25 2.25 0 0 0-2.134 0l-1.022.55m0 0-4.661 2.51m16.5 1.615a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V8.844a2.25 2.25 0 0 1 1.183-1.981l7.5-4.039a2.25 2.25 0 0 1 2.134 0l7.5 4.039a2.25 2.25 0 0 1 1.183 1.98V19.5Z" />
</svg>
</div>
<p class="font-poppinsBold text-secondosiblue text-center text-xl">Customer Support</p>
<p class="text-gray-500 font-light text-center">View or open Ositcom Support tickets.</p>
</div>
</div>
</div>
</div>

@ -50,12 +50,14 @@
<p class="">Projects</p>
</div>
<div class="w-full flex justify-start items-center gap-3 border-b border-slate-600 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[25px] text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 0 1 0 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 0 1 0-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375Z" />
</svg>
<p>Tickets</p>
</div>
<a href="{% url 'customertickets' %}" class="w-full">
<div class="w-full flex justify-start items-center gap-3 border-b border-slate-600 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[25px] text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 0 1 0 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 0 1 0-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375Z" />
</svg>
<p>Tickets</p>
</div>
</a>
<a href="{% url 'customerorders' %}" class="w-full">
<div class="w-full flex justify-start items-center gap-3 border-b border-slate-600 py-3 text-white">
@ -208,17 +210,18 @@
</div>
<div class="w-full">
<div class="w-full flex justify-between items-center border-b border-slate-600 py-3">
<div class="w-full flex justify-start items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[25px] text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 0 1 0 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 0 1 0-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375Z" />
</svg>
<p class="text-white">Tickets</p>
<a href="{% url 'customertickets' %}" class="w-full">
<div class="w-full">
<div class="w-full flex justify-between items-center border-b border-slate-600 py-3">
<div class="w-full flex justify-start items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-[25px] text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 0 1 0 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 0 1 0-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375Z" />
</svg>
<p class="text-white">Tickets</p>
</div>
</div>
</div>
</div>
</a>
<div class="w-full">

@ -86,13 +86,13 @@
<div class="w-full flex flex-col gap-5 mt-5">
<div>
<p class="text-gray-500 text-xl">Client: <span
class="text-slate-800 text-xl font-semibold">{{project.customer.user.first_name}}
class="text-secondosiblue text-xl font-semibold">{{project.customer.user.first_name}}
{{project.customer.user.last_name}}</span></p>
</div>
<div>
<p class="text-gray-500 text-xl">Project Manager: <span
class="text-slate-800 text-xl font-semibold">{{project.manager.user.first_name}}
class="text-secondosiblue text-xl font-semibold">{{project.manager.user.first_name}}
{{project.manager.last_name}}</span></p>
</div>
@ -100,7 +100,7 @@
<div>
<p class="text-gray-500 text-xl">Member(s):
{% for member in project.members.all %}
<span class="text-slate-800 text-xl font-semibold">
<span class="text-secondosiblue text-xl font-semibold">
{{member.user.first_name}} {{member.user.last_name}} {% if not forloop.last %}, {% endif %}
{% endfor %}</span>
</p>
@ -109,7 +109,7 @@
<div>
<p class="text-gray-500 text-xl">Type:
{% for type in project.project_type.all %}
<span class="text-slate-800 text-xl font-semibold">
<span class="text-secondosiblue text-xl font-semibold">
{{type.name}} {% if not forloop.last %}, {% endif %}
{% endfor %}</span>
</p>
@ -134,12 +134,12 @@
<div>
<p class="text-gray-500 text-xl">Start Date: <span
class="text-slate-800 text-xl font-semibold startDate">{{project.start_date}}</span></p>
class="text-secondosiblue text-xl font-semibold startDate">{{project.start_date}}</span></p>
</div>
<div>
<p class="text-gray-500 text-xl">End Date: <span
class="text-slate-800 text-xl font-semibold endDate">{{project.end_date}}</span></p>
class="text-secondosiblue text-xl font-semibold endDate">{{project.end_date}}</span></p>
</div>
<!-- PROJECT DETAILS -->
@ -147,7 +147,7 @@
<div>
<p class="text-gray-500 text-xl">Project Details:</p>
<div class="w-full pr-8">
<p class="text-slate-800 font-semibold">
<p class="text-secondosiblue font-semibold">
{{project.details}}
</p>
</div>
@ -215,7 +215,7 @@
{% for requirement in project.projectrequirement_set.all %}
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">{{requirement.content}}</p>
<p class="text-secondosiblue">{{requirement.content}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
@ -226,7 +226,7 @@
class="fas fa-angle-double-right"></i></a>
{% endfor %}
{%else%}
<p class="text-slate-800">None</p>
<p class="text-secondosiblue">None</p>
{% endif %}
</td>
@ -255,7 +255,7 @@
{% endfor %}
{% else %}
<tr>
<td colspan="3" class="px-6 py-4 text-center text-sm text-slate-800">
<td colspan="3" class="px-6 py-4 text-center text-sm text-secondosiblue">
No Requirements at the moment
</td>
</tr>
@ -308,21 +308,21 @@
{% for credential in project.projectcredential_set.all %}
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">{{credential.emailorusername}}</p>
<p class="text-secondosiblue">{{credential.emailorusername}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<a class="text-slate-800">{{credential.password}}</a>
<a class="text-secondosiblue">{{credential.password}}</a>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<a class="text-slate-800">{{credential.usedfor}}</a>
<a class="text-secondosiblue">{{credential.usedfor}}</a>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3" class="px-6 py-4 text-center text-sm text-slate-800">
<td colspan="3" class="px-6 py-4 text-center text-sm text-secondosiblue">
No Available Credentials
</td>
</tr>
@ -375,21 +375,21 @@
{% for file in project.projectfile_set.all %}
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-slate-800">{{file.name}}</p>
<p class="text-secondosiblue">{{file.name}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<a class="text-slate-800">{{file.file}}</a>
<a class="text-secondosiblue">{{file.file}}</a>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<a class="text-slate-800">{{file.date}}</a>
<a class="text-secondosiblue">{{file.date}}</a>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3" class="px-6 py-4 text-center text-sm text-slate-800">
<td colspan="3" class="px-6 py-4 text-center text-sm text-secondosiblue">
No Available Files
</td>
</tr>

@ -0,0 +1,179 @@
{% extends "main.html" %}
{%load static%}
{% block content %}
<div class="w-full xxlg1:w-[75%] bg-white h-fit rounded-md shadow-md p-5">
<div class="w-full h-fit flex flex-col gap-2 bg-gray-100 shadow-md rounded-md px-3 py-3">
<p class="text-secondosiblue text-xl">Ticket: <span class="font-semibold">#2226663535</span></p>
<div class="flex justify-start items-center gap-1">
<div class="w-[16px] h-[16px] rounded-full bg-red-200 border border-red-500 shadow-md"></div>
<p class="text-secondosiblue font-light">Closed by Linode at 20-4-24 16:30</p>
</div>
</div>
<div class="w-full flex flex-col gap-8 mt-5 s:mt-10">
<!-- REPLY 1 -->
<div class="flex gap-3">
<div>
<div class="w-[45px] s:w-[60px] h-[45px] s:h-[60px] rounded-full shadow-md border border-gray-100">
<img src="{% static 'images/ositcom_logos/full-logo.png' %}"
class="w-full h-full rounded-full object-cover">
</div>
</div>
<div class="w-full replyContainer shadow-md">
<div
class="w-full bg-gray-100 flex justify-between items-center gap-3 px-3 py-3 cursor-pointer rounded-t-md toggleReply">
<p class="text-secondosiblue font-light text-sm s:text-base"><span class="font-semibold">Ositcom
Ltd</span>
commented 2024-04-17 12:19</p>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowUp">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowDown hidden">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</div>
<div class="w-full bg-white p-5 flex flex-col gap-3 reply">
<p class="text-gray-500 font-light leading-8 text-[15px]">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non purus consectetur
magna sodales fringilla. Suspendisse non imperdiet metus. Curabitur feugiat tristique
varius. Curabitur fermentum sapien nisi, sed suscipit odio luctus sed. Mauris pretium risus
a tincidunt facilisis. Aliquam quis odio in mi aliquet scelerisque et ut urna. Ut ultrices
turpis odio, id hendrerit lectus dignissim in. Donec at tortor quis dui auctor sodales porta
et purus. Aliquam at nunc sit amet tortor lacinia porttitor. Proin auctor, eros ac
sollicitudin iaculis, felis quam vulputate ante, eu varius dolor arcu non enim. Vestibulum
ornare dapibus risus, id eleifend ipsum. Aliquam metus urna, bibendum quis cursus vitae,
placerat sit amet felis. Aliquam tellus ex, pretium id gravida id, vulputate et velit.
Phasellus leo felis, lobortis ut dolor eget, viverra aliquet ligula. Aliquam molestie ac
eros et fermentum.
</p>
</div>
</div>
</div>
<!-- CUSTOMER SUPPORT REPLY 2 -->
<div class="flex gap-3">
<div>
<div class="w-[45px] s:w-[60px] h-[45px] s:h-[60px] rounded-full shadow-md border border-gray-100">
<img src="{% static 'images/netcommerce-logo.png' %}"
class="w-full h-full rounded-full object-cover">
</div>
</div>
<div class="w-full replyContainer shadow-md">
<div
class="w-full bg-gray-100 flex justify-between items-center gap-3 px-3 py-3 cursor-pointer rounded-t-md toggleReply">
<p class="text-secondosiblue font-light text-sm s:text-base"><span
class="font-semibold">Scott</span>
Customer Support commented 2024-04-17 12:19</p>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowUp">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-4 h-4 text-secondosiblue arrowDown hidden">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</div>
<div class="w-full bg-white flex flex-col gap-5 p-5 reply">
<p class="text-gray-500 font-light leading-8 text-[15px]">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus non purus consectetur
magna sodales fringilla. Suspendisse non imperdiet metus. Curabitur feugiat tristique
varius. Curabitur fermentum sapien nisi, sed suscipit odio luctus sed. Mauris pretium risus
a tincidunt facilisis. Aliquam quis odio in mi aliquet scelerisque et ut urna. Ut ultrices
turpis odio, id hendrerit lectus dignissim in. Donec at tortor quis dui auctor sodales porta
et purus.
</p>
<div class="w-full border-t border-gray-200 pt-5 flex justify-start items-center gap-3">
<a class="text-secondosiblue font-light cursor-pointer hover:text-gray-500 duration-300">How
did I do?</a>
<div class="flex justify-start items-center gap-2">
<div class="w-fit h-fit rounded-full border-4 border-secondosiblue">
<img src="{% static 'images/icons/happy-icon.png' %}"
class="w-[30px] h-[30px] rounded-full cursor-pointer hover:scale-105 duration-300 transition-transform">
</div>
<div class="w-fit h-fit rounded-full">
<img src="{% static 'images/icons/neutral-icon.png' %}"
class="w-[30px] h-[30px] rounded-full cursor-pointer hover:scale-105 duration-300 transition-transform">
</div>
<div class="w-fit h-fit rounded-full">
<img src="{% static 'images/icons/unhappy-icon.png' %}"
class="w-[30px] h-[30px] rounded-full cursor-pointer hover:scale-105 duration-300 transition-transform">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- REPLYING SECTION -->
<div class="flex gap-3">
<div>
<div class="w-[45px] s:w-[60px] h-[45px] s:h-[60px] rounded-full shadow-md border border-gray-100">
<img src="{% static 'images/ositcom_logos/full-logo.png' %}"
class="w-full h-full rounded-full object-cover">
</div>
</div>
<div class="w-full flex flex-col gap-3">
<textarea
class="w-full bg-white px-3 py-3 border border-gray-200 rounded-md outline-none text-gray-500 resize-none"
rows="8" placeholder="Reply to Ositcom Ltd..."></textarea>
<div class="w-full flex flex-col s:flex-row justify-end items-center gap-3">
<div
class="w-full s:w-[50px] h-[50px] rounded-md bg-gray-50 shadow-md border border-gray-100 flex justify-center items-center p-2 cursor-pointer relative hover:scale-105 duration-300 transition-transform">
<input type="file" name="file" id="fileInput" class="opacity-0">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5 h-5 text-secondosiblue z-10 absolute pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round"
d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />
</svg>
</div>
<button
class="w-full s:w-fit bg-secondosiblue border border-secondosiblue text-gray-200 rounded-md cursor-pointer hover:bg-white hover:text-secondosiblue duration-300 px-9 py-3">
Send as Note
</button>
<button
class="w-full s:w-fit bg-gray-100 border border-secondosiblue text-secondosiblue hover:bg-secondosiblue hover:text-gray-200 rounded-md cursor-pointer duration-300 px-9 py-3">
Send as Reply
</button>
</div>
</div>
</div>
</div>
</div>
<!---------------------- JS SCRIPTS -------------------->
<script type="text/javascript" src="{% static 'js/customer_dashboard/ticket-details.js' %}"></script>
{% endblock %}

@ -0,0 +1,134 @@
{% extends "main.html" %}
{%load static%}
{% block content %}
<div class="w-full xxlg1:w-[75%]">
<div class="w-full h-fit bg-white rounded-md shadow-md p-5">
<h1 class="text-secondosiblue text-[25px]">Tags</h1>
<!-- FILTERING -->
<div
class="w-full py-4 px-3 bg-gray-200 rounded-md shadow-md mt-4 flex flex-col s:flex-row gap-3 justify-between items-center">
<div class="w-full s:w-fit flex justify-start items-center gap-5">
<div class="relative h-fit w-full s:w-fit flex items-center">
<input type="text" placeholder="Enter Ticket"
class="py-2 px-3 border border-gray-300 rounded-md outline-none w-full s:w-[300px] h-[40px] relative">
<button
class="text-gray-500 text-xl outline-none border-none cursor-pointer absolute right-2 bg-white">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<div class="w-full s:w-fit">
<a href="{% url 'addticket' %}">
<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"
data-modal-url="">Open
Ticket</button>
</a>
</div>
</div>
<div class="w-full flex flex-col gap-3 mt-5">
<div class="w-full bg-gray-200 rounded-md shadow-md h-fit p-3 flex items-center justify-between gap-5">
<div class="flex items-center gap-5 text-[17px]">
<p class="text-secondosiblue font-semibold cursor-pointer">Open Ticktes</p>
<p class="text-gray-500 cursor-pointer">Closed Ticktes</p>
</div>
</div>
<div class="overflow-x-auto border border-gray-300 rounded-md">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Subject
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Ticket ID
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Regarding
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Date Created
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 border-r border-gray-300 uppercase whitespace-nowrap">
Last Updated
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 border-r border-gray-300 uppercase whitespace-nowrap">
Updated By
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
Actions
</th>
</tr>
</thead>
<!-- TABLE BODY -->
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">My
Account Balance</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">22666766</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Django</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-2024</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-2024</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Ositcom Ltd</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<a href="{% url 'ticketdetails' %}">
<div class="text-[15px] text-blue-500 cursor-pointer">
<i class="fa fa-eye"></i>
</div>
</a>
<a href="">
<div class="text-[15px] text-blue-500 cursor-pointer">
<i class="fa fa-edit"></i>
</div>
</a>
<div class="text-[15px] text-red-500 cursor-pointer">
<i class="fa fa-trash"></i>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %}

@ -163,7 +163,7 @@
</div>
</a>
<a>
<a href="{% url 'tickets' %}">
<div
class="w-full flex justify-start items-center gap-3 text-white border-b border-slate-600 py-2">
<p class="text-white">Tickets</p>
@ -452,7 +452,7 @@
</div>
</a>
<a>
<a href="{% url 'tickets' %}">
<div
class="w-full flex justify-start items-center gap-3 text-white border-b border-slate-600 py-2">
<p class="text-white">My Tickets</p>
@ -637,35 +637,51 @@
</div>
</div>
<div class="relative">
<div class="w-fit flex justify-between items-center gap-2 cursor-pointer hover:bg-gray-50 rounded-md hover:p-2 duration-300"
id="userProfile">
<div>
<div class="w-[40px] s:w-[45px] h-[40px] s:h-[45px] rounded-full shadow-md">
<img src='{{request.user.staffprofile.image.url}}' alt="user-image"
class="w-full h-full object-cover rounded-full">
</div>
</div>
<div class="flex justify-center items-center gap-2 text-gray-500">
<p>{{request.user.first_name}} {{request.user.last_name}}</p>
<i class="fa fa-angle-down" id="arrowDown"></i>
<i class="fa fa-angle-up" style="display: none;" id="arrowUp"></i>
<div class="flex justify-end items-center gap-5">
<!-- NOTIFICATION -->
<div class="relative">
<div class="w-[20px] h-[20px] rounded-full bg-secondosiblue text-white flex justify-center items-center text-sm p-1 absolute top-[-5px] right-[-5px]">
<p>1</p>
</div>
<div class="w-[40px] s:w-[45px] h-[40px] s:h-[45px] rounded-full shadow-md bg-gray-50 border border-gray-100 flex justify-center items-center cursor-pointer hover:scale-105 duration-300 transition-transform">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0" />
</svg>
</div>
</div>
<!-- USER PROFILE DROPDOWN -->
<div class="w-[250px] h-fit bg-osiblue bg-opacity-70 rounded-md shadow-md px-3 absolute right-0 mt-3 flex flex-col"
style="display: none;" id="userProfileDropdown">
<a href="{% url 'signout' %}" class="w-full">
<div
class="w-full py-3 flex items-center gap-2 text-white hover:text-osiblue duration-300 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-[25px] text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M5.636 5.636a9 9 0 1 0 12.728 0M12 3v9" />
</svg>
<p>Logout</p>
<div class="relative">
<div class="w-fit flex justify-between items-center gap-2 cursor-pointer hover:bg-gray-50 rounded-md hover:p-2 duration-300"
id="userProfile">
<div>
<div class="w-[40px] s:w-[45px] h-[40px] s:h-[45px] rounded-full shadow-md">
<img src='{{request.user.staffprofile.image.url}}' alt="user-image"
class="w-full h-full object-cover rounded-full">
</div>
</div>
</a>
<div class="flex justify-center items-center gap-2 text-gray-500">
<p>{{request.user.first_name}} {{request.user.last_name}}</p>
<i class="fa fa-angle-down" id="arrowDown"></i>
<i class="fa fa-angle-up" style="display: none;" id="arrowUp"></i>
</div>
</div>
<!-- USER PROFILE DROPDOWN -->
<div class="w-[250px] h-fit bg-osiblue bg-opacity-70 rounded-md shadow-md px-3 absolute right-0 mt-3 flex flex-col"
style="display: none;" id="userProfileDropdown">
<a href="{% url 'signout' %}" class="w-full">
<div
class="w-full py-3 flex items-center gap-2 text-white hover:text-osiblue duration-300 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-[25px] text-white">
<path stroke-linecap="round" stroke-linejoin="round" d="M5.636 5.636a9 9 0 1 0 12.728 0M12 3v9" />
</svg>
<p>Logout</p>
</div>
</a>
</div>
</div>
</div>
</div>

@ -38,6 +38,7 @@ urlpatterns = [
#Listing Templates
path('customers/', views.customers, name='customers'),
path('tickets/', views.tickets, name='tickets'),
path('businesses/', views.businesses, name='businesses'),
path('staffs/', views.staffs, name='users'),
path('my-projects/', views.my_projects, name='my-projects'),
@ -53,6 +54,7 @@ urlpatterns = [
#Details Templates
path('customers/<str:customer_id>/', views.customerdetails, name='customerdetails'),
path('ticket-details/', views.ticket_details, name='ticketdetails'),
path('businesses/<str:business_id>/', views.businessdetails, name='businessdetails'),
path('staffs/<str:staff_id>/', views.staffdetails, name='userdetails'),
path('projectdetails/<str:project_id>/', views.projectdetails, name='detailed-project'),

@ -255,6 +255,16 @@ def customers(request, *args, **kwargs):
return render(request, 'listing_pages/customers.html', context)
@staff_login_required
def tickets(request, *args, **kwargs):
context = {
}
return render(request, 'listing_pages/tickets.html', context)
@staff_login_required
def businesses(request):
businesses = Business.objects.all().order_by('-business_id')
@ -439,6 +449,17 @@ def customerdetails(request, customer_id):
}
return render(request, 'details_templates/customer-details.html', context)
@staff_login_required
def ticket_details(request):
context = {
}
return render(request, 'details_templates/ticket-details.html', context)
@staff_login_required
def businessdetails(request, business_id):
business = get_object_or_404(Business, business_id=business_id)

@ -702,6 +702,10 @@ video {
right: -2.5rem;
}
.-right-2 {
right: -0.5rem;
}
.-right-40 {
right: -10rem;
}
@ -722,6 +726,10 @@ video {
top: -3rem;
}
.-top-2 {
top: -0.5rem;
}
.-top-\[54px\] {
top: -54px;
}
@ -794,6 +802,10 @@ video {
right: 1.25rem;
}
.right-\[-5px\] {
right: -5px;
}
.top-0 {
top: 0px;
}
@ -822,6 +834,10 @@ video {
top: 1.25rem;
}
.top-\[-5px\] {
top: -5px;
}
.top-\[14px\] {
top: 14px;
}
@ -1076,6 +1092,14 @@ video {
height: 150px;
}
.h-\[16px\] {
height: 16px;
}
.h-\[20px\] {
height: 20px;
}
.h-\[210px\] {
height: 210px;
}
@ -1174,6 +1198,10 @@ video {
max-height: 50px;
}
.min-h-\[200px\] {
min-height: 200px;
}
.w-1 {
width: 0.25rem;
}
@ -1182,6 +1210,10 @@ video {
width: 2.5rem;
}
.w-14 {
width: 3.5rem;
}
.w-4 {
width: 1rem;
}
@ -1226,6 +1258,10 @@ video {
width: 150px;
}
.w-\[16px\] {
width: 16px;
}
.w-\[180px\] {
width: 180px;
}
@ -1330,6 +1366,10 @@ video {
width: 85%;
}
.w-\[90\%\] {
width: 90%;
}
.w-\[95\%\] {
width: 95%;
}
@ -1439,6 +1479,16 @@ video {
animation: bounceX 4s infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
.cursor-default {
cursor: default;
}
@ -1695,6 +1745,10 @@ video {
border-bottom-left-radius: 0.375rem;
}
.rounded-bl-none {
border-bottom-left-radius: 0px;
}
.rounded-bl-xl {
border-bottom-left-radius: 0.75rem;
}
@ -1711,6 +1765,10 @@ video {
border-top-left-radius: 0.375rem;
}
.rounded-tl-none {
border-top-left-radius: 0px;
}
.rounded-tr-md {
border-top-right-radius: 0.375rem;
}
@ -2301,6 +2359,14 @@ video {
--tw-gradient-to: #fff var(--tw-gradient-to-position);
}
.fill-osiblue {
fill: #20336b;
}
.fill-secondosiblue {
fill: #374a7a;
}
.stroke-black {
stroke: #000;
}
@ -2483,6 +2549,10 @@ video {
padding-top: 0.75rem;
}
.pt-5 {
padding-top: 1.25rem;
}
.pt-9 {
padding-top: 2.25rem;
}
@ -2606,6 +2676,10 @@ video {
text-transform: uppercase;
}
.leading-7 {
line-height: 1.75rem;
}
.leading-8 {
line-height: 2rem;
}
@ -3156,6 +3230,11 @@ video {
color: rgb(146 156 183 / var(--tw-text-opacity));
}
.hover\:text-gray-200:hover {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity));
}
.hover\:text-gray-500:hover {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity));
@ -3206,7 +3285,18 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
@media (prefers-color-scheme: dark) {
.dark\:text-gray-600 {
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity));
}
}
@media (min-width: 650px) {
.s\:mt-10 {
margin-top: 2.5rem;
}
.s\:mt-5 {
margin-top: 1.25rem;
}
@ -3235,6 +3325,10 @@ video {
height: 55px;
}
.s\:h-\[60px\] {
height: 60px;
}
.s\:h-\[90px\] {
height: 90px;
}
@ -3267,10 +3361,22 @@ video {
width: 500px;
}
.s\:w-\[50px\] {
width: 50px;
}
.s\:w-\[550px\] {
width: 550px;
}
.s\:w-\[60px\] {
width: 60px;
}
.s\:w-\[85\%\] {
width: 85%;
}
.s\:w-\[90px\] {
width: 90px;
}
@ -3585,6 +3691,10 @@ video {
height: 500px;
}
.xxlg1\:h-full {
height: 100%;
}
.xxlg1\:w-\[74\.5\%\] {
width: 74.5%;
}
@ -3604,6 +3714,24 @@ video {
.xxlg1\:grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.xxlg1\:rounded-l-md {
border-top-left-radius: 0.375rem;
border-bottom-left-radius: 0.375rem;
}
.xxlg1\:rounded-r-md {
border-top-right-radius: 0.375rem;
border-bottom-right-radius: 0.375rem;
}
.xxlg1\:rounded-bl-none {
border-bottom-left-radius: 0px;
}
.xxlg1\:rounded-tr-none {
border-top-right-radius: 0px;
}
}
@media (min-width: 1390px) {
@ -3640,6 +3768,10 @@ video {
width: 550px;
}
.xll\:w-\[75\%\] {
width: 75%;
}
.xll\:grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 920 B

@ -0,0 +1,63 @@
const paymentContent = document.getElementById('paymentContent');
const paymentLoader = document.getElementById('paymentLoader');
const invoice_id = document.getElementById('invoiceId').textContent;
function initiateInvoiceCheckout(invoice_id) {
const csrftoken = getCookie('csrftoken');
console.log(invoice_id);
console.log('CSRF Token:', csrftoken);
paymentLoader.classList.remove('hidden');
fetch('/initiate_invoice_checkout/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({ invoice_id: invoice_id }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log("Session ID: " + data.session_id);
// Update Checkout session with the fetched session ID and show the embedded page
Checkout.configure({
session: {
id: data.session_id,
}
});
$('#paymentContent').empty();
Checkout.showEmbeddedPage('#paymentContent');
sessionStorage.clear();
paymentLoader.classList.add('hidden');
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
paymentLoader.classList.add('hidden');
});
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
initiateInvoiceCheckout(invoice_id);

@ -0,0 +1,13 @@
// TO CHANGE THE PRICE BASED ON THE CHOSEN CYCLE FROM THE SELECT TAG
function updateCyclePrice() {
var selectedOption = document.getElementById('cycle').options[document.getElementById('cycle').selectedIndex];
var cyclePrice = parseFloat(selectedOption.getAttribute('data-cycle-price'));
document.getElementById('cyclePrice').textContent = cyclePrice.toFixed(2);
}
document.getElementById('cycle').addEventListener('change', updateCyclePrice);
// Trigger the change event when the page loads to display the cycle price of the selected option by default
window.addEventListener('load', function () {
updateCyclePrice();
});

@ -1,4 +1,5 @@
const paymentContent = document.getElementById('paymentContent');
const paymentLoader = document.getElementById('paymentLoader');
const item_id = document.getElementById('itemId').textContent;
function initiateCheckout(item_id, selectedCycleId) {
@ -8,13 +9,15 @@ function initiateCheckout(item_id, selectedCycleId) {
console.log('CSRF Token:', csrftoken);
paymentLoader.classList.remove('hidden');
fetch('/initiate_checkout/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({ item_id: item_id, cycle_id: selectedCycleId }), // Include selected cycle ID in the request body
body: JSON.stringify({ item_id: item_id, cycle_id: selectedCycleId }),
})
.then(response => {
if (!response.ok) {
@ -23,7 +26,6 @@ function initiateCheckout(item_id, selectedCycleId) {
return response.json();
})
.then(data => {
// Handle success response
console.log("Session ID: " + data.session_id);
// Update Checkout session with the fetched session ID and show the embedded page
Checkout.configure({
@ -34,9 +36,13 @@ function initiateCheckout(item_id, selectedCycleId) {
$('#paymentContent').empty();
Checkout.showEmbeddedPage('#paymentContent');
sessionStorage.clear();
paymentLoader.classList.add('hidden');
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
paymentLoader.classList.add('hidden');
});
}

@ -0,0 +1,28 @@
document.addEventListener("DOMContentLoaded", function () {
const toggleButtons = document.querySelectorAll('.toggleReply');
toggleButtons.forEach(button => {
button.addEventListener('click', function () {
const replyContainer = this.closest('.replyContainer');
const reply = replyContainer.querySelector('.reply');
const arrowUp = replyContainer.querySelector('.arrowUp');
const arrowDown = replyContainer.querySelector('.arrowDown');
reply.classList.toggle('hidden');
if (reply.classList.contains('hidden')) {
arrowUp.classList.add('hidden');
arrowDown.classList.remove('hidden');
} else {
arrowUp.classList.remove('hidden');
arrowDown.classList.add('hidden');
}
if (!reply.classList.contains('hidden')) {
replyContainer.classList.add('shadow-md');
} else {
replyContainer.classList.remove('shadow-md');
}
});
});
});
Loading…
Cancel
Save