multiples mejoras añadidas, se retiró la categoría

This commit is contained in:
Abraham
2026-01-13 14:11:03 -08:00
parent cd23fdc071
commit 8612688aa3
8 changed files with 358 additions and 776 deletions

View File

@@ -214,55 +214,43 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
),
)
else
// Vista desktop: diseño original con icono, texto y botón
// Vista desktop: contador de videos y botón (sin título redundante)
Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color(0xFF4EC9F5),
const Color(0xFFFFB733),
],
),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color:
AppTheme.of(context).primaryColor.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: const Icon(
Icons.video_library,
color: Color(0xFF0B0B0D),
size: 24,
),
),
const Gap(16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
child: Row(
children: [
Text(
'Gestor de Videos',
style: AppTheme.of(context).title2.override(
fontFamily: 'Poppins',
color: AppTheme.of(context).primaryText,
fontWeight: FontWeight.bold,
fontSize: 22,
),
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color(0xFF4EC9F5).withOpacity(0.15),
const Color(0xFFFFB733).withOpacity(0.15),
],
),
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: AppTheme.of(context)
.primaryColor
.withOpacity(0.2),
width: 1.5,
),
),
child: Icon(
Icons.video_collection_rounded,
color: AppTheme.of(context).primaryColor,
size: 20,
),
),
const Gap(4),
const Gap(12),
Text(
'${provider.mediaFiles.length} videos disponibles',
style: AppTheme.of(context).bodyText2.override(
style: AppTheme.of(context).bodyText1.override(
fontFamily: 'Poppins',
color: AppTheme.of(context).tertiaryText,
fontSize: 13,
color: AppTheme.of(context).secondaryText,
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
],
@@ -334,6 +322,7 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
field: 'thumbnail',
type: PlutoColumnType.text(),
width: 150,
enableEditingMode: false,
enableColumnDrag: false,
enableSorting: false,
enableContextMenu: false,
@@ -411,54 +400,65 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
title: 'Título',
field: 'title',
type: PlutoColumnType.text(),
width: 350,
width: 300,
enableEditingMode: false,
renderer: (rendererContext) {
final title = rendererContext.cell.value?.toString() ?? '';
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
alignment: Alignment.centerLeft,
child: Text(
title,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppTheme.of(context).primaryText,
letterSpacing: 0.2,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
);
},
),
PlutoColumn(
title: 'Descripción',
field: 'file_description',
type: PlutoColumnType.text(),
width: 400,
),
PlutoColumn(
title: 'Categoría',
field: 'category',
type: PlutoColumnType.text(),
width: 160,
width: 425,
enableEditingMode: false,
renderer: (rendererContext) {
final category = rendererContext.cell.value?.toString() ?? '';
if (category.isEmpty) return const SizedBox();
return Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppTheme.of(context).primaryColor,
AppTheme.of(context).primaryColor.withOpacity(0.7),
],
),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: AppTheme.of(context).primaryColor.withOpacity(0.3),
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
final description = rendererContext.cell.value?.toString() ?? '';
if (description.isEmpty) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
alignment: Alignment.centerLeft,
child: Text(
category.toUpperCase(),
style: const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.w700,
letterSpacing: 0.5,
'Sin descripción',
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
fontStyle: FontStyle.italic,
color: AppTheme.of(context).tertiaryText,
),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
),
);
}
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
alignment: Alignment.centerLeft,
child: Text(
description,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 13,
fontWeight: FontWeight.w400,
color: AppTheme.of(context).secondaryText,
height: 1.4,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
);
},
@@ -468,6 +468,7 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
field: 'reproducciones',
type: PlutoColumnType.number(),
width: 160,
enableEditingMode: false,
textAlign: PlutoColumnTextAlign.center,
renderer: (rendererContext) {
final count = rendererContext.cell.value ?? 0;
@@ -512,18 +513,72 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
field: 'duration',
type: PlutoColumnType.text(),
width: 180,
enableEditingMode: false,
),
PlutoColumn(
title: 'Fecha de Creación',
field: 'createdAt',
type: PlutoColumnType.text(),
width: 180,
width: 280,
enableEditingMode: false,
renderer: (rendererContext) {
final video =
rendererContext.row.cells['video']?.value as MediaFileModel?;
if (video?.createdAt == null) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
alignment: Alignment.centerLeft,
child: Text(
'Fecha no disponible',
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 13,
fontStyle: FontStyle.italic,
color: AppTheme.of(context).tertiaryText,
),
),
);
}
final formattedDate = _formatDescriptiveDate(video!.createdAt!);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
alignment: Alignment.centerLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
formattedDate['date']!,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 13,
fontWeight: FontWeight.w600,
color: AppTheme.of(context).primaryText,
),
),
const SizedBox(height: 2),
Text(
formattedDate['time']!,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 12,
fontWeight: FontWeight.w400,
color: AppTheme.of(context).secondaryText,
),
),
],
),
);
},
),
PlutoColumn(
title: 'Etiquetas',
field: 'tags',
type: PlutoColumnType.text(),
width: 250,
enableEditingMode: false,
renderer: (rendererContext) {
final video =
rendererContext.row.cells['video']?.value as MediaFileModel?;
@@ -563,6 +618,7 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
field: 'actions',
type: PlutoColumnType.text(),
width: 160,
enableEditingMode: false,
enableColumnDrag: false,
enableSorting: false,
enableContextMenu: false,
@@ -605,12 +661,12 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
rows: provider.videosRows,
onLoaded: (PlutoGridOnLoadedEvent event) {
_stateManager = event.stateManager;
_stateManager!.setShowColumnFilter(true);
_stateManager!.setShowColumnFilter(false);
},
configuration: PlutoGridConfiguration(
style: plutoGridStyleConfig(context),
columnSize: const PlutoGridColumnSizeConfig(
autoSizeMode: PlutoAutoSizeMode.none,
autoSizeMode: PlutoAutoSizeMode.scale,
),
),
);
@@ -1174,4 +1230,51 @@ class _GestorVideosPageState extends State<GestorVideosPage> {
return '${secs}s';
}
}
Map<String, String> _formatDescriptiveDate(DateTime date) {
// Obtener día de la semana en español
final diasSemana = [
'lunes',
'martes',
'miércoles',
'jueves',
'viernes',
'sábado',
'domingo'
];
final diaSemana = diasSemana[date.weekday - 1];
// Obtener mes en español
final meses = [
'enero',
'febrero',
'marzo',
'abril',
'mayo',
'junio',
'julio',
'agosto',
'septiembre',
'octubre',
'noviembre',
'diciembre'
];
final mes = meses[date.month - 1];
// Formatear la hora
final hora = date.hour;
final minuto = date.minute.toString().padLeft(2, '0');
final segundo = date.second.toString().padLeft(2, '0');
final periodo = hora >= 12 ? 'pm' : 'am';
final hora12 = hora > 12 ? hora - 12 : (hora == 0 ? 12 : hora);
// Construir las cadenas
final fechaTexto = '$diaSemana ${date.day} de $mes del ${date.year}';
final horaTexto = 'a las $hora12:$minuto:$segundo $periodo';
return {
'date': fechaTexto,
'time': horaTexto,
};
}
}