diff --git a/app/interfaces/web/routes/profile.py b/app/interfaces/web/routes/profile.py index 413c2f0..0462ed4 100644 --- a/app/interfaces/web/routes/profile.py +++ b/app/interfaces/web/routes/profile.py @@ -209,6 +209,76 @@ def _render_profile_shell(request: Request, flash: str): ) +def _render_profile_skills_shell(request: Request, flash: str = "", include_oob: bool = False): + context = _build_profile_context(flash=flash) + template_name = "profile/_skills_fragment.html" if include_oob else "profile/_skills_shell.html" + return templates.TemplateResponse( + request=request, + name=template_name, + context={ + "request": request, + **context, + "skills_flash_message": context["flash_message"] if flash else None, + }, + ) + + +def _render_profile_basics_shell(request: Request, flash: str = "", include_oob: bool = False): + context = _build_profile_context(flash=flash) + template_name = "profile/_basics_fragment.html" if include_oob else "profile/_basics.html" + return templates.TemplateResponse( + request=request, + name=template_name, + context={ + "request": request, + **context, + "basics_flash_message": context["flash_message"] if flash else None, + }, + ) + + +def _render_profile_formation_shell(request: Request, flash: str = "", include_oob: bool = False): + context = _build_profile_context(flash=flash) + template_name = "profile/_formation_fragment.html" if include_oob else "profile/_formation_shell.html" + return templates.TemplateResponse( + request=request, + name=template_name, + context={ + "request": request, + **context, + "formation_flash_message": context["flash_message"] if flash else None, + }, + ) + + +def _render_profile_projects_shell(request: Request, flash: str = "", include_oob: bool = False): + context = _build_profile_context(flash=flash) + template_name = "profile/_projects_fragment.html" if include_oob else "profile/_projects_shell.html" + return templates.TemplateResponse( + request=request, + name=template_name, + context={ + "request": request, + **context, + "projects_flash_message": context["flash_message"] if flash else None, + }, + ) + + +def _render_profile_experiences_shell(request: Request, flash: str = "", include_oob: bool = False): + context = _build_profile_context(flash=flash) + template_name = "profile/_experiences_fragment.html" if include_oob else "profile/_experiences_shell.html" + return templates.TemplateResponse( + request=request, + name=template_name, + context={ + "request": request, + **context, + "experiences_flash_message": context["flash_message"] if flash else None, + }, + ) + + @router.get("/app/profile") def profile_index(request: Request, flash: str | None = None): context = _build_profile_context(flash=flash) @@ -230,6 +300,31 @@ def profile_shell_partial(request: Request, flash: str | None = None): return _render_profile_shell(request, flash or "") +@router.get("/app/profile/skills", response_class=HTMLResponse) +def profile_skills_partial(request: Request, flash: str | None = None): + return _render_profile_skills_shell(request, flash or "") + + +@router.get("/app/profile/basics", response_class=HTMLResponse) +def profile_basics_partial(request: Request, flash: str | None = None): + return _render_profile_basics_shell(request, flash or "") + + +@router.get("/app/profile/formation", response_class=HTMLResponse) +def profile_formation_partial(request: Request, flash: str | None = None): + return _render_profile_formation_shell(request, flash or "") + + +@router.get("/app/profile/projects", response_class=HTMLResponse) +def profile_projects_partial(request: Request, flash: str | None = None): + return _render_profile_projects_shell(request, flash or "") + + +@router.get("/app/profile/experiences", response_class=HTMLResponse) +def profile_experiences_partial(request: Request, flash: str | None = None): + return _render_profile_experiences_shell(request, flash or "") + + @router.post("/app/profile/save") def save_profile( request: Request, @@ -268,7 +363,7 @@ def save_profile( ) flash = "profile_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_basics_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -287,7 +382,7 @@ def add_skill( flash = "skill_added" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_skills_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -296,7 +391,7 @@ def delete_skill(request: Request, skill_id: int): result = profile_repository.delete_skill(skill_id) flash = "skill_deleted" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_skills_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -333,7 +428,7 @@ def add_experience( ) flash = "experience_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_experiences_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -367,7 +462,7 @@ def update_experience( ) flash = "experience_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_experiences_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -376,7 +471,7 @@ def delete_experience(request: Request, experience_id: int): result = profile_repository.delete_experience(experience_id) flash = "experience_deleted" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_experiences_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -415,7 +510,7 @@ def add_project( ) flash = "project_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_projects_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -451,7 +546,7 @@ def update_project( ) flash = "project_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_projects_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -460,7 +555,7 @@ def delete_project(request: Request, project_id: int): result = profile_repository.delete_project(project_id) flash = "project_deleted" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_projects_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -493,7 +588,7 @@ def add_education( ) flash = "education_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_formation_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -502,7 +597,7 @@ def delete_education(request: Request, education_id: int): result = profile_repository.delete_education(education_id) flash = "education_deleted" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_formation_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -533,7 +628,7 @@ def add_course( ) flash = "course_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_formation_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -542,7 +637,7 @@ def delete_course(request: Request, course_id: int): result = profile_repository.delete_course(course_id) flash = "course_deleted" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_formation_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -573,7 +668,7 @@ def add_certification( ) flash = "certification_saved" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_formation_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) @@ -582,6 +677,6 @@ def delete_certification(request: Request, certification_id: int): result = profile_repository.delete_certification(certification_id) flash = "certification_deleted" if result["success"] else "profile_error" if request.headers.get("HX-Request") == "true": - return _render_profile_shell(request, flash) + return _render_profile_formation_shell(request, flash, include_oob=True) return RedirectResponse(url=f"/app/profile?flash={flash}", status_code=303) diff --git a/app/interfaces/web/static/css/app.css b/app/interfaces/web/static/css/app.css index 4e637a8..b930856 100644 --- a/app/interfaces/web/static/css/app.css +++ b/app/interfaces/web/static/css/app.css @@ -1,3 +1,4 @@ +/* Layer 1: Design tokens */ :root { --bg: #f5f7fb; --surface: #ffffff; @@ -12,6 +13,7 @@ --shadow: 0 10px 24px rgba(15, 23, 42, 0.08); } +/* Layer 2: Reset and base elements */ * { box-sizing: border-box; } @@ -27,6 +29,7 @@ a { color: var(--brand); } +/* Layer 3: Global shell and page layout */ .shell-header, .kpi-strip, .page-shell { @@ -214,6 +217,7 @@ a { font-size: 0.92rem; } +/* Layer 4: Shared surfaces, links and summary components */ .primary-link, .stack-form button { display: inline-flex; @@ -304,6 +308,7 @@ a { color: var(--muted); } +/* Layer 5: Forms and interactive controls */ .filter-form { display: grid; grid-template-columns: minmax(0, 2fr) minmax(220px, 1fr) auto; @@ -403,6 +408,7 @@ a { font: inherit; } +/* Layer 6: Shared tables, rows, details and status states */ .simple-table { display: grid; gap: 8px; @@ -782,6 +788,7 @@ a { padding: 16px; } +/* Layer 7: Vacancies feature */ .inbox-workspace { align-items: start; } @@ -1086,6 +1093,35 @@ a { margin: 0; } +/* Layer 8: Applications feature */ +.application-row { + border: 1px solid var(--border); + border-radius: 14px; + background: #fbfcfe; +} + +.application-row:hover { + border-color: #bfdbfe; + background: #f8fbff; + transform: translateY(-1px); +} + +.application-row.is-selected { + border-color: #b3c9ff; + background: #eef4ff; + box-shadow: inset 4px 0 0 #1d4ed8; +} + +.application-list-panel, +.application-detail-panel { + min-width: 0; +} + +.application-detail-panel { + align-self: start; +} + +/* Layer 9: Shared helpers and feedback */ .pill-group { display: flex; flex-wrap: wrap; @@ -1120,6 +1156,7 @@ a { margin: 0 0 8px; } +/* Layer 10: Flash feedback states */ .flash-message { margin-bottom: 14px; padding: 12px 14px; @@ -1145,6 +1182,7 @@ a { color: #92400e; } +/* Layer 11: Profile feature and CV preview */ .profile-grid { display: grid; grid-template-columns: repeat(2, 1fr); @@ -1457,6 +1495,7 @@ a { color: var(--text); } +/* Layer 12: Responsive adjustments */ @media (max-width: 900px) { .shell-header, .page-header { diff --git a/app/interfaces/web/templates/applications/_filters.html b/app/interfaces/web/templates/applications/_filters.html new file mode 100644 index 0000000..c10c9af --- /dev/null +++ b/app/interfaces/web/templates/applications/_filters.html @@ -0,0 +1,35 @@ +
+
+ + + + + +
+
diff --git a/app/interfaces/web/templates/applications/_list.html b/app/interfaces/web/templates/applications/_list.html index 2ecb11b..a6e507c 100644 --- a/app/interfaces/web/templates/applications/_list.html +++ b/app/interfaces/web/templates/applications/_list.html @@ -9,7 +9,7 @@ {% for item in applications %} {% endfor %} - {% if pagination.total_pages > 1 %} -
- {% if pagination.has_prev %} - Anterior - {% endif %} - Pagina {{ pagination.page }} de {{ pagination.total_pages }} - {% if pagination.has_next %} - Siguiente - {% endif %} -
- {% endif %} + {% set pagination_prev_href = "/app/applications?q=%s&state=%s&page=%s&page_size=%s"|format(query, current_state, pagination.prev_page, pagination.page_size) %} + {% set pagination_prev_hx_get = "/app/applications/shell?q=%s&state=%s&page=%s&page_size=%s"|format(query, current_state, pagination.prev_page, pagination.page_size) %} + {% set pagination_next_href = "/app/applications?q=%s&state=%s&page=%s&page_size=%s"|format(query, current_state, pagination.next_page, pagination.page_size) %} + {% set pagination_next_hx_get = "/app/applications/shell?q=%s&state=%s&page=%s&page_size=%s"|format(query, current_state, pagination.next_page, pagination.page_size) %} + {% set pagination_hx_target = "#applications-shell" %} + {% set pagination_hx_swap = "outerHTML" %} + {% set pagination_hx_push_url = "true" %} + {% include "components/_pagination.html" %} {% else %}

Sin coincidencias

diff --git a/app/interfaces/web/templates/applications/_shell.html b/app/interfaces/web/templates/applications/_shell.html index f087755..9073819 100644 --- a/app/interfaces/web/templates/applications/_shell.html +++ b/app/interfaces/web/templates/applications/_shell.html @@ -1,53 +1,19 @@ {% if flash_message %} -
- {{ flash_message[1] }} -
+ {% set flash_tone = flash_message[0] %} + {% set flash_text = flash_message[1] %} + {% include "components/_flash.html" %} {% endif %} -
-
- - - - - -
-
+{% include "applications/_filters.html" %}
-
+
{% include "applications/_list.html" %}
-
+
{% include "applications/_detail.html" %}
diff --git a/app/interfaces/web/templates/applications/index.html b/app/interfaces/web/templates/applications/index.html index 8897e0c..4075b9b 100644 --- a/app/interfaces/web/templates/applications/index.html +++ b/app/interfaces/web/templates/applications/index.html @@ -1,12 +1,10 @@ {% extends "base.html" %} {% block content %} - +{% set page_header_title = "Seguimiento" %} +{% set page_header_description = "Control simple de vacantes que ya te interesan o a las que ya aplicaste." %} +{% set page_header_copy_class = none %} +{% include "components/_page_header.html" %}
{% include "applications/_shell.html" %} diff --git a/app/interfaces/web/templates/components/_flash.html b/app/interfaces/web/templates/components/_flash.html new file mode 100644 index 0000000..c10d301 --- /dev/null +++ b/app/interfaces/web/templates/components/_flash.html @@ -0,0 +1,3 @@ +
+ {{ flash_text }} +
diff --git a/app/interfaces/web/templates/components/_page_header.html b/app/interfaces/web/templates/components/_page_header.html new file mode 100644 index 0000000..3e0a299 --- /dev/null +++ b/app/interfaces/web/templates/components/_page_header.html @@ -0,0 +1,6 @@ +
+
diff --git a/app/interfaces/web/templates/components/_pagination.html b/app/interfaces/web/templates/components/_pagination.html new file mode 100644 index 0000000..29d9af1 --- /dev/null +++ b/app/interfaces/web/templates/components/_pagination.html @@ -0,0 +1,25 @@ +{% if pagination.total_pages > 1 %} +
+ {% if pagination.has_prev %} + Anterior + {% endif %} + Pagina {{ pagination.page }} de {{ pagination.total_pages }} + {% if pagination.has_next %} + Siguiente + {% endif %} +
+{% endif %} diff --git a/app/interfaces/web/templates/profile/_basics.html b/app/interfaces/web/templates/profile/_basics.html new file mode 100644 index 0000000..4e50e27 --- /dev/null +++ b/app/interfaces/web/templates/profile/_basics.html @@ -0,0 +1,57 @@ +
+ {% if basics_flash_message %} + {% set flash_tone = basics_flash_message[0] %} + {% set flash_text = basics_flash_message[1] %} + {% include "components/_flash.html" %} + {% endif %} +
+
+

Datos principales

+

Estos datos alimentan el analisis de vacantes y el resumen general del perfil.

+
+
+

Los campos de esta seccion son la base del perfil y del contexto que consume el analizador.

+
+
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+
+ + + +
+
+ +
+ Modalidades aceptadas +
+ {% for option in modality_options %} + + {% endfor %} +
+
+
+ +
+
diff --git a/app/interfaces/web/templates/profile/_basics_fragment.html b/app/interfaces/web/templates/profile/_basics_fragment.html new file mode 100644 index 0000000..cb13dcc --- /dev/null +++ b/app/interfaces/web/templates/profile/_basics_fragment.html @@ -0,0 +1,7 @@ +{% set skills_shell_oob = true %} +{% include "profile/_skills_shell.html" %} + +{% set cv_preview_oob = true %} +{% include "profile/_cv_preview.html" %} + +{% include "profile/_basics.html" %} diff --git a/app/interfaces/web/templates/profile/_certifications.html b/app/interfaces/web/templates/profile/_certifications.html new file mode 100644 index 0000000..08fc722 --- /dev/null +++ b/app/interfaces/web/templates/profile/_certifications.html @@ -0,0 +1,38 @@ +
+

Certificaciones

Credenciales y badges relevantes para tus postulaciones.

{{ certifications|length }} registros
+
+ Agregar certificacion +
+
+ + +
+
+ + + +
+ + +
+
+ {% if certifications %} +
+ {% for item in certifications %} +
+
+

{{ item.titulo }}

{{ item.institucion }}

+ {{ item.status }} +
+
+
+ +
+
+
+ {% endfor %} +
+ {% else %} +

Sin certificaciones registradas

No hay certificaciones cargadas todavia.

+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_courses.html b/app/interfaces/web/templates/profile/_courses.html new file mode 100644 index 0000000..9b0030e --- /dev/null +++ b/app/interfaces/web/templates/profile/_courses.html @@ -0,0 +1,38 @@ +
+

Cursos

Formacion complementaria para reforzar tu perfil.

{{ courses|length }} registros
+
+ Agregar curso +
+
+ + +
+
+ + + +
+ + +
+
+ {% if courses %} +
+ {% for item in courses %} +
+
+

{{ item.titulo }}

{{ item.institucion }}

+ {{ item.status }} +
+
+
+ +
+
+
+ {% endfor %} +
+ {% else %} +

Sin cursos registrados

No hay cursos cargados todavia.

+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_cv_preview.html b/app/interfaces/web/templates/profile/_cv_preview.html new file mode 100644 index 0000000..7cb7033 --- /dev/null +++ b/app/interfaces/web/templates/profile/_cv_preview.html @@ -0,0 +1,16 @@ +
+
+
+

Vista CV

+

Vista de solo lectura del perfil consolidado para revisar como se presentaria tu hoja de vida.

+
+
+ {% if cv_preview_html %} + {{ cv_preview_html | safe }} + {% else %} +
+

Sin vista CV disponible

+

Completa los datos principales del perfil para generar esta vista.

+
+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_education.html b/app/interfaces/web/templates/profile/_education.html new file mode 100644 index 0000000..828c86e --- /dev/null +++ b/app/interfaces/web/templates/profile/_education.html @@ -0,0 +1,41 @@ +
+

Educacion

Formacion academica principal.

{{ education|length }} registros
+
+ Agregar educacion +
+
+ + +
+
+ + + +
+
+ + +
+ +
+
+ {% if education %} +
+ {% for item in education %} +
+
+

{{ item.titulo }}

{{ item.institucion }} · {{ item.nivel }}

+ {{ item.status }} +
+
+
+ +
+
+
+ {% endfor %} +
+ {% else %} +

Sin educacion registrada

No hay estudios cargados todavia.

+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_experience_record.html b/app/interfaces/web/templates/profile/_experience_record.html new file mode 100644 index 0000000..af63a23 --- /dev/null +++ b/app/interfaces/web/templates/profile/_experience_record.html @@ -0,0 +1,31 @@ +
+ +
+

{{ item.cargo }} · {{ item.empresa }}

{{ item.ciudad or '-' }}

+ {{ item.fecha_inicio.strftime("%m/%Y") if item.fecha_inicio else "-" }} - {% if item.es_trabajo_actual %}Actual{% elif item.fecha_fin %}{{ item.fecha_fin.strftime("%m/%Y") }}{% else %}-{% endif %} +
+
+
+
+
+ + +
+
+ + +
+
+ + + +
+ + +
+
+
+ +
+
+
diff --git a/app/interfaces/web/templates/profile/_experiences.html b/app/interfaces/web/templates/profile/_experiences.html new file mode 100644 index 0000000..bd8e653 --- /dev/null +++ b/app/interfaces/web/templates/profile/_experiences.html @@ -0,0 +1,33 @@ +
+

Experiencia

Registra y actualiza tu trayectoria laboral actual.

{{ experiences|length }} registradas
+
+ Agregar experiencia +
+
+ + +
+
+ + +
+
+ + + +
+ + + +
+
+ {% if experiences %} +
+ {% for item in experiences %} + {% include "profile/_experience_record.html" %} + {% endfor %} +
+ {% else %} +

Sin experiencia registrada

Aun no hay experiencias cargadas en el perfil.

+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_experiences_fragment.html b/app/interfaces/web/templates/profile/_experiences_fragment.html new file mode 100644 index 0000000..c7ca43f --- /dev/null +++ b/app/interfaces/web/templates/profile/_experiences_fragment.html @@ -0,0 +1,11 @@ +
+ {% include "profile/_overview.html" %} +
+ +{% set skills_shell_oob = true %} +{% include "profile/_skills_shell.html" %} + +{% set cv_preview_oob = true %} +{% include "profile/_cv_preview.html" %} + +{% include "profile/_experiences_shell.html" %} diff --git a/app/interfaces/web/templates/profile/_experiences_shell.html b/app/interfaces/web/templates/profile/_experiences_shell.html new file mode 100644 index 0000000..cd25238 --- /dev/null +++ b/app/interfaces/web/templates/profile/_experiences_shell.html @@ -0,0 +1,11 @@ +
+ {% if experiences_flash_message %} + {% set flash_tone = experiences_flash_message[0] %} + {% set flash_text = experiences_flash_message[1] %} + {% include "components/_flash.html" %} + {% endif %} + +
+ {% include "profile/_experiences.html" %} +
+
diff --git a/app/interfaces/web/templates/profile/_formation_fragment.html b/app/interfaces/web/templates/profile/_formation_fragment.html new file mode 100644 index 0000000..1314b26 --- /dev/null +++ b/app/interfaces/web/templates/profile/_formation_fragment.html @@ -0,0 +1,11 @@ +
+ {% include "profile/_overview.html" %} +
+ +{% set skills_shell_oob = true %} +{% include "profile/_skills_shell.html" %} + +{% set cv_preview_oob = true %} +{% include "profile/_cv_preview.html" %} + +{% include "profile/_formation_shell.html" %} diff --git a/app/interfaces/web/templates/profile/_formation_shell.html b/app/interfaces/web/templates/profile/_formation_shell.html new file mode 100644 index 0000000..3a4a353 --- /dev/null +++ b/app/interfaces/web/templates/profile/_formation_shell.html @@ -0,0 +1,16 @@ +
+ {% if formation_flash_message %} + {% set flash_tone = formation_flash_message[0] %} + {% set flash_text = formation_flash_message[1] %} + {% include "components/_flash.html" %} + {% endif %} + +
+ {% include "profile/_education.html" %} + {% include "profile/_courses.html" %} +
+ +
+ {% include "profile/_certifications.html" %} +
+
diff --git a/app/interfaces/web/templates/profile/_overview.html b/app/interfaces/web/templates/profile/_overview.html new file mode 100644 index 0000000..74a5af6 --- /dev/null +++ b/app/interfaces/web/templates/profile/_overview.html @@ -0,0 +1,16 @@ +
+
Skills
{{ skills|length }}
+
Experiencias
{{ experiences|length }}
+
Formacion
{{ education|length + courses|length + certifications|length }}
+
+ +
+
+

Como usar esta pantalla

+

Empieza por datos principales y skills. Luego completa experiencia y proyectos para mejorar el analisis de vacantes.

+
+
+

Vista CV

+

La vista CV se actualiza con la informacion registrada aqui y te sirve para revisar la consistencia general del perfil.

+
+
diff --git a/app/interfaces/web/templates/profile/_profile_status.html b/app/interfaces/web/templates/profile/_profile_status.html new file mode 100644 index 0000000..9aec520 --- /dev/null +++ b/app/interfaces/web/templates/profile/_profile_status.html @@ -0,0 +1,14 @@ +
+

Estado del perfil

+ +
+

Estado de migracion

+

Mi Perfil ya puede mantenerse desde la web para el flujo principal del producto.

+
+
diff --git a/app/interfaces/web/templates/profile/_project_record.html b/app/interfaces/web/templates/profile/_project_record.html new file mode 100644 index 0000000..25ef504 --- /dev/null +++ b/app/interfaces/web/templates/profile/_project_record.html @@ -0,0 +1,32 @@ +
+ +
+

{{ item.nombre }}

{{ item.empresa or 'Proyecto personal' }}

+ {% if item.stack %}{{ item.stack }}{% endif %} +
+
+
+
+
+ + +
+
+ + +
+
+ + + +
+ + + +
+
+
+ +
+
+
diff --git a/app/interfaces/web/templates/profile/_projects.html b/app/interfaces/web/templates/profile/_projects.html new file mode 100644 index 0000000..078344a --- /dev/null +++ b/app/interfaces/web/templates/profile/_projects.html @@ -0,0 +1,34 @@ +
+

Proyectos

Proyectos que respaldan tu experiencia tecnica.

{{ projects|length }} registrados
+
+ Agregar proyecto +
+
+ + +
+
+ + +
+
+ + + +
+ + + + +
+
+ {% if projects %} +
+ {% for item in projects %} + {% include "profile/_project_record.html" %} + {% endfor %} +
+ {% else %} +

Sin proyectos registrados

No hay proyectos cargados todavia.

+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_projects_fragment.html b/app/interfaces/web/templates/profile/_projects_fragment.html new file mode 100644 index 0000000..74e0541 --- /dev/null +++ b/app/interfaces/web/templates/profile/_projects_fragment.html @@ -0,0 +1,4 @@ +{% set skills_shell_oob = true %} +{% include "profile/_skills_shell.html" %} + +{% include "profile/_projects_shell.html" %} diff --git a/app/interfaces/web/templates/profile/_projects_shell.html b/app/interfaces/web/templates/profile/_projects_shell.html new file mode 100644 index 0000000..fa78023 --- /dev/null +++ b/app/interfaces/web/templates/profile/_projects_shell.html @@ -0,0 +1,11 @@ +
+ {% if projects_flash_message %} + {% set flash_tone = projects_flash_message[0] %} + {% set flash_text = projects_flash_message[1] %} + {% include "components/_flash.html" %} + {% endif %} + +
+ {% include "profile/_projects.html" %} +
+
diff --git a/app/interfaces/web/templates/profile/_shell.html b/app/interfaces/web/templates/profile/_shell.html index 922b81d..044c2a8 100644 --- a/app/interfaces/web/templates/profile/_shell.html +++ b/app/interfaces/web/templates/profile/_shell.html @@ -1,411 +1,27 @@ {% if flash_message %} -
{{ flash_message[1] }}
+ {% set flash_tone = flash_message[0] %} + {% set flash_text = flash_message[1] %} + {% include "components/_flash.html" %} {% endif %} -
-
Skills
{{ skills|length }}
-
Experiencias
{{ experiences|length }}
-
Formacion
{{ education|length + courses|length + certifications|length }}
-
- -
-
-

Como usar esta pantalla

-

Empieza por datos principales y skills. Luego completa experiencia y proyectos para mejorar el analisis de vacantes.

-
-
-

Vista CV

-

La vista CV se actualiza con la informacion registrada aqui y te sirve para revisar la consistencia general del perfil.

-
-
+
+ {% include "profile/_overview.html" %} +
-
-
-
-

Datos principales

-

Estos datos alimentan el analisis de vacantes y el resumen general del perfil.

-
-
-

Los campos de esta seccion son la base del perfil y del contexto que consume el analizador.

-
-
- - -
-
- - -
- -
- - -
-
- - -
-
- - - -
-
- -
- Modalidades aceptadas -
- {% for option in modality_options %} - - {% endfor %} -
-
-
- -
-
+ {% include "profile/_basics.html" %} -
-
-
-
-

Skills

-

Manten tus skills clave visibles para el analisis de afinidad.

-
-
-

Mantener skills claras y concretas ayuda a que la afinidad con vacantes sea mas fiable.

-
-
- - -
- - -
- {% if skills %} -
- {% for item in skills %} -
-
-
-

{{ item.skill }}

-

{{ item.categoria }} · {{ item.nivel }}

-
-
- -
-
-
- {% endfor %} -
- {% else %} -

Sin skills

Agrega tus skills principales para que el analisis de vacantes sea mas preciso.

- {% endif %} -
- -
-

Estado del perfil

-
    -
  • Datos principales: {% if profile %}configurados{% else %}pendientes{% endif %}
  • -
  • Skills registradas: {{ skills|length }}
  • -
  • Experiencias registradas: {{ experiences|length }}
  • -
  • Proyectos registrados: {{ projects|length }}
  • -
  • Formacion registrada: {{ education|length + courses|length + certifications|length }}
  • -
-
-

Estado de migracion

-

Mi Perfil ya puede mantenerse desde la web para el flujo principal del producto.

-
-
-
+ {% include "profile/_skills_shell.html" %}
-
-

Experiencia

Registra y actualiza tu trayectoria laboral actual.

{{ experiences|length }} registradas
-
- Agregar experiencia -
-
- - -
-
- - -
-
- - - -
- - - -
-
- {% if experiences %} -
- {% for item in experiences %} -
- -
-

{{ item.cargo }} · {{ item.empresa }}

{{ item.ciudad or '-' }}

- {{ item.fecha_inicio.strftime("%m/%Y") if item.fecha_inicio else "-" }} - {% if item.es_trabajo_actual %}Actual{% elif item.fecha_fin %}{{ item.fecha_fin.strftime("%m/%Y") }}{% else %}-{% endif %} -
-
-
-
-
- - -
-
- - -
-
- - - -
- - -
-
-
- -
-
-
- {% endfor %} -
- {% else %} -

Sin experiencia registrada

Aun no hay experiencias cargadas en el perfil.

- {% endif %} -
+ {% include "profile/_experiences_shell.html" %} -
-

Proyectos

Proyectos que respaldan tu experiencia tecnica.

{{ projects|length }} registrados
-
- Agregar proyecto -
-
- - -
-
- - -
-
- - - -
- - - - -
-
- {% if projects %} -
- {% for item in projects %} -
- -
-

{{ item.nombre }}

{{ item.empresa or 'Proyecto personal' }}

- {% if item.stack %}{{ item.stack }}{% endif %} -
-
-
-
-
- - -
-
- - -
-
- - - -
- - - -
-
-
- -
-
-
- {% endfor %} -
- {% else %} -

Sin proyectos registrados

No hay proyectos cargados todavia.

- {% endif %} -
+ {% include "profile/_projects_shell.html" %}
-
-
-

Educacion

Formacion academica principal.

{{ education|length }} registros
-
- Agregar educacion -
-
- - -
-
- - - -
-
- - -
- -
-
- {% if education %} -
- {% for item in education %} -
-
-

{{ item.titulo }}

{{ item.institucion }} · {{ item.nivel }}

- {{ item.status }} -
-
-
- -
-
-
- {% endfor %} -
- {% else %} -

Sin educacion registrada

No hay estudios cargados todavia.

- {% endif %} -
+{% include "profile/_formation_shell.html" %} -
-

Cursos

Formacion complementaria para reforzar tu perfil.

{{ courses|length }} registros
-
- Agregar curso -
-
- - -
-
- - - -
- - -
-
- {% if courses %} -
- {% for item in courses %} -
-
-

{{ item.titulo }}

{{ item.institucion }}

- {{ item.status }} -
-
-
- -
-
-
- {% endfor %} -
- {% else %} -

Sin cursos registrados

No hay cursos cargados todavia.

- {% endif %} -
-
- -
-
-

Certificaciones

Credenciales y badges relevantes para tus postulaciones.

{{ certifications|length }} registros
-
- Agregar certificacion -
-
- - -
-
- - - -
- - -
-
- {% if certifications %} -
- {% for item in certifications %} -
-
-

{{ item.titulo }}

{{ item.institucion }}

- {{ item.status }} -
-
-
- -
-
-
- {% endfor %} -
- {% else %} -

Sin certificaciones registradas

No hay certificaciones cargadas todavia.

- {% endif %} -
-
- -
-
-
-

Vista CV

-

Vista de solo lectura del perfil consolidado para revisar como se presentaria tu hoja de vida.

-
-
- {% if cv_preview_html %} - {{ cv_preview_html | safe }} - {% else %} -
-

Sin vista CV disponible

-

Completa los datos principales del perfil para generar esta vista.

-
- {% endif %} -
+{% include "profile/_cv_preview.html" %} diff --git a/app/interfaces/web/templates/profile/_skills.html b/app/interfaces/web/templates/profile/_skills.html new file mode 100644 index 0000000..880bba2 --- /dev/null +++ b/app/interfaces/web/templates/profile/_skills.html @@ -0,0 +1,43 @@ +
+
+
+

Skills

+

Manten tus skills clave visibles para el analisis de afinidad.

+
+
+

Mantener skills claras y concretas ayuda a que la afinidad con vacantes sea mas fiable.

+
+
+ + +
+ + +
+ {% if skills %} +
+ {% for item in skills %} +
+
+
+

{{ item.skill }}

+

{{ item.categoria }} · {{ item.nivel }}

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

Sin skills

Agrega tus skills principales para que el analisis de vacantes sea mas preciso.

+ {% endif %} +
diff --git a/app/interfaces/web/templates/profile/_skills_fragment.html b/app/interfaces/web/templates/profile/_skills_fragment.html new file mode 100644 index 0000000..4860978 --- /dev/null +++ b/app/interfaces/web/templates/profile/_skills_fragment.html @@ -0,0 +1,5 @@ +
+ {% include "profile/_overview.html" %} +
+ +{% include "profile/_skills_shell.html" %} diff --git a/app/interfaces/web/templates/profile/_skills_shell.html b/app/interfaces/web/templates/profile/_skills_shell.html new file mode 100644 index 0000000..134887a --- /dev/null +++ b/app/interfaces/web/templates/profile/_skills_shell.html @@ -0,0 +1,9 @@ +
+ {% if skills_flash_message %} + {% set flash_tone = skills_flash_message[0] %} + {% set flash_text = skills_flash_message[1] %} + {% include "components/_flash.html" %} + {% endif %} + {% include "profile/_skills.html" %} + {% include "profile/_profile_status.html" %} +
diff --git a/app/interfaces/web/templates/profile/index.html b/app/interfaces/web/templates/profile/index.html index 9f8b8d1..446ddc9 100644 --- a/app/interfaces/web/templates/profile/index.html +++ b/app/interfaces/web/templates/profile/index.html @@ -1,12 +1,10 @@ {% extends "base.html" %} {% block content %} - +{% set page_header_title = "Mi Perfil" %} +{% set page_header_description = "Configura tu contexto profesional para mejorar el analisis de vacantes y mantener tu hoja de vida al dia." %} +{% set page_header_copy_class = none %} +{% include "components/_page_header.html" %}
{% include "profile/_shell.html" %} diff --git a/app/interfaces/web/templates/vacancies/_filters.html b/app/interfaces/web/templates/vacancies/_filters.html new file mode 100644 index 0000000..190a796 --- /dev/null +++ b/app/interfaces/web/templates/vacancies/_filters.html @@ -0,0 +1,34 @@ +
+
+ + + + + +
+
diff --git a/app/interfaces/web/templates/vacancies/_list.html b/app/interfaces/web/templates/vacancies/_list.html index a00f56d..e491385 100644 --- a/app/interfaces/web/templates/vacancies/_list.html +++ b/app/interfaces/web/templates/vacancies/_list.html @@ -69,31 +69,14 @@ {% endif %} {% endfor %}
- {% if pagination.total_pages > 1 %} -
- {% if pagination.has_prev %} - Anterior - {% endif %} - Pagina {{ pagination.page }} de {{ pagination.total_pages }} - {% if pagination.has_next %} - Siguiente - {% endif %} -
- {% endif %} + {% set pagination_prev_href = "/app/vacancies?q=%s&view=%s&page=%s&page_size=%s"|format(query, current_view, pagination.prev_page, pagination.page_size) %} + {% set pagination_prev_hx_get = "/app/vacancies/list?q=%s&view=%s&page=%s&page_size=%s"|format(query, current_view, pagination.prev_page, pagination.page_size) %} + {% set pagination_next_href = "/app/vacancies?q=%s&view=%s&page=%s&page_size=%s"|format(query, current_view, pagination.next_page, pagination.page_size) %} + {% set pagination_next_hx_get = "/app/vacancies/list?q=%s&view=%s&page=%s&page_size=%s"|format(query, current_view, pagination.next_page, pagination.page_size) %} + {% set pagination_hx_target = "#vacancy-list" %} + {% set pagination_hx_swap = "innerHTML" %} + {% set pagination_hx_push_url = "true" %} + {% include "components/_pagination.html" %} {% else %}

No hay coincidencias

diff --git a/app/interfaces/web/templates/vacancies/_shell.html b/app/interfaces/web/templates/vacancies/_shell.html new file mode 100644 index 0000000..3092f2c --- /dev/null +++ b/app/interfaces/web/templates/vacancies/_shell.html @@ -0,0 +1,15 @@ +{% include "vacancies/_summary.html" %} + +{% if flash_message %} + {% set flash_tone = flash_message[0] %} + {% set flash_text = flash_message[1] %} + {% include "components/_flash.html" %} +{% endif %} + +{% include "vacancies/_filters.html" %} + +
+
+ {% include "vacancies/_list.html" %} +
+
diff --git a/app/interfaces/web/templates/vacancies/_summary.html b/app/interfaces/web/templates/vacancies/_summary.html new file mode 100644 index 0000000..6220b36 --- /dev/null +++ b/app/interfaces/web/templates/vacancies/_summary.html @@ -0,0 +1,8 @@ +
+ {% for item in context_bar %} +
+ {{ item.value }} + {{ item.label }} +
+ {% endfor %} +
diff --git a/app/interfaces/web/templates/vacancies/index.html b/app/interfaces/web/templates/vacancies/index.html index 743d547..37c57ed 100644 --- a/app/interfaces/web/templates/vacancies/index.html +++ b/app/interfaces/web/templates/vacancies/index.html @@ -1,68 +1,12 @@ {% extends "base.html" %} {% block content %} - +{% set page_header_title = "Inbox de Vacantes" %} +{% set page_header_description = "Revisa, prioriza y decide sin salir del workspace." %} +{% set page_header_copy_class = "page-header-copy" %} +{% include "components/_page_header.html" %} -
- {% for item in context_bar %} -
- {{ item.value }} - {{ item.label }} -
- {% endfor %} -
- -{% if flash_message %} -
- {{ flash_message[1] }} -
-{% endif %} - -
-
- - - - - -
-
- -
-
- {% include "vacancies/_list.html" %} -
-
+{% include "vacancies/_shell.html" %}