This commit is contained in:
Xander 2025-03-12 19:36:39 +02:00
parent 5921c8874d
commit ab4454320a
7 changed files with 2261 additions and 60 deletions

File diff suppressed because it is too large Load Diff

25
main.py
View File

@ -3,7 +3,7 @@ from fastapi.responses import RedirectResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from model.database import init_db
from routers import index, logins, users, product, profile, jobs
from routers import index, logins, users, product, profile, jobs, client
import logging
@ -12,7 +12,16 @@ import logging
init_db()
# Инициализация приложения
app = FastAPI()
app = FastAPI(title="API для turboapply",
description="🚀 Это кастомное описание для Swagger UI", # ✅ Описание
version="1.0.3", # ✅ Версия API
# docs_url="/api/v1/documentation/",
redoc_url=None,
# docs_url=None, # Отключаем дефолтный Swagger
openapi_url="/openapi.json",
swagger_ui_parameters={"filter": True},
# on_startup=[start_workers]
)
# Настройка шаблонов
templates = Jinja2Templates(directory="templates")
@ -21,14 +30,16 @@ templates = Jinja2Templates(directory="templates")
app.mount("/static", StaticFiles(directory="static"), name="static")
# Подключение маршрутов
app.include_router(index.router, tags=["callback"])
app.include_router(logins.router, tags=["login"])
app.include_router(users.router, tags=["users"])
app.include_router(product.router, tags=["product"])
app.include_router(index.router, tags=["callback"], include_in_schema=False)
app.include_router(logins.router, tags=["login"], include_in_schema=False)
app.include_router(users.router, tags=["users"], include_in_schema=False)
app.include_router(product.router, tags=["product"], include_in_schema=False)
app.include_router(client.router, tags=["client"])
# Подключение роутеров
app.include_router(profile.router, tags=["Profile"])
app.include_router(jobs.router, tags=["Jobs"])
app.include_router(jobs.router, tags=["Jobs"], include_in_schema=False)
# Обработка 404
@app.exception_handler(404)

View File

@ -126,16 +126,33 @@ class Client(Base):
__tablename__ = "client"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(55), unique=True, index=True, nullable=False) # ✅ Правильно
phone = Column(String(55), unique=True, index=True, nullable=True) # ✅ Правильно
email = Column(String(55), unique=True, index=True, nullable=True) # ✅ Правильно
link = Column(String(2083), nullable=True) # URL вакансии
is_active = Column(Boolean, default=True)
user_login = Column(String(55), unique=True, index=True, nullable=False) # ✅ Правильно
user_nicename = Column(String(55), unique=True, index=True, nullable=True) # ✅ Правильно
user_email = Column(String(55), unique=True, index=True, nullable=True) # ✅ Правильно
# user_registered = Column(String(2083), nullable=True) # URL вакансии
user_status = Column(Boolean, default=True)
# Связь с AppliedJobs (заявки на вакансии)
applications = relationship("AppliedJob", back_populates="client")
class MetaClient(Base):
__tablename__ = "meta_client"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("client.id"), nullable=False)
meta_key = Column(String(255), nullable=False)
meta_value = Column(Text, nullable=True)
# Связь с Client
client = relationship("Client", back_populates="meta")
# Добавляем обратную связь в Client
Client.meta = relationship("MetaClient", back_populates="client", cascade="all, delete-orphan")
class AppliedJob(Base):
__tablename__ = "applied_jobs"
@ -151,3 +168,6 @@ class AppliedJob(Base):
job = relationship("Job", back_populates="applications")
users = relationship("User", back_populates="applications")

38
routers/client.py Normal file
View File

@ -0,0 +1,38 @@
from fastapi import FastAPI, HTTPException, APIRouter, Request, Header
from fastapi.responses import JSONResponse
from fastapi.templating import Jinja2Templates
from typing import Dict
from pydantic import BaseModel
import json
router = APIRouter()
templates = Jinja2Templates(directory="templates")
API_KEY = "4545454"
# Пример данных
clients = {
27: {"username": "John Doe", "email": "john@example.com", "phone": "+123456781"},
44: {"username": "Jane Smith", "email": "jane@example.com", "phone": "+987654321"}
}
@router.get("/get_client/{client_id}", include_in_schema=False)
async def get_client_modal(client_id: int):
client = clients.get(client_id) # Используй clients вместо clients_db
if not client:
raise HTTPException(status_code=404, detail="Client not found")
return JSONResponse(content=client)
class JsonData(BaseModel):
json_data: str
@router.post("/client/")
async def client(data: JsonData, x_api_key: str = Header(None)):
# Проверяем API-ключ
if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key")
try:
parsed_data = json.loads(data.json_data) # Декодируем JSON
print("Полученные данные:", parsed_data)
return {"message": "JSON получен", "data": parsed_data}
except json.JSONDecodeError as e:
raise HTTPException(status_code=400, detail=f"Invalid JSON: {str(e)}")

48
static/dist/js/prod.js vendored Normal file
View File

