From cd23fdc071fbe0f12dcad04c300f6efd8f9ca0ea Mon Sep 17 00:00:00 2001 From: Abraham Date: Mon, 12 Jan 2026 23:57:16 -0800 Subject: [PATCH] mejorado responsive --- lib/pages/videos/dashboard_page.dart | 877 ++++++++++++++++------- lib/pages/videos/gestor_videos_page.dart | 651 ++++++++++++----- 2 files changed, 1114 insertions(+), 414 deletions(-) diff --git a/lib/pages/videos/dashboard_page.dart b/lib/pages/videos/dashboard_page.dart index 845da2e..da7325d 100644 --- a/lib/pages/videos/dashboard_page.dart +++ b/lib/pages/videos/dashboard_page.dart @@ -86,13 +86,28 @@ class _DashboardPageState extends State Widget _buildHeader() { return Container( - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.all(32), decoration: BoxDecoration( - gradient: AppTheme.of(context).primaryGradient, - borderRadius: BorderRadius.circular(16), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + const Color(0xFF4EC9F5), + const Color(0xFF6B2F8A), + const Color(0xFFFFB733), + ], + stops: const [0.0, 0.5, 1.0], + ), + borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( - color: AppTheme.of(context).primaryColor.withOpacity(0.3), + color: const Color(0xFF4EC9F5).withOpacity(0.4), + blurRadius: 30, + offset: const Offset(0, 10), + spreadRadius: 2, + ), + BoxShadow( + color: const Color(0xFFFFB733).withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 5), ), @@ -101,39 +116,60 @@ class _DashboardPageState extends State child: Row( children: [ Container( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), + color: Colors.white.withOpacity(0.25), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: Colors.white.withOpacity(0.4), + width: 2, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius: 15, + offset: const Offset(0, 5), + ), + ], ), child: const Icon( - Icons.dashboard, - size: 32, + Icons.dashboard_rounded, + size: 40, color: Colors.white, ), ), - const Gap(16), + const Gap(24), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Dashboard MDF/IDF', + 'Dashboard Premium', style: AppTheme.of(context).title1.override( fontFamily: 'Poppins', color: Colors.white, - fontSize: 24, + fontSize: 32, fontWeight: FontWeight.bold, + letterSpacing: 0.5, ), ), - const Gap(4), - Text( - 'Panel de control de contenido multimedia', - style: AppTheme.of(context).bodyText1.override( - fontFamily: 'Poppins', - color: Colors.white.withOpacity(0.9), - fontSize: 14, - ), + const Gap(8), + Container( + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.25), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + 'Panel de control de contenido multimedia', + style: AppTheme.of(context).bodyText1.override( + fontFamily: 'Poppins', + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), ), ], ), @@ -220,63 +256,155 @@ class _DashboardPageState extends State Widget _buildStatCard( String title, String value, IconData icon, Color color) { return Container( - padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: AppTheme.of(context).secondaryBackground, - borderRadius: BorderRadius.circular(12), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppTheme.of(context).secondaryBackground, + AppTheme.of(context).tertiaryBackground, + ], + ), + borderRadius: BorderRadius.circular(20), border: Border.all( color: color.withOpacity(0.3), + width: 2, ), boxShadow: [ BoxShadow( - color: color.withOpacity(0.1), + color: color.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: 0, + ), + BoxShadow( + color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - padding: const EdgeInsets.all(12), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Stack( + children: [ + // Efecto de brillo sutil en la esquina + Positioned( + top: -50, + right: -50, + child: Container( + width: 150, + height: 150, decoration: BoxDecoration( - color: color.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - child: Icon( - icon, - color: color, - size: 24, + shape: BoxShape.circle, + gradient: RadialGradient( + colors: [ + color.withOpacity(0.15), + color.withOpacity(0.0), + ], + ), ), ), - ], - ), - const Gap(16), - Text( - value, - style: AppTheme.of(context).title1.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - fontSize: 28, - fontWeight: FontWeight.bold, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - const Gap(4), - Text( - title, - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).secondaryText, - fontSize: 14, - ), - ), - ], + ), + Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color.withOpacity(0.2), + color.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: color.withOpacity(0.3), + width: 2, + ), + boxShadow: [ + BoxShadow( + color: color.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Icon( + icon, + color: color, + size: 28, + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: color.withOpacity(0.15), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: color.withOpacity(0.3), + ), + ), + child: Icon( + Icons.trending_up_rounded, + color: color, + size: 16, + ), + ), + ], + ), + const Gap(24), + Text( + value, + style: AppTheme.of(context).title1.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).primaryText, + fontSize: 36, + fontWeight: FontWeight.bold, + letterSpacing: -0.5, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const Gap(8), + Row( + children: [ + Container( + width: 4, + height: 16, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(2), + ), + ), + const Gap(8), + Expanded( + child: Text( + title, + style: AppTheme.of(context).bodyText1.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).secondaryText, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), ), ); } @@ -285,60 +413,124 @@ class _DashboardPageState extends State final categoriesMap = stats['videos_by_category'] as Map?; return Container( - padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: AppTheme.of(context).secondaryBackground, - borderRadius: BorderRadius.circular(16), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppTheme.of(context).secondaryBackground, + AppTheme.of(context).tertiaryBackground, + ], + ), + borderRadius: BorderRadius.circular(24), border: Border.all( color: AppTheme.of(context).primaryColor.withOpacity(0.2), + width: 2, ), + boxShadow: [ + BoxShadow( + color: AppTheme.of(context).primaryColor.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + child: ClipRRect( + borderRadius: BorderRadius.circular(24), + child: Padding( + padding: const EdgeInsets.all(28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Icon( - Icons.pie_chart, - color: AppTheme.of(context).primaryColor, - ), - const Gap(8), - Text( - 'Distribución por Categoría', - style: AppTheme.of(context).title3.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - fontWeight: FontWeight.bold, + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).primaryColor.withOpacity(0.2), + AppTheme.of(context).primaryColor.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: + AppTheme.of(context).primaryColor.withOpacity(0.3), + ), ), + child: Icon( + Icons.pie_chart_rounded, + color: AppTheme.of(context).primaryColor, + size: 24, + ), + ), + const Gap(16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Distribución por Categoría', + style: AppTheme.of(context).title3.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).primaryText, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + const Gap(4), + Text( + 'Videos organizados por categoría', + style: AppTheme.of(context).bodyText2.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).tertiaryText, + fontSize: 12, + ), + ), + ], + ), + ), + ], ), + const Gap(24), + if (categoriesMap != null && categoriesMap.isNotEmpty) + ...categoriesMap.entries.map( + (entry) => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _buildCategoryBar( + entry.key, + entry.value, + categoriesMap.values.reduce((a, b) => a > b ? a : b), + ), + ), + ) + else + Center( + child: Padding( + padding: const EdgeInsets.all(40), + child: Column( + children: [ + Icon( + Icons.category_outlined, + size: 64, + color: AppTheme.of(context).tertiaryText, + ), + const Gap(16), + Text( + 'No hay datos de categorías', + style: AppTheme.of(context).bodyText1.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).tertiaryText, + ), + ), + ], + ), + ), + ), ], ), - const Gap(20), - if (categoriesMap != null && categoriesMap.isNotEmpty) - ...categoriesMap.entries.map( - (entry) => Padding( - padding: const EdgeInsets.only(bottom: 12), - child: _buildCategoryBar( - entry.key, - entry.value, - categoriesMap.values.reduce((a, b) => a > b ? a : b), - ), - ), - ) - else - Center( - child: Padding( - padding: const EdgeInsets.all(40), - child: Text( - 'No hay datos de categorías', - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).tertiaryText, - ), - ), - ), - ), - ], + ), ), ); } @@ -346,171 +538,362 @@ class _DashboardPageState extends State Widget _buildCategoryBar(String category, int count, int maxCount) { final percentage = maxCount > 0 ? count / maxCount : 0.0; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - category, - style: AppTheme.of(context).bodyText1.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - ), - ), - Text( - count.toString(), - style: AppTheme.of(context).bodyText1.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryColor, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const Gap(8), - ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LinearProgressIndicator( - value: percentage, - backgroundColor: AppTheme.of(context).tertiaryBackground, - valueColor: AlwaysStoppedAnimation( - AppTheme.of(context).primaryColor, - ), - minHeight: 8, - ), - ), - ], - ); - } - - Widget _buildRecentActivity() { return Container( - padding: const EdgeInsets.all(20), + padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: AppTheme.of(context).secondaryBackground, - borderRadius: BorderRadius.circular(16), + color: AppTheme.of(context).primaryBackground.withOpacity(0.5), + borderRadius: BorderRadius.circular(12), border: Border.all( - color: AppTheme.of(context).primaryColor.withOpacity(0.2), + color: AppTheme.of(context).primaryColor.withOpacity(0.1), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon( - Icons.access_time, - color: AppTheme.of(context).primaryColor, + Expanded( + child: Text( + category, + style: AppTheme.of(context).bodyText1.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).primaryText, + fontWeight: FontWeight.w600, + ), + ), ), - const Gap(8), - Text( - 'Actividad Reciente', - style: AppTheme.of(context).title3.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - fontWeight: FontWeight.bold, + Container( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).primaryColor, + AppTheme.of(context).secondaryColor, + ], + ), + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: AppTheme.of(context).primaryColor.withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 2), ), + ], + ), + child: Text( + count.toString(), + style: const TextStyle( + fontFamily: 'Poppins', + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), ), ], ), - const Gap(20), - Consumer( - builder: (context, provider, child) { - if (provider.mediaFiles.isEmpty) { - return Center( - child: Padding( - padding: const EdgeInsets.all(40), - child: Text( - 'No hay actividad reciente', - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).tertiaryText, - ), + const Gap(12), + Stack( + children: [ + Container( + height: 10, + decoration: BoxDecoration( + color: AppTheme.of(context).tertiaryBackground, + borderRadius: BorderRadius.circular(5), + ), + ), + FractionallySizedBox( + widthFactor: percentage, + child: Container( + height: 10, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).primaryColor, + AppTheme.of(context).secondaryColor, + ], + ), + borderRadius: BorderRadius.circular(5), + boxShadow: [ + BoxShadow( + color: + AppTheme.of(context).primaryColor.withOpacity(0.5), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildRecentActivity() { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppTheme.of(context).secondaryBackground, + AppTheme.of(context).tertiaryBackground, + ], + ), + borderRadius: BorderRadius.circular(24), + border: Border.all( + color: AppTheme.of(context).primaryColor.withOpacity(0.2), + width: 2, + ), + boxShadow: [ + BoxShadow( + color: AppTheme.of(context).primaryColor.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(24), + child: Padding( + padding: const EdgeInsets.all(28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).secondaryColor.withOpacity(0.2), + AppTheme.of(context).secondaryColor.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: AppTheme.of(context) + .secondaryColor + .withOpacity(0.3), + ), + ), + child: Icon( + Icons.history_rounded, + color: AppTheme.of(context).secondaryColor, + size: 24, ), ), - ); - } - - final recentVideos = provider.mediaFiles.take(5).toList(); - - return Column( - children: recentVideos.map((video) { - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Row( + const Gap(16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - width: 48, - height: 48, - decoration: BoxDecoration( - color: AppTheme.of(context) - .primaryColor - .withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - ), - child: Icon( - Icons.video_library, - color: AppTheme.of(context).primaryColor, - ), - ), - const Gap(12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - video.title ?? video.fileName, - style: AppTheme.of(context).bodyText1.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - fontWeight: FontWeight.w600, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, + Text( + 'Actividad Reciente', + style: AppTheme.of(context).title3.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).primaryText, + fontWeight: FontWeight.bold, + fontSize: 18, ), - const Gap(4), - Text( - 'Hace ${_getTimeAgo(video.createdAt)}', - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).tertiaryText, - fontSize: 12, - ), - ), - ], - ), ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, - ), - decoration: BoxDecoration( - color: AppTheme.of(context) - .secondaryColor - .withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - '${video.reproducciones} views', - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).secondaryColor, - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), + const Gap(4), + Text( + 'Últimos videos subidos', + style: AppTheme.of(context).bodyText2.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).tertiaryText, + fontSize: 12, + ), ), ], ), + ), + ], + ), + const Gap(24), + Consumer( + builder: (context, provider, child) { + if (provider.mediaFiles.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(40), + child: Column( + children: [ + Icon( + Icons.video_library_outlined, + size: 64, + color: AppTheme.of(context).tertiaryText, + ), + const Gap(16), + Text( + 'No hay actividad reciente', + style: AppTheme.of(context).bodyText1.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).tertiaryText, + ), + ), + ], + ), + ), + ); + } + + final recentVideos = provider.mediaFiles.take(5).toList(); + + return Column( + children: recentVideos.map((video) { + return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppTheme.of(context) + .primaryBackground + .withOpacity(0.5), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: AppTheme.of(context) + .primaryColor + .withOpacity(0.1), + ), + ), + child: Row( + children: [ + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).primaryColor, + AppTheme.of(context).secondaryColor, + ], + ), + 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.play_arrow_rounded, + color: Colors.white, + size: 28, + ), + ), + const Gap(16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + video.title ?? video.fileName, + style: AppTheme.of(context) + .bodyText1 + .override( + fontFamily: 'Poppins', + color: + AppTheme.of(context).primaryText, + fontWeight: FontWeight.w600, + fontSize: 14, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const Gap(6), + Row( + children: [ + Icon( + Icons.access_time_rounded, + size: 14, + color: + AppTheme.of(context).tertiaryText, + ), + const Gap(4), + Text( + 'Hace ${_getTimeAgo(video.createdAt)}', + style: AppTheme.of(context) + .bodyText2 + .override( + fontFamily: 'Poppins', + color: AppTheme.of(context) + .tertiaryText, + fontSize: 12, + ), + ), + ], + ), + ], + ), + ), + const Gap(12), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).success, + AppTheme.of(context) + .success + .withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: AppTheme.of(context) + .success + .withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.visibility_rounded, + color: Colors.white, + size: 14, + ), + const Gap(6), + Text( + '${video.reproducciones}', + style: const TextStyle( + fontFamily: 'Poppins', + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + ); + }).toList(), ); - }).toList(), - ); - }, + }, + ), + ], ), - ], + ), ), ); } diff --git a/lib/pages/videos/gestor_videos_page.dart b/lib/pages/videos/gestor_videos_page.dart index 4fbd7e3..abb9cbc 100644 --- a/lib/pages/videos/gestor_videos_page.dart +++ b/lib/pages/videos/gestor_videos_page.dart @@ -155,47 +155,107 @@ class _GestorVideosPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Container( - padding: const EdgeInsets.all(12), + if (isMobile) + // Vista móvil: solo botón centrado con diseño mejorado + Center( + child: Container( + width: double.infinity, + constraints: const BoxConstraints(maxWidth: 300), decoration: BoxDecoration( - gradient: LinearGradient( + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, colors: [ - const Color(0xFF4EC9F5), - const Color(0xFFFFB733), + Color(0xFF4EC9F5), + Color(0xFFFFB733), ], ), - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: AppTheme.of(context).primaryColor.withOpacity(0.3), - blurRadius: 8, - offset: const Offset(0, 2), + color: const Color(0xFF4EC9F5).withOpacity(0.4), + blurRadius: 12, + offset: const Offset(0, 4), ), ], ), - child: const Icon( - Icons.video_library, - color: Color(0xFF0B0B0D), - size: 24, + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => _showUploadDialog(provider), + borderRadius: BorderRadius.circular(16), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, vertical: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.cloud_upload_rounded, + color: Color(0xFF0B0B0D), + size: 24, + ), + const Gap(12), + Text( + 'Subir Video', + style: const TextStyle( + color: Color(0xFF0B0B0D), + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Poppins', + letterSpacing: 0.5, + ), + ), + ], + ), + ), + ), ), ), - const Gap(16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Gestor de Videos', - style: AppTheme.of(context).title2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - fontWeight: FontWeight.bold, - fontSize: 22, - ), + ) + else + // Vista desktop: diseño original con icono, texto y botón + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + const Color(0xFF4EC9F5), + const Color(0xFFFFB733), + ], ), - if (!isMobile) ...[ + 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, + children: [ + Text( + 'Gestor de Videos', + style: AppTheme.of(context).title2.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).primaryText, + fontWeight: FontWeight.bold, + fontSize: 22, + ), + ), const Gap(4), Text( '${provider.mediaFiles.length} videos disponibles', @@ -206,17 +266,15 @@ class _GestorVideosPageState extends State { ), ), ], - ], + ), ), - ), - PremiumButton( - text: isMobile ? 'Subir' : 'Subir Video', - icon: Icons.cloud_upload, - onPressed: () => _showUploadDialog(provider), - width: isMobile ? 100 : null, - ), - ], - ), + PremiumButton( + text: 'Subir Video', + icon: Icons.cloud_upload, + onPressed: () => _showUploadDialog(provider), + ), + ], + ), const Gap(16), _buildSearchField(provider), ], @@ -607,148 +665,407 @@ class _GestorVideosPageState extends State { } Widget _buildVideoCard(MediaFileModel video, VideosProvider provider) { - return Card( - margin: const EdgeInsets.only(bottom: 16), - color: AppTheme.of(context).secondaryBackground, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: BorderSide( - color: AppTheme.of(context).primaryColor.withOpacity(0.2), + return Container( + margin: const EdgeInsets.only(bottom: 20), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppTheme.of(context).secondaryBackground, + AppTheme.of(context).tertiaryBackground, + ], ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Mostrar poster si existe, sino mostrar placeholder - ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(12), - topRight: Radius.circular(12), - ), - child: AspectRatio( - aspectRatio: 16 / 9, - child: video.posterUrl != null && video.posterUrl!.isNotEmpty - ? Image.network( - video.posterUrl!, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => Container( - color: AppTheme.of(context).tertiaryBackground, - child: Icon( - Icons.video_library, - size: 64, - color: AppTheme.of(context).tertiaryText, - ), - ), - ) - : Container( - color: AppTheme.of(context).tertiaryBackground, - child: Icon( - Icons.video_library, - size: 64, - color: AppTheme.of(context).tertiaryText, - ), - ), - ), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppTheme.of(context).primaryColor.withOpacity(0.2), + width: 2, + ), + boxShadow: [ + BoxShadow( + color: AppTheme.of(context).primaryColor.withOpacity(0.15), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: 0, ), - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Thumbnail con overlay premium + Stack( children: [ - Text( - video.title ?? video.fileName, - style: AppTheme.of(context).title3.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).primaryText, - fontWeight: FontWeight.bold, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - const Gap(8), - if (video.fileDescription != null && - video.fileDescription!.isNotEmpty) - Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Text( - video.fileDescription!, - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).secondaryText, + AspectRatio( + aspectRatio: 16 / 9, + child: video.posterUrl != null && video.posterUrl!.isNotEmpty + ? Image.network( + video.posterUrl!, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) => + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).tertiaryBackground, + AppTheme.of(context).primaryBackground, + ], + ), + ), + child: Icon( + Icons.video_library_rounded, + size: 80, + color: AppTheme.of(context).tertiaryText, + ), ), - maxLines: 2, - overflow: TextOverflow.ellipsis, + ) + : Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).tertiaryBackground, + AppTheme.of(context).primaryBackground, + ], + ), + ), + child: Icon( + Icons.video_library_rounded, + size: 80, + color: AppTheme.of(context).tertiaryText, + ), + ), + ), + // Overlay con gradiente + Positioned.fill( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + Colors.black.withOpacity(0.7), + ], + stops: const [0.5, 1.0], + ), ), ), - Row( - children: [ - Icon( - Icons.play_circle_filled, - size: 16, - color: AppTheme.of(context).tertiaryText, - ), - const Gap(4), - Text( - '${video.reproducciones} reproducciones', - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).tertiaryText, - fontSize: 12, - ), - ), - if (video.durationSeconds != null) ...[ - const Gap(12), - Icon( - Icons.access_time, - size: 16, - color: AppTheme.of(context).tertiaryText, - ), - const Gap(4), - Text( - _formatDuration(video.durationSeconds!), - style: AppTheme.of(context).bodyText2.override( - fontFamily: 'Poppins', - color: AppTheme.of(context).tertiaryText, - fontSize: 12, - ), - ), - ], - ], ), - const Gap(12), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton.icon( - onPressed: () => _playVideo(video), - icon: const Icon(Icons.play_circle_outline, size: 18), - label: const Text('Reproducir'), - style: TextButton.styleFrom( - foregroundColor: const Color(0xFF4EC9F5), + // Botón de play central + Positioned.fill( + child: Center( + child: Container( + width: 64, + height: 64, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppTheme.of(context).primaryColor, + AppTheme.of(context).secondaryColor, + ], + ), + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: AppTheme.of(context) + .primaryColor + .withOpacity(0.5), + blurRadius: 20, + offset: const Offset(0, 4), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => _playVideo(video), + customBorder: const CircleBorder(), + child: const Icon( + Icons.play_arrow_rounded, + color: Colors.white, + size: 36, + ), + ), ), ), - TextButton.icon( - onPressed: () => _editVideoDialog(video, provider), - icon: const Icon(Icons.edit, size: 18), - label: const Text('Editar'), - style: TextButton.styleFrom( - foregroundColor: const Color(0xFFFFB733), + ), + ), + // Stats en la parte inferior + Positioned( + bottom: 12, + left: 12, + right: 12, + child: Row( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.6), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: + AppTheme.of(context).success.withOpacity(0.5), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.visibility_rounded, + size: 14, + color: AppTheme.of(context).success, + ), + const Gap(4), + Text( + '${video.reproducciones}', + style: TextStyle( + color: AppTheme.of(context).success, + fontSize: 11, + fontWeight: FontWeight.bold, + ), + ), + ], + ), ), - ), - TextButton.icon( - onPressed: () => _deleteVideoDialog(video, provider), - icon: const Icon(Icons.delete, size: 18), - label: const Text('Eliminar'), - style: TextButton.styleFrom( - foregroundColor: const Color(0xFFFF2D2D), - ), - ), - ], + const Gap(8), + if (video.durationSeconds != null) + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.6), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: Colors.white.withOpacity(0.3), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.access_time_rounded, + size: 14, + color: Colors.white, + ), + const Gap(4), + Text( + _formatDuration(video.durationSeconds!), + style: const TextStyle( + color: Colors.white, + fontSize: 11, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), ), ], ), + // Contenido de la card + Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Título + Text( + video.title ?? video.fileName, + style: AppTheme.of(context).title3.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).primaryText, + fontWeight: FontWeight.bold, + fontSize: 18, + letterSpacing: 0.3, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const Gap(12), + // Descripción + if (video.fileDescription != null && + video.fileDescription!.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text( + video.fileDescription!, + style: AppTheme.of(context).bodyText2.override( + fontFamily: 'Poppins', + color: AppTheme.of(context).secondaryText, + fontSize: 14, + lineHeight: 1.5, + ), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + ), + // Tags si existen + if (video.tags.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Wrap( + spacing: 8, + runSpacing: 8, + children: video.tags.take(4).map((tag) { + return Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppTheme.of(context) + .primaryColor + .withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: AppTheme.of(context) + .primaryColor + .withOpacity(0.3), + ), + ), + child: Text( + tag, + style: TextStyle( + color: AppTheme.of(context).primaryColor, + fontSize: 11, + fontWeight: FontWeight.w600, + ), + ), + ); + }).toList(), + ), + ), + // Divisor + Container( + height: 1, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Colors.transparent, + AppTheme.of(context).primaryColor.withOpacity(0.2), + Colors.transparent, + ], + ), + ), + ), + const Gap(16), + // Botones de acción premium + Row( + children: [ + Expanded( + child: _buildMobilePremiumButton( + icon: Icons.edit_rounded, + label: 'Editar', + color: AppTheme.of(context).secondaryColor, + onPressed: () => _editVideoDialog(video, provider), + ), + ), + const Gap(12), + _buildMobileIconButton( + icon: Icons.delete_rounded, + color: AppTheme.of(context).error, + onPressed: () => _deleteVideoDialog(video, provider), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildMobilePremiumButton({ + required IconData icon, + required String label, + required Color color, + required VoidCallback onPressed, + }) { + return Container( + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color.withOpacity(0.15), + color.withOpacity(0.08), + ], + ), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: color.withOpacity(0.3), + width: 2, + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onPressed, + borderRadius: BorderRadius.circular(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(icon, color: color, size: 20), + const Gap(8), + Text( + label, + style: TextStyle( + color: color, + fontSize: 14, + fontWeight: FontWeight.bold, + fontFamily: 'Poppins', + ), + ), + ], ), - ], + ), + ), + ); + } + + Widget _buildMobileIconButton({ + required IconData icon, + required Color color, + required VoidCallback onPressed, + }) { + return Container( + width: 48, + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color.withOpacity(0.15), + color.withOpacity(0.08), + ], + ), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: color.withOpacity(0.3), + width: 2, + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onPressed, + borderRadius: BorderRadius.circular(12), + child: Icon(icon, color: color, size: 20), + ), ), ); }