MVCPostall/Postall/Views/Videos/Index.cshtml
2025-03-25 22:16:31 -03:00

339 lines
15 KiB
Plaintext

@model List<Postall.Models.ChannelVideosViewModel>
@{
ViewData["Title"] = "Gerenciador de Vídeos";
}
<style>
/* Estilos para cards de vídeo na página principal */
.card-title-truncate {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 0;
}
.card-desc-truncate {
height: 60px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
margin-bottom: 0;
}
/* Garantir que o thumbnail tenha tamanho consistente */
.video-thumbnail {
width: 100%;
height: 100px;
object-fit: cover;
}
/* Garantir altura consistente para os cards */
.video-card {
height: 100%;
}
/* Estilo para o botão ler mais */
.read-more-btn {
font-size: 0.8rem;
color: #007bff;
cursor: pointer;
display: inline-block;
margin-top: 3px;
}
.read-more-btn:hover {
text-decoration: underline;
}
/* Estilo para o conteúdo expandido em largura total */
.description-expanded {
max-height: 150px;
overflow-y: auto;
padding: 10px;
background-color: #f8f9fa;
border-radius: 0 0 4px 4px;
border-top: 1px solid #dee2e6;
margin: 10px 5px 5px 5px; /* Margem negativa para alinhar com os limites do card */
display: none;
position: relative;
z-index: 5;
}
/* Ajuste na posição do botão Fechar */
.card-body {
padding-bottom: 5px;
}
/* Ajuste para cards com descrição expandida */
.card-with-expanded-desc {
overflow: visible;
}
</style>
<div class="container mt-4">
<div class="row mb-4">
<div class="col-md-8">
<h2>Meus Vídeos</h2>
<p class="text-muted">Gerencie seus vídeos do YouTube por canal</p>
</div>
<div class="col-md-4 text-right">
<a href="@Url.Action("Index", "Channels")" class="btn btn-outline-primary mr-2">
<i class="bi bi-collection"></i> Gerenciar Canais
</a>
</div>
</div>
@if (TempData["Message"] != null)
{
<div class="alert alert-success alert-dismissible fade show" role="alert">
@TempData["Message"]
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
}
@if (TempData["Error"] != null)
{
<div class="alert alert-danger alert-dismissible fade show" role="alert">
@TempData["Error"]
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
}
@if (Model == null || !Model.Any())
{
<div class="alert alert-info">
<i class="bi bi-info-circle"></i> Você não possui nenhum canal com vídeos.
<a href="@Url.Action("Index", "Channels")">Clique aqui</a> para adicionar um canal primeiro.
</div>
}
else
{
<div class="accordion" id="channelsAccordion">
@foreach (var channelVideos in Model)
{
<div class="card mb-4">
<div class="card-header" id="heading-@channelVideos.Channel.Id">
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<img src="@channelVideos.Channel.ThumbnailUrl" alt="@channelVideos.Channel.Title" class="img-thumbnail mr-3" style="width: 50px; height: 50px;">
<h5 class="mb-0">@channelVideos.Channel.Title</h5>
</div>
<div>
<button class="btn btn-link" type="button" data-toggle="collapse"
data-target="#collapse-@channelVideos.Channel.Id" aria-expanded="true"
aria-controls="collapse-@channelVideos.Channel.Id">
<i class="bi bi-chevron-down"></i>
</button>
<button type="button" class="btn btn-primary btn-sm"
onclick="loadChannelVideos('@channelVideos.Channel.ChannelId')"
data-toggle="modal" data-target="#addVideosModal">
<i class="bi bi-plus-circle"></i> Adicionar Vídeos
</button>
</div>
</div>
</div>
<div id="collapse-@channelVideos.Channel.Id" class="collapse show"
aria-labelledby="heading-@channelVideos.Channel.Id" data-parent="#channelsAccordion">
<div class="card-body">
@if (channelVideos.Videos != null && channelVideos.Videos.Any())
{
<div class="row">
@foreach (var video in channelVideos.Videos)
{
<div class="col-md-6 mb-4">
<div class="card video-card">
<div class="card-header bg-transparent">
<div class="d-flex justify-content-between align-items-center">
<h5 class="card-title-truncate">@video.Title</h5>
<button class="btn btn-sm btn-link" type="button" data-toggle="collapse"
data-target="#videoCollapse-@video.Id" aria-expanded="true">
<i class="bi bi-chevron-down"></i>
</button>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-5">
<img src="@video.ThumbnailUrl" alt="@video.Title" class="img-fluid rounded video-thumbnail">
</div>
<div class="col-md-7">
<div>
<p class="card-desc-truncate mb-0">@video.Description</p>
<span class="read-more-btn" data-target="main-desc-@video.Id">Ler mais</span>
</div>
<p class="text-muted small mt-2">Publicado em: @video.PublishedAt.ToString("dd/MM/yyyy")</p>
</div>
</div>
<div id="main-desc-@video.Id" class="description-expanded">
<p><b>@video.Title</b></p>
@video.Description
</div>
</div>
<div class="collapse show" id="videoCollapse-@video.Id">
<div class="card-footer bg-white">
<div class="d-flex justify-content-between">
<div>
<a href="@video.VideoUrl" target="_blank" class="btn btn-sm btn-outline-primary">
<i class="bi bi-youtube"></i> Ver no YouTube
</a>
</div>
<div>
<button class="btn btn-sm btn-outline-danger"
onclick="removeVideo('@video.Id', '@channelVideos.Channel.Id')">
<i class="bi bi-trash"></i> Remover
</button>
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
}
else
{
<div class="alert alert-info">
<i class="bi bi-info-circle"></i> Este canal não possui vídeos adicionados.
Clique em "Adicionar Vídeos" para começar.
</div>
}
</div>
</div>
</div>
}
</div>
}
</div>
<!-- Modal para adicionar vídeos -->
<div class="modal fade" id="addVideosModal" tabindex="-1" role="dialog" aria-labelledby="addVideosModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addVideosModalLabel">Adicionar Vídeos do Canal</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div id="channelVideosContainer">
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Carregando...</span>
</div>
<p class="mt-2">Carregando vídeos...</p>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary" id="btnAddSelectedVideos">Adicionar Selecionados</button>
</div>
</div>
</div>
</div>
<!-- Formulário oculto para remover vídeos -->
<form id="removeVideoForm" method="post" action="@Url.Action("Remove", "Videos")">
<input type="hidden" id="videoIdToRemove" name="id">
<input type="hidden" id="channelIdForRemove" name="channelId">
</form>
@section Scripts {
<script type="text/javascript">
// Variável para armazenar o ID do canal atual
let currentChannelId = '';
// Função para carregar os vídeos do canal
function loadChannelVideos(channelId) {
currentChannelId = channelId;
$.ajax({
url: '@Url.Action("GetChannelVideos", "Videos")',
type: 'GET',
data: { channelId: channelId },
success: function (result) {
$('#channelVideosContainer').html(result);
// Inicializa os botões "Ler mais" após carregar o conteúdo
setTimeout(function() {
initReadMoreButtons();
}, 200);
},
error: function (error) {
$('#channelVideosContainer').html('<div class="alert alert-danger">Erro ao carregar vídeos. Tente novamente.</div>');
console.error('Erro:', error);
}
});
}
// Função para remover um vídeo
function removeVideo(videoId, channelId) {
if (confirm('Tem certeza que deseja remover este vídeo?')) {
$('#videoIdToRemove').val(videoId);
$('#channelIdForRemove').val(channelId);
$('#removeVideoForm').submit();
}
}
// Função para inicializar os botões "Ler mais"
function initReadMoreButtons() {
$('.read-more-btn').off('click').on('click', function() {
var targetId = $(this).data('target');
$('#' + targetId).slideToggle(200);
// Alternar texto do botão
var btnText = $(this).text() === 'Ler mais' ? 'Fechar' : 'Ler mais';
$(this).text(btnText);
});
}
$(function () {
// Inicializar botões "Ler mais" na carga da página
initReadMoreButtons();
// Reinicializar botões quando um accordion é aberto
$('.collapse').on('shown.bs.collapse', function () {
initReadMoreButtons();
});
// Manipula o clique no botão de adicionar vídeos selecionados
$('#btnAddSelectedVideos').click(function () {
var selectedVideos = [];
// Coleta todos os checkboxes selecionados
$('.video-checkbox:checked').each(function () {
selectedVideos.push($(this).val());
});
if (selectedVideos.length === 0) {
alert('Selecione pelo menos um vídeo para adicionar.');
return;
}
// Cria um formulário para enviar os IDs dos vídeos selecionados
var form = $('<form action="@Url.Action("AddVideos", "Videos")" method="post"></form>');
// Adiciona o ID do canal
form.append('<input type="hidden" name="channelId" value="' + currentChannelId + '">');
// Adiciona inputs ocultos para cada vídeo selecionado
selectedVideos.forEach(function (videoId) {
form.append('<input type="hidden" name="selectedVideos" value="' + videoId + '">');
});
// Adiciona o formulário ao corpo do documento e o submete
$('body').append(form);
form.submit();
});
});
</script>
}