1250 lines
38 KiB
Plaintext
1250 lines
38 KiB
Plaintext
import 'dart:convert';
|
|
|
|
import 'dart:typed_data';
|
|
import 'package:auto_size_text/auto_size_text.dart';
|
|
import 'package:file_picker/_internal/file_picker_web.dart';
|
|
import 'package:file_picker/file_picker.dart';
|
|
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:pluto_grid/pluto_grid.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
import 'package:cbluna_crm_lu/helpers/globals.dart';
|
|
import 'package:cbluna_crm_lu/models/content_manager/ad_by_genre.dart';
|
|
import 'package:cbluna_crm_lu/pages/widgets/toasts/msj_toast.dart';
|
|
|
|
import '../../lib/models/content_manager/all_ads_one_table_model.dart';
|
|
import '../../lib/pages/widgets/video_player_caro.dart';
|
|
|
|
class VideosProvider extends ChangeNotifier {
|
|
List<PlutoGridStateManager> listStateManager = [];
|
|
PlutoGridStateManager? stateManager;
|
|
|
|
final controllerBusqueda = TextEditingController();
|
|
String parametroBusqueda = "";
|
|
|
|
TextEditingController modeloController = TextEditingController();
|
|
|
|
String? videoCoverFile;
|
|
String? videoName;
|
|
String? videoUrl;
|
|
String? videoPath;
|
|
|
|
String fileExtension = '';
|
|
String resolucion = "1";
|
|
String area = "7";
|
|
|
|
Uint8List? webVideo;
|
|
String? categoryImgFileName;
|
|
Uint8List? categoryImageToUpload;
|
|
|
|
String? categoryName;
|
|
bool noImageToUpload = true;
|
|
|
|
//-------
|
|
late final TextEditingController filasController;
|
|
//-------
|
|
|
|
List<List<dynamic>> listPagos = [];
|
|
|
|
final controllerCount = TextEditingController();
|
|
int countI = 0;
|
|
int countF = 19;
|
|
|
|
final controllerBusquedaFiltro = TextEditingController();
|
|
|
|
bool filtroAvanzado = false;
|
|
bool filtroSimple = false;
|
|
|
|
///////////////////////////////////////////
|
|
|
|
var tableTop1Gourp = AutoSizeGroup();
|
|
var tableTopGroup = AutoSizeGroup();
|
|
var tableContentGroup = AutoSizeGroup();
|
|
final busquedaVideoController = TextEditingController();
|
|
///////////////////////////////////////////
|
|
late MsjToast toastMessage;
|
|
|
|
///
|
|
///
|
|
|
|
List<AdsByGenre> adsByGenre = [];
|
|
List<List<PlutoRow>> rows = [];
|
|
List<PlutoRow> rows_ = [];
|
|
List<PlutoRow> allVideoRows = [];
|
|
List<String> listaQrsSeleccionados = [];
|
|
//----------------------------------------------Paginador variables
|
|
|
|
int seccionActual = 1;
|
|
int totalSecciones = 1;
|
|
int totalFilas = 0;
|
|
int from = 0;
|
|
int hasta = 20;
|
|
|
|
//----------------------------------------------Calendario Programacion
|
|
|
|
FilePickerResult? docProveedor;
|
|
//----------------------------------------------Video data
|
|
String? videoCoverFileNameNoModif;
|
|
List<String> videoCategories = [];
|
|
List<int> videoCategoriesId = [];
|
|
List<String> selectedVideoCategories = [];
|
|
List<int> selectedVideoCategoriesId = [];
|
|
List<String> videoCategoriesImages = [];
|
|
|
|
String? posterPath;
|
|
String tituloVideo = '';
|
|
String descripcionVideo = '';
|
|
String videoOutlink = '';
|
|
String videoPatner = '';
|
|
Uint8List? videoPoster;
|
|
int videoPoints = 0;
|
|
Duration duracionVideo = Duration.zero;
|
|
int duratinVideoSeconds = 0;
|
|
List<String> videoPriority = [];
|
|
String? videoPosterPath;
|
|
//----------------------------------------------VideoYables
|
|
bool showFullVideoTable = true;
|
|
List<AllAdsOneTableModel> videos = [];
|
|
String selectePriority = "baja";
|
|
|
|
int warningCountTablaVideos = 0;
|
|
bool showWarningsOnTable = false;
|
|
int? selectedVideoId;
|
|
//----------------------------------------------
|
|
VideosProvider() {
|
|
getVideoPrioritiesList();
|
|
getCategories();
|
|
refreshVideoTablet();
|
|
}
|
|
|
|
updateState(AdsByGenre expandir) {
|
|
expandir.isExpanded = !expandir.isExpanded;
|
|
notifyListeners();
|
|
}
|
|
|
|
getVideoData(Duration? duracion, int? duracionSegundos) async {
|
|
duracionVideo = duracion ?? Duration.zero;
|
|
duratinVideoSeconds = duracionSegundos ?? 0;
|
|
}
|
|
|
|
setVideoTableFullOrCategories(int index) {
|
|
switch (index) {
|
|
case 0:
|
|
showFullVideoTable = true;
|
|
getAllAdsOnOneTable();
|
|
break;
|
|
case 1:
|
|
showFullVideoTable = false;
|
|
getAdsByCategories();
|
|
break;
|
|
default:
|
|
showFullVideoTable = false;
|
|
getAdsByCategories();
|
|
}
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
getAdsByCategories() async {
|
|
try {
|
|
final query = supabaseLU.rpc('lu_buscar_videos_por_genero', params: {
|
|
'busqueda': busquedaVideoController.text,
|
|
});
|
|
|
|
final res = await query.select();
|
|
|
|
if (res == null) {
|
|
return;
|
|
}
|
|
|
|
adsByGenre = (res as List<dynamic>)
|
|
.map((ad) => AdsByGenre.fromJson(jsonEncode(ad)))
|
|
.toList();
|
|
|
|
rows_ = [];
|
|
rows_.clear();
|
|
rows.clear();
|
|
|
|
for (var genre in adsByGenre) {
|
|
adsByGenre[adsByGenre.indexOf(genre)].videoCount = genre.videos.length;
|
|
for (var video in genre.videos) {
|
|
rows_.add(PlutoRow(cells: {
|
|
'video_id': PlutoCell(value: video.videoId.toString()),
|
|
'posterPath': PlutoCell(
|
|
value: video.posterFileName != null
|
|
? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: ''),
|
|
'status': PlutoCell(value: video.status ?? 'neutra'),
|
|
'priority': PlutoCell(value: video.priority),
|
|
'title': PlutoCell(value: video.title),
|
|
'urlAd': PlutoCell(value: video.urlAd ?? ''),
|
|
'overview': PlutoCell(value: video.overview),
|
|
'points': PlutoCell(value: 1),
|
|
'expirationDate': PlutoCell(value: video.expirationDate ?? ''),
|
|
'created_at': PlutoCell(value: video.createdAt ?? ''),
|
|
'durationVideo': PlutoCell(value: video.duration ?? ''),
|
|
'video_url': PlutoCell(
|
|
value: video.videoUrl != null
|
|
? "${supabase.storage.from('lectores_urb/videos/cm_videos').getPublicUrl(video.videoFileName.toString())}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: ''),
|
|
'editar': PlutoCell(value: video.videoId),
|
|
'eliminar': PlutoCell(value: video.videoId),
|
|
'video_file_name': PlutoCell(value: video.videoFileName.toString()),
|
|
'poster_file_name':
|
|
PlutoCell(value: video.posterFileName.toString()),
|
|
'patner': PlutoCell(value: video.partner ?? ''),
|
|
'categories': PlutoCell(value: video.categories ?? ''),
|
|
'video_status': PlutoCell(value: video.videoStatus),
|
|
}));
|
|
}
|
|
rows.add(rows_);
|
|
rows_ = [];
|
|
}
|
|
showWarningsOnTable = false;
|
|
notifyListeners();
|
|
return;
|
|
} catch (e) {
|
|
print('error en getAdsByCategories(): ${e.toString()}');
|
|
}
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
getAdsByCategoriesWarnings() async {
|
|
try {
|
|
final query = supabaseLU.rpc('lu_buscar_videos_por_genero', params: {
|
|
'busqueda': busquedaVideoController.text,
|
|
});
|
|
|
|
final res = await query.select();
|
|
|
|
if (res == null) {
|
|
return;
|
|
}
|
|
|
|
adsByGenre = (res as List<dynamic>)
|
|
.map((ad) => AdsByGenre.fromJson(jsonEncode(ad)))
|
|
.toList();
|
|
|
|
rows_ = [];
|
|
rows_.clear();
|
|
rows.clear();
|
|
for (var genre in adsByGenre) {
|
|
genre.videoCount = 0;
|
|
for (var video in genre.videos!) {
|
|
if (video.categories[0] == [null] ||
|
|
video.categories[0].isEmpty ||
|
|
video.categories[0] == [""] ||
|
|
video.categories[0] == ["null"] ||
|
|
video.urlAd == null ||
|
|
video.urlAd == "" ||
|
|
video.urlAd == "null" ||
|
|
video.overview == "" ||
|
|
video.overview == "null" ||
|
|
video.partner == "" ||
|
|
video.partner == null) {
|
|
rows_.add(PlutoRow(cells: {
|
|
'video_id': PlutoCell(value: video.videoId.toString()),
|
|
'posterPath': PlutoCell(
|
|
value: video.posterFileName != null
|
|
? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: 'https://placehold.co/150x150'),
|
|
'status': PlutoCell(value: video.status ?? 'neutra'),
|
|
'priority': PlutoCell(value: video.priority ?? '4'),
|
|
'title': PlutoCell(value: video.title),
|
|
'urlAd': PlutoCell(value: video.urlAd ?? ''),
|
|
'overview': PlutoCell(value: video.overview),
|
|
'points': PlutoCell(value: video.points ?? ''),
|
|
'expirationDate': PlutoCell(value: video.expirationDate ?? ''),
|
|
'created_at': PlutoCell(value: video.createdAt ?? ''),
|
|
'durationVideo': PlutoCell(value: video.duration ?? ''),
|
|
'video_url': PlutoCell(
|
|
value: video.videoUrl != null
|
|
? "${supabase.storage.from('lectores_urb/videos/cm_videos').getPublicUrl(video.videoFileName.toString())}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: ''),
|
|
'editar': PlutoCell(value: video.videoId),
|
|
'eliminar': PlutoCell(value: video.videoId),
|
|
'video_file_name':
|
|
PlutoCell(value: video.videoFileName.toString()),
|
|
'poster_file_name':
|
|
PlutoCell(value: video.posterFileName.toString()),
|
|
'patner': PlutoCell(value: video.partner ?? ''),
|
|
'categories': PlutoCell(value: video.categories ?? ''),
|
|
'video_status': PlutoCell(value: video.videoStatus),
|
|
}));
|
|
genre.videoCount += 1;
|
|
}
|
|
}
|
|
rows.add(rows_);
|
|
rows_ = [];
|
|
}
|
|
|
|
showWarningsOnTable = true;
|
|
notifyListeners();
|
|
return;
|
|
} catch (e) {
|
|
print('error en getAdsCategoriesWarning: ${e.toString()}');
|
|
}
|
|
}
|
|
|
|
getAllAdsOnOneTable([bool warningMode = false]) async {
|
|
try {
|
|
final String query = busquedaVideoController.text.trim();
|
|
|
|
final res = await supabaseLU.rpc('lu_buscar_videos', params: {
|
|
'busqueda': query.isEmpty ? null : query,
|
|
'warningmode': false,
|
|
});
|
|
|
|
if (res == null) {
|
|
print("--X---Error: respuesta nula al llamar RPC.");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
videos = (res as List<dynamic>)
|
|
.map((ad) => AllAdsOneTableModel.fromJson(jsonEncode(ad)))
|
|
.toList();
|
|
} catch (e) {
|
|
print("Error al parsear lista de videos: ${e.toString()}");
|
|
}
|
|
|
|
allVideoRows.clear();
|
|
|
|
// El warning count total lo devuelve cada fila, tomamos el primero
|
|
warningCountTablaVideos =
|
|
videos.isNotEmpty ? videos.first.warningCount : 0;
|
|
|
|
for (AllAdsOneTableModel video in videos) {
|
|
allVideoRows.add(PlutoRow(cells: {
|
|
'video_id': PlutoCell(value: video.id),
|
|
'poster_path': PlutoCell(
|
|
value: video.posterFileName != null
|
|
? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: 'https://placehold.co/150x150'),
|
|
'priority': PlutoCell(value: video.priority),
|
|
'title': PlutoCell(value: video.title),
|
|
'url_ad': PlutoCell(value: video.urlAd ?? ''),
|
|
'overview': PlutoCell(value: video.overview),
|
|
'points': PlutoCell(value: video.points),
|
|
'expiration_date': PlutoCell(value: video.expirationDate),
|
|
'created_at': PlutoCell(value: video.createdAt),
|
|
'duration_video': PlutoCell(value: video.durationVideo),
|
|
'video_url': PlutoCell(
|
|
value: video.video.isNotEmpty
|
|
? "${video.video}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: '',
|
|
),
|
|
'editar': PlutoCell(value: video.id),
|
|
'eliminar': PlutoCell(value: video.id),
|
|
'video_file_name': PlutoCell(value: video.videoFileName ?? ''),
|
|
'poster_file_name': PlutoCell(value: video.posterFileName ?? ''),
|
|
'partner': PlutoCell(value: video.partner ?? ''),
|
|
'categories': PlutoCell(value: video.categories),
|
|
'video_status': PlutoCell(value: video.videoStatus),
|
|
'qr_codes': PlutoCell(
|
|
value: video.qrCodes.expand((entry) {
|
|
try {
|
|
final details = entry['details'];
|
|
|
|
// Verifica si 'details' está presente y tiene la clave 'qrs'
|
|
if (details != null &&
|
|
details is Map<String, dynamic> &&
|
|
details['qrs'] is List) {
|
|
return (details['qrs'] as List)
|
|
.map((qrsEntry) => qrsEntry['qrs_concat'])
|
|
.whereType<String>();
|
|
}
|
|
} catch (e) {
|
|
// Si ocurre un error al intentar acceder a los datos, lo manejamos de forma silenciosa
|
|
print('Error al acceder a QR details: $e');
|
|
}
|
|
return []; // Devuelve una lista vacía en caso de error o datos inválidos
|
|
}).join('\n'), // o ', ' si prefieres en una sola línea
|
|
),
|
|
'qr_codes_list': PlutoCell(
|
|
value: video.qrCodes.expand((entry) {
|
|
try {
|
|
final details = entry['details'];
|
|
if (details != null &&
|
|
details is Map<String, dynamic> &&
|
|
details['qrs'] is List) {
|
|
return (details['qrs'] as List)
|
|
.map((qrsEntry) => qrsEntry['qrs_concat'])
|
|
.whereType<String>();
|
|
}
|
|
} catch (e) {
|
|
print('Error al acceder a QR details (lista): $e');
|
|
}
|
|
return [];
|
|
}).toList(), // ← clave aquí
|
|
),
|
|
}));
|
|
}
|
|
|
|
showWarningsOnTable = false;
|
|
notifyListeners();
|
|
} catch (e) {
|
|
print('Error en getAllAdsOnOneTable: ${e.toString()}');
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
getAllAdsOnOneTableWarnings() async {
|
|
try {
|
|
final res = await supabaseLU.from('videos_view').select();
|
|
if (res == null) {
|
|
print("--X---Error: ${res.error}");
|
|
return;
|
|
}
|
|
|
|
videos = (res as List<dynamic>)
|
|
.map((ad) => AllAdsOneTableModel.fromJson(jsonEncode(ad)))
|
|
.toList();
|
|
|
|
allVideoRows.clear();
|
|
|
|
for (AllAdsOneTableModel video in videos) {
|
|
if (video.categories[0] == [null] ||
|
|
video.categories[0] == null ||
|
|
video.categories[0] == [] ||
|
|
video.categories[0] == [""] ||
|
|
video.categories[0] == ["null"] ||
|
|
video.urlAd == "" ||
|
|
video.urlAd == null ||
|
|
video.urlAd == "null" ||
|
|
video.overview == "" ||
|
|
video.overview == "null" ||
|
|
video.partner == "" ||
|
|
video.partner == null) {
|
|
allVideoRows.add(PlutoRow(cells: {
|
|
'id': PlutoCell(value: video.id),
|
|
'posterPath': PlutoCell(
|
|
value: video.posterFileName != null
|
|
? "${supabase.storage.from('lectores_urb/imagenes/videos/posters').getPublicUrl(video.posterFileName)}?${DateTime.now().millisecondsSinceEpoch}"
|
|
: 'https://placehold.co/150x150'),
|
|
'priority': PlutoCell(value: video.priority ?? '4'),
|
|
'title': PlutoCell(value: video.title ?? ''),
|
|
'urlAd': PlutoCell(value: video.urlAd.toString() ?? ''),
|
|
'overview': PlutoCell(value: video.overview ?? ''),
|
|
'points': PlutoCell(value: video.points ?? ''),
|
|
'expirationDate': PlutoCell(value: video.expirationDate ?? ''),
|
|
'created_at': PlutoCell(value: video.createdAt ?? ''),
|
|
'durationVideo': PlutoCell(value: video.durationVideo ?? ''),
|
|
'video_url': PlutoCell(
|
|
value:
|
|
"${supabase.storage.from('lectores_urb/videos/cm_videos').getPublicUrl(video.videoFileName.toString())}?${DateTime.now().millisecondsSinceEpoch}"),
|
|
'editar': PlutoCell(value: video.id),
|
|
'eliminar': PlutoCell(value: video.id),
|
|
'video_file_name': PlutoCell(value: video.videoFileName ?? ''),
|
|
'poster_file_name': PlutoCell(value: video.posterFileName ?? ''),
|
|
'patner': PlutoCell(value: video.partner ?? ''),
|
|
'categories': PlutoCell(value: video.categories ?? ''),
|
|
'video_status': PlutoCell(value: video.videoStatus),
|
|
}));
|
|
}
|
|
}
|
|
showWarningsOnTable = true;
|
|
notifyListeners();
|
|
return;
|
|
} catch (e) {
|
|
print('error en getAllAdsOnOneTableWarnings: ${e.toString()}');
|
|
}
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
Future<List<String>> getCategories() async {
|
|
try {
|
|
final res = await supabaseLU
|
|
.from('video_genero')
|
|
.select('name, id, poster_image_file')
|
|
.eq('visible', true)
|
|
.order('name', ascending: true);
|
|
|
|
videoCategories = (res as List<dynamic>)
|
|
.map((category) => category['name'] as String)
|
|
.toList();
|
|
|
|
videoCategoriesId = (res as List<dynamic>)
|
|
.map((category) => category['id'] as int)
|
|
.toList();
|
|
|
|
videoCategoriesImages = (res as List<dynamic>)
|
|
.map((category) => category['poster_image_file'] as String)
|
|
.toList();
|
|
|
|
return videoCategories;
|
|
} catch (e) {
|
|
print("ERROR en getVideosVinculados: " + e.toString());
|
|
notifyListeners();
|
|
return [];
|
|
}
|
|
}
|
|
|
|
//usando el id del video cambiar su estado "video_status" a true o false
|
|
cambiarEstadoVideo(int idVideo, bool estado) async {
|
|
await supabaseLU
|
|
.from('videos')
|
|
.update({'video_status': estado})
|
|
.eq('id', idVideo)
|
|
.select();
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* ------------------------------------------------------------------------- */
|
|
/* ------------------------------------------------------------------------- */
|
|
/* ------------------------------------------------------------------------- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
Widget? getPosterImage(dynamic image,
|
|
{double height = 180, BoxFit boxFit = BoxFit.cover}) {
|
|
if (image == null) {
|
|
return Image.asset('assets/images/placeholder_no_image.jpg');
|
|
} else if (image is Uint8List) {
|
|
return Image.memory(
|
|
image,
|
|
height: height,
|
|
width: double.infinity,
|
|
fit: boxFit,
|
|
);
|
|
} else if (image is String) {
|
|
return Image.network(
|
|
image,
|
|
height: height,
|
|
width: double.infinity,
|
|
filterQuality: FilterQuality.high,
|
|
fit: boxFit,
|
|
);
|
|
} else {
|
|
return Image.asset('assets/images/placeholder_no_image.jpg');
|
|
}
|
|
}
|
|
|
|
Widget? getCategoryImage(dynamic image,
|
|
{double height = 180, BoxFit boxFit = BoxFit.cover}) {
|
|
if (image == null) {
|
|
noImageToUpload = true;
|
|
|
|
return Image.asset('assets/images/placeholder_upload_image.png');
|
|
} else if (image is Uint8List) {
|
|
noImageToUpload = false;
|
|
|
|
return Image.memory(
|
|
image,
|
|
height: height,
|
|
width: double.infinity,
|
|
fit: boxFit,
|
|
);
|
|
} else if (image is String) {
|
|
noImageToUpload = false;
|
|
|
|
return Image.network(
|
|
"${supabase.storage.from('lectores_urb/imagenes/videos/categories').getPublicUrl(image)}?${DateTime.now().millisecondsSinceEpoch}",
|
|
height: height,
|
|
width: double.infinity,
|
|
filterQuality: FilterQuality.high,
|
|
fit: boxFit,
|
|
);
|
|
} else {
|
|
noImageToUpload = true;
|
|
|
|
return Image.asset('assets/images/placeholder_upload_image.png');
|
|
}
|
|
}
|
|
|
|
//get video widget VideoScreenNew;
|
|
|
|
Widget? getVideoWidget(dynamic image,
|
|
{double height = 180, width = 500, BoxFit boxFit = BoxFit.contain}) {
|
|
if (videoPath == null) {
|
|
return Image.asset('assets/images/placeholder_no_video.png',
|
|
width: width, height: height, fit: boxFit);
|
|
} else {
|
|
return VideoScreenNew(
|
|
videoUrl: videoPath,
|
|
);
|
|
}
|
|
}
|
|
|
|
/////////////CATEGORY///////////////////////
|
|
|
|
Future<void> selectCategoryImage() async {
|
|
categoryImgFileName = null;
|
|
categoryImageToUpload = null;
|
|
FilePickerResult? picker = await FilePickerWeb.platform
|
|
.pickFiles(type: FileType.custom, allowedExtensions: ['jpg', 'png']);
|
|
|
|
//get and load pdf
|
|
if (picker != null) {
|
|
var now = DateTime.now();
|
|
var formatter = DateFormat('yyyyMMddHHmmss');
|
|
var timestamp = formatter.format(now);
|
|
|
|
categoryImgFileName = 'category-$timestamp-${picker.files.single.name}';
|
|
categoryImageToUpload = picker.files.single.bytes;
|
|
noImageToUpload = false;
|
|
} else {
|
|
categoryImgFileName = null;
|
|
categoryImageToUpload = null;
|
|
}
|
|
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
uploadCategoryImage() async {
|
|
if (categoryImageToUpload != null && categoryImgFileName != null) {
|
|
await supabase.storage
|
|
.from('lectores_urb/imagenes/videos/categories')
|
|
.uploadBinary(
|
|
categoryImgFileName!,
|
|
categoryImageToUpload!,
|
|
fileOptions: const FileOptions(
|
|
cacheControl: '3600',
|
|
upsert: false,
|
|
),
|
|
);
|
|
|
|
return;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Future<bool> registrarNuevaCategoria() async {
|
|
await uploadCategoryImage();
|
|
|
|
final res = await supabaseLU.from('video_genero').insert(
|
|
{
|
|
'name': categoryName,
|
|
'poster_image_file': categoryImgFileName,
|
|
},
|
|
).select();
|
|
|
|
if (res == null) {
|
|
print("Error al registrar categoria");
|
|
print(res.error!.message);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/////////////ACTUALIZAR CATEGORIA///////////////////////
|
|
|
|
Future<bool> updateCategory(int idCategory, String? name) async {
|
|
if (categoryImageToUpload == null) {
|
|
final res = await supabaseLU
|
|
.from('video_genero')
|
|
.update(
|
|
{
|
|
'name': name.toString(),
|
|
},
|
|
)
|
|
.eq('id', idCategory)
|
|
.select();
|
|
|
|
if (res == null) {
|
|
print("Error al registrar updateCategory1");
|
|
print(res.error!.message);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------
|
|
final getFileName = await supabaseLU
|
|
.from('video_genero')
|
|
.select('poster_image_file')
|
|
.eq('id', idCategory)
|
|
.single();
|
|
|
|
if (getFileName['poster_image_file'] != null &&
|
|
categoryImageToUpload != null) {
|
|
await supabase.storage
|
|
.from('lectores_urb/imagenes/videos/categories')
|
|
.updateBinary(
|
|
getFileName['poster_image_file'],
|
|
categoryImageToUpload!,
|
|
fileOptions: const FileOptions(
|
|
cacheControl: '3600',
|
|
upsert: false,
|
|
),
|
|
);
|
|
} else {
|
|
print("NO EXISTE SUBIR");
|
|
await supabase.storage
|
|
.from('lectores_urb/imagenes/videos/categories')
|
|
.uploadBinary(
|
|
categoryImgFileName!,
|
|
categoryImageToUpload!,
|
|
fileOptions: const FileOptions(
|
|
cacheControl: '3600',
|
|
upsert: false,
|
|
),
|
|
);
|
|
await supabaseLU
|
|
.from('video_genero')
|
|
.update(
|
|
{
|
|
'poster_image_file': categoryImgFileName,
|
|
},
|
|
)
|
|
.eq('id', idCategory)
|
|
.select();
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
return true;
|
|
}
|
|
|
|
/////////////BORRAR CATEGORIA///////////////////////
|
|
|
|
Future<bool> deleteCategory(int idCategory, String? filename) async {
|
|
await supabaseLU
|
|
.from('video_in_genero')
|
|
.delete()
|
|
.eq('genero_id', idCategory)
|
|
.select();
|
|
|
|
await supabase.storage
|
|
.from('lectores_urb')
|
|
.remove(["imagenes/videos/categories/$filename"]);
|
|
|
|
await supabaseLU
|
|
.from('video_genero')
|
|
.delete()
|
|
.eq('id', idCategory)
|
|
.select();
|
|
categoryImgFileName = null;
|
|
|
|
resetAllvideoData();
|
|
getCategories();
|
|
refreshVideoTablet();
|
|
|
|
return true;
|
|
}
|
|
|
|
//---------------ATUALIZAR VIDEOS------------------
|
|
|
|
Future<bool> updateVideoData(
|
|
int idVideo,
|
|
String title,
|
|
String description,
|
|
String partner,
|
|
String outlink,
|
|
int points,
|
|
List<int> selectedVideoCategoriesId, {
|
|
String? videoImage,
|
|
String? posterImage,
|
|
String? posterFileName,
|
|
List<String>? qrList,
|
|
}) async {
|
|
/* print("updateVideoData");
|
|
print("idVideo: $idVideo");
|
|
print("title: $title");
|
|
print("description: $description");
|
|
print("partner: $partner");
|
|
print("outlink: $outlink");
|
|
print("points: $points");
|
|
print("selectedVideoCategoriesId: $selectedVideoCategoriesId");
|
|
print("posterFileName: $posterFileName");
|
|
print("posterImage: $posterImage");
|
|
print("videoImage: $videoImage");
|
|
print("qrList: $qrList"); */
|
|
|
|
if (qrList != null) {
|
|
final existingQrs = await getQrsByVideoId(idVideo);
|
|
// Eliminar los QRs que no están en qrList
|
|
for (String qr in existingQrs) {
|
|
if (!qrList.contains(qr)) {
|
|
await supabaseLU
|
|
.from('video_in_qr')
|
|
.delete()
|
|
.eq('id_qr_fk', qr)
|
|
.eq('id_video_fk', idVideo)
|
|
.select();
|
|
}
|
|
}
|
|
|
|
// Agregar nuevos QRs
|
|
for (String qr in qrList) {
|
|
if (!existingQrs.contains(qr)) {
|
|
await supabaseLU.from('video_in_qr').insert({
|
|
'id_qr_fk': qr,
|
|
'id_video_fk': idVideo,
|
|
}).select();
|
|
}
|
|
}
|
|
}
|
|
|
|
final priorityrecibe = await getPriorityId(selectePriority);
|
|
final res = await supabaseLU
|
|
.from('videos')
|
|
.update(
|
|
{
|
|
'title': title.toString(),
|
|
'overview': description.toString(),
|
|
'url_ad': outlink.toString(),
|
|
'partner': partner.toString(),
|
|
'points': 1,
|
|
'priority': priorityrecibe,
|
|
'video_status': true,
|
|
},
|
|
)
|
|
.eq('id', idVideo)
|
|
.select();
|
|
|
|
if (res == null) {
|
|
print("Error al registrar updateVideoTitulo");
|
|
print(res.error!.message);
|
|
resetAllvideoData();
|
|
return false;
|
|
}
|
|
|
|
if (webVideo != null) {
|
|
final getFileName = await supabaseLU
|
|
.from('videos')
|
|
.select('video_file_name')
|
|
.eq('id', idVideo)
|
|
.single();
|
|
|
|
print("getFileName: $getFileName");
|
|
if (getFileName['video_file_name'] != null) {
|
|
await supabase.storage
|
|
.from('lectores_urb/videos/cm_videos')
|
|
.updateBinary(
|
|
getFileName['video_file_name'],
|
|
webVideo!,
|
|
fileOptions: const FileOptions(
|
|
cacheControl: '3600',
|
|
upsert: false,
|
|
),
|
|
);
|
|
|
|
webVideo = null;
|
|
}
|
|
}
|
|
|
|
if (videoPoster != null) {
|
|
await supabase.storage
|
|
.from('lectores_urb/imagenes/videos/posters')
|
|
.updateBinary(videoCoverFileNameNoModif.toString(), videoPoster!);
|
|
}
|
|
await supabaseLU
|
|
.from('video_in_genero')
|
|
.delete()
|
|
.eq('video_id', idVideo)
|
|
.select();
|
|
await registrarCategoriasDelVideoUsandoId(
|
|
idVideo, selectedVideoCategoriesId);
|
|
|
|
resetAllvideoData();
|
|
|
|
refreshVideoTablet();
|
|
return true;
|
|
}
|
|
|
|
/////////////VIDEOS///////////////////////
|
|
|
|
getVideoPrioritiesList() async {
|
|
final res = await supabaseLU.from('video_priority').select("name");
|
|
|
|
videoPriority = (res as List<dynamic>)
|
|
.map((priority) => priority['name'] as String)
|
|
.toList();
|
|
|
|
return videoPriority;
|
|
}
|
|
|
|
Future<String?> uploadPosterImage() async {
|
|
if (videoPoster != null && videoCoverFile != null) {
|
|
await supabase.storage
|
|
.from('lectores_urb/imagenes/videos/posters')
|
|
.uploadBinary(
|
|
'$videoName-$videoCoverFile',
|
|
videoPoster!,
|
|
fileOptions: const FileOptions(
|
|
cacheControl: '3600',
|
|
upsert: false,
|
|
),
|
|
);
|
|
|
|
final res = await supabase.storage
|
|
.from('lectores_urb/imagenes/videos/posters')
|
|
.getPublicUrl('$videoName-$videoCoverFile');
|
|
|
|
posterPath = res;
|
|
|
|
return videoCoverFile;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Future<void> selectPosterImage() async {
|
|
videoCoverFile = null;
|
|
videoPoster = null;
|
|
FilePickerResult? picker = await FilePickerWeb.platform
|
|
.pickFiles(type: FileType.custom, allowedExtensions: ['jpg', 'png']);
|
|
|
|
//get and load pdf
|
|
if (picker != null) {
|
|
var now = DateTime.now();
|
|
var formatter = DateFormat('yyyyMMddHHmmss');
|
|
var timestamp = formatter.format(now);
|
|
|
|
videoCoverFile = 'poster-$timestamp-${picker.files.single.name}';
|
|
videoPoster = picker.files.single.bytes;
|
|
} else {
|
|
videoCoverFile = null;
|
|
videoPoster = null;
|
|
}
|
|
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
Future<bool> selectVideo() async {
|
|
videoName = "";
|
|
|
|
final ImagePicker picker = ImagePicker();
|
|
|
|
final XFile? pickedVideo = await picker.pickVideo(
|
|
source: ImageSource.gallery,
|
|
);
|
|
|
|
if (pickedVideo == null) return false;
|
|
|
|
fileExtension = p.extension(pickedVideo.name);
|
|
|
|
videoPath = pickedVideo.path;
|
|
videoName = pickedVideo.name;
|
|
videoName = videoName!.replaceAll(fileExtension, "");
|
|
webVideo = await pickedVideo.readAsBytes();
|
|
|
|
return true;
|
|
}
|
|
|
|
Future<bool> uploadVideo(List<int> categoryID, {List<String>? qrList}) async {
|
|
try {
|
|
if (webVideo != null && videoName != null) {
|
|
final files = await supabase.storage
|
|
.from('lectores_urb')
|
|
.list(path: 'videos/cm_videos');
|
|
|
|
// Verificar si el archivo ya existe
|
|
final fileExists =
|
|
files.any((file) => file.name == '$videoName$fileExtension');
|
|
|
|
if (fileExists) {
|
|
toastMessage = MsjToast(
|
|
message: 'video already exists',
|
|
color: Color.fromARGB(255, 236, 187, 50),
|
|
);
|
|
return false;
|
|
}
|
|
|
|
if (videoCoverFile == null) {
|
|
toastMessage = MsjToast(
|
|
message: 'No poster selected, upload an image to continue',
|
|
color: Color.fromARGB(255, 236, 187, 50),
|
|
);
|
|
|
|
return false;
|
|
}
|
|
|
|
//check if videoCoverFile ya existe en storage
|
|
final filesPoster = await supabase.storage
|
|
.from('lectores_urb')
|
|
.list(path: 'imagenes/videos/posters');
|
|
|
|
// Verificar si el archivo ya existe
|
|
final fileExistsPoster = filesPoster
|
|
.any((file) => file.name == '$videoName-$videoCoverFile');
|
|
|
|
if (fileExistsPoster) {
|
|
toastMessage = MsjToast(
|
|
message: 'poster file name already exists, (change the name)',
|
|
color: Color.fromARGB(255, 236, 187, 50),
|
|
);
|
|
return false;
|
|
}
|
|
|
|
final storageResponse = await supabase.storage
|
|
.from('lectores_urb/videos/cm_videos')
|
|
.uploadBinary(
|
|
'$videoName$fileExtension',
|
|
webVideo!,
|
|
fileOptions: const FileOptions(
|
|
cacheControl: '3600',
|
|
upsert: false,
|
|
),
|
|
);
|
|
|
|
if (storageResponse == null) return false;
|
|
|
|
dynamic res = supabase.storage
|
|
.from('lectores_urb/videos/cm_videos')
|
|
.getPublicUrl('$videoName$fileExtension');
|
|
videoUrl = res;
|
|
|
|
if (await registrarVideo2(categoryID, qrList: qrList)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
} catch (e) {
|
|
print("Error en uploadVideo: $e");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//get priority id using name
|
|
Future<int> getPriorityId(String priorityName) async {
|
|
final res = await supabaseLU
|
|
.from('video_priority')
|
|
.select("id")
|
|
.eq("name", priorityName)
|
|
.limit(1);
|
|
|
|
if (res == null) {
|
|
print("Error al obtener id de prioridad");
|
|
print(res.error!.message);
|
|
return 0;
|
|
}
|
|
|
|
return res[0]['id'];
|
|
}
|
|
|
|
Future<bool> registrarCategoriasDelVideoUsandoId(
|
|
int idVideo, List<int> listaIdsCategorias) async {
|
|
try {
|
|
await supabaseLU.rpc('lu_añadir_generos_al_video', params: {
|
|
'lista_id_generos': listaIdsCategorias,
|
|
'videoid': idVideo
|
|
}).select();
|
|
|
|
return true;
|
|
} catch (e) {
|
|
print("Error al registrar Categorias del video");
|
|
print(e.toString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> obtenerIdVideoUsandoNombreArchivoStorage(
|
|
String videoPath) async {
|
|
//obtiene el id del video recien registrado usando su archivo cargado
|
|
final res = await supabaseLU
|
|
.from('videos')
|
|
.select("id")
|
|
.eq("video_file_name", videoPath)
|
|
.limit(1);
|
|
|
|
if (res == null) {
|
|
print("Error al al obtener id del video");
|
|
print(res.error!.message);
|
|
return false;
|
|
}
|
|
|
|
await registrarCategoriasDelVideoUsandoId(
|
|
res[0]['id'], selectedVideoCategoriesId);
|
|
|
|
return true;
|
|
}
|
|
|
|
Future<bool> deleteVideo2(
|
|
int idVideo, String videoFileName, String posterFileName) async {
|
|
try {
|
|
// Llamada al RPC para eliminar el video y obtener los nombres de archivos
|
|
final res = await supabaseLU
|
|
.rpc('lu_borrar_video', params: {'id_video': idVideo});
|
|
|
|
// Validar la respuesta
|
|
if (res == null || res.isEmpty) {
|
|
print("El video no pudo ser eliminado o no existe.");
|
|
refreshVideoTablet();
|
|
return false;
|
|
}
|
|
await supabaseLU.from('videos').delete().eq('id', idVideo).select();
|
|
await eliminarVideo(videoFileName, posterFileName);
|
|
|
|
refreshVideoTablet();
|
|
return true;
|
|
} catch (e) {
|
|
print("Error al eliminar el video: ${e.toString()}");
|
|
refreshVideoTablet();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> eliminarVideo(
|
|
String videoFileName, String posterFileName) async {
|
|
await supabase.storage
|
|
.from('lectores_urb')
|
|
.remove(['videos/cm_videos/$videoFileName']);
|
|
await supabase.storage
|
|
.from('lectores_urb')
|
|
.remove(['imagenes/videos/posters/$posterFileName']);
|
|
|
|
return true;
|
|
}
|
|
|
|
Future<List<Map<String, dynamic>>> getGroupedQRCodesByCustomer() async {
|
|
try {
|
|
// Llamada al RPC en Supabase
|
|
final res = await supabaseLU.rpc('get_qr_codes_grouped_by_customer');
|
|
|
|
// Validar el resultado
|
|
if (res == null || res.isEmpty) {
|
|
print("No se encontraron datos agrupados.");
|
|
return [];
|
|
}
|
|
|
|
// Convertir los resultados en una lista de Map
|
|
return List<Map<String, dynamic>>.from(res).map((group) {
|
|
return {
|
|
'row_number': group['row_number'],
|
|
'customer_fk': group['customer_fk'],
|
|
'customer_name': group['customer_name'],
|
|
'details': group['details'], // JSONB con los detalles
|
|
};
|
|
}).toList();
|
|
} catch (e) {
|
|
print("Error en getGroupedQRCodesByCustomer: ${e.toString()}");
|
|
return []; // Retornar una lista vacía en caso de error
|
|
}
|
|
}
|
|
|
|
Future<List<String>> getQrsByVideoId(int videoId) async {
|
|
try {
|
|
final response = await supabaseLU
|
|
.from('video_in_qr')
|
|
.select('id_qr_fk')
|
|
.eq('id_video_fk', videoId);
|
|
|
|
if (response == null) {
|
|
print('Error al obtener getQrsByCouponId()');
|
|
return [];
|
|
}
|
|
|
|
return List<String>.from(
|
|
(response as List<dynamic>).map((item) => item['id_qr_fk']),
|
|
);
|
|
} catch (e) {
|
|
print("Error en getQrsByVideoId: ${e.toString()}");
|
|
return []; // Retornar una lista vacía en caso de error
|
|
}
|
|
}
|
|
|
|
void resetAllvideoData() {
|
|
videoPoster = null;
|
|
videoCoverFile = null;
|
|
videoPath = null;
|
|
videoName = null;
|
|
selectedVideoCategoriesId = [];
|
|
selectedVideoCategories = [];
|
|
categoryImgFileName = null;
|
|
categoryImageToUpload = null;
|
|
noImageToUpload = true;
|
|
selectePriority = "baja";
|
|
videoOutlink = "";
|
|
videoPoints = 0;
|
|
descripcionVideo = "";
|
|
videoPatner = "";
|
|
videoUrl = null;
|
|
webVideo = null;
|
|
posterPath = null;
|
|
videoPosterPath = null;
|
|
tituloVideo = "";
|
|
return;
|
|
}
|
|
|
|
void clearPosterImage() {
|
|
videoPoster = null;
|
|
videoCoverFile = null;
|
|
videoPosterPath = null;
|
|
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
void clearControllers() {
|
|
modeloController.clear();
|
|
notifyListeners();
|
|
}
|
|
|
|
void updatestateManager() {
|
|
print(videoName);
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
void clearVideo() {
|
|
videoPath = null;
|
|
webVideo = null;
|
|
notifyListeners();
|
|
}
|
|
|
|
void refreshVideoTablet() {
|
|
print(showWarningsOnTable);
|
|
if (showWarningsOnTable && warningCountTablaVideos > 0) {
|
|
showFullVideoTable == true
|
|
? getAllAdsOnOneTableWarnings()
|
|
: getAdsByCategoriesWarnings();
|
|
} else {
|
|
showFullVideoTable == true ? getAllAdsOnOneTable() : getAdsByCategories();
|
|
}
|
|
}
|
|
|
|
Future<bool> registrarVideo2(List<int> categoryIds,
|
|
{List<String>? qrList}) async {
|
|
await uploadPosterImage();
|
|
final priorityrecibe = await getPriorityId(selectePriority);
|
|
|
|
final res = await supabaseLU.rpc(
|
|
'lu_registrar_videos_master',
|
|
params: {
|
|
'p_title': tituloVideo,
|
|
'p_overview': descripcionVideo,
|
|
'p_video_url': videoUrl,
|
|
'p_url_ad': videoOutlink,
|
|
'p_poster_path': posterPath ??
|
|
"https://u-supabase.virtalus.cbluna-dev.com/storage/v1/object/public/assets/placeholder_no_image.jpg",
|
|
'p_poster_file_name': '$videoName-$videoCoverFile',
|
|
'p_video_file_name': '$videoName$fileExtension',
|
|
'p_duration_video': duratinVideoSeconds,
|
|
'p_partner': videoPatner,
|
|
'p_priority': priorityrecibe,
|
|
'p_qr_list': qrList,
|
|
'p_category_ids': categoryIds
|
|
},
|
|
).select();
|
|
|
|
if (res == null) {
|
|
print("Error al registrar video");
|
|
print(res.error!.message);
|
|
return false;
|
|
}
|
|
|
|
if (await obtenerIdVideoUsandoNombreArchivoStorage(
|
|
'$videoName$fileExtension')) {
|
|
videoName = "";
|
|
descripcionVideo = "";
|
|
refreshVideoTablet();
|
|
return true;
|
|
} else {
|
|
videoName = "";
|
|
descripcionVideo = "";
|
|
refreshVideoTablet();
|
|
return false;
|
|
}
|
|
}
|
|
}
|