From 5bf8837f1cc57322af9dac8ef70ce18a5d3a41fa Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 3 Feb 2026 15:57:35 +0000 Subject: [PATCH] v1 --- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 1819 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 3601 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 1294 bytes core/admin.py | 22 +- core/migrations/0001_initial.py | 56 ++++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 3126 bytes core/models.py | 41 ++- core/templates/base.html | 50 ++-- core/templates/core/index.html | 267 +++++++++--------- core/views.py | 30 +- static/css/custom.css | 83 +++++- 11 files changed, 367 insertions(+), 182 deletions(-) create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392d6714413db63120e4233d2e96cbadb5de..cb46a21f138f50f2de98bcb29d2402ecc02037d6 100644 GIT binary patch literal 1819 zcmbW1OK;Oa5XX1@%DeQHHh>6)5+n=Jh)UcL5+@F{5fVs9=3trZwsEoJuucTw6rp~A z-1-fQs-E~JtrVncPn9_J)~Y@A#EhMUHjPBpwf*-##=o5zkNq>3OA~0n3P0T63L$@R zFla`pY~QoV&dAw^axQOLrelOb!}p1glLQ*rh%Bb zHZjYx?}(W@!aSH%>JIbW`Vr>Q)THqt5TCh_iMJxy;MJzo-gC#737lRD)~mzhL1&Qq z(>WMy5l$@1h@~)UsZ6mnrouLw%*4c3xQnSvt?u|->MpbEflM}PL7ii7!Vl`rn%A~N z$8$tmCYjT=h12AwDl&irb(lz zikQSrF!}Lz=#aQGkQ8*T_-LY!_b&Q~_BZe`g=G;rDDDDbhsp$Ijf=2i>S79=m`0gF znFWzkYp&Pi!mb6v{SGhN@kU)QqAkht5W4=PRZ$Hk3?MT5&w$0T_-(vWRmi7=E|_axs#}5Xp3@ z^X6(e_(;Xf$qBaM)YpThD&$GHpM(nY(ttweUMO@J2>g8t{1*!R)ybsb>rn3S;igy7 zDtb{TyL=vy<-Px%hxAq_zgg@W z`*glX=Z_VIE+3Pt(k=C-AD-aC8On)Dl)}(HNtDTmlGvv(TR=(?DWlST-kVuON)ahV zq}(3b4=LI{&G%>?DJ7(gN>}eqE+D0ZloC?rhW10s&=(Z}SEcU@ES%x$KVL4HMuqzq DIs}H4 delta 168 zcmbQucZD%!IWI340}xFAk)LS~q#uJgFu(+5d=>&SrZc24q%h_%AZt6v;8x%nxjIjMF< c96&KfATE{#5+9fu85wUdC|tmXir9cE0HXROz5oCK diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640edbdcec3e5c1744466c916e7acdd2763b..5c3c7504c875e21e274ac2551d25121f584d2c69 100644 GIT binary patch literal 3601 zcmbtWOKclO7@oD)UOzVLI3=afR0-u3tHLQIR7F&kXw&crjjA>{$U<6eJk!MK+MCX< z+t_fhP!Bou&;wEr2q{QVg2?|*zZG?XGxzB}@H`R5oRe`2Fspe@SYukg7?D4~)`DpFCBupTiZm1r?4>QPg! z#ELPAM98~@%C`xPF=;j4nNRLV3HbrupcEA$6$dHh2~r6ml>n*a6Qq(tDg{#MCrG8J zdX?mccJKf>$&Xho%1j$-*-PbW!7ytKpiB+N;?Swguu{2Vn5E8v#ix7xy#_Sz5k`s< zCB;aDu;{AX6{OO3J$0TQtui6jMO6;o7!OC)^d zGPhP)$=Uf0rhG5?sfw|#o2rhdRnq%oz>y~a%TG~GmOu{aVa0ivELV*R!>`TEYc@`p_&YzfVpZ5wZK+muYEx{Tm0$xtb<5({?KPvs zrb-rPQ-N;tYjt1Ib=%>(-pF)LobPlX<@OMoq@6i*r|u?>?BVwFxwN0qb=+Fl{gkf5 zS~U~vs;=Lt8D=oT@$7!`!ivFX%gm&FM6?&!x+B_tnlih@%WF>As`^7ShQk)h6&8%8 zN}NFl)eVOqhI!u;egr;z6hY|%Qr}(zXzu^o>7yH`z4Xyd+fAQnrB8V26U~|S$nm?c zcq7NRo^eO=t&zMpl5ftnvoGI0>}6kmFzsf~w6bTs?3v~VyRsB}ZkO~!us!Y^;#(3r zu;e9utiB@K<?d1IkFc;pSpqYkvnWAav0fS>;PGN?ITg%e+ zP|toiGrFpF*QWBe7M@caVj9idCig+)hpreYX6P_5f0$;0`6GUO5vayEM_b{jpq*0y z3ytLaGZXW*$`a$bC`VrT@mjTfqsDyoCgV$%%><`*o`Io;dU?gFvaWnY$n#flF`T)B z_ixB2^CwT{qJe4A@^aa+eT@cQL0>b0>$ab|*>xEsjZC1Se76H{ zY$MH^?B4;NX4vZ3#;m7~ZABhT|8m_`ue8)Fo_eKuv7H&;xanoa zw@&>u?`Gy&nK>^r*L<%%I(fI?jZQu||H}=xu#C@&h0of}*2*n!>I=)>X8`}% zgX~8vrihpo_6-o6!JfN53c@{j7@*E$aSx&uSZ?30wlF0W z3NX!y!ru*VP>L89qO0gZMPcayq)~+oTA(NcNTUhTWICi#(4Bl}E&H-*E!*G>lU7xS z#Em(OzXeP9N&GW(9OP%9y}-eJhW#)e5Z^s?8DT&CC8V>E`5?hWS>2C(Uy`q)fftTW zyfy)0K!(ha`3krh%)5lM8tedt`-KyCIhTW#?PCCt=!_ixBIjn_fM-+wM)f9M4;pUb zjgEU99z;k#iRnu~zzeXDpPGdvtGryDV|9_P_{xQMu3mU&<|3bgVg5G4iwI{CaBn|W zwH#&-0^-VXyZuH@lEBy=^xLzmkX}8*wPj~Z4r2SK;ILt zHrvu>J#7}cJ6?2i+Epi8>ZGSmHZLN5r_pisLg2^nG?)k`>8ep(w(@i-$oCF++L&bK zAB(**$oonsIE(n;$1Y)hA7pbv7s4FHUBhwV@5I?4#XQF^!7|7N`!9gqs3b{kGUkS# zHko$APn#Td!_Tf9mmtsUhmC7@%!k(44TX@K?*b( zZ?Wa(r=;c-`)M-W;!Md(%uCPLOGzqX21>4E_zY6>OHV%|KQ~psG^sSNq*On(A~m_R zB)>?%JijQrxF9h(RX;huC{-U~j9x+IFAf_ZyEG@&u80Guoe_wOWr4&8W=2NF8w@fR Ku%RM0pb7xLi8T)Z diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd69370b38a98d8b01bf8eb9817c42f16ed6..26ee8f4fdda73b89ffac2ed04871e384ee4c2ada 100644 GIT binary patch literal 1294 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 Aod5s; literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 71a8362..524f06e 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,42 @@ from django.db import models +from django.core.validators import MinValueValidator +from decimal import Decimal -# Create your models here. +class Project(models.Model): + name = models.CharField(max_length=200) + description = models.TextField(blank=True) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.name + +class Worker(models.Model): + name = models.CharField(max_length=200) + id_no = models.CharField(max_length=50, unique=True, verbose_name="ID Number") + phone_no = models.CharField(max_length=20, verbose_name="Phone Number") + monthly_salary = models.DecimalField(max_digits=10, decimal_places=2, validators=[MinValueValidator(Decimal('0.00'))]) + created_at = models.DateTimeField(auto_now_add=True) + + @property + def day_rate(self): + return self.monthly_salary / Decimal('20.0') + + def __str__(self): + return self.name + +class Team(models.Model): + name = models.CharField(max_length=200) + workers = models.ManyToManyField(Worker, related_name='teams') + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.name + +class WorkLog(models.Model): + date = models.DateField() + project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='logs') + workers = models.ManyToManyField(Worker, related_name='work_logs') + notes = models.TextField(blank=True) + + def __str__(self): + return f"{self.date} - {self.project.name}" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..a19c620 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,37 @@ - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}LabourFlow - Work & Payroll{% endblock %} + {% if project_description %} + + {% endif %} + {% load static %} + + + + + {% block head %}{% endblock %} - - {% block content %}{% endblock %} - + - + {% block content %}{% endblock %} + + + + \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..a4cae95 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,130 @@ -{% extends "base.html" %} +{% extends 'base.html' %} +{% load static %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Dashboard | LabourFlow{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+
+
+

