| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- <?xml version="1.0" encoding="utf-8"?>
- <odoo>
- <data>
- <!-- Dashboard Template for Tickets -->
- <template id="portal_helpdesk_ticket_dashboard" name="Tickets Dashboard">
- <t t-call="portal.portal_layout">
- <t t-set="breadcrumbs_searchbar" t-value="True"/>
- <t t-call="portal.portal_searchbar">
- <t t-set="title">Tickets</t>
- </t>
- <div class="container-fluid py-4">
- <!-- Dashboard Header -->
- <div class="row mb-4">
- <div class="col-12">
- <h1 class="h2 mb-2">Dashboard de Tickets</h1>
- <p class="text-muted">Resumen de tus tickets y métricas</p>
- </div>
- </div>
- <!-- Main Metrics Cards (4 cards) -->
- <div class="row g-4 mb-4">
- <!-- Card 1: Tiempo Usado/Disponible -->
- <div class="col-12 col-md-6 col-lg-3">
- <div class="card m22-dashboard-card h-100">
- <div class="card-body">
- <div class="d-flex align-items-center justify-content-between mb-3">
- <div>
- <h6 class="text-muted mb-1 small text-uppercase">Tiempo</h6>
- <h3 class="mb-0">
- <span t-esc="round(dashboard_data['time_stats']['used'], 1)"/>h
- <small class="text-muted">/ <span t-esc="round(dashboard_data['time_stats']['available'], 1)"/>h</small>
- </h3>
- </div>
- <div class="m22-dashboard-icon">
- <i class="fa fa-clock-o fa-2x" style="color: rgba(255, 124, 0, 0.3);"></i>
- </div>
- </div>
- <div class="progress" style="height: 8px; border-radius: 4px;">
- <div class="progress-bar"
- role="progressbar"
- t-attf-style="width: #{dashboard_data['time_stats']['percentage']}%; background: linear-gradient(90deg, #FF7C00, #E0407B);"
- t-attf-aria-valuenow="#{dashboard_data['time_stats']['percentage']}"
- aria-valuemin="0"
- aria-valuemax="100">
- </div>
- </div>
- <div class="mt-2">
- <small class="text-muted">
- <span t-esc="round(dashboard_data['time_stats']['percentage'], 1)"/>% utilizado
- </small>
- </div>
- <!-- Desglose: Prepago y Crédito -->
- <t t-if="dashboard_data['time_stats']['prepaid_hours'] > 0 or dashboard_data['time_stats']['credit_hours'] > 0 or dashboard_data['time_stats']['credit_available'] > 0">
- <div class="mt-3 pt-2 border-top">
- <t t-if="dashboard_data['time_stats']['prepaid_hours'] > 0">
- <div class="d-flex justify-content-between small mb-1">
- <span class="text-muted">Prepago:</span>
- <span class="fw-semibold"><span t-esc="round(dashboard_data['time_stats']['prepaid_hours'], 1)"/>h</span>
- </div>
- </t>
- <t t-if="dashboard_data['time_stats']['credit_hours'] > 0">
- <div class="d-flex justify-content-between small mb-1">
- <span class="text-muted">Crédito:</span>
- <span class="fw-semibold"><span t-esc="round(dashboard_data['time_stats']['credit_hours'], 1)"/>h</span>
- </div>
- </t>
- <t t-if="dashboard_data['time_stats']['credit_available'] > 0">
- <div class="d-flex justify-content-between small">
- <span class="text-muted">Crédito disponible:</span>
- <span class="fw-semibold">
- <span t-esc="request.env.company.currency_id.symbol"/>
- <span t-esc="round(dashboard_data['time_stats']['credit_available'], 2)"/>
- </span>
- </div>
- </t>
- </div>
- </t>
- </div>
- </div>
- </div>
- <!-- Card 2: Total Tickets -->
- <div class="col-12 col-md-6 col-lg-3">
- <div class="card m22-dashboard-card h-100">
- <div class="card-body">
- <div class="d-flex align-items-center justify-content-between mb-3">
- <div>
- <h6 class="text-muted mb-1 small text-uppercase">Tickets</h6>
- <h3 class="mb-0">
- <span t-esc="dashboard_data['ticket_summary']['total']"/>
- </h3>
- <small class="text-muted">
- <span t-esc="dashboard_data['ticket_summary']['open']"/> abiertos
- </small>
- </div>
- <div class="m22-dashboard-icon">
- <i class="fa fa-ticket fa-2x" style="color: rgba(255, 124, 0, 0.3);"></i>
- </div>
- </div>
- <div class="mt-3">
- <div class="d-flex justify-content-between small">
- <span class="text-muted">Abiertos:</span>
- <span class="fw-semibold" t-esc="dashboard_data['ticket_summary']['open']"/>
- </div>
- <div class="d-flex justify-content-between small mt-1">
- <span class="text-muted">Cerrados:</span>
- <span class="fw-semibold" t-esc="dashboard_data['ticket_summary']['closed']"/>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- Card 3: SLA Compliance -->
- <div class="col-12 col-md-6 col-lg-3">
- <div class="card m22-dashboard-card h-100">
- <div class="card-body">
- <div class="d-flex align-items-center justify-content-between mb-3">
- <div>
- <h6 class="text-muted mb-1 small text-uppercase">Cumplimiento SLA</h6>
- <h3 class="mb-0">
- <span t-esc="round(dashboard_data['sla_compliance']['percentage'], 1)"/>%
- </h3>
- </div>
- <div class="m22-dashboard-icon">
- <i class="fa fa-check-circle fa-2x"
- t-attf-style="color: rgba(#{34 if dashboard_data['sla_compliance']['is_good'] else 239}, #{197 if dashboard_data['sla_compliance']['is_good'] else 68}, #{94 if dashboard_data['sla_compliance']['is_good'] else 68}, 0.3);">
- </i>
- </div>
- </div>
- <div class="mt-3">
- <div class="d-flex justify-content-between small">
- <span class="text-muted">Exitosos:</span>
- <span class="fw-semibold text-success" t-esc="dashboard_data['sla_compliance']['success']"/>
- </div>
- <div class="d-flex justify-content-between small mt-1">
- <span class="text-muted">Fallidos:</span>
- <span class="fw-semibold text-danger" t-esc="dashboard_data['sla_compliance']['failed']"/>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- Card 4: Esperando Respuesta -->
- <div class="col-12 col-md-6 col-lg-3">
- <div class="card m22-dashboard-card h-100">
- <div class="card-body">
- <div class="d-flex align-items-center justify-content-between mb-3">
- <div>
- <h6 class="text-muted mb-1 small text-uppercase">Esperando Respuesta</h6>
- <h3 class="mb-0">
- <span t-esc="dashboard_data['waiting_response']['count']"/>
- </h3>
- </div>
- <div class="m22-dashboard-icon">
- <i class="fa fa-exclamation-circle fa-2x" style="color: rgba(234, 179, 8, 0.3);"></i>
- </div>
- </div>
- <div class="mt-3">
- <a href="/my/tickets?filterby=open" class="btn btn-sm btn-outline-primary">
- Ver tickets
- </a>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- Summary by Stage -->
- <div class="row g-4 mb-4">
- <div class="col-12">
- <div class="card m22-dashboard-card">
- <div class="card-body">
- <h5 class="card-title mb-4">Resumen por Etapa</h5>
- <div class="row g-3">
- <t t-foreach="dashboard_data['ticket_summary']['by_stage']" t-as="stage_item">
- <div class="col-6 col-md-4 col-lg-3">
- <div class="m22-stage-card p-3 rounded">
- <div class="fw-semibold mb-1" t-esc="stage_item[0]"/>
- <div class="h4 mb-0" style="color: #FF7C00;" t-esc="stage_item[1]"/>
- </div>
- </div>
- </t>
- <t t-if="not dashboard_data['ticket_summary']['by_stage'] or len(dashboard_data['ticket_summary']['by_stage']) == 0">
- <div class="col-12">
- <p class="text-muted mb-0">No hay tickets abiertos</p>
- </div>
- </t>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- Recent Tickets -->
- <div class="row g-4 mb-4">
- <div class="col-12">
- <div class="card m22-dashboard-card">
- <div class="card-body">
- <div class="d-flex justify-content-between align-items-center mb-4">
- <h5 class="card-title mb-0">Tickets Recientes</h5>
- <a href="/my/tickets" class="btn btn-primary">
- Ver todos los tickets
- </a>
- </div>
- <t t-if="dashboard_data['recent_tickets']">
- <div class="table-responsive">
- <table class="table table-hover">
- <thead>
- <tr>
- <th>Ticket</th>
- <th>Asunto</th>
- <th>Etapa</th>
- <th>Prioridad</th>
- <th>Fecha</th>
- </tr>
- </thead>
- <tbody>
- <t t-foreach="dashboard_data['recent_tickets']" t-as="ticket">
- <tr>
- <td>
- <a t-attf-href="/helpdesk/ticket/#{ticket.id}">
- #<span t-esc="ticket.ticket_ref"/>
- </a>
- </td>
- <td>
- <a t-attf-href="/helpdesk/ticket/#{ticket.id}">
- <span t-esc="ticket.name"/>
- </a>
- </td>
- <td>
- <span t-attf-class="badge rounded-pill #{'text-bg-success' if ticket.stage_id.fold else 'text-bg-primary'}"
- t-esc="ticket.stage_id.name"/>
- </td>
- <td>
- <t t-if="ticket.priority == '3'">
- <span class="badge bg-danger">Urgente</span>
- </t>
- <t t-elif="ticket.priority == '2'">
- <span class="badge bg-warning">Alta</span>
- </t>
- <t t-elif="ticket.priority == '1'">
- <span class="badge bg-info">Media</span>
- </t>
- <t t-else="">
- <span class="badge bg-secondary">Baja</span>
- </t>
- </td>
- <td>
- <span t-field="ticket.create_date" t-options='{"widget": "datetime", "hide_seconds": True}'/>
- </td>
- </tr>
- </t>
- </tbody>
- </table>
- </div>
- </t>
- <t t-else="">
- <p class="text-muted mb-0">No hay tickets recientes</p>
- </t>
- </div>
- </div>
- </div>
- </div>
- <!-- Waiting Response Tickets (if any) -->
- <t t-if="dashboard_data['waiting_response']['count'] > 0">
- <div class="row g-4 mb-4">
- <div class="col-12">
- <div class="card m22-dashboard-card border-warning">
- <div class="card-body">
- <div class="d-flex justify-content-between align-items-center mb-3">
- <h5 class="card-title mb-0">
- <i class="fa fa-exclamation-circle text-warning me-2"></i>
- Tickets Esperando tu Respuesta
- </h5>
- <span class="badge bg-warning" t-esc="dashboard_data['waiting_response']['count']"/>
- </div>
- <div class="list-group">
- <t t-foreach="dashboard_data['waiting_response']['tickets']" t-as="ticket">
- <a t-attf-href="/helpdesk/ticket/#{ticket.id}"
- class="list-group-item list-group-item-action">
- <div class="d-flex w-100 justify-content-between">
- <h6 class="mb-1">
- #<span t-esc="ticket.ticket_ref"/> - <span t-esc="ticket.name"/>
- </h6>
- <small>
- <span t-field="ticket.create_date" t-options='{"widget": "datetime", "hide_seconds": True}'/>
- </small>
- </div>
- <p class="mb-1 text-muted small">
- <span t-esc="ticket.stage_id.name"/>
- <t t-if="ticket.user_id">
- - Asignado a: <span t-esc="ticket.user_id.name"/>
- </t>
- </p>
- </a>
- </t>
- </div>
- </div>
- </div>
- </div>
- </div>
- </t>
- </div>
- </t>
- </template>
- </data>
- </odoo>
|