up Filter, docs, base temletes

This commit is contained in:
Xander 2025-04-09 13:57:13 +03:00
parent c83938bddc
commit 13f065d4fc
13 changed files with 50230 additions and 72928 deletions

25198
logs/app.log

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -114,7 +114,8 @@ async def process_client_data(
get_jobs = await get_applied_jobs(db, user_id) get_jobs = await get_applied_jobs(db, user_id)
# [ ]: NOTE Рабоиа в фоне BackgroundTasks process_client_data() # [ ]: NOTE Рабоиа в фоне BackgroundTasks process_client_data()
@router.post("/client/") @router.post("/client/", summary="Обновления json_data и переобновление вакансий",
description="Этот эндпоинт обновляет json_data, удаляет все вакансии со статусом Scheduled и создаёт по полученным данным новые вакансии")
async def client( async def client(
data: JsonData, data: JsonData,
x_api_key: str = Header(...), x_api_key: str = Header(...),
@ -236,7 +237,8 @@ async def client(
# return {"status": "ok", "message": "JSON получен"} # return {"status": "ok", "message": "JSON получен"}
@router.post("/client_update") @router.post("/client_update", summary="Обновления клиента",
description="Этот эндпоинт получает ID пользователя, переходит по ссылки что бы получить json_data")
async def client_update(data: update, x_api_key: str = Header(...), db: Session = Depends(get_async_session)): async def client_update(data: update, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454": if x_api_key != "4545454":
@ -256,7 +258,8 @@ async def client_update(data: update, x_api_key: str = Header(...), db: Session
@router.post("/client_jobs/") @router.post("/client_jobs/", summary="Получить список работ по клиенту",
description="Этот эндпоинт получает ID пользователя, в ответ отдаёт список вакансий")
async def client_jobs(data: update, x_api_key: str = Header(...), db: Session = Depends(get_async_session)): async def client_jobs(data: update, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454": if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key") raise HTTPException(status_code=403, detail="Invalid API Key")
@ -274,7 +277,8 @@ async def client_jobs(data: update, x_api_key: str = Header(...), db: Session =
# return {"message": "JSON получен", "data": get_jobs} # return {"message": "JSON получен", "data": get_jobs}
@router.post("/avtopilot") @router.post("/avtopilot", summary="Автопилот вкл, выкл",
description="Этот эндпоинт получает ID пользователя, включает или отключает автопилот. При false все вакансии со статусом Scheduled становятся Paused при true наоборот!")
async def avtopilot(data: avtopilots, x_api_key: str = Header(...), db: Session = Depends(get_async_session)): async def avtopilot(data: avtopilots, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454": if x_api_key != "4545454":
@ -295,7 +299,8 @@ async def avtopilot(data: avtopilots, x_api_key: str = Header(...), db: Session
@router.post("/jobs_delete") @router.post("/jobs_delete", summary="Удаление вакансии",
description="Этот эндпоинт получает ID пользователя и ID вакансии, Удаляет у пользователя вакансию")
async def jobs_delete(data: jobs_delete, x_api_key: str = Header(...), db: Session = Depends(get_async_session)): async def jobs_delete(data: jobs_delete, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454": if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key") raise HTTPException(status_code=403, detail="Invalid API Key")

View File

@ -318,6 +318,10 @@ async def product_filtered(
if conditions: if conditions:
stmt = stmt.join(Job).where(and_(*conditions)) stmt = stmt.join(Job).where(and_(*conditions))
print("client_id:", client)
print("status:", status)
# Выполняем запрос # Выполняем запрос
try: try:
result = await session.execute(stmt) result = await session.execute(stmt)
@ -359,6 +363,8 @@ async def product_filtered(
"jobs": applied_jobs, "role": username["role"], "jobs": applied_jobs, "role": username["role"],
"username": username['username'], "users": users, "username": username['username'], "users": users,
"role": username["role"], "role": username["role"],
"status": status, "assigned_users_ids": assignees,
"client_id": client,
"current_path": request.url.path "current_path": request.url.path
} }

File diff suppressed because it is too large Load Diff

View File

@ -56,8 +56,38 @@
<div class="-intro-x breadcrumb mr-auto hidden sm:flex"> </div> <div class="-intro-x breadcrumb mr-auto hidden sm:flex"> </div>
<!-- END: Breadcrumb --> <!-- END: Breadcrumb -->
<h2 class="text-lg font-medium mr-auto">
{{size}}
</h2>
<!-- BEGIN: Account Menu --> {% set current_path = request.url.path %}
{% if size == "Work" %}
<a href="/productuj">
<button class="button text-white shadow-md mr-2 {% if current_path == '/productuj' %}bg-red-700{% else %}bg-theme-1{% endif %}">
Unassigned Jobs
</button>
</a>
<a href="/productmj">
<button class="button text-white shadow-md mr-2 {% if current_path == '/productmj' %}bg-red-700{% else %}bg-theme-1{% endif %}">
My Jobs
</button>
</a>
<a href="/product">
<button class="button text-white shadow-md mr-2 {% if current_path == '/product' %}bg-red-700{% else %}bg-theme-1{% endif %}">
All Jobs
</button>
</a>
<a href="/productoj">
<button class="button text-white shadow-md mr-2 {% if current_path == '/productoj' %}bg-red-700{% else %}bg-theme-1{% endif %}">
Outstanding Jobs
</button>
</a>
{% endif %}
<!-- BEGIN: Account Menu -->
<div class="intro-x dropdown w-8 h-8 relative"> <div class="intro-x dropdown w-8 h-8 relative">
<div class="dropdown-toggle w-8 h-8 rounded-full overflow-hidden shadow-lg image-fit zoom-in"> <div class="dropdown-toggle w-8 h-8 rounded-full overflow-hidden shadow-lg image-fit zoom-in">
<img alt="Midone Tailwind HTML Admin Template" src="/static/dist/images/333.png"> <img alt="Midone Tailwind HTML Admin Template" src="/static/dist/images/333.png">

View File

@ -26,23 +26,10 @@
transform: scale(1.002); /* Немного увеличиваем размер при наведении */ transform: scale(1.002); /* Немного увеличиваем размер при наведении */
} }
</style> </style>
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
</div>
<div class="p-5" id="boxed-accordion"> <div class="p-5" id="boxed-accordion">
<div class="preview"> <div class="preview">
@ -98,10 +85,10 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Applied on --> <!-- Applied on -->
<div class="col-span-6 mt-4"> <div class="w-1/2">
<div class="text-xs">Applied on</div> <div class="text-xs">Applied on</div>
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied"> <select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
<option value=""></option> <option value=""></option>
@ -121,8 +108,9 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку --> <div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
<!-- Clients (50% ширины) --> <!-- Clients (50% ширины) -->
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" --> <div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
<label class="block mb-1 text-sm">Clients</label> <label class="block mb-1 text-sm">Clients</label>
@ -147,16 +135,17 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
</div>
<!-- Status и кнопка Apply Filters --> <!-- Status и кнопка Apply Filters -->
<div class="col-span-6 mt-4"> <div class="flex-1 min-w-0">
<label>Status</label> <label>Status</label>
<div class="mt-2"> <div class="mt-2">
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status"> <select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
<option value="Scheduled">Scheduled</option> <option value="Scheduled">Scheduled</option>
<option value="Requested">Requested</option> <option value="Requested">Requested</option>
<option value="In-Progress">In-Progress</option> <option value="In-Progress">In-Progress</option>
<option value="Paused">Paused</option>
<option value="Applied">Applied</option> <option value="Applied">Applied</option>
<option value="Issues Applying">Issues Applying</option> <option value="Issues Applying">Issues Applying</option>
<option value="Cancelled">Cancelled</option> <option value="Cancelled">Cancelled</option>
@ -164,6 +153,7 @@
</div> </div>
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button> <button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
</div> </div>
</div>
</form> </form>
</div> </div>
</div> </div>
@ -241,6 +231,7 @@ document.addEventListener('DOMContentLoaded', function() {
<option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %}>Scheduled</option> <option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %}>Scheduled</option>
<option value="Requested" {% if job.status == "Requested" %}selected{% endif %}>Requested</option> <option value="Requested" {% if job.status == "Requested" %}selected{% endif %}>Requested</option>
<option value="In-Progress" {% if job.status == "In-Progress" %}selected{% endif %}>In-Progress</option> <option value="In-Progress" {% if job.status == "In-Progress" %}selected{% endif %}>In-Progress</option>
<option value="Paused" {% if job.status == "Paused" %}selected{% endif %}>Paused</option>
<option value="Applied" {% if job.status == "Applied" %}selected{% endif %}>Applied</option> <option value="Applied" {% if job.status == "Applied" %}selected{% endif %}>Applied</option>
<option value="Issues Applying" {% if job.status == "Issues Applying" %}selected{% endif %}>Issues Applying</option> <option value="Issues Applying" {% if job.status == "Issues Applying" %}selected{% endif %}>Issues Applying</option>
<option value="Cancelled" {% if job.status == "Cancelled" %}selected{% endif %}>Cancelled</option> <option value="Cancelled" {% if job.status == "Cancelled" %}selected{% endif %}>Cancelled</option>

View File

@ -4,17 +4,192 @@
{% block content %} {% block content %}
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button> <style>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button> .select2-container {
width: 100% !important;
}
</style>
<style>
.filter-link {
font-size: 18px; /* Увеличиваем размер шрифта */
font-weight: bold; /* Делаем текст жирным */
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
background-color: #7a61fe; /* Добавляем зелёный фон */
color: white; /* Текст белый */
border-radius: 5px; /* Слегка скругляем углы */
text-align: center; /* Выравнивание по центру */
cursor: pointer; /* Курсор в виде указателя при наведении */
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
}
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button> .filter-link:hover {
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button> background-color: #7a61fe; /* Темнее при наведении */
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
}
</style>
<div class="p-5" id="boxed-accordion">
<div class="preview">
<div class="accordion">
<div class="accordion__pane__content mt-3 text-gray-700 leading-relaxed">
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
<div class="dropdown-box__content box p-5">
<form method="POST" action="/productf">
<!-- Дата-фильтры (Requested, Posted, Applied) -->
<div class="flex gap-4">
<!-- Requested on -->
<div class="w-1/2">
<div class="text-xs">Requested on</div>
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
<option value=""></option>
<option value="Today">Today</option>
<option value="Last 7 days">Last 7 days</option>
<option value="For all time">For all time</option>
<option value="custom_date_requested">from date to date</option>
</select>
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
<div class="col-span-12 sm:col-span-6">
<label>From</label>
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
</div>
<div class="col-span-12 sm:col-span-6">
<label>To</label>
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
</div>
</div>
</div>
<!-- Posted on -->
<div class="w-1/2">
<div class="text-xs">Posted on</div>
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
<option value=""></option>
<option value="Today">Today</option>
<option value="Last 7 days">Last 7 days</option>
<option value="For all time">For all time</option>
<option value="custom_date_posted">from date to date</option>
</select>
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
<div class="col-span-12 sm:col-span-6">
<label>From</label>
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
</div>
<div class="col-span-12 sm:col-span-6">
<label>To</label>
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
</div>
</div>
</div>
<!-- Applied on -->
<div class="w-1/2">
<div class="text-xs">Applied on</div>
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
<option value=""></option>
<option value="Today">Today</option>
<option value="Last 7 days">Last 7 days</option>
<option value="For all time">For all time</option>
<option value="custom_date_applied">from date to date</option>
</select>
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
<div class="col-span-12 sm:col-span-6">
<label>From</label>
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
</div>
<div class="col-span-12 sm:col-span-6">
<label>To</label>
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
</div>
</div>
</div>
</div>
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
<!-- Clients (50% ширины) -->
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
<label class="block mb-1 text-sm">Clients</label>
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
{% set seen_ids = [] %}
{% for job in jobs %}
{% if job.client.id not in seen_ids %}
<option value="{{ job.client.id }}" {% if job.client.id|string in client_id %}selected{% endif %}>
{{ job.client.user_nicename }}
</option>
{% set _ = seen_ids.append(job.client.id) %}
{% endif %}
{% endfor %}
</select>
</div>
<!-- Assignee (50% ширины) -->
<div class="flex-1 min-w-0">
<label class="block mb-1 text-sm">Assignee</label>
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
{% for user in users %}
<option value="{{ user.id }}" {% if user.id|string in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
{% endfor %}
</select>
</div>
<!-- Status и кнопка Apply Filters -->
<div class="flex-1 min-w-0">
<label>Status</label>
<div class="mt-2">
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
{% for option in ["Scheduled", "Requested", "In-Progress", "Paused", "Applied", "Issues Applying", "Cancelled"] %}
<option value="{{ option }}" {% if option in status %}selected{% endif %}>{{ option }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
</div>
</div>
</form>
</div>
</div> </div>
</div>
</div>
</div>
</div>
<script>
// Функция для настройки обработчиков событий для каждого селекта
function setupDateSelect(selectId, wrapperId, customValue) {
const select = document.getElementById(selectId);
const dateRangeWrapper = document.getElementById(wrapperId);
select.addEventListener('change', function() {
if (this.value === customValue) {
dateRangeWrapper.style.display = 'grid';
} else {
dateRangeWrapper.style.display = 'none';
}
});
// Инициализация при загрузке страницы
if (select.value === customValue) {
dateRangeWrapper.style.display = 'grid';
}
}
// Настройка всех трех селектов
document.addEventListener('DOMContentLoaded', function() {
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
});
</script>
<!-- BEGIN: Datatable --> <!-- BEGIN: Datatable -->
<div class="intro-y datatable-wrapper box p-5 mt-5"> <div class="intro-y datatable-wrapper box p-5 mt-5">
<table class="table table-report table-report--bordered display datatable w-full"> <table class="table table-report table-report--bordered display datatable w-full">
@ -54,6 +229,7 @@
<option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %}>Scheduled</option> <option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %}>Scheduled</option>
<option value="Requested" {% if job.status == "Requested" %}selected{% endif %}>Requested</option> <option value="Requested" {% if job.status == "Requested" %}selected{% endif %}>Requested</option>
<option value="In-Progress" {% if job.status == "In-Progress" %}selected{% endif %}>In-Progress</option> <option value="In-Progress" {% if job.status == "In-Progress" %}selected{% endif %}>In-Progress</option>
<option value="Paused" {% if job.status == "Paused" %}selected{% endif %}>Paused</option>
<option value="Applied" {% if job.status == "Applied" %}selected{% endif %}>Applied</option> <option value="Applied" {% if job.status == "Applied" %}selected{% endif %}>Applied</option>
<option value="Issues Applying" {% if job.status == "Issues Applying" %}selected{% endif %}>Issues Applying</option> <option value="Issues Applying" {% if job.status == "Issues Applying" %}selected{% endif %}>Issues Applying</option>
<option value="Cancelled" {% if job.status == "Cancelled" %}selected{% endif %}>Cancelled</option> <option value="Cancelled" {% if job.status == "Cancelled" %}selected{% endif %}>Cancelled</option>

View File

@ -26,23 +26,6 @@
transform: scale(1.002); /* Немного увеличиваем размер при наведении */ transform: scale(1.002); /* Немного увеличиваем размер при наведении */
} }
</style> </style>
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
</div>
<div class="p-5" id="boxed-accordion"> <div class="p-5" id="boxed-accordion">
<div class="preview"> <div class="preview">

View File

@ -26,21 +26,6 @@
transform: scale(1.002); /* Немного увеличиваем размер при наведении */ transform: scale(1.002); /* Немного увеличиваем размер при наведении */
} }
</style> </style>
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
</div>

View File

@ -4,202 +4,104 @@
{% block content %} {% block content %}
<style>
.select2-container {
width: 100% !important;
}
</style>
<style>
.filter-link {
font-size: 18px; /* Увеличиваем размер шрифта */
font-weight: bold; /* Делаем текст жирным */
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
background-color: #7a61fe; /* Добавляем зелёный фон */
color: white; /* Текст белый */
border-radius: 5px; /* Слегка скругляем углы */
text-align: center; /* Выравнивание по центру */
cursor: pointer; /* Курсор в виде указателя при наведении */
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
}
.filter-link:hover {
background-color: #7a61fe; /* Темнее при наведении */
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
}
</style>
<div class="intro-y flex flex-col sm:flex-row items-center mt-8"> <div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto"> <h2 class="text-lg font-medium mr-auto">
Tasks Tasks
</h2> </h2>
<!-- BEGIN: Inbox Filter
<div class="intro-y flex flex-col-reverse sm:flex-row items-center">
<div class="w-full sm:w-auto relative mr-auto mt-3 sm:mt-0">
<i class="w-4 h-4 absolute my-auto inset-y-0 ml-3 left-0 z-10 text-gray-700" data-feather="search"></i>
<input type="text" class="input w-full sm:w-64 box px-10 text-gray-700 placeholder-theme-13" placeholder="Filter">
<div class="inbox-filter dropdown absolute inset-y-0 mr-3 right-0 flex items-center">
<i class="dropdown-toggle w-4 h-4 cursor-pointer text-gray-700" data-feather="chevron-down"></i>
<div class="inbox-filter__dropdown-box dropdown-box mt-10 absolute top-0 left-0 z-20">
<div class="dropdown-box__content box p-5">
<div class="grid grid-cols-12 gap-4 row-gap-3">
<div class="col-span-6">
<div class="text-xs">Requested o</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>Сегодня</option>
<option>Последние 7 дней</option>
<option>За все время</option>
<option>От даты - до даты.</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Posted on</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>Сегодня</option>
<option>Последние 7 дней</option>
<option>За все время</option>
<option>От даты - до даты.</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Applied on</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>Сегодня</option>
<option>Последние 7 дней</option>
<option>За все время</option>
<option>От даты - до даты.</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Client</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>-</option>
<option>-</option>
<option>-</option>
<option>-</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Assignee</div>
<select class="select2 w-full" multiple>
<option value="" selected disabled>Выберите</option>
<option>-</option>
<option>-</option>
<option>-</option>
<option>-</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Status</div>
<select class="select2 w-full" multiple>
<option>Scheduled</option>
<option>Requested</option>
<option>Applying</option>
<option>Applied</option>
</select>
</div>
<div class="col-span-12 flex items-center mt-3">
<button class="button w-32 justify-center block bg-theme-1 text-white ml-2">Search</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="w-full sm:w-auto flex">
<div class="dropdown relative">
</div>
</div>
</div>
END: Inbox Filter -->
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button> <button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button> <button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button> <button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button> <button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
</div> </div>
<div class="p-5" id="boxed-accordion">
<div class="preview">
<div class="accordion">
<div class="accordion__pane border border-gray-200 p-4 mt-3">
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
<div class="dropdown-box__content box p-5">
<form method="POST" action="/productf">
<!-- Дата-фильтры (Requested, Posted, Applied) -->
<div class="flex gap-4">
<!-- Requested on -->
<div class="w-1/2">
<div class="text-xs">Requested on</div>
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
<option value=""></option>
<option value="Today">Today</option>
<option value="Last 7 days">Last 7 days</option>
<option value="For all time">For all time</option>
<option value="custom_date_requested">from date to date</option>
</select>
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
<div class="col-span-12 sm:col-span-6">
<label>From</label>
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
</div>
<div class="col-span-12 sm:col-span-6">
<label>To</label>
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
</div>
</div>
</div>
<!-- Posted on -->
<div class="w-1/2">
<div class="text-xs">Posted on</div>
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
<option value=""></option>
<option value="Today">Today</option>
<option value="Last 7 days">Last 7 days</option>
<option value="For all time">For all time</option>
<option value="custom_date_posted">from date to date</option>
</select>
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
<div class="col-span-12 sm:col-span-6">
<label>From</label>
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
</div>
<div class="col-span-12 sm:col-span-6">
<label>To</label>
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
</div>
</div>
</div>
</div>
<!-- Applied on -->
<div class="col-span-6 mt-4">
<div class="text-xs">Applied on</div>
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
<option value=""></option>
<option value="Today">Today</option>
<option value="Last 7 days">Last 7 days</option>
<option value="For all time">For all time</option>
<option value="custom_date_applied">from date to date</option>
</select>
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
<div class="col-span-12 sm:col-span-6">
<label>From</label>
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
</div>
<div class="col-span-12 sm:col-span-6">
<label>To</label>
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
</div>
</div>
</div>
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
<!-- Clients (50% ширины) -->
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
<label class="block mb-1 text-sm">Clients</label>
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
{% set seen_ids = [] %}
{% for job in jobs %}
{% if job.client.id not in seen_ids %}
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
{% set _ = seen_ids.append(job.client.id) %}
{% endif %}
{% endfor %}
</select>
</div>
<!-- Assignee (50% ширины) -->
<div class="flex-1 min-w-0"> <!-- flex-1 дает равную ширину -->
<label class="block mb-1 text-sm">Assignee</label>
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
<option value="">— Not selected —</option>
{% for user in users %}
<option value="{{ user.id }}" {% if user.id in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
{% endfor %}
</select>
</div>
</div>
<!-- Status и кнопка Apply Filters -->
<div class="col-span-6 mt-4">
<label>Status</label>
<div class="mt-2">
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
<option value="Scheduled">Scheduled</option>
<option value="Requested">Requested</option>
<option value="In-Progress">In-Progress</option>
<option value="Applied">Applied</option>
<option value="Issues Applying">Issues Applying</option>
<option value="Cancelled">Cancelled</option>
</select>
</div>
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Функция для настройки обработчиков событий для каждого селекта
function setupDateSelect(selectId, wrapperId, customValue) {
const select = document.getElementById(selectId);
const dateRangeWrapper = document.getElementById(wrapperId);
select.addEventListener('change', function() {
if (this.value === customValue) {
dateRangeWrapper.style.display = 'grid';
} else {
dateRangeWrapper.style.display = 'none';
}
});
// Инициализация при загрузке страницы
if (select.value === customValue) {
dateRangeWrapper.style.display = 'grid';
}
}
// Настройка всех трех селектов
document.addEventListener('DOMContentLoaded', function() {
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
});
</script>
<!-- BEGIN: Datatable --> <!-- BEGIN: Datatable -->
<div class="intro-y datatable-wrapper box p-5 mt-5"> <div class="intro-y datatable-wrapper box p-5 mt-5">
<table class="table table-report table-report--bordered display datatable w-full"> <table class="table table-report table-report--bordered display datatable w-full">

View File

@ -27,22 +27,6 @@
transform: scale(1.002); /* Немного увеличиваем размер при наведении */ transform: scale(1.002); /* Немного увеличиваем размер при наведении */
} }
</style> </style>
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
</div>
<div class="p-5" id="boxed-accordion"> <div class="p-5" id="boxed-accordion">