Welcome Back, Admin

+

Track your projects, workers, and payroll in one place.

+
+ +
-

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 + + +
+
+ +
+
+
+
+

Active Workers

+

{{ workers_count }}

+
+
+ +
+
+
+
+
+
+
+
+

Projects

+

{{ projects_count }}

+
+
+ +
+
+
+
+
+
+
+
+

Teams

+

{{ teams_count }}

+
+
+ +
+
+
+
+
+ +
+
+
+

Recent Daily Logs

+ {% if recent_logs %} +
+ + + + + + + + + + + {% for log in recent_logs %} + + + + + + + {% endfor %} + +
DateProjectWorkersStatus
{{ log.date }}{{ log.project.name }}{{ log.workers.count }} labourersSubmitted
+
+ {% else %} +
+
+ +
+

No recent work logs found.

+ Create First Log +
+ {% endif %} +
+
+ +
+
+{% endblock %} diff --git a/core/views.py b/core/views.py index c9aed12..eb4620b 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,21 @@ import os import platform - -from django import get_version as django_version from django.shortcuts import render from django.utils import timezone - +from .models import Worker, Project, Team, WorkLog 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() - + """Render the landing screen with dashboard stats.""" + workers_count = Worker.objects.count() + projects_count = Project.objects.count() + teams_count = Team.objects.count() + recent_logs = WorkLog.objects.order_by('-date')[:5] + 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", ""), + "workers_count": workers_count, + "projects_count": projects_count, + "teams_count": teams_count, + "recent_logs": recent_logs, + "current_time": timezone.now(), } - return render(request, "core/index.html", context) + return render(request, "core/index.html", context) \ No newline at end of file diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..13343f9 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,81 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Poppins:wght@600;700&display=swap'); + +:root { + --primary-color: #1e293b; + --accent-color: #10b981; + --bg-color: #f1f5f9; + --text-main: #334155; + --text-light: #64748b; + --white: #ffffff; + --glass-bg: rgba(255, 255, 255, 0.7); } + +body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-color); + color: var(--text-main); + margin: 0; + padding: 0; +} + +h1, h2, h3, .heading-font { + font-family: 'Poppins', sans-serif; + font-weight: 700; +} + +.dashboard-header { + background: linear-gradient(135deg, var(--primary-color) 0%, #334155 100%); + color: var(--white); + padding: 4rem 2rem; + margin-bottom: -4rem; +} + +.card { + border: none; + border-radius: 1rem; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + transition: transform 0.2s ease-in-out; +} + +.card:hover { + transform: translateY(-5px); +} + +.stat-card { + background: var(--glass-bg); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); +} + +.btn-accent { + background-color: var(--accent-color); + color: white; + font-weight: 600; + padding: 0.75rem 1.5rem; + border-radius: 0.5rem; + border: none; +} + +.btn-accent:hover { + background-color: #059669; + color: white; +} + +.sidebar-link { + display: block; + padding: 0.75rem 1rem; + color: var(--text-main); + text-decoration: none; + border-radius: 0.5rem; + margin-bottom: 0.5rem; +} + +.sidebar-link:hover { + background-color: #e2e8f0; + color: var(--primary-color); +} + +.sidebar-link.active { + background-color: var(--primary-color); + color: var(--white); +} \ No newline at end of file