diff --git a/commcare_connect/opportunity/tw_tables.py b/commcare_connect/opportunity/tw_tables.py new file mode 100644 index 000000000..09df99a97 --- /dev/null +++ b/commcare_connect/opportunity/tw_tables.py @@ -0,0 +1,167 @@ +import django_tables2 as tables +from django.utils.html import format_html +from django_tables2.utils import A + + +class BaseTailwindTable(tables.Table): + """Base table using Tailwind styling and custom template.""" + + class Meta: + template_name = "tailwind/base_table.html" # Use your custom template + attrs = {"class": "w-full text-left text-sm text-gray-600"} + + +class WorkerFlaggedTable(BaseTailwindTable): + index = tables.Column(verbose_name="", orderable=False) + time = tables.Column(verbose_name="Time") + entityName = tables.Column(verbose_name="Entity Name") + flags = tables.TemplateColumn( + verbose_name="Flags", + orderable=False, + template_code=""" +
+ {% if value %} + {% for flag in value|slice:":2" %} + {% include "tailwind/components/badges/badge_sm.html" with text=flag %} + {% endfor %} + {% if value|length > 2 %} + {% include "tailwind/components/badges/badge_sm_dropdown.html" with title='All Flags' list=value %} + {% endif %} + {% endif %} +
+ """, + ) + reportIcons = tables.TemplateColumn( + verbose_name="", + orderable=False, + template_code=""" + + """, + ) + + class Meta: + attrs = { + "class": "w-full max-w-full", + "thead": {"class": "hidden"}, + "tbody": {"class": "block w-full bg-gray-200 rounded-lg h-[400px] overflow-y-auto"}, + } + row_attrs = { + "class": "flex w-full justify-between gap-x-4 p-3 bg-white hover:bg-gray-100 relative transition-colors duration-300 group", + "x-data": "{ hovered: false }", + "@mouseenter": "hovered = true", + "@mouseleave": "hovered = false", + } + sequence = ("index", "time", "entityName", "flags", "reportIcons") + + def render_index(self, value, record): + return format_html( + """ +
+ {} + +
+ """, + value, + value, + value, + value, + value, + ) + + def render_time(self, value): + return format_html( + '
{}
', value + ) + + def render_entityName(self, value): + return format_html( + '
{}
', value + ) + + def render_reportIcons(self): + return format_html( + """ +
+ +
+ """ + ) + + +class VisitsTable(BaseTailwindTable): + index = tables.Column(verbose_name="#", orderable=False) + user_id = tables.Column(verbose_name="User ID") + name = tables.Column(verbose_name="Name") + max_visit = tables.Column(verbose_name="Max Visits") + used_visits = tables.Column(verbose_name="Used Visits") + end_date = tables.Column(verbose_name="End Date") + + class Meta: + attrs = { + "thead": {"class": "hidden"}, + "class": "", + } + row_attrs = { + "class": "grid grid-cols-[30px_222px_213px_168px_172px_151px] text-slate-900 pl-5 py-4 items-center text-xs ml-1" + } + sequence = ("index", "user_id", "name", "max_visit", "used_visits", "end_date") + + def render_index(self, value): + return format_html('
{}
', value) + + def render_user_id(self, value): + return format_html("
{}
", value) + + def render_name(self, value): + return format_html("
{}
", value) + + def render_max_visit(self, value): + return format_html( + """ +
+
+ +
+
+ """, + value, + value, + value, + ) + + def render_used_visits(self, value): + return format_html("
{}
", value) + + def render_end_date(self, value): + return format_html( + """ +
+ +
+ """, + value, + ) diff --git a/commcare_connect/opportunity/tw_views.py b/commcare_connect/opportunity/tw_views.py new file mode 100644 index 000000000..c839f54ab --- /dev/null +++ b/commcare_connect/opportunity/tw_views.py @@ -0,0 +1,391 @@ +from django.shortcuts import render + +from .tw_tables import VisitsTable, WorkerFlaggedTable + + +def home(request, org_slug=None, opp_id=None): + # Static data for the cards + rows = [ + {"name": "Data Points 1", "value": "45"}, + {"name": "Data Points 1", "value": "45"}, + {"name": "Data Points 2", "value": "45"}, + {"name": "Data Points 3", "value": "45"}, + {"name": "Data Points 4", "value": "45"}, + {"name": "Data Points 5", "value": "45"}, + {"name": "Data Points 6", "value": "45"}, + {"name": "Data Points 7", "value": "45"}, + {"name": "Data Points 8", "value": "45"}, + ] + timeline = [ + {"title": "Event Title", "desc": "Additional Supporting Message with the Event", "date": "24 Feb, 2024"}, + {"title": "Event Title", "desc": "Additional Supporting Message with the Event", "date": "24 Feb, 2024"}, + {"title": "Event Title", "desc": "Additional Supporting Message with the Event", "date": "24 Feb, 2024"}, + ] + flags = [ + {"title": "Location", "desc": "Minimum distance between deliveries.", "value": "2.5m"}, + {"title": "Form Duration", "desc": "Minimum time between deliveries.", "value": "10min"}, + {"title": "Photos", "desc": "Added media for proof"}, + {"title": "GPS location", "desc": "GPS location of the site is present"}, + ] + return render( + request, + "tailwind/pages/home.html", + {"rows": rows, "timeline": timeline, "flags": flags, "header_title": "Worker"}, + ) + + +def about(request, org_slug=None, opp_id=None): + return render(request, "tailwind/pages/about.html") + + +def worker(request, org_slug=None, opp_id=None): + data = [ + {"name": "Flagged", "count": "45", "url": "/tables"}, + {"name": "PM Review", "count": "45", "url": "/tables"}, + {"name": "Revalidate", "count": "45", "url": "/tables"}, + {"name": "Approved", "count": "45", "url": "/tabls"}, + {"name": "Rejected", "count": "45", "url": "/tables"}, + {"name": "All", "count": "45", "url": "/tables"}, + ] + + return render(request, "tailwind/pages/worker.html", {"header_title": "Worker", "tabs": data}) + + +def opportunities(request, org_slug=None, opp_id=None): + data = [ + {"name": "Learn App", "count": "2", "icon": "fa-book-open-cover"}, + {"name": "Delivery App", "count": "2", "icon": "fa-clipboard-check"}, + {"name": "Payments Units", "count": "2", "icon": "fa-hand-holding-dollar"}, + ] + totalinfo = [ + { + "name": "Delivery Type", + "count": "Early Childhood Development", + "icon": "fa-file-check", + "color": "", + }, + { + "name": "Start Date", + "count": "21-Dec-2024", + "icon": "fa-calendar-range", + "color": "", + }, + { + "name": "End Date", + "count": "21-Dec-2024", + "icon": "fa-arrow-right", + "color": "", + }, + { + "name": "Total Workers", + "count": "248", + "icon": "fa-users", + "color": "brand-mango", + }, + { + "name": "Total Service Deliveries", + "count": "350", + "icon": "fa-gears", + "color": "", + }, + { + "name": "Worker Budget", + "count": "₹250,000", + "icon": "fa-money-bill", + "color": "", + }, + ] + opList = [ + { + "opName": "Workers", + "opLabel": "Active Yesterday", + "opValue": "10", + "ops": [ + {"icon": "fa-user-group", "name": "Workers", "status": "Invited", "value": "25"}, + {"icon": "fa-user-check", "name": "Workers", "status": "Yet to Accept Invitation", "value": "12"}, + { + "icon": "fa-clipboard-list", + "name": "Workers", + "status": "Inactive last 3 days", + "value": "7", + "type": "2", + }, + ], + }, + { + "opName": "Deliveries", + "opLabel": "Last Delivery", + "opValue": "10 Feb, 2025 | 14:67", + "ops": [ + { + "icon": "fa-clipboard-list-check", + "name": "Deliveries", + "status": "Total", + "value": "248", + "incr": "6", + }, + { + "icon": "fa-clipboard-list-check", + "name": "Deliveries", + "status": "Awaiting Flag Review", + "value": "32", + }, + ], + }, + { + "opName": "Worker Payments", + "opLabel": "Last Payment ", + "opValue": "10 Feb, 2025 | 14:67", + "ops": [ + { + "icon": "fa-hand-holding-dollar", + "name": "Payments", + "status": "Earned", + "value": "₹25,000", + "incr": "6", + }, + {"icon": "fa-light", "name": "Payments", "status": "Due", "value": "₹1,200"}, + ], + }, + ] + return render( + request, + "tailwind/pages/opportunities.html", + {"data": data, "totalinfo": totalinfo, "opList": opList, "header_title": "Opportunities"}, + ) + + +def flagged_workers(request, org_slug=None, opp_id=None): + # Sample dynamic data (replace with your actual data source later) + data = [ + { + "index": 1, + "time": "14:56", + "entityName": "Violla Maeya", + "flags": ["Location", "Form Duration", "Photos", "Flag Name 1", "Flag Name 2", "Flag Name 3"], + }, + {"index": 2, "time": "14:57", "entityName": "John Doe", "flags": ["Location", "Photos"]}, + { + "index": 3, + "time": "14:58", + "entityName": "Jane Smith", + "flags": ["Form Duration", "Flag Name 1", "Flag Name 2"], + }, + {"index": 4, "time": "14:59", "entityName": "Alex Brown", "flags": []}, + {"index": 5, "time": "15:00", "entityName": "Violla Maeya", "flags": ["Location", "Form Duration", "Photos"]}, + { + "index": 11, + "time": "14:56", + "entityName": "Violla Maeya", + "flags": ["Location", "Form Duration", "Photos", "Flag Name 1", "Flag Name 2", "Flag Name 3"], + }, + {"index": 12, "time": "14:57", "entityName": "John Doe", "flags": ["Location", "Photos"]}, + { + "index": 13, + "time": "14:58", + "entityName": "Jane Smith", + "flags": ["Form Duration", "Flag Name 1", "Flag Name 2"], + }, + {"index": 14, "time": "14:59", "entityName": "Alex Brown", "flags": []}, + {"index": 15, "time": "15:00", "entityName": "Violla Maeya", "flags": ["Location", "Form Duration", "Photos"]}, + { + "index": 21, + "time": "14:56", + "entityName": "Violla Maeya", + "flags": ["Location", "Form Duration", "Photos", "Flag Name 1", "Flag Name 2", "Flag Name 3"], + }, + {"index": 22, "time": "14:57", "entityName": "John Doe", "flags": ["Location", "Photos"]}, + { + "index": 23, + "time": "14:58", + "entityName": "Jane Smith", + "flags": ["Form Duration", "Flag Name 1", "Flag Name 2"], + }, + {"index": 24, "time": "14:59", "entityName": "Alex Brown", "flags": []}, + {"index": 25, "time": "15:00", "entityName": "Violla Maeya", "flags": ["Location", "Form Duration", "Photos"]}, + { + "index": 31, + "time": "14:56", + "entityName": "Violla Maeya", + "flags": ["Location", "Form Duration", "Photos", "Flag Name 1", "Flag Name 2", "Flag Name 3"], + }, + {"index": 32, "time": "14:57", "entityName": "John Doe", "flags": ["Location", "Photos"]}, + { + "index": 33, + "time": "14:58", + "entityName": "Jane Smith", + "flags": ["Form Duration", "Flag Name 1", "Flag Name 2"], + }, + {"index": 34, "time": "14:59", "entityName": "Alex Brown", "flags": []}, + {"index": 35, "time": "15:00", "entityName": "Violla Maeya", "flags": ["Location", "Form Duration", "Photos"]}, + ] + table = WorkerFlaggedTable(data) + return render(request, "tailwind/components/tables/worker_flagged_table.html", {"table": table}) + + +def opportunity_visits(request, org_slug=None, opp_id=None): + data = [ + { + "index": 1, + "user_id": "AB12CD34EF56", + "name": "John Doe", + "max_visit": 120, + "used_visits": 89, + "end_date": "2025-07-12", + }, + { + "index": 2, + "user_id": "XY98GH76IJ54", + "name": "Alice Smith", + "max_visit": 150, + "used_visits": 45, + "end_date": "2025-09-30", + }, + { + "index": 3, + "user_id": "MN45KL89OP12", + "name": "Bob Johnson", + "max_visit": 100, + "used_visits": 72, + "end_date": "2026-02-15", + }, + { + "index": 4, + "user_id": "QR23ST56UV78", + "name": "Emma Wilson", + "max_visit": 180, + "used_visits": 160, + "end_date": "2025-11-20", + }, + { + "index": 5, + "user_id": "WX67YZ12AB34", + "name": "Michael Brown", + "max_visit": 90, + "used_visits": 25, + "end_date": "2026-05-10", + }, + { + "index": 6, + "user_id": "KL34MN78OP56", + "name": "Sophia Martinez", + "max_visit": 130, + "used_visits": 98, + "end_date": "2025-08-21", + }, + { + "index": 7, + "user_id": "UV12WX34YZ56", + "name": "James Anderson", + "max_visit": 170, + "used_visits": 140, + "end_date": "2026-04-05", + }, + { + "index": 8, + "user_id": "CD78EF12GH34", + "name": "Olivia Taylor", + "max_visit": 200, + "used_visits": 180, + "end_date": "2025-12-25", + }, + { + "index": 9, + "user_id": "IJ45KL67MN89", + "name": "William Harris", + "max_visit": 95, + "used_visits": 50, + "end_date": "2025-06-18", + }, + { + "index": 10, + "user_id": "OP23QR45ST67", + "name": "Charlotte White", + "max_visit": 160, + "used_visits": 130, + "end_date": "2026-07-01", + }, + { + "index": 11, + "user_id": "EF12GH34IJ56", + "name": "Benjamin Lewis", + "max_visit": 110, + "used_visits": 85, + "end_date": "2025-10-11", + }, + { + "index": 12, + "user_id": "ST78UV12WX34", + "name": "Mia Scott", + "max_visit": 140, + "used_visits": 95, + "end_date": "2026-03-30", + }, + { + "index": 13, + "user_id": "YZ45AB67CD89", + "name": "Elijah Hall", + "max_visit": 180, + "used_visits": 170, + "end_date": "2025-09-09", + }, + { + "index": 14, + "user_id": "GH23IJ45KL67", + "name": "Amelia Young", + "max_visit": 125, + "used_visits": 110, + "end_date": "2026-01-25", + }, + { + "index": 15, + "user_id": "MN78OP12QR34", + "name": "Lucas King", + "max_visit": 190, + "used_visits": 150, + "end_date": "2025-11-15", + }, + { + "index": 16, + "user_id": "WX45YZ67AB89", + "name": "Harper Wright", + "max_visit": 105, + "used_visits": 70, + "end_date": "2026-06-20", + }, + { + "index": 17, + "user_id": "CD12EF34GH56", + "name": "Henry Green", + "max_visit": 175, + "used_visits": 160, + "end_date": "2025-12-01", + }, + { + "index": 18, + "user_id": "IJ78KL12MN34", + "name": "Evelyn Adams", + "max_visit": 115, + "used_visits": 90, + "end_date": "2026-05-17", + }, + { + "index": 19, + "user_id": "OP45QR67ST89", + "name": "Alexander Nelson", + "max_visit": 145, + "used_visits": 120, + "end_date": "2025-08-05", + }, + { + "index": 20, + "user_id": "UV23WX45YZ67", + "name": "Isabella Carter", + "max_visit": 135, + "used_visits": 100, + "end_date": "2026-02-22", + }, + ] + + table = VisitsTable(data) + return render(request, "tailwind/pages/opportunity_visits.html", {"table": table}) diff --git a/commcare_connect/opportunity/urls.py b/commcare_connect/opportunity/urls.py index ff26f8161..d339bb94a 100644 --- a/commcare_connect/opportunity/urls.py +++ b/commcare_connect/opportunity/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from commcare_connect.opportunity import views +from commcare_connect.opportunity import tw_views, views from commcare_connect.opportunity.views import ( OpportunityCompletedWorkTable, OpportunityCreate, @@ -52,6 +52,10 @@ user_visits_list, verification_flags_config, visit_verification, + worker_deliver, + worker_learn, + worker_list, + worker_verify, ) app_name = "opportunity" @@ -108,6 +112,10 @@ path("/suspend_user//", view=suspend_user, name="suspend_user"), path("/revoke_user_suspension//", view=revoke_user_suspension, name="revoke_user_suspension"), path("/delete_form_json_rule//", view=delete_form_json_rule, name="delete_form_json_rule"), + path("/workers/list/", view=worker_list, name="worker_list"), + path("/workers/learn/", view=worker_learn, name="worker_learn"), + path("/workers/deliver/", view=worker_deliver, name="worker_deliver"), + path("/workers/verify/", view=worker_verify, name="worker_verify"), path("/catchment_area_export/", view=export_catchment_area, name="catchment_area_export"), path("/catchment_area_import/", view=import_catchment_area, name="catchment_area_import"), path("/payment_report/", payment_report, name="payment_report"), @@ -119,4 +127,9 @@ path("/invoice/approve/", views.invoice_approve, name="invoice_approve"), path("/user_invite_delete//", views.user_invite_delete, name="user_invite_delete"), path("/resend_invite/", resend_user_invite, name="resend_user_invite"), + # New tailwind based views + path("/tw/worker/", tw_views.worker, name="tw_worker"), + path("/tw/opportunities/", tw_views.opportunities, name="tw_opportunities"), + path("/tw/flagged_workers/", tw_views.flagged_workers, name="tw_flagged_workers"), + path("/tw/visits/", tw_views.opportunity_visits, name="tw_visits"), ] diff --git a/commcare_connect/opportunity/views.py b/commcare_connect/opportunity/views.py index a869ecc21..798d3040e 100644 --- a/commcare_connect/opportunity/views.py +++ b/commcare_connect/opportunity/views.py @@ -1321,3 +1321,19 @@ def resend_user_invite(request, org_slug, opp_id, pk): invite_user.delay(user.id, access.pk) return HttpResponse("The invitation has been successfully resent to the user.") + + +def worker_list(request, org_slug=None, opp_id=None): + return render(request, "opportunity/tailwind/workers.html") + + +def worker_learn(request, org_slug=None, opp_id=None): + return render(request, "opportunity/tailwind/learn.html") + + +def worker_deliver(request, org_slug=None, opp_id=None): + return render(request, "opportunity/tailwind/deliver.html") + + +def worker_verify(request, org_slug=None, opp_id=None): + return render(request, "opportunity/tailwind/verify.html") diff --git a/commcare_connect/program/urls.py b/commcare_connect/program/urls.py index 7d9cd6c1e..efd483110 100644 --- a/commcare_connect/program/urls.py +++ b/commcare_connect/program/urls.py @@ -12,10 +12,12 @@ dashboard, invite_organization, manage_application, + program_home, ) app_name = "program" urlpatterns = [ + path("home", view=program_home, name="home"), path("", view=ProgramList.as_view(), name="list"), path("init/", view=ProgramCreateOrUpdate.as_view(), name="init"), path("/edit", view=ProgramCreateOrUpdate.as_view(), name="edit"), diff --git a/commcare_connect/program/views.py b/commcare_connect/program/views.py index ff60a8b56..c90d6f438 100644 --- a/commcare_connect/program/views.py +++ b/commcare_connect/program/views.py @@ -6,6 +6,7 @@ from django.views.generic import ListView, UpdateView from django_tables2 import SingleTableView +from commcare_connect.opportunity.models import UserVisit from commcare_connect.opportunity.views import OpportunityInit from commcare_connect.organization.decorators import org_admin_required, org_program_manager_required from commcare_connect.organization.models import Organization @@ -277,3 +278,47 @@ def get_queryset(self): start_date = self.request.GET.get("start_date") or None end_date = self.request.GET.get("end_date") or None return get_delivery_performance_report(program, start_date, end_date) + + +from django.contrib.auth.decorators import login_required, user_passes_test + + +# @login_required +# @user_passes_test(lambda u: u.is_superuser) +def program_home(request, org_slug): + from django.db.models import Count, F + + # Fetch the organization by slug + org = Organization.objects.get(slug=org_slug) + + # Get ProgramApplications with related Program details + apps = ( + ProgramApplication.objects.filter(organization=org) + .select_related("program", "program__organization", "program__delivery_type") + .order_by("-date_created") + .values( + "program__name", + "program__start_date", + "program__end_date", + "program__description", + "status", + "program__organization__name", + "program__delivery_type__name", + "date_created", + ) + ) + + # Sort by ProgramApplication date first, then Program start_date + results = sorted(apps, key=lambda x: (x["date_created"], x["program__start_date"]), reverse=True) + pending_counts = ( + UserVisit.objects.filter(status="pending") + .values("opportunity__id", "opportunity__name", "opportunity__organization__name") # Separate field names + .annotate(count=Count("id")) + ) + context = { + "program_apps": results, + "review_counts": pending_counts, + "pending_payments": pending_counts, # Todo + "inactive_workers": pending_counts, # Todo + } # The queryset from the ORM query + return render(request, "program/tailwind/home.html", context) diff --git a/commcare_connect/static/css/tailwind.css b/commcare_connect/static/css/tailwind.css new file mode 100644 index 000000000..f71140e11 --- /dev/null +++ b/commcare_connect/static/css/tailwind.css @@ -0,0 +1,15 @@ +@import "tailwindcss"; + + +@theme { + --color-brand-deep-purple: #16006D; + --color-brand-indigo: #3843D0; + --color-brand-cornflower-blue: #5D70D2; + --color-brand-sky: #8EA1FF; + --color-brand-sunset: #E44434; + --color-brand-mango: #FC5F36; + --color-brand-marigold: #FEAF31; + --color-brand-blue-light: #94A3B8; + --color-brand-sunset-light: #FC5F3633; + --color-brand-border-light: #E2E8F0; +} diff --git a/commcare_connect/static/images/history.svg b/commcare_connect/static/images/history.svg new file mode 100644 index 000000000..cb2d4c547 --- /dev/null +++ b/commcare_connect/static/images/history.svg @@ -0,0 +1,3 @@ + + + diff --git a/commcare_connect/static/images/logo.svg b/commcare_connect/static/images/logo.svg new file mode 100644 index 000000000..ecd4ce2c1 --- /dev/null +++ b/commcare_connect/static/images/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/commcare_connect/static/js/tailwind.js b/commcare_connect/static/js/tailwind.js new file mode 100644 index 000000000..6a3f04e35 --- /dev/null +++ b/commcare_connect/static/js/tailwind.js @@ -0,0 +1 @@ +import '../sass/tailwind.css'; diff --git a/commcare_connect/templates/logo.svg b/commcare_connect/templates/logo.svg new file mode 100644 index 000000000..ecd4ce2c1 --- /dev/null +++ b/commcare_connect/templates/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/commcare_connect/templates/opportunity/tailwind/deliver.html b/commcare_connect/templates/opportunity/tailwind/deliver.html new file mode 100644 index 000000000..ba52afe99 --- /dev/null +++ b/commcare_connect/templates/opportunity/tailwind/deliver.html @@ -0,0 +1,7 @@ +{% extends "tailwind/base.html" %} + +{% block content %} +
+

Override as needed

+
+{% endblock content %} diff --git a/commcare_connect/templates/opportunity/tailwind/learn.html b/commcare_connect/templates/opportunity/tailwind/learn.html new file mode 100644 index 000000000..ba52afe99 --- /dev/null +++ b/commcare_connect/templates/opportunity/tailwind/learn.html @@ -0,0 +1,7 @@ +{% extends "tailwind/base.html" %} + +{% block content %} +
+

Override as needed

+
+{% endblock content %} diff --git a/commcare_connect/templates/opportunity/tailwind/payments.html b/commcare_connect/templates/opportunity/tailwind/payments.html new file mode 100644 index 000000000..ba52afe99 --- /dev/null +++ b/commcare_connect/templates/opportunity/tailwind/payments.html @@ -0,0 +1,7 @@ +{% extends "tailwind/base.html" %} + +{% block content %} +
+

Override as needed

+
+{% endblock content %} diff --git a/commcare_connect/templates/opportunity/tailwind/verify.html b/commcare_connect/templates/opportunity/tailwind/verify.html new file mode 100644 index 000000000..ba52afe99 --- /dev/null +++ b/commcare_connect/templates/opportunity/tailwind/verify.html @@ -0,0 +1,7 @@ +{% extends "tailwind/base.html" %} + +{% block content %} +
+

Override as needed

+
+{% endblock content %} diff --git a/commcare_connect/templates/opportunity/tailwind/workers.html b/commcare_connect/templates/opportunity/tailwind/workers.html new file mode 100644 index 000000000..ba52afe99 --- /dev/null +++ b/commcare_connect/templates/opportunity/tailwind/workers.html @@ -0,0 +1,7 @@ +{% extends "tailwind/base.html" %} + +{% block content %} +
+

Override as needed

+
+{% endblock content %} diff --git a/commcare_connect/templates/program/tailwind/home.html b/commcare_connect/templates/program/tailwind/home.html new file mode 100644 index 000000000..1706701b1 --- /dev/null +++ b/commcare_connect/templates/program/tailwind/home.html @@ -0,0 +1,81 @@ +{% extends "tailwind/base.html" %} + +{% block content %} +
+ +
+

Programs

+
+ {% for app in program_apps %} +
+
+ + +
+
+ {{ app.date_created|date:"d M, Y" }} + + + {{ app.program__organization__name }} + +
+ + {{ app.status|title }} + +
+ + +

{{ app.program__name }}

+ + +

+ {{ app.program__description|default:"No description available." }} +

+ + +
+
+ +
+

Delivery Type

+

{{ app.program__delivery_type__name }}

+
+ + +
+
+

Start Date

+

{{ app.program__start_date|date:"d-M-Y" }}

+
+
+

End Date

+

{{ app.program__end_date|date:"d-M-Y" }}

+
+
+
+ + + +
+
+ {% empty %} +

No programs found.

+ {% endfor %} +
+
+ + +
+
Recent Activities
+
+
+ {% include 'tailwind/components/cards/activity_card.html' with title="Visits Pending Review" rows=review_counts icon="fa-clock-rotate-left" %} + {% include 'tailwind/components/cards/activity_card.html' with title="Pending Payment" rows=pending_payments icon="fa-hand-holding-dollar" %} + {% include 'tailwind/components/cards/activity_card.html' with title="Inactive Workers" rows=inactive_workers icon="fa-user-slash" %} +
+
+
+
+{% endblock %} diff --git a/commcare_connect/templates/tailwind/base.html b/commcare_connect/templates/tailwind/base.html new file mode 100644 index 000000000..ea7f3eb66 --- /dev/null +++ b/commcare_connect/templates/tailwind/base.html @@ -0,0 +1,34 @@ +{% load static i18n %} + + + + + + + CommCareConnect + {% load static %} + {% block css %} + + + + {% endblock %} + {% block javascript %} + + + + + {% endblock javascript %} + + + {% include 'tailwind/layouts/sidenav.html'%} +
+ {% include 'tailwind/layouts/header.html'%} +
+
+ {% block content %} + {% endblock %} +
+
+ + + diff --git a/commcare_connect/templates/tailwind/base_table.html b/commcare_connect/templates/tailwind/base_table.html new file mode 100644 index 000000000..4721997fa --- /dev/null +++ b/commcare_connect/templates/tailwind/base_table.html @@ -0,0 +1,113 @@ +{% load django_tables2 %} +{% load i18n l10n %} +{% block table-wrapper %} +
+ {% block table %} + + {% block table.thead %} + {% if table.show_header %} + + + {% for column in table.columns %} + + {% endfor %} + + + {% endif %} + {% endblock table.thead %} + {% block table.tbody %} + + {% for row in table.paginated_rows %} + {% block table.tbody.row %} + + {% for column, cell in row.items %} + + {% endfor %} + + {% endblock table.tbody.row %} + {% empty %} + {% if table.empty_text %} + {% block table.tbody.empty_text %} + + + + {% endblock table.tbody.empty_text %} + {% endif %} + {% endfor %} + + {% endblock table.tbody %} + {% block table.tfoot %} + {% if table.has_footer %} + + + {% for column in table.columns %} + + {% endfor %} + + + {% endif %} + {% endblock table.tfoot %} +
+ {% if column.orderable %} + {{ column.header }} + {% else %} + {{ column.header }} + {% endif %} +
+ {% if column.localize == None %} + {{ cell }} + {% else %} + {% if column.localize %} + {{ cell|localize }} + {% else %} + {{ cell|unlocalize }} + {% endif %} + {% endif %} +
+ {{ table.empty_text }} +
+ {{ column.footer }} +
+ {% endblock table %} + + {% block pagination %} + {% if table.page and table.paginator.num_pages > 1 %} + + {% endif %} + {% endblock pagination %} +
+{% endblock table-wrapper %} \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/badges/badge_md.html b/commcare_connect/templates/tailwind/components/badges/badge_md.html new file mode 100644 index 000000000..af43d83a8 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/badges/badge_md.html @@ -0,0 +1,5 @@ + + {{ text }} + diff --git a/commcare_connect/templates/tailwind/components/badges/badge_sm.html b/commcare_connect/templates/tailwind/components/badges/badge_sm.html new file mode 100644 index 000000000..f9cfe2233 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/badges/badge_sm.html @@ -0,0 +1,5 @@ + + {{ text }} + diff --git a/commcare_connect/templates/tailwind/components/badges/badge_sm_dropdown.html b/commcare_connect/templates/tailwind/components/badges/badge_sm_dropdown.html new file mode 100644 index 000000000..946d82f58 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/badges/badge_sm_dropdown.html @@ -0,0 +1,73 @@ +{% comment %} {% load static %} {% endcomment %} + + + +{{ list|length|add:-2 }} + + +
+

{{ title|default:'Flags' }}

+
+ {% for item in list %} +

{{ item }}

+ {% endfor %} +
+
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/breadcrumbs/breadcrumbs_row.html b/commcare_connect/templates/tailwind/components/breadcrumbs/breadcrumbs_row.html new file mode 100644 index 000000000..64aadfbd7 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/breadcrumbs/breadcrumbs_row.html @@ -0,0 +1,11 @@ +
+ Program + + Opportunities + + Opportunity Name + + Worker +
+ + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/buttons/button_cancel.html b/commcare_connect/templates/tailwind/components/buttons/button_cancel.html new file mode 100644 index 000000000..e673864d3 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_cancel.html @@ -0,0 +1 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/button_disabled.html b/commcare_connect/templates/tailwind/components/buttons/button_disabled.html new file mode 100644 index 000000000..192b5bc78 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_disabled.html @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/buttons/button_icon.html b/commcare_connect/templates/tailwind/components/buttons/button_icon.html new file mode 100644 index 000000000..c73cf2f6e --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_icon.html @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/buttons/button_primary.html b/commcare_connect/templates/tailwind/components/buttons/button_primary.html new file mode 100644 index 000000000..ad1047af2 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_primary.html @@ -0,0 +1,5 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/button_primary_sm.html b/commcare_connect/templates/tailwind/components/buttons/button_primary_sm.html new file mode 100644 index 000000000..15c21bd00 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_primary_sm.html @@ -0,0 +1,6 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/button_primary_sm_disabled.html b/commcare_connect/templates/tailwind/components/buttons/button_primary_sm_disabled.html new file mode 100644 index 000000000..d9b01176d --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_primary_sm_disabled.html @@ -0,0 +1,3 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/button_secondary.html b/commcare_connect/templates/tailwind/components/buttons/button_secondary.html new file mode 100644 index 000000000..3c400b088 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_secondary.html @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/buttons/button_secondary_rounded.html b/commcare_connect/templates/tailwind/components/buttons/button_secondary_rounded.html new file mode 100644 index 000000000..5256aca63 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_secondary_rounded.html @@ -0,0 +1,4 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/button_secondary_sm.html b/commcare_connect/templates/tailwind/components/buttons/button_secondary_sm.html new file mode 100644 index 000000000..3501f6b4e --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_secondary_sm.html @@ -0,0 +1,6 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/button_text.html b/commcare_connect/templates/tailwind/components/buttons/button_text.html new file mode 100644 index 000000000..7ef20002c --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/button_text.html @@ -0,0 +1,4 @@ + diff --git a/commcare_connect/templates/tailwind/components/buttons/danger.html b/commcare_connect/templates/tailwind/components/buttons/danger.html new file mode 100644 index 000000000..e9f302151 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/danger.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/buttons/success.html b/commcare_connect/templates/tailwind/components/buttons/success.html new file mode 100644 index 000000000..94d947631 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/buttons/success.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/cards/activity_card.html b/commcare_connect/templates/tailwind/components/cards/activity_card.html new file mode 100644 index 000000000..72a61e417 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/activity_card.html @@ -0,0 +1,26 @@ +{% load static i18n %} +
+
+ +

+ {{ title }} +

+
+ {% for row in rows %} +
+
+

+ + {{ row.opportunity__name }} + +

+

{{ row.opportunity__name }}

+
+ {% include 'tailwind/components/buttons/button_secondary_rounded.html' with text=row.count %} + +
+ {% endfor %} +
+ {% include 'tailwind/components/buttons/button_text.html' with text='more' %} +
+
diff --git a/commcare_connect/templates/tailwind/components/cards/approval_card.html b/commcare_connect/templates/tailwind/components/cards/approval_card.html new file mode 100644 index 000000000..67aab4670 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/approval_card.html @@ -0,0 +1,24 @@ +
+
+

Reason for Approval

+
+
+

48 items has been marked for approval Provide a justification for approving flagged visits

+
+
+ + +
+
+ {% include "tailwind/components/buttons/button_cancel.html" %} {% include "tailwind/components/buttons/success.html" %} +
+
diff --git a/commcare_connect/templates/tailwind/components/cards/card-toggle.html b/commcare_connect/templates/tailwind/components/cards/card-toggle.html new file mode 100644 index 000000000..a160c5655 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/card-toggle.html @@ -0,0 +1,13 @@ +
+
+ {{title}} + {{description}} +
+ +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/cards/card.html b/commcare_connect/templates/tailwind/components/cards/card.html new file mode 100644 index 000000000..2127e289f --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/card.html @@ -0,0 +1,19 @@ + +
+
+

{{ card.data.title }}

+

{{ card.data.subtitle }}

+
+ +
+ {% for button in card.data.buttons %} + {% if button.variant == 'button-primary' %} + {% include 'tailwind/components/buttons/button_primary.html' with text=button.text size=button.size %} + {% elif button.variant == 'button-secondary' %} + {% include 'tailwind/components/buttons/button_secondary.html' with text=button.text size=button.size icon=button.icon %} + {% endif %} + {% endfor %} +
+
diff --git a/commcare_connect/templates/tailwind/components/cards/filter_card.html b/commcare_connect/templates/tailwind/components/cards/filter_card.html new file mode 100644 index 000000000..a5707b645 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/filter_card.html @@ -0,0 +1,53 @@ +
+
+

Filter

+ + +
+
+ Delivery Status Filters +
+
+
+

Overlimit

+
+
+

Duplicate

+
+
+
+ Flags +
+ {% include "tailwind/components/cards/filter_flag_row.html" with flags=flags %} + +
+
+ +
+

+ Select Filtered Pending Visits for + Approval or Rejection +

+ {% include "tailwind/components/buttons/button_primary.html" with text='Accept' %} +
+ + +
diff --git a/commcare_connect/templates/tailwind/components/cards/filter_flag_row.html b/commcare_connect/templates/tailwind/components/cards/filter_flag_row.html new file mode 100644 index 000000000..c8312ab69 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/filter_flag_row.html @@ -0,0 +1,28 @@ +
+ {% for flag in flags %} +
+
+

{{ flag.title }}

+

{{ flag.desc }}

+
+
+

{{ flag.value }}

+
+ {% if flag.title == "Location" or flag.title == "Form Duration" %} +
+ + +
+ {% endif %} +
+ + + {% if flag.title != "GPS location" %} +
+ {% endif %} {% endfor %} +
diff --git a/commcare_connect/templates/tailwind/components/cards/oppurtunity_card.html b/commcare_connect/templates/tailwind/components/cards/oppurtunity_card.html new file mode 100644 index 000000000..e69de29bb diff --git a/commcare_connect/templates/tailwind/components/cards/program_card.html b/commcare_connect/templates/tailwind/components/cards/program_card.html new file mode 100644 index 000000000..b78024d47 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/program_card.html @@ -0,0 +1,58 @@ +
+
+
+
+ +
+

{{ organization_name }}

+
+
+ {% if status == 'invited' %} + {% include "tailwind/components/badges/badge_md.html" with text='invited' color='brand-deep-purple' bg_color='marigold' %} + {% elif status == 'applied' %} + {% include "tailwind/components/buttons/button_icon.html" with style='h-5' icon='download' icon_color='gray-400' %} + {% include "tailwind/components/badges/badge_md.html" with text='applied' color='white' bg_color='brand-deep-purple'%} + {% elif status == 'accepted' %} + {% include "tailwind/components/buttons/button_icon.html" with style='h-5' icon='download' icon_color='gray-400' %} + {% include "tailwind/components/badges/badge_md.html" with text='accepted' color='white' bg_color='green-600'%} + {% endif %} +
+
+
+

{{ name }}

+

{{ description }}

+
+
+
+
+

Delivery Type

+

{{ delievery_type }}

+
+
+
+
+ +
+
+

Start Date

+

{{ start_date }}

+
+ +
+

End Date

+

{{ end_date }}

+
+
+
+ {% if status == 'invited' %} + {% include 'tailwind/components/buttons/button_primary.html' with text='Apply' %} + {% elif status == 'applied' %} + {% include 'tailwind/components/buttons/button_disabled.html' with text='Apply' %} + {% elif status == 'accepted' %} + {% include 'tailwind/components/buttons/button_secondary.html' with text='View Opportunities' %} + {% endif %} +
+ {% if status == 'accepted' %} +
+ {% endif %} +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/cards/rejection_card.html b/commcare_connect/templates/tailwind/components/cards/rejection_card.html new file mode 100644 index 000000000..245b79dc5 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/rejection_card.html @@ -0,0 +1,26 @@ +
+
+

Reason for Rejection

+
+
+

+ 48 items has been marked for approval Provide a justification for approving flagged visits +

+
+
+ + +
+
+ {% include "tailwind/components/buttons/button_cancel.html" %} {% include "tailwind/components/buttons/danger.html" %} +
+
diff --git a/commcare_connect/templates/tailwind/components/cards/user_status_card.html b/commcare_connect/templates/tailwind/components/cards/user_status_card.html new file mode 100644 index 000000000..8387f28aa --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/user_status_card.html @@ -0,0 +1,22 @@ +
+
+

User Status Details

+ +
+
+ User has yellow status + {% include "tailwind/components/buttons/button_primary_sm.html" with text='Suspend' %} +
+
+
+

Data Points

+

Score

+
+ {% for row in rows %} +
+

{{ row.name }}

+

45

+
+ {% endfor %} +
+
diff --git a/commcare_connect/templates/tailwind/components/cards/user_timeline_card.html b/commcare_connect/templates/tailwind/components/cards/user_timeline_card.html new file mode 100644 index 000000000..bce167ab5 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/user_timeline_card.html @@ -0,0 +1,45 @@ +
+
+ +

User Journey Timeline

+ +
+
+ {% for data in timeline %} +
+
+ {{data.date}} +
+
+
+
+
+

{{data.title}}

+

{{data.desc}}

+
+
+
+ {% endfor %} +
+
+

March 2024

+
+ +
+ {% for data in timeline %} +
+
+ {{data.date}} +
+
+
+
+
+

{{data.title}}

+

{{data.desc}}

+
+
+
+ {% endfor %} +
+
diff --git a/commcare_connect/templates/tailwind/components/cards/worker_page/worker_dashboard_card.html b/commcare_connect/templates/tailwind/components/cards/worker_page/worker_dashboard_card.html new file mode 100644 index 000000000..b7c14ba25 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/cards/worker_page/worker_dashboard_card.html @@ -0,0 +1,26 @@ + +
+
+ +
{{count|default:"128"}}
+ + +
+
+ {{text|default:"Total Delieveries"}} + {% if dropdown %} + + {% endif %} +
+ + {% if dropdown %} + + {% endif %} +
+ diff --git a/commcare_connect/templates/tailwind/components/create/details-form.html b/commcare_connect/templates/tailwind/components/create/details-form.html new file mode 100644 index 000000000..2ed435513 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/create/details-form.html @@ -0,0 +1,30 @@ +
+

{{data.selected}}

+
+
+
Opportunity Details
+ Add the details of the opportunity. All fields are mandatory. +
+ {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/cards/card-toggle.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + +
+
+
+
Apps
+ Add the details of the opportunity. All fields are mandatory. +
+ {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} + {% include "tailwind/components/inputs/text-input.html" with title='Make this test opportunity' description='Test opportunities are hidden from users.' selected='True' %} +
+
+ {% include "tailwind/components/buttons/button_primary.html" with text='Next' %} +
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/inputs/text-input.html b/commcare_connect/templates/tailwind/components/inputs/text-input.html new file mode 100644 index 000000000..2d641b428 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/inputs/text-input.html @@ -0,0 +1,12 @@ +
+ + + +
+ + +
+ + + +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/activity.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/activity.html new file mode 100644 index 000000000..2e06f0c08 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/activity.html @@ -0,0 +1,17 @@ +
+
+ +
+
+

{{name}}

+

+ {{status}} +

+
+

{{value}}

+ {% if data.incr %} {% include "tailwind/components/badges/badge_sm.html" with text='+6 ↑' bg_color='green-600' text_color='white' %} {% + endif %} + +
diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/app.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/app.html new file mode 100644 index 000000000..798b63996 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/app.html @@ -0,0 +1,7 @@ +
+
+ +

{{title }}

+
+

{{count}}

+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/apps_list.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/apps_list.html new file mode 100644 index 000000000..726ffe8a8 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/apps_list.html @@ -0,0 +1,5 @@ +
+ {% for app in data %} + {% include 'tailwind/components/opportunity-dashboard/app.html' with icon=app.icon title=app.name count='2'%} + {% endfor %} +
diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/arrow.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/arrow.html new file mode 100644 index 000000000..9e82964e1 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/arrow.html @@ -0,0 +1,4 @@ +
+ +
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/detials.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/detials.html new file mode 100644 index 000000000..937ee03f1 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/detials.html @@ -0,0 +1,18 @@ +
+
+

Program Name

+ +
+
+
+

Opportunity Name

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididuni ipsum dolor m ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididuni

+
+
+ {% include "tailwind/components/opportunity-dashboard/apps_list.html" with data=data %} +
+
+
+ {% include "tailwind/components/opportunity-dashboard/info.html" with totalinfo=totalinfo %} +
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/info.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/info.html new file mode 100644 index 000000000..21f106a9b --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/info.html @@ -0,0 +1,11 @@ +
+ {% for data in totalinfo %} +
+ {% include 'tailwind/components/opportunity-dashboard/info_card.html' with icon=data.icon name=data.name count=data.count id=forloop.counter|stringformat:"s" %} +
+ {% if not forloop.last and forloop.counter != 2 %} +
+ {% endif %} + {% endfor %} +
{% include 'tailwind/components/badges/badge_md.html' with text='active' bg_color='green-600' text_color='' %}
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/info_card.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/info_card.html new file mode 100644 index 000000000..8e8a29360 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/info_card.html @@ -0,0 +1,7 @@ +
+ +
+

{{name }}

+

{{count }}

+
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress-breakdown.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress-breakdown.html new file mode 100644 index 000000000..3e43987fd --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress-breakdown.html @@ -0,0 +1,11 @@ +
+

{{title}}

+
+ + {% include 'tailwind/components/opportunity-dashboard/progress.html' with title='Total' value='70' progress='70' percentage='' visibility='hidden' %} + + {% include 'tailwind/components/opportunity-dashboard/progress.html' with title='Maximum' value='30' progress='30' percentage='' visibility='' %} + + {% include 'tailwind/components/opportunity-dashboard/progress.html' with title='Avg' value='14' progress='14' percentage='' visibility='' %} +
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress-view.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress-view.html new file mode 100644 index 000000000..e5b806292 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress-view.html @@ -0,0 +1,5 @@ +
+ {% include 'tailwind/components/opportunity-dashboard/progress-breakdown.html' with title='Daily Active Worker' data_a_title='maximum' data_a_value='50' %} + {% include 'tailwind/components/opportunity-dashboard/progress-breakdown.html' with title='Daily Active Worker' data_a_title='maximum' data_a_value='50' %} + {% include 'tailwind/components/opportunity-dashboard/progress-breakdown.html' with title='Daily Active Worker' data_a_title='maximum' data_a_value='50' %} +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress.html new file mode 100644 index 000000000..33f024ed7 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/progress.html @@ -0,0 +1,11 @@ +
+
+
+ {{title}} {{precentage}} +
+
+
+
+
+ {{value}} +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers-funnelview.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers-funnelview.html new file mode 100644 index 000000000..1381d0c30 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers-funnelview.html @@ -0,0 +1,12 @@ +
+

Worker Progress Funnel

+
+ {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Invited" icon="envelope" count="25" %} + {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Accepted" icon="circle-check" count="25" %} + {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Started Learning" icon="book-open-cover" count="25" %} + {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Completed Learning" icon="book-blank" count="25" %} + {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Complted Assesment" icon="award-simple" count="25" %} + {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Claimed Job" icon="user-check" count="25" %} + {% include 'tailwind/components/opportunity-dashboard/workers-stage.html' with text="Started Delivery" icon="house-chimney-user" count="25" visibility='hidden' %} +
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers-stage.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers-stage.html new file mode 100644 index 000000000..a942ca68b --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers-stage.html @@ -0,0 +1,12 @@ +
+
+
+ +
+
+ {% include 'tailwind/components/opportunity-dashboard/arrow.html' %} +
+
+

{{ count }}

+

{{ text }}

+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers_activity.html b/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers_activity.html new file mode 100644 index 000000000..452cc54ff --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-dashboard/workers_activity.html @@ -0,0 +1,28 @@ +
+ {% for op in opList %} +
+
+

{{op.opName}}

+

{{op.opLabel}} {{op.opValue}}

+
+ {% for data in op.ops %} +
+
+ +
+
+

{{data.name}}

+

{{data.status}}

+
+

{{data.value}}

+ {% if data.incr %} + {% include "tailwind/components/badges/badge_sm.html" with text='+6 ↑' bg_color='green-600' text_color='white' %} + {% endif %} +
+ +
+
+ {% endfor %} +
+{% endfor %} +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-visits/opportunity_footer.html b/commcare_connect/templates/tailwind/components/opportunity-visits/opportunity_footer.html new file mode 100644 index 000000000..a8fa03848 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-visits/opportunity_footer.html @@ -0,0 +1,40 @@ +
+ {# Navigation Buttons #} +
+ + +
+ + {# Pagination Controls #} +
+ {# Rows per Page Selector #} + + + {# Page Navigation #} + + + of 12 + +
+ + {# Action Buttons #} +
+ {% include "tailwind/components/buttons/button_secondary.html" with text="Reset" %} + {% include "tailwind/components/buttons/button_primary.html" with text="Update" %} +
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/opportunity-visits/table_header.html b/commcare_connect/templates/tailwind/components/opportunity-visits/table_header.html new file mode 100644 index 000000000..d235decdf --- /dev/null +++ b/commcare_connect/templates/tailwind/components/opportunity-visits/table_header.html @@ -0,0 +1,10 @@ +
+
+
#
+
User ID
+
Name
+
Max Visit
+
Used Visits
+
End Date
+
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/sidenav-items.html b/commcare_connect/templates/tailwind/components/sidenav-items.html new file mode 100644 index 000000000..24e36b281 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/sidenav-items.html @@ -0,0 +1,10 @@ +
+ + + {{name}} + + {% if name == 'Dashboard' %} +
+ {% endif %} + +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/tables/table.html b/commcare_connect/templates/tailwind/components/tables/table.html new file mode 100644 index 000000000..601475761 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/tables/table.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + +
MonthSavings
January$100
February$80
Sum$180
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/tables/worker_flagged_table-backup.html b/commcare_connect/templates/tailwind/components/tables/worker_flagged_table-backup.html new file mode 100644 index 000000000..e51d16490 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/tables/worker_flagged_table-backup.html @@ -0,0 +1,141 @@ +{% comment %} + + + + + Your Page + + + + + + + + {% endcomment %} +
+ + + + + + + + + + + + + + +
+
+
+ {% if table %} {% for row in table %} +
+ + + + + + + + {% endfor %} {% else %} + + + + {% endif %} + + + +
+ + TimeEntity NameFlags
+ {{ row.index }} + + {{ row.time }}{{ row.entityName }} + {% if row.flags and row.flags|length > 0 %} {% for flag in row.flags|slice:":2" %} {% include + "tailwind/components/badges/badge_sm.html" with text=flag %} {% endfor %} {% if row.flags|length > 2 %} {% include + "tailwind/components/badges/badge_sm_dropdown.html" with list=row.flags %} {% comment %} {% include + "tailwind/components/badges/badge_sm.html" with text=row.flags.0 %} {% endcomment %} {% endif %} {% endif %} + + +
No data available
+ +
+ {% comment %} + + +{% endcomment %} diff --git a/commcare_connect/templates/tailwind/components/tables/worker_flagged_table.html b/commcare_connect/templates/tailwind/components/tables/worker_flagged_table.html new file mode 100644 index 000000000..6563956d5 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/tables/worker_flagged_table.html @@ -0,0 +1,79 @@ + +{% load render_table from django_tables2 %} + +
+
+
+
+ + + + Time + Entity Name + Flags + + +
+
{% render_table table %}
+ +
+
+
+ + + + +
+
+ +
+
+
+ Rows per page + +
+ + 10 + of 12 + +
+
diff --git a/commcare_connect/templates/tailwind/components/tabs/tabs.html b/commcare_connect/templates/tailwind/components/tabs/tabs.html new file mode 100644 index 000000000..37bfa43c3 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/tabs/tabs.html @@ -0,0 +1,2 @@ +{% include "tailwind/components/tabs/tabs_header.html" with tabs=tabs %} +
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/tabs/tabs_header.html b/commcare_connect/templates/tailwind/components/tabs/tabs_header.html new file mode 100644 index 000000000..40da347e4 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/tabs/tabs_header.html @@ -0,0 +1,27 @@ +
+ {% for tab in tabs %} +
+ {{ tab.name }} + ({{ tab.count }}) +
+
+ {% endfor %} +
diff --git a/commcare_connect/templates/tailwind/components/text-input/drop_down.html b/commcare_connect/templates/tailwind/components/text-input/drop_down.html new file mode 100644 index 000000000..25a135b4c --- /dev/null +++ b/commcare_connect/templates/tailwind/components/text-input/drop_down.html @@ -0,0 +1,79 @@ + +
+
+ +
+
+ +
+ +
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/text-input/outlined_textfield.html b/commcare_connect/templates/tailwind/components/text-input/outlined_textfield.html new file mode 100644 index 000000000..9bea32ae3 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/text-input/outlined_textfield.html @@ -0,0 +1,49 @@ + +
+
+ +
+
+ +
+ +
+ + + + +
+
+
+
\ No newline at end of file diff --git a/commcare_connect/templates/tailwind/components/worker_page/detail_panel.html b/commcare_connect/templates/tailwind/components/worker_page/detail_panel.html new file mode 100644 index 000000000..7dab10db3 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/worker_page/detail_panel.html @@ -0,0 +1,192 @@ +
+
+

Details

+
+ +
+ + + + +
+

Media

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

Verification flags

+
+
+
Location
+
Less than 2m
+
+
+
Form Duration
+
4.6min
+
+
+
Photos
+
Yes
+
+
+
+ + +
+
+

Delivery Time-stamp

+ +
+
+ + +
+

Map

+
+

map image

+
+
+
+ + +
+ + +
+ + +
+ +
+
diff --git a/commcare_connect/templates/tailwind/components/worker_page/profile.html b/commcare_connect/templates/tailwind/components/worker_page/profile.html new file mode 100644 index 000000000..294988553 --- /dev/null +++ b/commcare_connect/templates/tailwind/components/worker_page/profile.html @@ -0,0 +1,29 @@ +
+
+
+
+ + + + + +
+ Profile Image z-0 +
+ +
+ +
+

Worker Name

+

ZW69YOSSRSQ203HUNH1F

+

+ + +25 472 643 0281 +

+
+
diff --git a/commcare_connect/templates/tailwind/header.html b/commcare_connect/templates/tailwind/header.html new file mode 100644 index 000000000..348e9c787 --- /dev/null +++ b/commcare_connect/templates/tailwind/header.html @@ -0,0 +1,96 @@ + + + +
+ +

Dashboard

+ + +
+ +
+ + + + +
+ + +
+ + + + +
+
+
+ + diff --git a/commcare_connect/templates/tailwind/layouts/header.html b/commcare_connect/templates/tailwind/layouts/header.html new file mode 100644 index 000000000..52c27f4a6 --- /dev/null +++ b/commcare_connect/templates/tailwind/layouts/header.html @@ -0,0 +1,88 @@ +
+
+ +

{{ header_title|default:"CommCareConnect" }}

+ + +
+ + + + + + + + +
+ + + +
+
    +
  • +

    Meca Healthcare

    +

    Program Manager

    +
  • +
  • +

    Ecma Education

    +

    Network Manager

    +
  • +
  • +

    Cmea Kindheart

    +

    Program Manager

    +
  • +
  • +

    Acme Venture

    +

    Network Manager

    +
  • +
+
+
+ + +
+ + + +
+
    +
  • +

    User Name

    + Role +
  • +
  • +

    Profile

    +
  • +
  • +

    Settings

    +
  • +
  • +
    + Logout +
    +
  • +
+
+
+ +
+
+
diff --git a/commcare_connect/templates/tailwind/layouts/sidenav.html b/commcare_connect/templates/tailwind/layouts/sidenav.html new file mode 100644 index 000000000..1e2e6cede --- /dev/null +++ b/commcare_connect/templates/tailwind/layouts/sidenav.html @@ -0,0 +1,37 @@ +{% load static i18n %} + + \ No newline at end of file diff --git a/commcare_connect/templates/tailwind/pages/create_opportunity.html b/commcare_connect/templates/tailwind/pages/create_opportunity.html new file mode 100644 index 000000000..edaa1fab0 --- /dev/null +++ b/commcare_connect/templates/tailwind/pages/create_opportunity.html @@ -0,0 +1,19 @@ + +{% extends 'tailwind/base.html' %} + +{% block content %} +
+
+ {% for data in data.stage %} +
+ +
{{data.index}}
+ +
{{data.label}}
+
+ + {% endfor %} +
+ {% include "tailwind/components/create/details-form.html" %} +
+{% endblock %} diff --git a/commcare_connect/templates/tailwind/pages/home.html b/commcare_connect/templates/tailwind/pages/home.html new file mode 100644 index 000000000..e6db395a1 --- /dev/null +++ b/commcare_connect/templates/tailwind/pages/home.html @@ -0,0 +1,35 @@ +{% extends 'tailwind/base.html' %} {% block content %} +
+ {% comment %}
{% endcomment %} + +
+ {% include "tailwind/components/worker_page/profile.html" %} + {% include "tailwind/components/cards/worker_page/worker_dashboard_card.html" %} + {% comment %}
+
{% endcomment %} +
+ + {% comment %}
+
+
+ +
+
+
+
+
+
+
{% endcomment %} + +
+ {% include "tailwind/components/cards/user_status_card.html" with rows=rows %} + {% include "tailwind/components/cards/user_timeline_card.html" with timeline=timeline%} +
+ {% include "tailwind/components/cards/approval_card.html" %} + {% include "tailwind/components/cards/rejection_card.html" %} +
+
+ {% include "tailwind/components/cards/filter_card.html" with flags=flags %} +
+ +{% endblock %} diff --git a/commcare_connect/templates/tailwind/pages/opportunities.html b/commcare_connect/templates/tailwind/pages/opportunities.html new file mode 100644 index 000000000..981b7c43a --- /dev/null +++ b/commcare_connect/templates/tailwind/pages/opportunities.html @@ -0,0 +1,14 @@ + +{% extends 'tailwind/base.html' %} + +{% block content %} +
+ {% include "tailwind/components/opportunity-dashboard/detials.html" with data=data totalinfo=totalinfo %} +
+ {% include "tailwind/components/opportunity-dashboard/workers_activity.html"%} + {% include 'tailwind/components/opportunity-dashboard/progress-view.html' with title='Daily Active Worker' data_a_title='maximum' data_a_value='50' %} +
+ {% include 'tailwind/components/opportunity-dashboard/workers-funnelview.html' %} +
+{% endblock %} + diff --git a/commcare_connect/templates/tailwind/pages/opportunity_visits.html b/commcare_connect/templates/tailwind/pages/opportunity_visits.html new file mode 100644 index 000000000..a3ddfaf8a --- /dev/null +++ b/commcare_connect/templates/tailwind/pages/opportunity_visits.html @@ -0,0 +1,25 @@ +{% extends 'tailwind/base.html' %} +{% load django_tables2 %} + +{% block content %} + {# Main container with the table #} +
+ + {# Opportunity Name Component #} +

Opportunity Name

+ + {# Content Container #} +
+ + {# Header Panel #} +
+

Adding Budget

+
+ +
+ {% render_table table %} +
+ +
+
+{% endblock %} diff --git a/commcare_connect/templates/tailwind/pages/worker.html b/commcare_connect/templates/tailwind/pages/worker.html new file mode 100644 index 000000000..b8a3d7f37 --- /dev/null +++ b/commcare_connect/templates/tailwind/pages/worker.html @@ -0,0 +1,30 @@ +{% extends 'tailwind/base.html' %} {% block content %} +
+
+ {% comment %}
{% endcomment %} + +
+ {% include "tailwind/components/worker_page/profile.html" %} + {% include "tailwind/components/cards/worker_page/worker_dashboard_card.html" with count='234' text='Total Delieveries' icon='memo' %} + {% include "tailwind/components/cards/worker_page/worker_dashboard_card.html" with count='234' text='Flagged Delieveries' icon='flag-swallowtail' dropdown='true' %} + {% include "tailwind/components/cards/worker_page/worker_dashboard_card.html" with count='234' text='Rejected Delieveries' icon='thumbs-down' dropdown='true' %} + {% include "tailwind/components/cards/worker_page/worker_dashboard_card.html" with count='234' text='Accrued Payments' icon='money-bill-simple-wave' %} + {% include "tailwind/components/cards/worker_page/worker_dashboard_card.html" with count='234' text='Paid Payments' icon='hand-holding-dollar' dropdown='true' %} + {% comment %}
+
{% endcomment %} +
+ +
+
+
+ + {% include "tailwind/components/tabs/tabs.html" with tabs=tabs %} +
+
+ {% include "tailwind/components/worker_page/detail_panel.html" %} +
+ +
+
+
+{% endblock %} diff --git a/commcare_connect/templates/tailwind/sidebar.html b/commcare_connect/templates/tailwind/sidebar.html new file mode 100644 index 000000000..5fec2dfaf --- /dev/null +++ b/commcare_connect/templates/tailwind/sidebar.html @@ -0,0 +1,75 @@ +{% load static i18n %} + + + diff --git a/commcare_connect/users/management/commands/promote_user_to_superuser.py b/commcare_connect/users/management/commands/promote_user_to_superuser.py deleted file mode 100644 index 6a55de366..000000000 --- a/commcare_connect/users/management/commands/promote_user_to_superuser.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.core.management.base import BaseCommand, CommandError - -from commcare_connect.users.models import User - - -class Command(BaseCommand): - help = "Promotes the given user to a superuser and provides admin access." - - def add_arguments(self, parser): - parser.add_argument("email", type=str) - - def handle(self, email, **options): - try: - user = User.objects.get(email=email) - except User.DoesNotExist: - raise CommandError(f"No user with email {email} found!") - user.is_superuser = True - user.is_staff = True - user.save() - print(f"{email} successfully promoted to superuser and can now access the admin site") diff --git a/commcare_connect/users/middleware.py b/commcare_connect/users/middleware.py index 4441d9d86..bed2efb37 100644 --- a/commcare_connect/users/middleware.py +++ b/commcare_connect/users/middleware.py @@ -25,7 +25,16 @@ def _get_org_membership(request): return request._cached_org_membership +def _get_all_memberships(request): + if not hasattr(request, "_cached_memberships"): + org = request.org + membership = Membership.objects.filter(user=request.user).exclude(organization=org) + request._cached_memberships = membership + return request._cached_memberships + + class OrganizationMiddleware(MiddlewareMixin): def process_view(self, request, view_func, view_args, view_kwargs): request.org = SimpleLazyObject(lambda: _get_organization(request, view_kwargs)) request.org_membership = SimpleLazyObject(lambda: _get_org_membership(request)) + request.memberships = SimpleLazyObject(lambda: _get_all_memberships(request)) diff --git a/config/settings/base.py b/config/settings/base.py index c2ddd7feb..1311142a6 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -330,7 +330,7 @@ } } -DJANGO_TABLES2_TEMPLATE = "tables/tabbed_table.html" +DJANGO_TABLES2_TEMPLATE = "tailwind/base_table.html" DJANGO_TABLES2_TABLE_ATTRS = { "class": "table table-bordered mb-0", "thead": { diff --git a/package-lock.json b/package-lock.json index 373efb7a7..01c220477 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,14 @@ "name": "commcare_connect", "version": "0.1.0", "dependencies": { + "@tailwindcss/postcss": "^4.0.14", "@turf/circle": "^6.5.0", "alpinejs": "^3.13.0", "bootstrap-icons": "^1.10.5", "bootswatch": "^5.3.2", "htmx.org": "^1.9.4", - "mapbox-gl": "^3.1.2" + "mapbox-gl": "^3.1.2", + "tailwindcss": "^4.0.14" }, "devDependencies": { "@babel/core": "^7.16.5", @@ -30,7 +32,7 @@ "mini-css-extract-plugin": "^2.4.5", "node-sass-tilde-importer": "^1.0.2", "pixrem": "^5.0.0", - "postcss": "^8.3.11", + "postcss": "^8.5.3", "postcss-loader": "^7.0.2", "postcss-preset-env": "^8.0.1", "sass": "^1.43.4", @@ -45,6 +47,17 @@ "node": "18" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -2533,6 +2546,223 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@tailwindcss/node": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.14.tgz", + "integrity": "sha512-Ux9NbFkKWYE4rfUFz6M5JFLs/GEYP6ysxT8uSyPn6aTbh2K3xDE1zz++eVK4Vwx799fzMF8CID9sdHn4j/Ab8w==", + "dependencies": { + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "tailwindcss": "4.0.14" + } + }, + "node_modules/@tailwindcss/node/node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.0.14.tgz", + "integrity": "sha512-M8VCNyO/NBi5vJ2cRcI9u8w7Si+i76a7o1vveoGtbbjpEYJZYiyc7f2VGps/DqawO56l3tImIbq2OT/533jcrA==", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.0.14", + "@tailwindcss/oxide-darwin-arm64": "4.0.14", + "@tailwindcss/oxide-darwin-x64": "4.0.14", + "@tailwindcss/oxide-freebsd-x64": "4.0.14", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.14", + "@tailwindcss/oxide-linux-arm64-gnu": "4.0.14", + "@tailwindcss/oxide-linux-arm64-musl": "4.0.14", + "@tailwindcss/oxide-linux-x64-gnu": "4.0.14", + "@tailwindcss/oxide-linux-x64-musl": "4.0.14", + "@tailwindcss/oxide-win32-arm64-msvc": "4.0.14", + "@tailwindcss/oxide-win32-x64-msvc": "4.0.14" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.0.14.tgz", + "integrity": "sha512-VBFKC2rFyfJ5J8lRwjy6ub3rgpY186kAcYgiUr8ArR8BAZzMruyeKJ6mlsD22Zp5ZLcPW/FXMasJiJBx0WsdQg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.0.14.tgz", + "integrity": "sha512-U3XOwLrefGr2YQZ9DXasDSNWGPZBCh8F62+AExBEDMLDfvLLgI/HDzY8Oq8p/JtqkAY38sWPOaNnRwEGKU5Zmg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.0.14.tgz", + "integrity": "sha512-V5AjFuc3ndWGnOi1d379UsODb0TzAS2DYIP/lwEbfvafUaD2aNZIcbwJtYu2DQqO2+s/XBvDVA+w4yUyaewRwg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.0.14.tgz", + "integrity": "sha512-tXvtxbaZfcPfqBwW3f53lTcyH6EDT+1eT7yabwcfcxTs+8yTPqxsDUhrqe9MrnEzpNkd+R/QAjJapfd4tjWdLg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.0.14.tgz", + "integrity": "sha512-cSeLNWWqIWeSTmBntQvyY2/2gcLX8rkPFfDDTQVF8qbRcRMVPLxBvFVJyfSAYRNch6ZyVH2GI6dtgALOBDpdNA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.0.14.tgz", + "integrity": "sha512-bwDWLBalXFMDItcSXzFk6y7QKvj6oFlaY9vM+agTlwFL1n1OhDHYLZkSjaYsh6KCeG0VB0r7H8PUJVOM1LRZyg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.0.14.tgz", + "integrity": "sha512-gVkJdnR/L6iIcGYXx64HGJRmlme2FGr/aZH0W6u4A3RgPMAb+6ELRLi+UBiH83RXBm9vwCfkIC/q8T51h8vUJQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.0.14.tgz", + "integrity": "sha512-EE+EQ+c6tTpzsg+LGO1uuusjXxYx0Q00JE5ubcIGfsogSKth8n8i2BcS2wYTQe4jXGs+BQs35l78BIPzgwLddw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.0.14.tgz", + "integrity": "sha512-KCCOzo+L6XPT0oUp2Jwh233ETRQ/F6cwUnMnR0FvMUCbkDAzHbcyOgpfuAtRa5HD0WbTbH4pVD+S0pn1EhNfbw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.0.14.tgz", + "integrity": "sha512-AHObFiFL9lNYcm3tZSPqa/cHGpM5wOrNmM2uOMoKppp+0Hom5uuyRh0QkOp7jftsHZdrZUpmoz0Mp6vhh2XtUg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.0.14.tgz", + "integrity": "sha512-rNXXMDJfCJLw/ZaFTOLOHoGULxyXfh2iXTGiChFiYTSgKBKQHIGEpV0yn5N25WGzJJ+VBnRjHzlmDqRV+d//oQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.0.14.tgz", + "integrity": "sha512-+uIR6KtKhla1XeIanF27KtrfYy+PX+R679v5LxbkmEZlhQe3g8rk+wKj7Xgt++rWGRuFLGMXY80Ek8JNn+kN/g==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.0.14", + "@tailwindcss/oxide": "4.0.14", + "lightningcss": "1.29.2", + "postcss": "^8.4.41", + "tailwindcss": "4.0.14" + } + }, "node_modules/@turf/circle": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-6.5.0.tgz", @@ -4108,6 +4338,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -4198,10 +4436,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.14.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", - "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", - "dev": true, + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -4751,8 +4988,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/grid-index": { "version": "1.1.0", @@ -5327,6 +5563,223 @@ "shell-quote": "^1.7.3" } }, + "node_modules/lightningcss": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", + "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.29.2", + "lightningcss-darwin-x64": "1.29.2", + "lightningcss-freebsd-x64": "1.29.2", + "lightningcss-linux-arm-gnueabihf": "1.29.2", + "lightningcss-linux-arm64-gnu": "1.29.2", + "lightningcss-linux-arm64-musl": "1.29.2", + "lightningcss-linux-x64-gnu": "1.29.2", + "lightningcss-linux-x64-musl": "1.29.2", + "lightningcss-win32-arm64-msvc": "1.29.2", + "lightningcss-win32-x64-msvc": "1.29.2" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", + "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", + "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", + "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", + "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", + "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", + "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", + "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", + "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", + "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", + "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -5623,10 +6076,9 @@ "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true, + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -5935,10 +6387,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -6003,10 +6454,9 @@ } }, "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", - "dev": true, + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -6022,9 +6472,9 @@ } ], "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -7442,10 +7892,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "engines": { "node": ">=0.10.0" } @@ -7595,11 +8044,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwindcss": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.14.tgz", + "integrity": "sha512-92YT2dpt671tFiHH/e1ok9D987N9fHD5VWoly1CdPD/Cd1HMglvZwP3nx2yTj2lbXDAHt8QssZkxTLCCTNL+xw==" + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } diff --git a/package.json b/package.json index 54d099f0f..5f300298c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "mini-css-extract-plugin": "^2.4.5", "node-sass-tilde-importer": "^1.0.2", "pixrem": "^5.0.0", - "postcss": "^8.3.11", + "postcss": "^8.5.3", "postcss-loader": "^7.0.2", "postcss-preset-env": "^8.0.1", "sass": "^1.43.4", @@ -44,11 +44,13 @@ "dev-watch": "webpack --mode development --config webpack/base.config.js --watch" }, "dependencies": { + "@tailwindcss/postcss": "^4.0.14", "@turf/circle": "^6.5.0", "alpinejs": "^3.13.0", "bootstrap-icons": "^1.10.5", "bootswatch": "^5.3.2", "htmx.org": "^1.9.4", - "mapbox-gl": "^3.1.2" + "mapbox-gl": "^3.1.2", + "tailwindcss": "^4.0.14" } } diff --git a/webpack/base.config.js b/webpack/base.config.js index 8f1fe4de3..cfba81e55 100644 --- a/webpack/base.config.js +++ b/webpack/base.config.js @@ -8,11 +8,9 @@ module.exports = { context: path.join(__dirname, '../'), entry: { project: path.resolve(__dirname, '../commcare_connect/static/js/project'), - dashboard: path.resolve( - __dirname, - '../commcare_connect/static/js/dashboard', - ), + dashboard: path.resolve(__dirname, '../commcare_connect/static/js/dashboard'), vendors: path.resolve(__dirname, '../commcare_connect/static/js/vendors'), + tailwind: path.resolve(__dirname, '../commcare_connect/static/css/tailwind.css'), }, output: { path: path.resolve(__dirname, '../commcare_connect/static/bundles/'), @@ -30,9 +28,9 @@ module.exports = { ], module: { rules: [ - // we pass the output from babel loader to react-hot loader { test: /\.js$/, + exclude: /node_modules/, loader: 'babel-loader', }, { @@ -44,7 +42,10 @@ module.exports = { loader: 'postcss-loader', options: { postcssOptions: { - plugins: ['postcss-preset-env', 'autoprefixer', 'pixrem'], + plugins: [ + require('@tailwindcss/postcss'), + require('autoprefixer'), + ], }, }, }, @@ -58,4 +59,4 @@ module.exports = { extensions: ['.js', '.jsx'], }, devtool: 'eval-cheap-source-map', -}; +}; \ No newline at end of file