Update for alpine.js

This commit is contained in:
DariusIII
2026-02-09 10:36:38 +01:00
parent e5cf4b737c
commit e26d3f6edb
18 changed files with 190 additions and 179 deletions
+1 -1
View File
@@ -122,7 +122,7 @@ class MyMoviesController extends BasePageController
$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['cat_selected'] = ! empty($movie['categories']) ? explode('|', $movie['categories']) : [];
$this->viewData['imdbid'] = $imdbid;
$this->viewData['movie'] = $movie;
$this->viewData['content'] = view('mymovies.add', $this->viewData)->render();
+4 -3
View File
@@ -75,11 +75,12 @@ class UserMovie extends Model
public static function getMovie($uid, $imdbid): array
{
return self::query()
$result = self::query()
->where(['user_movies.users_id' => $uid, 'user_movies.imdbid' => $imdbid])
->leftJoin('movieinfo as mi', 'mi.imdbid', '=', 'user_movies.imdbid')
->get(['user_movies.*', 'mi.title'])
->toArray();
->first(['user_movies.*', 'mi.title']);
return $result ? $result->toArray() : [];
}
public static function delMovieForUser($uid)
@@ -0,0 +1,88 @@
/**
* Alpine.data('confirmLink') - Confirm before navigating to a URL
* Uses the styled confirmation modal instead of native confirm()
* Usage: x-data="confirmLink" data-url="/path" data-message="Are you sure?" data-title="Confirm" data-type="danger"
*/
import Alpine from '@alpinejs/csp';
Alpine.data('confirmLink', () => ({
url: '',
message: 'Are you sure?',
title: 'Confirm Action',
type: 'danger',
confirmText: 'Delete',
cancelText: 'Cancel',
init() {
this.url = this.$el.dataset.url || this.$el.href || '';
this.message = this.$el.dataset.message || 'Are you sure?';
this.title = this.$el.dataset.title || 'Confirm Action';
this.type = this.$el.dataset.type || 'danger';
this.confirmText = this.$el.dataset.confirmText || 'Delete';
this.cancelText = this.$el.dataset.cancelText || 'Cancel';
},
navigate() {
const url = this.url;
if (typeof window.showConfirm === 'function') {
window.showConfirm({
title: this.title,
message: this.message,
type: this.type,
confirmText: this.confirmText,
cancelText: this.cancelText,
onConfirm: function() {
window.location.href = url;
}
});
} else {
// Fallback to native confirm if modal not available
if (confirm(this.message)) {
window.location.href = url;
}
}
}
}));
/**
* Alpine.data('confirmForm') - Confirm before submitting a form
* Uses the styled confirmation modal instead of native confirm()
* Usage on form: x-data="confirmForm" data-message="Are you sure?" data-title="Confirm" data-type="warning"
*/
Alpine.data('confirmForm', () => ({
message: 'Are you sure?',
title: 'Confirm Action',
type: 'warning',
confirmText: 'Confirm',
cancelText: 'Cancel',
init() {
this.message = this.$el.dataset.message || 'Are you sure?';
this.title = this.$el.dataset.title || 'Confirm Action';
this.type = this.$el.dataset.type || 'warning';
this.confirmText = this.$el.dataset.confirmText || 'Confirm';
this.cancelText = this.$el.dataset.cancelText || 'Cancel';
},
submit() {
const form = this.$el;
if (typeof window.showConfirm === 'function') {
window.showConfirm({
title: this.title,
message: this.message,
type: this.type,
confirmText: this.confirmText,
cancelText: this.cancelText,
onConfirm: function() {
form.submit();
}
});
} else {
// Fallback to native confirm if modal not available
if (confirm(this.message)) {
form.submit();
}
}
}
}));
+2
View File
@@ -36,6 +36,8 @@ import './components/search-autocomplete.js';
import './components/quality-filter.js';
import './components/content-toggle.js';
import './components/movies-layout.js';
import './components/movies-page.js';
import './components/confirm-link.js';
// --- Page-specific components ---
import './components/release-report.js';
@@ -121,10 +121,10 @@
<!-- Form Actions -->
<div class="flex justify-between items-center pt-6 border-t border-gray-200 dark:border-gray-700">
<button type="button" onclick="window.location='{{ url('/admin/category-list') }}'"
class="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition">
<a href="{{ url('/admin/category-list') }}"
class="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition">
<i class="fa fa-times mr-2"></i>Cancel
</button>
</a>
<button type="submit" class="px-4 py-2 bg-green-600 dark:bg-green-700 text-white rounded-lg hover:bg-green-700 dark:hover:bg-green-800 transition">
<i class="fa fa-save mr-2"></i>{{ $isCreate ?? false ? 'Create Category' : 'Save Changes' }}
</button>
@@ -119,7 +119,7 @@
</a>
<button type="button"
class="text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300"
onclick="confirmDelete({{ $category->id }})"
x-on:click="$dispatch('open-category-delete-modal', { id: {{ $category->id }} })"
title="Delete Category">
<i class="fa fa-trash"></i>
</button>
@@ -156,12 +156,16 @@
</div>
<!-- Delete Confirmation Modal -->
<div id="deleteModal" class="hidden fixed inset-0 bg-gray-600/50 overflow-y-auto h-full w-full z-50">
<div x-data="{ open: false, categoryId: null }"
x-on:open-category-delete-modal.window="open = true; categoryId = $event.detail.id"
x-show="open"
x-cloak
class="fixed inset-0 bg-gray-600/50 overflow-y-auto h-full w-full z-50">
<div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white dark:bg-gray-800">
<div class="mt-3">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Confirm Delete</h3>
<button type="button" onclick="closeDeleteModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
<button type="button" x-on:click="open = false" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
<i class="fa fa-times"></i>
</button>
</div>
@@ -174,10 +178,10 @@
</p>
</div>
<div class="flex gap-3 px-4 py-3">
<button type="button" onclick="closeDeleteModal()" class="flex-1 px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition">
<button type="button" x-on:click="open = false" class="flex-1 px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition">
Cancel
</button>
<a href="#" id="confirmDeleteLink" class="flex-1 px-4 py-2 bg-red-600 dark:bg-red-700 text-white text-center rounded-lg hover:bg-red-700 dark:hover:bg-red-800 transition">
<a x-bind:href="'{{ url('/admin/category-delete') }}?id=' + categoryId" class="flex-1 px-4 py-2 bg-red-600 dark:bg-red-700 text-white text-center rounded-lg hover:bg-red-700 dark:hover:bg-red-800 transition">
Delete
</a>
</div>
+14 -10
View File
@@ -4,24 +4,24 @@
<div class="container mx-auto px-4 py-6">
<!-- Flash Messages -->
@if(session('success'))
<div class="mb-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-4 flex items-center justify-between">
<div x-data="{ show: true }" x-show="show" class="mb-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-4 flex items-center justify-between">
<div class="flex items-center">
<i class="fas fa-check-circle text-green-600 dark:text-green-400 mr-3 text-xl"></i>
<p class="text-sm text-green-800 dark:text-green-200 font-medium">{{ session('success') }}</p>
</div>
<button onclick="this.parentElement.parentElement.remove()" class="text-green-600 dark:text-green-400 hover:text-green-800 dark:hover:text-green-200">
<button x-on:click="show = false" class="text-green-600 dark:text-green-400 hover:text-green-800 dark:hover:text-green-200">
<i class="fas fa-times"></i>
</button>
</div>
@endif
@if(session('error'))
<div class="mb-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-center justify-between">
<div x-data="{ show: true }" x-show="show" class="mb-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-center justify-between">
<div class="flex items-center">
<i class="fas fa-exclamation-circle text-red-600 dark:text-red-400 mr-3 text-xl"></i>
<p class="text-sm text-red-800 dark:text-red-200 font-medium">{{ session('error') }}</p>
</div>
<button onclick="this.parentElement.parentElement.remove()" class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200">
<button x-on:click="show = false" class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200">
<i class="fas fa-times"></i>
</button>
</div>
@@ -123,7 +123,7 @@
<button type="button"
class="text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300 transition"
title="Delete"
onclick="openDeleteModal({{ $comment->id }}, '{{ addslashes(Str::limit($comment->text, 50)) }}')">
x-on:click="$dispatch('open-delete-modal', { id: {{ $comment->id }}, text: '{{ addslashes(Str::limit($comment->text, 50)) }}' })">
<i class="fas fa-trash"></i>
</button>
</td>
@@ -147,7 +147,11 @@
</div>
<!-- Delete Confirmation Modal -->
<div id="deleteModal" class="fixed inset-0 bg-gray-900/50 hidden items-center justify-center z-50 transition-opacity">
<div x-data="{ open: false, commentId: null, commentText: '' }"
x-on:open-delete-modal.window="open = true; commentId = $event.detail.id; commentText = $event.detail.text; $refs.deleteForm.action = '{{ url('admin/comment-delete') }}?id=' + $event.detail.id"
x-show="open"
x-cloak
class="fixed inset-0 bg-gray-900/50 flex items-center justify-center z-50 transition-opacity">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4 transform transition-all">
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
<div class="flex items-center justify-between">
@@ -155,7 +159,7 @@
<i class="fas fa-exclamation-triangle text-red-600 dark:text-red-400 mr-2"></i>
Confirm Deletion
</h3>
<button type="button" onclick="closeDeleteModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
<button type="button" x-on:click="open = false" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
<i class="fas fa-times text-xl"></i>
</button>
</div>
@@ -163,17 +167,17 @@
<div class="px-6 py-4">
<p class="text-gray-700 dark:text-gray-300 mb-2">Are you sure you want to delete this comment?</p>
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-3 mt-3">
<p class="text-sm text-gray-600 dark:text-gray-400 italic" id="deleteCommentPreview"></p>
<p class="text-sm text-gray-600 dark:text-gray-400 italic" x-text="commentText"></p>
</div>
<p class="text-sm text-red-600 dark:text-red-400 mt-3 font-medium">This action cannot be undone.</p>
</div>
<div class="px-6 py-4 bg-gray-50 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
<button type="button"
onclick="closeDeleteModal()"
x-on:click="open = false"
class="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition font-medium">
<i class="fas fa-times mr-2"></i>Cancel
</button>
<form id="deleteForm" method="POST" action="" class="inline">
<form x-ref="deleteForm" method="POST" action="" class="inline">
@csrf
<button type="submit"
class="px-4 py-2 bg-red-600 dark:bg-red-700 text-white rounded-lg hover:bg-red-700 dark:hover:bg-red-800 transition font-medium">
@@ -17,9 +17,11 @@
<i class="fas fa-paper-plane mr-2"></i>Resend
</button>
</form>
<form method="POST" action="{{ url('admin/invitations/' . $invitation->id . '/cancel') }}" class="inline">
<form method="POST" action="{{ url('admin/invitations/' . $invitation->id . '/cancel') }}" class="inline"
x-data="confirmForm"
data-message="Are you sure you want to cancel this invitation?">
@csrf
<button type="submit" class="px-4 py-2 bg-yellow-600 text-white rounded-lg hover:bg-yellow-700" onclick="return confirm('Are you sure you want to cancel this invitation?')">
<button type="button" class="px-4 py-2 bg-yellow-600 text-white rounded-lg hover:bg-yellow-700" x-on:click="submit">
<i class="fas fa-ban mr-2"></i>Cancel
</button>
</form>
@@ -181,9 +183,10 @@
<div class="bg-gray-100 dark:bg-gray-800 p-2 rounded break-all font-mono text-xs">
{{ url('register?invitation=' . $invitation->token) }}
</div>
<button onclick="copyToClipboard('{{ url('register?invitation=' . $invitation->token) }}')" class="mt-2 px-3 py-1 bg-blue-600 text-white text-xs rounded hover:bg-blue-700">
<i class="fas fa-copy mr-1"></i>Copy Link
<button x-data="copyToClipboard()" x-on:click="copy('invitation-link-{{ $invitation->id }}')" class="mt-2 px-3 py-1 bg-blue-600 text-white text-xs rounded hover:bg-blue-700">
<i class="fas fa-copy mr-1"></i><span x-text="copied ? 'Copied!' : 'Copy Link'"></span>
</button>
<input type="hidden" id="invitation-link-{{ $invitation->id }}" value="{{ url('register?invitation=' . $invitation->token) }}" />
@else
<span class="text-gray-500 dark:text-gray-400">Invitation not active</span>
@endif
@@ -60,10 +60,10 @@
<!-- Date Range Filter -->
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-6 mb-6">
<form method="GET" action="{{ route('admin.promotions.show-statistics', $promotion->id) }}" class="flex flex-wrap gap-4 items-end">
<form method="GET" action="{{ route('admin.promotions.show-statistics', $promotion->id) }}" class="flex flex-wrap gap-4 items-end" x-data="{ showCustom: {{ $selectedPeriod === 'custom' ? 'true' : 'false' }} }" x-ref="periodForm">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Time Period</label>
<select name="period" class="form-select rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200" onchange="this.form.submit()">
<select name="period" class="form-select rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200" x-on:change="if($event.target.value === 'custom') { showCustom = true } else { showCustom = false; $refs.periodForm.submit() }">
<option value="7days" {{ $selectedPeriod === '7days' ? 'selected' : '' }}>Last 7 Days</option>
<option value="30days" {{ $selectedPeriod === '30days' ? 'selected' : '' }}>Last 30 Days</option>
<option value="90days" {{ $selectedPeriod === '90days' ? 'selected' : '' }}>Last 90 Days</option>
@@ -72,7 +72,7 @@
<option value="custom" {{ $selectedPeriod === 'custom' ? 'selected' : '' }}>Custom Range</option>
</select>
</div>
<div id="customDateRange" style="display: {{ $selectedPeriod === 'custom' ? 'flex' : 'none' }};" class="flex gap-4">
<div x-show="showCustom" x-cloak class="flex gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Start Date</label>
<input type="date" name="start_date" value="{{ $startDate ? $startDate->format('Y-m-d') : '' }}" class="form-input rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200">
@@ -293,17 +293,5 @@
@endif
</div>
</div>
<script>
document.querySelector('select[name="period"]').addEventListener('change', function() {
const customRange = document.getElementById('customDateRange');
if (this.value === 'custom') {
customRange.style.display = 'flex';
} else {
customRange.style.display = 'none';
this.form.submit();
}
});
</script>
@endsection
@@ -19,10 +19,10 @@
<!-- Date Range Filter -->
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-sm p-6 mb-6">
<form method="GET" action="{{ route('admin.promotions.statistics') }}" class="flex flex-wrap gap-4 items-end">
<form method="GET" action="{{ route('admin.promotions.statistics') }}" class="flex flex-wrap gap-4 items-end" x-data="{ showCustom: {{ $selectedPeriod === 'custom' ? 'true' : 'false' }} }" x-ref="periodForm">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Quick Select</label>
<select name="period" class="form-select rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200" onchange="this.form.submit()">
<select name="period" class="form-select rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200" x-on:change="if($event.target.value === 'custom') { showCustom = true } else { showCustom = false; $refs.periodForm.submit() }">
<option value="7days" {{ $selectedPeriod === '7days' ? 'selected' : '' }}>Last 7 Days</option>
<option value="30days" {{ $selectedPeriod === '30days' ? 'selected' : '' }}>Last 30 Days</option>
<option value="90days" {{ $selectedPeriod === '90days' ? 'selected' : '' }}>Last 90 Days</option>
@@ -31,7 +31,7 @@
<option value="custom" {{ $selectedPeriod === 'custom' ? 'selected' : '' }}>Custom Range</option>
</select>
</div>
<div id="customDateRange" style="display: {{ $selectedPeriod === 'custom' ? 'flex' : 'none' }};" class="flex gap-4">
<div x-show="showCustom" x-cloak class="flex gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Start Date</label>
<input type="date" name="start_date" value="{{ $startDate ? $startDate->format('Y-m-d') : '' }}" class="form-input rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200">
@@ -298,17 +298,5 @@
</div>
</div>
</div>
<script>
document.querySelector('select[name="period"]').addEventListener('change', function() {
const customRange = document.getElementById('customDateRange');
if (this.value === 'custom') {
customRange.style.display = 'flex';
} else {
customRange.style.display = 'none';
this.form.submit();
}
});
</script>
@endsection
@@ -4,24 +4,24 @@
<div class="container mx-auto px-4 py-6">
<!-- Flash Messages -->
@if(session('success'))
<div class="mb-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-4 flex items-center justify-between">
<div x-data="{ show: true }" x-show="show" class="mb-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-4 flex items-center justify-between">
<div class="flex items-center">
<i class="fas fa-check-circle text-green-600 dark:text-green-400 mr-3 text-xl"></i>
<p class="text-sm text-green-800 dark:text-green-200 font-medium">{{ session('success') }}</p>
</div>
<button onclick="this.parentElement.parentElement.remove()" class="text-green-600 dark:text-green-400 hover:text-green-800 dark:hover:text-green-200">
<button x-on:click="show = false" class="text-green-600 dark:text-green-400 hover:text-green-800 dark:hover:text-green-200">
<i class="fas fa-times"></i>
</button>
</div>
@endif
@if(session('error'))
<div class="mb-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-center justify-between">
<div x-data="{ show: true }" x-show="show" class="mb-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-center justify-between">
<div class="flex items-center">
<i class="fas fa-exclamation-circle text-red-600 dark:text-red-400 mr-3 text-xl"></i>
<p class="text-sm text-red-800 dark:text-red-200 font-medium">{{ session('error') }}</p>
</div>
<button onclick="this.parentElement.parentElement.remove()" class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200">
<button x-on:click="show = false" class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200">
<i class="fas fa-times"></i>
</button>
</div>
+4 -1
View File
@@ -63,7 +63,10 @@
<a href="{{ url('admin/role-delete?id=' . $role->id) }}"
class="text-red-600 hover:text-red-900"
title="Delete"
onclick="return confirm('Are you sure you want to delete role \'{{ $role->name }}\'?')">
x-data="confirmLink"
data-url="{{ url('admin/role-delete?id=' . $role->id) }}"
data-message="Are you sure you want to delete role '{{ $role->name }}'?"
x-on:click.prevent="navigate">
<i class="fa fa-trash"></i>
</a>
</div>
+3 -23
View File
@@ -16,10 +16,10 @@
<h4 class="text-lg font-semibold mb-3 text-gray-900 dark:text-gray-100 dark:text-white flex items-center">
<i class="fa fa-key mr-2 text-gray-600 dark:text-gray-400"></i>Your API Credentials
</h4>
<div class="flex rounded-md shadow-sm">
<div class="flex rounded-md shadow-sm" x-data="copyToClipboard()">
<input type="text" class="flex-1 rounded-l-md border-gray-300 dark:border-gray-600 font-mono text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-600 dark:border-gray-500 dark:text-white" value="apikey={{ $userdata->api_token }}" readonly id="apikeyInput">
<button class="inline-flex items-center px-4 py-2 border border-l-0 border-gray-300 dark:border-gray-600 rounded-r-md bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-gray-600 dark:text-gray-200 dark:border-gray-500 dark:hover:bg-gray-500" type="button" id="copyApiKey" title="Copy to clipboard">
<i class="fa fa-copy"></i>
<button class="inline-flex items-center px-4 py-2 border border-l-0 border-gray-300 dark:border-gray-600 rounded-r-md bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-gray-600 dark:text-gray-200 dark:border-gray-500 dark:hover:bg-gray-500" type="button" x-on:click="copy('apikeyInput')" title="Copy to clipboard" x-bind:class="copied ? 'text-green-600' : ''">
<i class="fa" x-bind:class="copied ? 'fa-check' : 'fa-copy'"></i>
</button>
</div>
</div>
@@ -203,24 +203,4 @@
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const copyBtn = document.getElementById('copyApiKey');
if (copyBtn) {
copyBtn.addEventListener('click', function() {
const apiKeyInput = document.getElementById('apikeyInput');
apiKeyInput.select();
apiKeyInput.setSelectionRange(0, 99999);
navigator.clipboard.writeText(apiKeyInput.value);
const originalText = copyBtn.innerHTML;
copyBtn.innerHTML = '<i class="fa fa-check"></i>';
copyBtn.classList.add('text-green-600');
setTimeout(function() {
copyBtn.innerHTML = originalText;
copyBtn.classList.remove('text-green-600');
}, 2000);
});
}
});
</script>
@endsection
+3 -24
View File
@@ -17,10 +17,10 @@
<h4 class="text-lg font-semibold mb-3 text-gray-900 dark:text-gray-100 dark:text-white flex items-center">
<i class="fa fa-key mr-2 text-gray-600 dark:text-gray-400"></i>Your API Credentials
</h4>
<div class="flex rounded-md shadow-sm">
<div class="flex rounded-md shadow-sm" x-data="copyToClipboard()">
<input type="text" class="flex-1 rounded-l-md border-gray-300 dark:border-gray-600 font-mono text-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-600 dark:border-gray-500 dark:text-white" value="api_token={{ $userdata->api_token }}" readonly id="apikeyInput">
<button class="inline-flex items-center px-4 py-2 border border-l-0 border-gray-300 dark:border-gray-600 rounded-r-md bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-gray-600 dark:text-gray-200 dark:border-gray-500 dark:hover:bg-gray-500" type="button" id="copyApiKey" title="Copy to clipboard">
<i class="fa fa-copy"></i>
<button class="inline-flex items-center px-4 py-2 border border-l-0 border-gray-300 dark:border-gray-600 rounded-r-md bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-gray-600 dark:text-gray-200 dark:border-gray-500 dark:hover:bg-gray-500" type="button" x-on:click="copy('apikeyInput')" title="Copy to clipboard" x-bind:class="copied ? 'text-green-600' : ''">
<i class="fa" x-bind:class="copied ? 'fa-check' : 'fa-copy'"></i>
</button>
</div>
</div>
@@ -193,26 +193,5 @@
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const copyBtn = document.getElementById('copyApiKey');
if (copyBtn) {
copyBtn.addEventListener('click', function() {
const apiKeyInput = document.getElementById('apikeyInput');
apiKeyInput.select();
apiKeyInput.setSelectionRange(0, 99999);
navigator.clipboard.writeText(apiKeyInput.value);
const originalText = copyBtn.innerHTML;
copyBtn.innerHTML = '<i class="fa fa-check"></i>';
copyBtn.classList.add('text-green-600');
setTimeout(function() {
copyBtn.innerHTML = originalText;
copyBtn.classList.remove('text-green-600');
}, 2000);
});
}
});
</script>
@endsection
-8
View File
@@ -226,11 +226,3 @@
</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>
+18 -17
View File
@@ -106,9 +106,16 @@
title="Edit Categories">
<i class="fa fa-edit mr-1.5"></i>Edit
</a>
<a class="inline-flex items-center px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 shadow hover:shadow-md transition-all duration-200 text-sm font-medium confirm_action"
<a class="inline-flex items-center px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 shadow hover:shadow-md transition-all duration-200 text-sm font-medium"
href="{{ url("/mymovies?id=delete&imdb={$movie['imdbid']}") }}"
title="Remove from My Movies">
title="Remove from My Movies"
x-data="confirmLink"
data-url="{{ url("/mymovies?id=delete&imdb={$movie['imdbid']}") }}"
data-title="Remove Movie"
data-message="Are you sure you want to remove this movie from your watchlist?"
data-confirm-text="Remove"
data-type="danger"
x-on:click.prevent="navigate">
<i class="fa fa-trash mr-1.5"></i>Delete
</a>
</div>
@@ -212,9 +219,16 @@
title="Edit">
<i class="fa fa-edit"></i>
</a>
<a class="px-3 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 text-sm font-medium shadow confirm_action"
<a class="px-3 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 text-sm font-medium shadow"
href="{{ url("/mymovies?id=delete&imdb={$movie['imdbid']}") }}"
title="Remove">
title="Remove"
x-data="confirmLink"
data-url="{{ url("/mymovies?id=delete&imdb={$movie['imdbid']}") }}"
data-title="Remove Movie"
data-message="Are you sure you want to remove this movie from your watchlist?"
data-confirm-text="Remove"
data-type="danger"
x-on:click.prevent="navigate">
<i class="fa fa-trash"></i>
</a>
</div>
@@ -243,16 +257,3 @@
@endif
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Confirm before removing movies
document.querySelectorAll('.confirm_action').forEach(element => {
element.addEventListener('click', function(e) {
if (!confirm('Are you sure you want to remove this movie from your watchlist?')) {
e.preventDefault();
}
});
});
});
</script>
+18 -17
View File
@@ -141,9 +141,16 @@
<i class="fa fa-edit mr-1.5"></i>
<span class="hidden xl:inline">Edit</span>
</a>
<a class="inline-flex items-center px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 shadow hover:shadow-md transition-all duration-200 text-sm font-medium confirm_action"
<a class="inline-flex items-center px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 shadow hover:shadow-md transition-all duration-200 text-sm font-medium"
href="{{ url("/myshows?action=delete&id={$show['videos_id']}") }}"
title="Remove from My Shows">
title="Remove from My Shows"
x-data="confirmLink"
data-url="{{ url("/myshows?action=delete&id={$show['videos_id']}") }}"
data-title="Remove Show"
data-message="Are you sure you want to remove this show from your list?"
data-confirm-text="Remove"
data-type="danger"
x-on:click.prevent="navigate">
<i class="fa fa-trash mr-1.5"></i>
<span class="hidden xl:inline">Delete</span>
</a>
@@ -194,9 +201,16 @@
title="Edit">
<i class="fa fa-edit"></i>
</a>
<a class="px-3 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 text-sm font-medium shadow confirm_action"
<a class="px-3 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-700 text-sm font-medium shadow"
href="{{ url("/myshows?action=delete&id={$show['videos_id']}") }}"
title="Remove">
title="Remove"
x-data="confirmLink"
data-url="{{ url("/myshows?action=delete&id={$show['videos_id']}") }}"
data-title="Remove Show"
data-message="Are you sure you want to remove this show from your list?"
data-confirm-text="Remove"
data-type="danger"
x-on:click.prevent="navigate">
<i class="fa fa-trash"></i>
</a>
</div>
@@ -225,16 +239,3 @@
@endif
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Confirm before removing shows
document.querySelectorAll('.confirm_action').forEach(element => {
element.addEventListener('click', function(e) {
if (!confirm('Are you sure you want to remove this show from your list?')) {
e.preventDefault();
}
});
});
});
</script>
+6 -29
View File
@@ -302,15 +302,16 @@
<p class="text-green-700 dark:text-green-300 text-sm mb-4">Your account is protected with an additional layer of security. You'll need your authenticator app to log in.</p>
<!-- Collapsible Disable Form -->
<div class="space-y-3">
<button id="toggle-disable-2fa-btn"
<div class="space-y-3" x-data="{ show2faForm: false }">
<button x-show="!show2faForm"
x-on:click="show2faForm = true"
type="button"
class="px-4 py-2 bg-red-600 dark:bg-red-700 text-white text-sm rounded-lg hover:bg-red-700 dark:hover:bg-red-800 transition">
<i class="fas fa-times-circle mr-2"></i>Disable 2FA
</button>
<div id="disable-2fa-form-container"
style="display: none;"
<div x-show="show2faForm"
x-cloak
class="bg-white dark:bg-gray-800 border border-red-200 dark:border-red-700 rounded-lg p-4 mt-3">
<div class="mb-4 p-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-700 rounded-lg">
<div class="flex items-start">
@@ -344,7 +345,7 @@
class="px-4 py-2 bg-red-600 dark:bg-red-700 text-white text-sm rounded-lg hover:bg-red-700 dark:hover:bg-red-800 transition">
<i class="fas fa-check mr-2"></i>Confirm Disable
</button>
<button id="cancel-disable-2fa-btn"
<button x-on:click="show2faForm = false"
type="button"
class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-700 dark:text-gray-200 text-sm rounded-lg hover:bg-gray-400 dark:hover:bg-gray-500 transition">
<i class="fas fa-times mr-2"></i>Cancel
@@ -443,27 +444,3 @@
</div>
@endsection
@push('scripts')
<script>
// 2FA disable form toggle
document.addEventListener('DOMContentLoaded', function() {
const toggleBtn = document.getElementById('toggle-disable-2fa-btn');
const cancelBtn = document.getElementById('cancel-disable-2fa-btn');
const formContainer = document.getElementById('disable-2fa-form-container');
if (toggleBtn) {
toggleBtn.addEventListener('click', function() {
formContainer.style.display = 'block';
toggleBtn.style.display = 'none';
});
}
if (cancelBtn) {
cancelBtn.addEventListener('click', function() {
formContainer.style.display = 'none';
toggleBtn.style.display = 'inline-block';
});
}
});
</script>
@endpush