@ -0,0 +1,48 @@
function updateStatus(selectElement, jobId) {
let selectedStatus = selectElement.value;
fetch('/update_status/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
job_id: jobId,
status: selectedStatus
})
})
.then(response => response.json())
.then(data => {
console.log('Успешно обновлено:', data);
})
.catch(error => {
console.error('Ошибка:', error);
});
}
function updateAssignee(selectElement, jobId) {
let selectedUserId = selectElement.value;
fetch('/update_assignee/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
job_id: jobId,
assignee_id: selectedUserId
})
})
.then(response => response.json())
.then(data => {
console.log('Успешно обновлено:', data);
})
.catch(error => {
console.error('Ошибка:', error);
});
}

101
templates/modal.html Normal file
View File

@ -0,0 +1,101 @@
<!-- Модальное окно &times;-->
<!-- Модальное окно &times;-->
<div id="client-modal" class="fixed inset-0 hidden bg-gray-800 bg-opacity-75 flex items-center justify-center z-50">
<div class="bg-white rounded-lg p-6 w-1/3 relative shadow-2xl">
<span id="close-modal" class="absolute top-2 right-4 text-xl cursor-pointer"></span>
<h2 class="modal__content">Client Details</h2>
<div class="post intro-y overflow-hidden box mt-5">
<div class="post__tabs nav-tabs flex flex-col sm:flex-row bg-gray-200 text-gray-600">
<a title="Main" data-toggle="tab" data-target="#content" href="javascript:;" class="tooltip w-full sm:w-40 py-4 text-center flex justify-center items-center active"> <i data-feather="file-text" class="w-4 h-4 mr-2"></i> Main </a>
<a title="Profile" data-toggle="tab" data-target="#prom" href="javascript:;" class="tooltip w-full sm:w-40 py-4 text-center flex justify-center items-center"> <i data-feather="code" class="w-4 h-4 mr-2"></i> Profile </a>
<a title="Knowledge Base" data-toggle="tab" data-target="#rozetka" href="javascript:;" class="tooltip w-full sm:w-40 py-4 text-center flex justify-center items-center"> <i data-feather="align-left" class="w-4 h-4 mr-2"></i> Knowledge Base </a>
</div>
<div class="post__content tab-content">
<div class="tab-content__pane p-5 active" id="content">
<div class="border border-gray-200 rounded-md p-5 mt-5">
<p><strong>Name:</strong> <span id="client-name"></span></p>
<p><strong>Email:</strong> <span id="client-email"></span></p>
<p><strong>Phone:</strong> <span id="client-phone"></span></p>
</div>
</div>
<div class="tab-content__pane p-5 " id="prom">
<div class="border border-gray-200 rounded-md p-5 mt-5">
</div>
</div>
<div class="tab-content__pane p-5" id="rozetka">
<div class="border border-gray-200 rounded-md p-5 mt-5">
</div>
</div>
</div>
</div>
</div>
<!-- END: Post Content -->
<!-- BEGIN: Post Info -->
</div>
</div>
</div>
<!-- JS только для модалки -->
<script>
document.addEventListener("DOMContentLoaded", () => {
const modal = document.getElementById("client-modal");
const closeModal = document.getElementById("close-modal");
// Открытие модалки по клику на имя клиента
document.querySelectorAll(".client-link").forEach(link => {
link.addEventListener("click", (e) => {
e.preventDefault();
const clientId = link.getAttribute("data-client-id");
fetch(`/get_client/${clientId}`)
.then(response => response.json())
.then(data => {
document.getElementById("client-name").textContent = data.username;
document.getElementById("client-email").textContent = data.email;
document.getElementById("client-phone").textContent = data.phone;
modal.classList.remove("hidden");
})
.catch(err => console.error("Error fetching client data:", err));
});
});
// Закрытие модалки
closeModal.addEventListener("click", () => {
modal.classList.add("hidden");
});
// Закрытие по клику вне модалки
modal.addEventListener("click", (e) => {
if (e.target === modal) {
modal.classList.add("hidden");
}
});
});
</script>

View File

@ -35,7 +35,12 @@
<div class="text-gray-600 text-xs whitespace-no-wrap">{{ job.job.job_id }}</div>
</td>
<td class="text-center border-b">Company</td>
<td class="text-center border-b">{{job.client.username}}</td>
<td class="text-center border-b">
<a href="#" class="client-link text-blue-500" data-client-id="{{ job.client.id }}">{{ job.client.user_nicename }}</a>
</td>
<td class="text-center border-b">Requested on</td>
<td class="text-center border-b">Posted on</td>
<td class="text-center border-b">
@ -66,52 +71,9 @@
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку -->
<!-- Модальное окно -->
{% include "modal.html" %}
<script src="/static/dist/js/prod.js"></script>
<script>
function updateStatus(selectElement, jobId) {
let selectedStatus = selectElement.value;
fetch('/update_status/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
job_id: jobId,
status: selectedStatus
})
})
.then(response => response.json())
.then(data => {
console.log('Успешно обновлено:', data);
})
.catch(error => {
console.error('Ошибка:', error);
});
}
function updateAssignee(selectElement, jobId) {
let selectedUserId = selectElement.value;
fetch('/update_assignee/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
job_id: jobId,
assignee_id: selectedUserId
})
})
.then(response => response.json())
.then(data => {
console.log('Успешно обновлено:', data);
})
.catch(error => {
console.error('Ошибка:', error);
});
}
</script>
{% endblock %}