From 19fb9af18d2d2bc1197ee10a92ab2d27c84622d5 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 16 Feb 2026 13:17:54 +0000 Subject: [PATCH] Autosave: 20260216-131754 --- config/__pycache__/settings.cpython-311.pyc | Bin 5552 -> 5631 bytes config/__pycache__/urls.cpython-311.pyc | Bin 1557 -> 1660 bytes config/settings.py | 3 + config/urls.py | 3 +- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 1145 bytes core/__pycache__/forms.cpython-311.pyc | Bin 0 -> 1926 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 3218 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 559 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 4122 bytes core/admin.py | 12 +- core/forms.py | 21 ++ core/migrations/0001_initial.py | 48 ++++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 3207 bytes core/models.py | 51 +++- core/templates/base.html | 92 ++++++-- core/templates/core/index.html | 221 +++++++----------- core/templates/core/ticket_detail.html | 108 +++++++++ core/templates/core/ticket_form.html | 34 +++ core/templates/registration/login.html | 41 ++++ core/urls.py | 9 +- core/views.py | 90 +++++-- static/css/custom.css | 87 ++++++- 22 files changed, 628 insertions(+), 192 deletions(-) create mode 100644 core/__pycache__/forms.cpython-311.pyc create mode 100644 core/forms.py create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/templates/core/ticket_detail.html create mode 100644 core/templates/core/ticket_form.html create mode 100644 core/templates/registration/login.html diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce5584823cd4ebfccfc40c2b36df8beaee7db..8ccc282c91e5c3c1c7f78455ad959246bd73b9d6 100644 GIT binary patch delta 178 zcmdm>{a>4RIWI340}vGbnv~fxkyn!O&PMesEW9pJ`YEna1}V(J44Q76Sf_G{+~Q10 zEY3*EPb^Bg#hR0!o|&gHtPrvveR~OG9SLcxU&>){%!ayVnZ+N7DqLU?x*;Zefk7C8z}f&= C9W>$q delta 100 zcmeyby+NCIIWI340}xbw%g=O~$ScWsWuy8P7FOn922GdE9IR8hm^Ae_Z{+7^QYqpA rDk~BM5&S^n7l%!5eoARhs$EeUkjn_f#rHPz3f*SrzQ7;^L|~-=AF&vJ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94ece283a83ff1af1d71f1b265c943eb37a..ea61c966decd7416cbea3399cbda60dca7ed28b9 100644 GIT binary patch delta 258 zcmbQr^M^-$IWI340}$l@nv|K&!octt#DM`0DC4uyMD>0iCWchj6iy(?lEO7{maHyw z6i+I97B5V3kx42@31{)y;1u0xr z+zbqBxFicD5ulxGC7L^*ka8B%~)lXr6*<9?>iPAqDSOdlC0XR+2yViVzDW#(sU M;QqihS%xhE09P6ry#N3J diff --git a/config/settings.py b/config/settings.py index 291d043..3a184a9 100644 --- a/config/settings.py +++ b/config/settings.py @@ -180,3 +180,6 @@ if EMAIL_USE_SSL: # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +LOGIN_REDIRECT_URL = 'dashboard' +LOGOUT_REDIRECT_URL = 'login' diff --git a/config/urls.py b/config/urls.py index bcfc074..fecf250 100644 --- a/config/urls.py +++ b/config/urls.py @@ -21,9 +21,10 @@ from django.conf.urls.static import static urlpatterns = [ path("admin/", admin.site.urls), + path("accounts/", include("django.contrib.auth.urls")), path("", include("core.urls")), ] if settings.DEBUG: urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") - urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392d6714413db63120e4233d2e96cbadb5de..8463b1e2e9b5ec38fecf943a9012130c89bf71f2 100644 GIT binary patch literal 1145 zcma)5OHUL*5bo}I?640}9s(MTKs-z$>_u+I#CY(4aM9CT#$mdJhIy<#J<+}GfgeD; z@DDJCpJCz|5)PYAOh`O&TLKq3*)_uukUiKv^G$VE)mPP3J>OcbI?`kI&sY8nBlH^< z)vzyxv!7bnMHEpSp%{A@BTA?dk=XEz*z`<{2x55CsvMcIr@8j^TMmNWAZl(SYH6#A z73~??M!)6Q)1UonfxOy3jOGwVTQk=Fo6(`pJLHa>KnxcvE1)q?P9R5@DEmDRx0qD5 z*J&KHM21(HXrVgC*#o`UMGSeEB9Bn)8I*V?H9U)&n%h#1lI9gqyER2PRhHy3V#>~B zAoEN)9l=wb@VRG><@T`u?Xph%PnFh-cELJnKY3S2c>&M;=KgR4ZeF2siwXoJBPI zj?Q!pbg|IhNMqK{*YZT>ZT5wQxlBd-b1Js7P7tzomW-*8bTdfS)5S1N zq~L1;uC%gsA6S$L_$LHhdF2SUu6v*hUS9!Sk$qXWBJ#~_E}R!-Ctr#=?G0Bj`=McA zV2u0d$-&L1kLC}CJ;!*oH@W?I$3DbUM|f&L47@Nvw_)e$(b(K6D9!;+4Me7|?CXf! jEm&%YSno~`2*Gm$bQ^Y-j>hLtL2(WMEHk(5i|YLa+>s3c literal 212 zcmZ3^%ge<81k-=yXW9el#~=<2FhLogg@BCd3@HpLj5!Rsj8Tk?3@J>(44TX@K?*b( zZ?Pt(n;80F)6nZ2$lO diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..44ec54c2e5b767c84a2a571fd7ba0e753cf00d0b GIT binary patch literal 1926 zcmbVM&2Jk;6rb5IukBP#L)@4a)TK=kR#jU)aH}Gqp;bZkfrQIS#oBl#$)>wrcXmze zoH%gE(V$4}At!_aQ90y<_!BrfQV!OfkT~ULE56hx-do!>Zd@cf9{>Di-t+r@^UH+` zDFSQp<&SQt67n}5MoS+OXB8lx5k?sGh)-=w2~(KrDZXl}zGiEbDC7ZQ+V_O%oNkT& zM-D*a3-}I}ZNyRrNG1M5D#6SZl1rZApK?^{>w)mYQ;H`=8mn&k36EsrUf}z@5|sz4 z2dE7XXCDFajBsL8MrK4#Zd=S8Z(r za`6+jb%k(aYa|zEg=zcBZ~6iF`vQHAS1e_YPLMl;L6rOIRJr6Uxg<-u^lfAq-Pi0C zOG9)s{fp!1@{f4rK)`zBMjn@G#>293tC1U2q*)biAl#@S&9W2mjX*T|Gno6^<)9LY zz}va*e$LLsiUzsMJKT9g0gp#^;@M>`2HxUXF^nv@}bl zisSQANv29AKVUTv>6udLY0dEl9D!XZbzpK&8tX3iSSYX;Wpb6*qlcAhEs`dZj^K_o zR$}EcvF)-A9)*YG3}i|Fc40H{d7-vet3-lrjvlve-D_o+kF(1s+2uD} zcar)$sSW|yP2fj-0FH_q0L4R1EZ`xF@b2hZSV+ZE*O9_zjsYth-US$k*-=a#l%Iz# z-u0$128vPV#QdRdT>p2T)5FK%%>#WOv`!8*qZ=^Jj7}S9ro*TjlOyd?+hhqCFtb1V zFLUvPNiBl55*NY9DR$h>!fK;B?0UhgUc=htf?%Sy&QzVBkv}{s7QXDWz?aZB6brxzU=oJ6e)L gAm^c(*}K-o``(y&*+ALz(7d@<=;D2E3Nv>3AIpclegFUf literal 0 HcmV?d00001 diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640edbdcec3e5c1744466c916e7acdd2763b..934d1a3f8ebadca70c2d4a850b10b547ea28ad1c 100644 GIT binary patch literal 3218 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 delta 251 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 e3 - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}Support Center{% endblock %} + + + + + + + + {% block extra_head %}{% endblock %} - - {% block content %}{% endblock %} - + - +
+ {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} + + {% block content %}{% endblock %} +
+ +
+
+

© {% now 'Y' %} Support Center. Built with Django.

+
+
+ + + + {% block extra_js %}{% endblock %} + + \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..3f8d784 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,84 @@ {% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Dashboard - Support Center{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+

Support Dashboard

+

Manage and track your support requests

-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
-{% endblock %} \ No newline at end of file + + +
+
+
+

{{ open_count }}

+ Open Tickets +
+
+
+
+

{{ pending_count }}

+ Pending +
+
+
+
+

{{ resolved_count }}

+ Resolved +
+
+
+ +
+
+
+ + + + + + + + + + + + {% for ticket in tickets %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
TicketStatusPriorityUpdatedAction
+
{{ ticket.title }}
+
#{{ ticket.id }} • {{ ticket.get_category_display }}
+
+ + {{ ticket.get_status_display }} + + + + {{ ticket.get_priority_display }} + + + {{ ticket.updated_at|timesince }} ago + + View +
+
+

No tickets found. Need help? Create a new ticket!

+ Create First Ticket +
+
+
+
+{% endblock %} diff --git a/core/templates/core/ticket_detail.html b/core/templates/core/ticket_detail.html new file mode 100644 index 0000000..a3e25ca --- /dev/null +++ b/core/templates/core/ticket_detail.html @@ -0,0 +1,108 @@ +{% extends "base.html" %} +{% block title %}Ticket #{{ ticket.id }} - Support Center{% endblock %} + +{% block content %} +
+
+ + + +
+
+
+ + {{ ticket.get_status_display }} + +

{{ ticket.title }}

+

+ Submitted by {{ ticket.created_by.username }} • + {{ ticket.created_at|date:"F j, Y, g:i a" }} +

+
+
+ #{{ ticket.id }} +
+
+ +
+ +
+

{{ ticket.description }}

+
+
+ + +

Discussion

+
+ {% for comment in ticket.comments.all %} +
+
+ + {{ comment.author.username }} + {% if comment.author.is_staff %}(Agent){% endif %} + + {{ comment.created_at|timesince }} ago +
+

{{ comment.text }}

+
+ {% empty %} +

No replies yet.

+ {% endfor %} +
+ + +
+
Add a Reply
+
+ {% csrf_token %} +
+ {{ comment_form.text }} +
+
+ +
+
+
+
+ + +
+
+
Ticket Details
+ +
+ + {{ ticket.get_priority_display }} +
+ +
+ + {{ ticket.get_category_display }} +
+ +
+ + {{ ticket.assigned_to.username|default:"Unassigned" }} +
+ + {% if user.is_staff %} +
+
Manage Status
+
+ {% csrf_token %} +
+ +
+ +
+ {% endif %} +
+
+
+{% endblock %} diff --git a/core/templates/core/ticket_form.html b/core/templates/core/ticket_form.html new file mode 100644 index 0000000..96d8e8e --- /dev/null +++ b/core/templates/core/ticket_form.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% block title %}New Ticket - Support Center{% endblock %} + +{% block content %} +
+
+ + +
+

Submit a Ticket

+

Please fill out the form below and our team will get back to you as soon as possible.

+ +
+ {% csrf_token %} + {% for field in form %} +
+ + {{ field }} + {% if field.errors %} +
{{ field.errors|first }}
+ {% endif %} +
+ {% endfor %} + +
+ +
+
+
+
+
+{% endblock %} diff --git a/core/templates/registration/login.html b/core/templates/registration/login.html new file mode 100644 index 0000000..bec6415 --- /dev/null +++ b/core/templates/registration/login.html @@ -0,0 +1,41 @@ +{% extends 'base.html' %} + +{% block title %}Login - Support Center{% endblock %} + +{% block content %} +
+
+
+
+

Welcome Back

+

Please log in to manage your support tickets.

+ +
+ {% csrf_token %} +
+ + +
+
+ + +
+ + {% if form.errors %} +
+ Your username and password didn't match. Please try again. +
+ {% endif %} + + + +
+ +
+

Don't have an account? Contact your administrator.

+
+
+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..da1ea0b 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,8 @@ from django.urls import path - -from .views import home +from . import views urlpatterns = [ - path("", home, name="home"), -] + path("", views.dashboard, name="dashboard"), + path("ticket/new/", views.ticket_create, name="ticket_create"), + path("ticket//", views.ticket_detail, name="ticket_detail"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..b1eb88b 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,71 @@ -import os -import platform - -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone - - -def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() +from django.shortcuts import render, redirect, get_object_or_404 +from django.contrib.auth.decorators import login_required +from django.contrib import messages +from .models import Ticket, Comment +from .forms import TicketForm, CommentForm +@login_required +def dashboard(request): + """User dashboard showing their tickets.""" + if request.user.is_staff: + tickets = Ticket.objects.all() + else: + tickets = Ticket.objects.filter(created_by=request.user) + context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), + 'tickets': tickets, + 'open_count': tickets.filter(status='open').count(), + 'pending_count': tickets.filter(status='pending').count(), + 'resolved_count': tickets.filter(status='resolved').count(), } - return render(request, "core/index.html", context) + return render(request, 'core/index.html', context) + +@login_required +def ticket_create(request): + """View to create a new ticket.""" + if request.method == 'POST': + form = TicketForm(request.POST) + if form.is_valid(): + ticket = form.save(commit=False) + ticket.created_by = request.user + ticket.save() + messages.success(request, "Ticket created successfully!") + return redirect('dashboard') + else: + form = TicketForm() + + return render(request, 'core/ticket_form.html', {'form': form}) + +@login_required +def ticket_detail(request, pk): + """View ticket details and handle comments.""" + ticket = get_object_or_404(Ticket, pk=pk) + + # Simple permission check + if not request.user.is_staff and ticket.created_by != request.user: + messages.error(request, "You do not have permission to view this ticket.") + return redirect('dashboard') + + if request.method == 'POST': + # Check if it's a comment or a status update + if 'status' in request.POST and request.user.is_staff: + ticket.status = request.POST.get('status') + ticket.save() + messages.success(request, f"Status updated to {ticket.get_status_display()}") + return redirect('ticket_detail', pk=pk) + + comment_form = CommentForm(request.POST) + if comment_form.is_valid(): + comment = comment_form.save(commit=False) + comment.ticket = ticket + comment.author = request.user + comment.save() + messages.success(request, "Reply added!") + return redirect('ticket_detail', pk=pk) + else: + comment_form = CommentForm() + + return render(request, 'core/ticket_detail.html', { + 'ticket': ticket, + 'comment_form': comment_form, + }) \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..9e2ea4c 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,85 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Poppins:wght@500;600;700&display=swap'); + +:root { + --primary-color: #0984E3; + --success-color: #00B894; + --warning-color: #FDCB6E; + --danger-color: #D63031; + --bg-color: #F9FAFB; + --card-bg: rgba(255, 255, 255, 0.95); + --text-main: #2D3436; + --text-muted: #636E72; } + +body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-color); + color: var(--text-main); + line-height: 1.6; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Poppins', sans-serif; + font-weight: 600; +} + +.navbar { + background: var(--card-bg); + backdrop-filter: blur(10px); + border-bottom: 1px solid rgba(0,0,0,0.05); +} + +.btn-primary { + background-color: var(--primary-color); + border: none; + padding: 0.6rem 1.5rem; + border-radius: 8px; + font-weight: 500; + transition: all 0.3s ease; +} + +.btn-primary:hover { + background-color: #0873C4; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(9, 132, 227, 0.2); +} + +.card { + border: none; + border-radius: 12px; + box-shadow: 0 4px 20px rgba(0,0,0,0.03); + background: var(--card-bg); + transition: transform 0.2s ease; +} + +.card-ticket:hover { + transform: translateY(-2px); + box-shadow: 0 8px 30px rgba(0,0,0,0.06); +} + +.status-badge { + padding: 0.4rem 0.8rem; + border-radius: 50px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.status-open { background: rgba(9, 132, 227, 0.1); color: var(--primary-color); } +.status-pending { background: rgba(253, 203, 110, 0.1); color: #E17055; } +.status-resolved { background: rgba(0, 184, 148, 0.1); color: var(--success-color); } +.status-closed { background: rgba(99, 110, 114, 0.1); color: var(--text-muted); } + +.priority-high { color: var(--danger-color); font-weight: 600; } +.priority-urgent { color: #D63031; text-decoration: underline; } + +.thread-comment { + border-left: 3px solid #dfe6e9; + margin-bottom: 1.5rem; + padding-left: 1.5rem; +} + +.thread-comment.agent-reply { + border-left-color: var(--primary-color); +} \ No newline at end of file