Update mymovies

This commit is contained in:
DariusIII
2025-10-06 12:38:12 +02:00
parent f19a154965
commit 0f82fe05cd
8 changed files with 995 additions and 174 deletions
+54 -135
View File
@@ -3,11 +3,12 @@
namespace App\Http\Controllers;
use App\Models\Invitation;
use App\Models\Settings; // Added for registerstatus check
use App\Models\Settings;
use App\Services\InvitationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class InvitationController extends BasePageController
{
@@ -23,45 +24,38 @@ class InvitationController extends BasePageController
/**
* Display a listing of the user's invitations
*/
public function index(Request $request): void
public function index(Request $request): View
{
$this->setPreferences();
$inviteMode = (int) Settings::settingValue('registerstatus') === Settings::REGISTER_STATUS_INVITE;
$status = $request->get('status');
$this->viewData['meta_title'] = 'My Invitations';
$this->viewData['meta_keywords'] = 'invitations,invite,users,manage';
$this->viewData['meta_description'] = 'Manage your sent invitations and send new invitations to friends';
$this->viewData['status'] = $status;
if (! $inviteMode) {
// Invitations disabled: show informational message only, no queries.
$this->smarty->assign([
'invite_mode' => false,
'status' => null,
'stats' => [],
'invitations' => [],
'pagination_links' => null,
'csrf_token' => csrf_token(),
]);
$this->viewData['invite_mode'] = false;
$this->viewData['stats'] = [];
$this->viewData['invitations'] = [];
$this->viewData['pagination_links'] = null;
$meta_title = 'Invitations Disabled';
$meta_keywords = 'invitations,disabled';
$meta_description = 'Invitations are currently disabled on this site.';
$this->viewData['meta_title'] = 'Invitations Disabled';
$this->viewData['meta_keywords'] = 'invitations,disabled';
$this->viewData['meta_description'] = 'Invitations are currently disabled on this site.';
$content = $this->smarty->fetch('invitations_index.tpl');
$this->smarty->assign([
'content' => $content,
'meta_title' => $meta_title,
'meta_keywords' => $meta_keywords,
'meta_description' => $meta_description,
]);
$this->pagerender();
return;
return view('invitations.index', $this->viewData);
}
$status = $request->get('status');
$user = auth()->user();
$invitations = $this->invitationService->getUserInvitations($user->id, $status);
$stats = $this->invitationService->getUserInvitationStats($user->id);
// Convert paginated results to array for Smarty
// Convert paginated results to array for Blade
$invitationsArray = [];
foreach ($invitations as $invitation) {
$invitationData = $invitation->toArray();
@@ -71,7 +65,7 @@ class InvitationController extends BasePageController
$invitationData['used_by_user'] = $invitation->usedBy->toArray();
}
// Convert timestamps for Smarty
// Convert timestamps
$invitationData['created_at'] = strtotime($invitation->created_at);
$invitationData['expires_at'] = strtotime($invitation->expires_at);
if ($invitation->used_at) {
@@ -81,61 +75,35 @@ class InvitationController extends BasePageController
$invitationsArray[] = $invitationData;
}
$this->smarty->assign([
'invite_mode' => true,
'invitations' => $invitationsArray,
'stats' => $stats,
'status' => $status,
'pagination_links' => $invitations->links(),
'csrf_token' => csrf_token(),
]);
$this->viewData['invite_mode'] = true;
$this->viewData['invitations'] = $invitationsArray;
$this->viewData['stats'] = $stats;
$this->viewData['status'] = $status;
$this->viewData['pagination_links'] = $invitations->links();
// Set meta information
$meta_title = 'My Invitations';
$meta_keywords = 'invitations,invite,users,manage';
$meta_description = 'Manage your sent invitations and send new invitations to friends';
// Fetch the template content
$content = $this->smarty->fetch('invitations_index.tpl');
// Assign content and meta data for final rendering
$this->smarty->assign([
'content' => $content,
'meta_title' => $meta_title,
'meta_keywords' => $meta_keywords,
'meta_description' => $meta_description,
]);
// Render the page with proper styling
$this->pagerender();
return view('invitations.index', $this->viewData);
}
/**
* Show the form for creating a new invitation
*/
public function create(): void
public function create(): View
{
$this->setPreferences();
$inviteMode = (int) Settings::settingValue('registerstatus') === Settings::REGISTER_STATUS_INVITE;
if (! $inviteMode) {
$this->smarty->assign([
'invite_mode' => false,
'csrf_token' => csrf_token(),
]);
$meta_title = 'Invitations Disabled';
$meta_keywords = 'invitations,disabled';
$meta_description = 'Invitations are currently disabled on this site.';
$content = $this->smarty->fetch('invitations_create.tpl');
$this->smarty->assign([
'content' => $content,
'meta_title' => $meta_title,
'meta_keywords' => $meta_keywords,
'meta_description' => $meta_description,
]);
$this->pagerender();
return;
$this->viewData['meta_title'] = 'Send New Invitation';
$this->viewData['meta_keywords'] = 'invitation,invite,send,new,user';
$this->viewData['meta_description'] = 'Send a new invitation to invite someone to join the site';
if (! $inviteMode) {
$this->viewData['invite_mode'] = false;
$this->viewData['meta_title'] = 'Invitations Disabled';
$this->viewData['meta_keywords'] = 'invitations,disabled';
$this->viewData['meta_description'] = 'Invitations are currently disabled on this site.';
return view('invitations.create', $this->viewData);
}
$user = auth()->user();
@@ -148,36 +116,15 @@ class InvitationController extends BasePageController
->count();
$availableInvites = $user->invites - $activeInvitations;
$this->smarty->assign([
'invite_mode' => true,
'user_roles' => config('nntmux.user_roles', []),
'csrf_token' => csrf_token(),
'old' => old(),
'errors' => session('errors') ? session('errors')->getBag('default')->getMessages() : [],
'user_invites_left' => $availableInvites,
'user_invites_total' => $user->invites,
'user_invites_pending' => $activeInvitations,
'can_send_invites' => $availableInvites > 0,
]);
// Set meta information
$meta_title = 'Send New Invitation';
$meta_keywords = 'invitation,invite,send,new,user';
$meta_description = 'Send a new invitation to invite someone to join the site';
$this->viewData['invite_mode'] = true;
$this->viewData['user_roles'] = config('nntmux.user_roles', []);
$this->viewData['user_invites_left'] = $availableInvites;
$this->viewData['user_invites_total'] = $user->invites;
$this->viewData['user_invites_pending'] = $activeInvitations;
$this->viewData['can_send_invites'] = $availableInvites > 0;
// Fetch the template content
$content = $this->smarty->fetch('invitations_create.tpl');
// Assign content and meta data for final rendering
$this->smarty->assign([
'content' => $content,
'meta_title' => $meta_title,
'meta_keywords' => $meta_keywords,
'meta_description' => $meta_description,
]);
// Render the page with proper styling
$this->pagerender();
return view('invitations.create', $this->viewData);
}
/**
@@ -223,31 +170,16 @@ class InvitationController extends BasePageController
/**
* Display the specified invitation
*/
public function show(string $token): void
public function show(string $token): View
{
// For public invitation page, we need to handle both logged in and guest users
if (auth()->check()) {
$this->setPreferences();
} else {
// Set up basic Smarty configuration for guests
$this->smarty->setTemplateDir([
'user' => config('ytake-laravel-smarty.template_path').'/Gentele',
'shared' => config('ytake-laravel-smarty.template_path').'/shared',
'default' => config('ytake-laravel-smarty.template_path').'/Gentele',
]);
$this->smarty->assign([
'isadmin' => false,
'ismod' => false,
'loggedin' => false,
'theme' => 'Gentele',
'site' => $this->settings,
]);
}
$preview = $this->invitationService->getInvitationPreview($token);
// Convert timestamps for Smarty
// Convert timestamps
if ($preview && isset($preview['expires_at'])) {
$preview['expires_at'] = strtotime($preview['expires_at']);
}
@@ -258,29 +190,15 @@ class InvitationController extends BasePageController
$preview['role_name'] = $roles[$preview['metadata']['role']] ?? 'Default';
}
$this->smarty->assign([
'preview' => $preview,
'token' => $token,
]);
$this->viewData['preview'] = $preview;
$this->viewData['token'] = $token;
// Set meta information
$meta_title = $preview ? 'Invitation to Join' : 'Invalid Invitation';
$meta_keywords = 'invitation,join,register,signup';
$meta_description = $preview ? 'You have been invited to join our community' : 'This invitation link is invalid or expired';
$this->viewData['meta_title'] = $preview ? 'Invitation to Join' : 'Invalid Invitation';
$this->viewData['meta_keywords'] = 'invitation,join,register,signup';
$this->viewData['meta_description'] = $preview ? 'You have been invited to join our community' : 'This invitation link is invalid or expired';
// Fetch the template content
$content = $this->smarty->fetch('invitations_show.tpl');
// Assign content and meta data for final rendering
$this->smarty->assign([
'content' => $content,
'meta_title' => $meta_title,
'meta_keywords' => $meta_keywords,
'meta_description' => $meta_description,
]);
// Render the page with proper styling
$this->pagerender();
return view('invitations.show', $this->viewData);
}
/**
@@ -371,3 +289,4 @@ class InvitationController extends BasePageController
]);
}
}
+35 -39
View File
@@ -20,9 +20,9 @@ class MyMoviesController extends BasePageController
$imdbid = $request->input('imdb') ?? '';
if ($request->has('from')) {
$this->smarty->assign('from', url($request->input('from')));
$this->viewData['from'] = url($request->input('from'));
} else {
$this->smarty->assign('from', url('/mymovies'));
$this->viewData['from'] = url('/mymovies');
}
switch ($action) {
@@ -70,16 +70,15 @@ class MyMoviesController extends BasePageController
}
$categories[$c['id']] = $c['title'];
}
$this->smarty->assign('type', 'add');
$this->smarty->assign('cat_ids', array_keys($categories));
$this->smarty->assign('cat_names', $categories);
$this->smarty->assign('cat_selected', []);
$this->smarty->assign('imdbid', $imdbid);
$this->smarty->assign('movie', $movie);
$content = $this->smarty->fetch('mymovies-add.tpl');
$this->smarty->assign('content', $content);
$this->pagerender();
break;
$this->viewData['type'] = 'add';
$this->viewData['cat_ids'] = array_keys($categories);
$this->viewData['cat_names'] = $categories;
$this->viewData['cat_selected'] = [];
$this->viewData['imdbid'] = $imdbid;
$this->viewData['movie'] = $movie;
$this->viewData['content'] = view('themes/Gentele/mymovies-add', $this->viewData)->render();
return $this->pagerender();
case 'edit':
case 'doedit':
$movie = UserMovie::getMovie($this->userdata->id, $imdbid);
@@ -104,16 +103,15 @@ class MyMoviesController extends BasePageController
$categories[$c['id']] = $c['title'];
}
$this->smarty->assign('type', 'edit');
$this->smarty->assign('cat_ids', array_keys($categories));
$this->smarty->assign('cat_names', $categories);
$this->smarty->assign('cat_selected', explode('|', $movie['categories']));
$this->smarty->assign('imdbid', $imdbid);
$this->smarty->assign('movie', $movie);
$content = $this->smarty->fetch('mymovies-add.tpl');
$this->smarty->assign('content', $content);
$this->pagerender();
break;
$this->viewData['type'] = 'edit';
$this->viewData['cat_ids'] = array_keys($categories);
$this->viewData['cat_names'] = $categories;
$this->viewData['cat_selected'] = explode('|', $movie['categories']);
$this->viewData['imdbid'] = $imdbid;
$this->viewData['movie'] = $movie;
$this->viewData['content'] = view('themes/Gentele/mymovies-add', $this->viewData)->render();
return $this->pagerender();
case 'browse':
$title = 'Browse My Movies';
@@ -148,22 +146,19 @@ class MyMoviesController extends BasePageController
$results = $mv->getMovieRange($page, $movie['categoryNames'], $offset, config('nntmux.items_per_cover_page'), $ordering, -1, $this->userdata->categoryexclusions);
$this->smarty->assign('covgroup', '');
$this->viewData['covgroup'] = '';
foreach ($ordering as $ordertype) {
$this->smarty->assign('orderby'.$ordertype, url('/mymovies/browse?ob='.$ordertype.'&offset=0'));
$this->viewData['orderby'.$ordertype] = url('/mymovies/browse?ob='.$ordertype.'&offset=0');
}
$this->smarty->assign('lastvisit', $this->userdata->lastlogin);
$this->viewData['lastvisit'] = $this->userdata->lastlogin;
$this->viewData['results'] = $results;
$this->viewData['movies'] = true;
$this->viewData['content'] = view('themes/Gentele/browse', $this->viewData)->render();
$this->viewData = array_merge($this->viewData, compact('title', 'meta_title', 'meta_keywords', 'meta_description'));
return $this->pagerender();
$this->smarty->assign('results', $results);
$this->smarty->assign('movies', true);
$content = $this->smarty->fetch('browse.tpl');
$this->smarty->assign(compact('content', 'title', 'meta_title', 'meta_keywords', 'meta_description'));
$this->pagerender();
break;
default:
$title = 'My Movies';
@@ -195,12 +190,13 @@ class MyMoviesController extends BasePageController
$results[$moviek] = $movie;
}
$this->smarty->assign('movies', $results);
$content = $this->smarty->fetch('mymovies.tpl');
$this->smarty->assign(compact('content', 'title', 'meta_title', 'meta_keywords', 'meta_description'));
$this->pagerender();
break;
$this->viewData['movies'] = $results;
$this->viewData['content'] = view('themes/Gentele/mymovies', $this->viewData)->render();
$this->viewData = array_merge($this->viewData, compact('title', 'meta_title', 'meta_keywords', 'meta_description'));
return $this->pagerender();
}
// Fallback return in case no case matches
return redirect()->to('/mymovies');
}
}
@@ -0,0 +1,202 @@
@extends('layouts.main')
@section('content')
@if(!$invite_mode)
<div class="header">
<div class="breadcrumb-wrapper">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ $site->home_link }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ url('/profile') }}">Profile</a></li>
<li class="breadcrumb-item"><a href="{{ url('/invitations') }}">My Invitations</a></li>
<li class="breadcrumb-item active">Invitations Disabled</li>
</ol>
</nav>
</div>
</div>
<div class="container-fluid px-4 py-3">
<div class="row">
<div class="col-md-8 mx-auto">
<div class="alert alert-warning shadow-sm">
<h5 class="mb-2"><i class="fa fa-ban me-2"></i>Invitations Disabled</h5>
<p class="mb-3">User invitations are currently disabled on this site. You cannot send new invitations at this time.</p>
<a href="{{ url('/profile') }}" class="btn btn-outline-secondary"><i class="fa fa-arrow-left me-1"></i> Back to Profile</a>
</div>
</div>
</div>
</div>
@else
<div class="header">
<div class="breadcrumb-wrapper">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ $site->home_link }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ url('/profile') }}">Profile</a></li>
<li class="breadcrumb-item"><a href="{{ url('/invitations') }}">My Invitations</a></li>
<li class="breadcrumb-item active">Send New Invitation</li>
</ol>
</nav>
</div>
</div>
<div class="container-fluid px-4 py-3">
<div class="row">
<div class="col-md-8 mx-auto">
<div class="card shadow-sm">
<div class="card-header bg-light d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="fa fa-paper-plane me-2"></i>Send New Invitation</h5>
<div class="d-flex align-items-center gap-3">
<div class="badge @if($user_invites_left > 0) bg-success @else bg-danger @endif text-white">
<i class="fa fa-envelope me-1"></i>
{{ $user_invites_left }} invites left
</div>
<a href="{{ url('/invitations') }}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left me-1"></i> Back to Invitations
</a>
</div>
</div>
<div class="card-body">
@if(session('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="fa fa-exclamation-triangle me-2"></i>{{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if(!$can_send_invites)
<div class="alert alert-warning text-center">
<i class="fa fa-exclamation-triangle fa-3x mb-3"></i>
<h5>No Invitations Available</h5>
<p class="mb-3">You have used all of your available invitations. You cannot send new invitations at this time.</p>
<div class="d-flex gap-2 justify-content-center">
<a href="{{ url('/invitations') }}" class="btn btn-primary">
<i class="fa fa-arrow-left me-1"></i> Back to My Invitations
</a>
<a href="{{ url('/contact') }}" class="btn btn-outline-primary">
<i class="fa fa-envelope me-1"></i> Contact Support
</a>
</div>
</div>
@else
<form method="POST" action="{{ url('/invitations/store') }}">
@csrf
<div class="alert alert-info mb-4">
<div class="d-flex">
<i class="fa fa-info-circle fa-lg me-3 mt-1"></i>
<div>
<strong>Available Invitations:</strong> You have <strong>{{ $user_invites_left }}</strong> invitation{{ $user_invites_left != 1 ? 's' : '' }} remaining.
@if($user_invites_left == 1)
This is your last invitation, so use it wisely!
@endif
</div>
</div>
</div>
<div class="mb-4">
<label for="email" class="form-label">
<i class="fa fa-envelope me-1"></i>Email Address <span class="text-danger">*</span>
</label>
<input type="email"
class="form-control @error('email') is-invalid @enderror"
id="email"
name="email"
value="{{ old('email') }}"
required
placeholder="Enter recipient's email address">
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<div class="form-text">
<i class="fa fa-info-circle me-1"></i>The person will receive an invitation email at this address.
</div>
</div>
<div class="mb-4">
<label for="expiry_days" class="form-label">
<i class="fa fa-clock-o me-1"></i>Expiry Period
</label>
<select class="form-select @error('expiry_days') is-invalid @enderror"
id="expiry_days"
name="expiry_days">
<option value="1" @if(old('expiry_days') == '1') selected @endif>1 Day</option>
<option value="3" @if(old('expiry_days') == '3') selected @endif>3 Days</option>
<option value="7" @if(old('expiry_days') == '7' || !old('expiry_days')) selected @endif>1 Week (Default)</option>
<option value="14" @if(old('expiry_days') == '14') selected @endif>2 Weeks</option>
<option value="30" @if(old('expiry_days') == '30') selected @endif>1 Month</option>
</select>
@error('expiry_days')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<div class="form-text">
<i class="fa fa-info-circle me-1"></i>How long the invitation will remain valid.
</div>
</div>
@if(isset($user_roles) && !empty($user_roles))
<div class="mb-4">
<label for="role" class="form-label">
<i class="fa fa-user-tag me-1"></i>Default Role <small class="text-muted">(Optional)</small>
</label>
<select class="form-select @error('role') is-invalid @enderror"
id="role"
name="role">
<option value="">Use System Default</option>
@foreach($user_roles as $roleId => $roleName)
<option value="{{ $roleId }}" @if(old('role') == $roleId) selected @endif>
{{ $roleName }}
</option>
@endforeach
</select>
@error('role')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<div class="form-text">
<i class="fa fa-info-circle me-1"></i>The role to assign to the user when they accept the invitation.
</div>
</div>
@endif
<div class="alert alert-info mb-4">
<div class="d-flex">
<i class="fa fa-lightbulb-o fa-lg me-3 mt-1"></i>
<div>
<strong>How it works:</strong>
<ul class="mb-0 mt-2">
<li>The recipient will receive an email with a secure invitation link</li>
<li>They can use this link to create their account within the specified time period</li>
<li>Once the time expires, the invitation link becomes invalid</li>
<li>You can track the status of all your invitations from the main invitations page</li>
</ul>
</div>
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{{ url('/invitations') }}" class="btn btn-outline-secondary me-md-2">
<i class="fa fa-times me-1"></i>Cancel
</a>
<button type="submit" class="btn btn-primary">
<i class="fas fa-paper-plane me-1"></i> Send Invitation
</button>
</div>
</form>
@endif
</div>
</div>
</div>
</div>
</div>
@endif
@endsection
+233
View File
@@ -0,0 +1,233 @@
@extends('layouts.main')
@section('content')
@if(!$invite_mode)
<div class="container-fluid px-4 py-3">
<div class="row">
<div class="col-md-8 mx-auto">
<div class="alert alert-warning shadow-sm">
<h5 class="mb-2"><i class="fa fa-ban me-2"></i>Invitations Disabled</h5>
<p class="mb-0">User invitations are currently disabled on this site. If you believe this is an error, please contact an administrator.</p>
</div>
</div>
</div>
</div>
@else
<div class="header">
<div class="breadcrumb-wrapper">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ $site->home_link }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ url('/profile') }}">Profile</a></li>
<li class="breadcrumb-item active">My Invitations</li>
</ol>
</nav>
</div>
</div>
<div class="container-fluid px-4 py-3">
<div class="row">
<div class="col-md-12">
<div class="card shadow-sm mb-4">
<div class="card-header bg-light d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="fa fa-envelope me-2"></i>My Invitations</h5>
<a href="{{ url('/invitations/create') }}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i> Send New Invitation
</a>
</div>
<div class="card-body">
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if(session('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
{{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
<!-- Stats Cards -->
<div class="row mb-4">
<div class="col-md-3">
<div class="card bg-primary text-white">
<div class="card-body text-center">
<h4 class="mb-1">{{ $stats['total'] ?? 0 }}</h4>
<small>Total Sent</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-success text-white">
<div class="card-body text-center">
<h4 class="mb-1">{{ $stats['used'] ?? 0 }}</h4>
<small>Accepted</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-warning text-white">
<div class="card-body text-center">
<h4 class="mb-1">{{ $stats['pending'] ?? 0 }}</h4>
<small>Pending</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-danger text-white">
<div class="card-body text-center">
<h4 class="mb-1">{{ $stats['expired'] ?? 0 }}</h4>
<small>Expired</small>
</div>
</div>
</div>
</div>
<!-- Filter Tabs -->
<ul class="nav nav-tabs mb-3">
<li class="nav-item">
<a class="nav-link @if(empty($status)) active @endif" href="{{ url('/invitations') }}">
<i class="fa fa-list me-1"></i>All
</a>
</li>
<li class="nav-item">
<a class="nav-link @if(($status ?? '') == 'pending') active @endif" href="{{ url('/invitations?status=pending') }}">
<i class="fa fa-clock-o me-1"></i>Pending
</a>
</li>
<li class="nav-item">
<a class="nav-link @if(($status ?? '') == 'used') active @endif" href="{{ url('/invitations?status=used') }}">
<i class="fa fa-check me-1"></i>Accepted
</a>
</li>
<li class="nav-item">
<a class="nav-link @if(($status ?? '') == 'expired') active @endif" href="{{ url('/invitations?status=expired') }}">
<i class="fa fa-times me-1"></i>Expired
</a>
</li>
</ul>
<!-- Invitations Table -->
@if(count($invitations) > 0)
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-light">
<tr>
<th><i class="fa fa-envelope me-1"></i>Email</th>
<th><i class="fa fa-info-circle me-1"></i>Status</th>
<th><i class="fa fa-calendar me-1"></i>Sent Date</th>
<th><i class="fa fa-clock-o me-1"></i>Expires</th>
<th><i class="fa fa-user me-1"></i>Used By</th>
<th><i class="fa fa-check me-1"></i>Used Date</th>
<th><i class="fa fa-cogs me-1"></i>Actions</th>
</tr>
</thead>
<tbody>
@foreach($invitations as $invitation)
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fa fa-envelope text-muted me-2"></i>
{{ $invitation['email'] }}
</div>
</td>
<td>
@if($invitation['used_at'])
<span class="badge bg-success"><i class="fa fa-check me-1"></i>Accepted</span>
@elseif($invitation['expires_at'] < time())
<span class="badge bg-danger"><i class="fa fa-times me-1"></i>Expired</span>
@elseif(!$invitation['is_active'])
<span class="badge bg-secondary"><i class="fa fa-ban me-1"></i>Cancelled</span>
@else
<span class="badge bg-warning"><i class="fa fa-clock-o me-1"></i>Pending</span>
@endif
</td>
<td>
<div class="d-flex align-items-center">
<i class="fa fa-calendar text-muted me-2"></i>
{{ date('M j, Y', $invitation['created_at']) }}
<small class="text-muted ms-1">{{ date('H:i', $invitation['created_at']) }}</small>
</div>
</td>
<td>
<div class="d-flex align-items-center">
<i class="fa fa-clock-o text-muted me-2"></i>
{{ date('M j, Y', $invitation['expires_at']) }}
<small class="text-muted ms-1">{{ date('H:i', $invitation['expires_at']) }}</small>
</div>
</td>
<td>
@if(isset($invitation['used_by_user']))
<div class="d-flex align-items-center">
<i class="fa fa-user text-muted me-2"></i>
{{ $invitation['used_by_user']['username'] ?? $invitation['used_by_user']['email'] }}
</div>
@else
<span class="text-muted">-</span>
@endif
</td>
<td>
@if($invitation['used_at'])
<div class="d-flex align-items-center">
<i class="fa fa-check text-muted me-2"></i>
{{ date('M j, Y', $invitation['used_at']) }}
<small class="text-muted ms-1">{{ date('H:i', $invitation['used_at']) }}</small>
</div>
@else
<span class="text-muted">-</span>
@endif
</td>
<td>
@if(!$invitation['used_at'] && $invitation['expires_at'] > time() && $invitation['is_active'])
<div class="btn-group" role="group">
<form method="POST" action="{{ url('/invitations/' . $invitation['id'] . '/resend') }}" class="d-inline">
@csrf
<button type="submit" class="btn btn-sm btn-outline-primary" title="Resend Invitation">
<i class="fas fa-paper-plane"></i>
</button>
</form>
<form method="POST" action="{{ url('/invitations/' . $invitation['id']) }}" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger" title="Cancel Invitation"
onclick="return confirm('Are you sure you want to cancel this invitation?')">
<i class="fas fa-times"></i>
</button>
</form>
</div>
@else
<span class="text-muted">-</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@if(isset($pagination_links))
<div class="mt-4">
{!! $pagination_links !!}
</div>
@endif
@else
<div class="alert alert-info text-center">
<i class="fa fa-info-circle fa-2x mb-3"></i>
<h5>No Invitations Found</h5>
<p class="mb-3">You haven't sent any invitations yet.</p>
<a href="{{ url('/invitations/create') }}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i> Send Your First Invitation
</a>
</div>
@endif
</div>
</div>
</div>
</div>
</div>
@endif
@endsection
+144
View File
@@ -0,0 +1,144 @@
@extends('layouts.main')
@section('content')
<div class="container-fluid px-4 py-3">
<nav aria-label="breadcrumb" class="mb-3">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ $site->home_link }}">Home</a></li>
<li class="breadcrumb-item active">Invitation</li>
</ol>
</nav>
<div class="row">
<div class="col-md-8 mx-auto">
<div class="card shadow-sm">
<div class="card-header bg-light">
<h5 class="mb-0"><i class="fa fa-envelope-open me-2"></i>Invitation to Join {{ $site->title }}</h5>
</div>
<div class="card-body">
@if($preview)
<div class="alert alert-info border-0 mb-4">
<div class="d-flex">
<i class="fa fa-user-plus fa-2x me-3 mt-1"></i>
<div>
<h6 class="alert-heading mb-2">You've been invited!</h6>
<p class="mb-0">
<strong>{{ $preview['inviter_name'] ?? 'Someone' }}</strong> has invited you to join <strong>{{ $site->title }}</strong>.
</p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-4">
<div class="card border-0 bg-light">
<div class="card-header bg-transparent border-bottom">
<h6 class="mb-0"><i class="fa fa-info-circle me-1"></i>Invitation Details</h6>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-5 text-muted"><i class="fa fa-user me-1"></i>Invited by:</div>
<div class="col-7 fw-medium">{{ $preview['inviter_name'] ?? 'Anonymous' }}</div>
</div>
<div class="row mb-3">
<div class="col-5 text-muted"><i class="fa fa-envelope me-1"></i>Email:</div>
<div class="col-7 fw-medium">{{ $preview['email'] ?? 'N/A' }}</div>
</div>
<div class="row mb-3">
<div class="col-5 text-muted"><i class="fa fa-clock-o me-1"></i>Expires:</div>
<div class="col-7">
@if(isset($preview['expires_at']))
{{ date('M j, Y H:i', $preview['expires_at']) }}
@if($preview['expires_at'] < time())
<br><span class="badge bg-danger mt-1"><i class="fa fa-times me-1"></i>Expired</span>
@elseif($preview['is_used'])
<br><span class="badge bg-success mt-1"><i class="fa fa-check me-1"></i>Already Used</span>
@else
<br><span class="badge bg-success mt-1"><i class="fa fa-check me-1"></i>Valid</span>
@endif
@else
N/A
@endif
</div>
</div>
@if(isset($preview['metadata']['role']) && isset($preview['role_name']))
<div class="row">
<div class="col-5 text-muted"><i class="fa fa-user-tag me-1"></i>Assigned Role:</div>
<div class="col-7 fw-medium">
<span class="badge bg-primary">{{ $preview['role_name'] ?? 'Default' }}</span>
</div>
</div>
@endif
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card border-0 bg-light">
<div class="card-header bg-transparent border-bottom">
<h6 class="mb-0"><i class="fa fa-list-ol me-1"></i>What's Next?</h6>
</div>
<div class="card-body">
<p class="mb-3">To accept this invitation and create your account:</p>
<ol class="mb-0">
<li class="mb-2">Click the "Accept Invitation" button below</li>
<li class="mb-2">Fill out the registration form with your details</li>
<li class="mb-2">Verify your email address when prompted</li>
<li class="mb-0">Start exploring {{ $site->title }}!</li>
</ol>
</div>
</div>
</div>
</div>
<div class="text-center mt-4">
@if($preview['is_used'])
<div class="alert alert-success border-0 mb-4">
<i class="fas fa-check-circle fa-2x mb-2"></i>
<h6>This invitation has already been used</h6>
<p class="mb-0">The account has been successfully created using this invitation.</p>
</div>
<a href="{{ url('/login') }}" class="btn btn-primary btn-lg">
<i class="fas fa-sign-in-alt me-2"></i> Login to Your Account
</a>
@elseif($preview['expires_at'] < time())
<div class="alert alert-danger border-0 mb-4">
<i class="fas fa-exclamation-triangle fa-2x mb-2"></i>
<h6>This invitation has expired</h6>
<p class="mb-0">Please contact the person who invited you for a new invitation.</p>
</div>
<a href="{{ url('/contact') }}" class="btn btn-outline-primary">
<i class="fa fa-envelope me-1"></i> Contact Support
</a>
@else
<a href="{{ url('/register?invitation=' . $token) }}" class="btn btn-primary btn-lg shadow">
<i class="fas fa-user-plus me-2"></i> Accept Invitation & Create Account
</a>
<div class="mt-3">
<small class="text-muted">
Already have an account? <a href="{{ url('/login') }}" class="text-decoration-none">Login here</a>
</small>
</div>
@endif
</div>
@else
<div class="alert alert-danger border-0 text-center">
<i class="fas fa-exclamation-triangle fa-3x mb-3 text-danger"></i>
<h5 class="text-danger">Invalid Invitation</h5>
<p class="mb-4">This invitation link is not valid, has expired, or has been removed.</p>
<div class="d-flex gap-2 justify-content-center">
<a href="{{ url('/contact') }}" class="btn btn-outline-primary">
<i class="fa fa-envelope me-1"></i> Contact Support
</a>
<a href="{{ url('/register') }}" class="btn btn-primary">
<i class="fa fa-user-plus me-1"></i> Register Without Invitation
</a>
</div>
</div>
@endif
</div>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,70 @@
<div class="header">
<div class="breadcrumb-wrapper">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ url($site->home_link) }}">Home</a></li>
<li class="breadcrumb-item active">Browse Movies</li>
</ol>
</nav>
</div>
</div>
{!! $site->adbrowse ?? '' !!}
@if(count($results ?? []) > 0)
<div class="card">
<div class="card-body px-0 py-0">
<div class="table-responsive">
<table class="table table-striped table-hover data mb-0">
<thead class="thead-light">
<tr>
<th>Name</th>
<th>Category</th>
<th>Posted</th>
<th>Size</th>
<th>Files</th>
<th class="text-end">Action</th>
</tr>
</thead>
<tbody>
@foreach($results as $result)
<tr>
<td>
<div class="mb-1">
<a href="{{ url("/details/{$result->guid}") }}" class="title fw-semibold">{{ e(str_replace('.', ' ', $result->searchname ?? '')) }}</a>
</div>
</td>
<td>
<span class="badge bg-secondary text-white rounded-pill">
<i class="fa fa-folder-open me-1"></i>{{ $result->category_name ?? '' }}
</span>
</td>
<td>
<span title="{{ $result->postdate ?? '' }}">{{ isset($result->postdate) ? \Carbon\Carbon::parse($result->postdate)->diffForHumans() : '' }}</span>
</td>
<td class="text-center">
<span class="fw-medium">{{ isset($result->size) ? \App\Extensions\helper\formatBytes($result->size) : '' }}</span>
</td>
<td class="text-center">
<span class="fw-medium">{{ $result->totalpart ?? 0 }}</span>
</td>
<td class="text-end">
<div class="d-flex justify-content-end gap-2">
<a href="{{ url("/getnzb?id={$result->guid}") }}" class="btn btn-sm btn-outline-secondary">
<i class="fa fa-cloud-download"></i>
</a>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@else
<div class="alert alert-info">
<i class="fa fa-info-circle me-2"></i>No results found.
</div>
@endif
@@ -0,0 +1,109 @@
<div class="card card-default shadow-sm mb-4">
<div class="card-header bg-light">
<div class="d-flex justify-content-between align-items-center">
<h3 class="mb-0"><i class="fa fa-film me-2 text-primary"></i>{{ ucfirst($type ?? 'add') }} Movie to Watchlist</h3>
<div class="breadcrumb-wrapper">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0 py-0">
<li class="breadcrumb-item"><a href="{{ url($site->home_link) }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ url('/mymovies') }}">My Movies</a></li>
<li class="breadcrumb-item active">{{ ucfirst($type ?? 'add') }} Movie</li>
</ol>
</nav>
</div>
</div>
</div>
<div class="card-body">
<div class="mb-4">
<div class="d-flex align-items-center gap-3 mb-3">
<img class="rounded shadow-sm" style="max-width:100px"
src="{{ url("/covers/movies/{$imdbid}-cover.jpg") }}"
onerror="this.src='{{ url('/covers/movies/no-cover.jpg') }}'"
alt="{{ e($movie['title'] ?? '') }}" />
<div>
<h4 class="mb-1">{{ ucfirst($type ?? 'add') }} "{{ e($movie['title'] ?? '') }}" to watchlist</h4>
<p class="text-muted mb-0">Select categories below to organize this movie in your collection.</p>
</div>
</div>
<div class="alert alert-info">
<i class="fa fa-info-circle me-2"></i>
Adding movies to your watchlist will notify you through your
<a href="{{ url("/rss/mymovies?dl=1&i={$userdata->id}&api_token={$userdata->api_token}") }}" class="alert-link">
<i class="fa fa-rss me-1"></i>RSS Feed
</a>
when they become available.
</div>
</div>
{!! Form::open(['id' => 'mymovies', 'class' => 'form', 'url' => "mymovies?id=do{$type}"]) !!}
<input type="hidden" name="imdb" value="{{ $imdbid }}"/>
@if(!empty($from))
<input type="hidden" name="from" value="{{ $from }}" />
@endif
<div class="mb-4">
<label class="form-label fw-bold mb-3">Choose Categories:</label>
<div class="d-flex flex-wrap gap-3" id="category-container">
@foreach($cat_ids ?? [] as $index => $cat_id)
<div class="category-checkbox">
<input type="checkbox"
id="category_{{ $cat_id }}"
name="category[]"
value="{{ $cat_id }}"
@if(in_array($cat_id, $cat_selected ?? [])) checked @endif>
<label for="category_{{ $cat_id }}">{{ $cat_names[$cat_id] ?? '' }}</label>
</div>
@endforeach
</div>
</div>
<div class="d-flex gap-2">
<button class="btn btn-primary" type="submit" name="{{ $type ?? 'add' }}">
<i class="fa {{ ($type ?? 'add') == 'add' ? 'fa-plus' : 'fa-edit' }} me-2"></i>{{ ucfirst($type ?? 'add') }} Movie
</button>
<a href="{{ url('/mymovies') }}" class="btn btn-outline-secondary">
<i class="fa fa-arrow-left me-2"></i>Back to My Movies
</a>
</div>
{!! Form::close() !!}
</div>
</div>
<style>
/* Style for checkboxes to make them more modern */
.category-checkbox {
display: inline-flex;
align-items: center;
}
.category-checkbox label {
display: flex;
align-items: center;
padding: 8px 15px;
margin-bottom: 0;
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.category-checkbox label:hover {
background-color: #e9ecef;
}
.category-checkbox input[type="checkbox"] {
margin-right: 8px;
cursor: pointer;
}
.category-checkbox input[type="checkbox"]:checked ~ label,
.category-checkbox input[type="checkbox"]:checked + label {
background-color: #d1ecf1;
border-color: #4dabf7;
}
</style>
@@ -0,0 +1,148 @@
<div class="card card-default shadow-sm mb-4">
<div class="card-header bg-light">
<div class="d-flex justify-content-between align-items-center">
<h3 class="mb-0"><i class="fa fa-film me-2 text-primary"></i>My Movies</h3>
<div class="breadcrumb-wrapper">
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0 py-0">
<li class="breadcrumb-item"><a href="{{ url($site->home_link) }}">Home</a></li>
<li class="breadcrumb-item active">My Movies</li>
</ol>
</nav>
</div>
</div>
</div>
<div class="card-body">
<div class="alert alert-info mb-4">
<i class="fa fa-info-circle me-2"></i>
Using 'My Movies' you can search for movies, and add them to a wishlist. If the movie becomes available it will be added to an
<strong><a href="{{ url("/rss/mymovies?dl=1&i={$userdata->id}&api_token={$userdata->api_token}") }}" class="alert-link">
<i class="fa fa-rss me-1"></i>RSS Feed
</a></strong>
you can use to automatically download. You can
<strong><a href="{{ route('mymovies') }}" class="alert-link">
<i class="fa fa-list me-1"></i>Manage Your Movie List
</a></strong>
to remove old items.
</div>
<div class="d-flex justify-content-between align-items-center mb-3">
<a href="{{ url("/rss/mymovies?dl=1&i={$userdata->id}&api_token={$userdata->api_token}") }}" class="btn btn-outline-secondary">
<i class="fa fa-rss me-2"></i>RSS Feed
</a>
</div>
@if(count($movies ?? []) > 0)
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-light">
<tr>
<th style="width:140px">Cover</th>
<th>Information</th>
<th>Category</th>
<th>Added</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@foreach($movies as $movie)
<tr>
<td>
<div class="text-center">
<img class="img-fluid rounded shadow-sm" style="max-width:120px"
src="{{ url('/covers/movies/' . (($movie['cover'] ?? 0) == 1 ? $movie['imdbid'] . '-cover.jpg' : 'no-cover.jpg')) }}"
alt="{{ e($movie['title'] ?? '') }}"/>
</div>
</td>
<td>
<div class="mb-2">
<h5 class="mb-1">
<a href="{{ url("/Movies?imdb={$movie['imdbid']}") }}" class="text-decoration-none" data-bs-toggle="tooltip" data-bs-placement="top" title="View movie details">
{{ e($movie['title'] ?? '') }} ({{ $movie['year'] ?? '' }})
</a>
</h5>
@if(!empty($movie['tagline']))
<div class="fst-italic text-muted mb-2">{{ e($movie['tagline']) }}</div>
@endif
</div>
@if(!empty($movie['plot']))
<p class="mb-2">{{ e($movie['plot']) }}</p>
@endif
<div class="d-flex flex-wrap gap-3 mt-2">
@if(!empty($movie['genre']))
<div>
<span class="fw-bold text-secondary"><i class="fa fa-tag me-1"></i>Genre:</span> {{ e($movie['genre']) }}
</div>
@endif
@if(!empty($movie['director']))
<div>
<span class="fw-bold text-secondary"><i class="fa fa-video-camera me-1"></i>Director:</span> {{ e($movie['director']) }}
</div>
@endif
@if(!empty($movie['actors']))
<div class="w-100 mt-1">
<span class="fw-bold text-secondary"><i class="fa fa-users me-1"></i>Starring:</span> {{ e($movie['actors']) }}
</div>
@endif
</div>
<div class="mt-2">
<a class="badge bg-warning text-dark" target="_blank"
href="{{ $site->dereferrer_link }}http://www.imdb.com/title/tt{{ $movie['imdbid'] }}"
data-bs-toggle="tooltip" data-bs-placement="top" title="View on IMDB">
<i class="fa fa-external-link me-1"></i>IMDB
</a>
</div>
</td>
<td>
<span class="badge bg-secondary rounded-pill">
<i class="fa fa-folder-open me-1"></i>{{ !empty($movie['categoryNames']) ? e($movie['categoryNames']) : 'All' }}
</span>
</td>
<td>
<div class="d-flex align-items-center" title="Added on {{ $movie['created_at'] ?? '' }}">
<i class="fa fa-calendar text-muted me-2"></i>
{{ isset($movie['created_at']) ? date('M d, Y', strtotime($movie['created_at'])) : '' }}
</div>
</td>
<td class="text-end">
<div class="btn-group">
<a class="btn btn-sm btn-warning mymovies"
href="{{ url("/mymovies?id=edit&imdb={$movie['imdbid']}") }}" rel="edit"
name="movies{{ $movie['imdbid'] }}" data-bs-toggle="tooltip" data-bs-placement="top" title="Edit Categories">
<i class="fa fa-edit"></i>
</a>
<a class="btn btn-sm btn-danger mymovies"
href="{{ url("/mymovies?id=delete&imdb={$movie['imdbid']}") }}" rel="remove"
name="movies{{ $movie['imdbid'] }}" data-bs-toggle="tooltip" data-bs-placement="top" title="Remove from My Movies">
<i class="fa fa-trash"></i>
</a>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="alert alert-info">
<i class="fa fa-info-circle me-2"></i>No movies bookmarked yet. Add movies from movie pages.
</div>
@endif
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize tooltips
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
});
</script>