|
99 | 99 | @endphp |
100 | 100 |
|
101 | 101 | @if($fileUrl) |
102 | | - @if($showAsLink) |
103 | | - {{-- Click opens new tab (no preview) --}} |
104 | | - <a |
105 | | - href="{{ $fileUrl }}" |
106 | | - target="_blank" |
107 | | - class="group block" |
| 102 | + @if($showAsLink && $canPreview) |
| 103 | + {{-- Compact list view with modal --}} |
| 104 | + <div |
| 105 | + x-data="{ open: false }" |
| 106 | + class="group cursor-pointer" |
108 | 107 | > |
109 | | - <div class="w-full aspect-square p-4 rounded-2xl bg-gray-50 dark:bg-gray-800 hover:bg-primary-50 dark:hover:bg-primary-900/20 border border-gray-200 dark:border-gray-700 hover:border-primary-200 dark:hover:border-primary-800 transition-all flex flex-col items-center justify-center text-center"> |
110 | | - {{-- Icon at top --}} |
111 | | - <div class="flex-1 flex items-center justify-center"> |
112 | | - @svg($fileIcon, 'w-12 h-12 text-gray-400 group-hover:text-primary-500') |
113 | | - </div> |
| 108 | + <div |
| 109 | + class="flex items-center gap-3 p-3 rounded-lg bg-gray-50 dark:bg-gray-800 hover:bg-primary-50 dark:hover:bg-primary-900/20 border border-gray-200 dark:border-gray-700 hover:border-primary-200 dark:hover:border-primary-800 transition-all" |
| 110 | + x-on:click="open = true" |
| 111 | + > |
| 112 | + {{-- Icon --}} |
| 113 | + @svg($fileIcon, 'w-5 h-5 text-gray-400 group-hover:text-primary-500 flex-shrink-0') |
114 | 114 |
|
115 | 115 | {{-- Filename --}} |
116 | | - <span class="text-sm font-medium text-gray-900 dark:text-white truncate w-full mt-2">{{ $fileTitle }}</span> |
| 116 | + <span class="text-sm font-medium text-gray-900 dark:text-white truncate flex-1">{{ $fileTitle }}</span> |
117 | 117 |
|
118 | 118 | @if($displayDate) |
119 | 119 | {{-- Date --}} |
120 | | - <span class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ $displayDate }}</span> |
| 120 | + <span class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0">{{ $displayDate }}</span> |
121 | 121 | @endif |
122 | 122 | </div> |
| 123 | + |
| 124 | + {{-- Modal --}} |
| 125 | + <div |
| 126 | + x-show="open" |
| 127 | + style="display: none;" |
| 128 | + x-on:keydown.escape.window="open = false" |
| 129 | + class="fixed inset-0 z-50 overflow-y-auto" |
| 130 | + aria-labelledby="modal-title-{{ $index }}" |
| 131 | + role="dialog" |
| 132 | + aria-modal="true" |
| 133 | + > |
| 134 | + {{-- Backdrop --}} |
| 135 | + <div |
| 136 | + x-show="open" |
| 137 | + x-transition:enter="ease-out duration-300" |
| 138 | + x-transition:enter-start="opacity-0" |
| 139 | + x-transition:enter-end="opacity-100" |
| 140 | + x-transition:leave="ease-in duration-200" |
| 141 | + x-transition:leave-start="opacity-100" |
| 142 | + x-transition:leave-end="opacity-0" |
| 143 | + class="fixed inset-0 bg-gray-500 dark:bg-gray-900 bg-opacity-75 dark:bg-opacity-75 transition-opacity" |
| 144 | + x-on:click="open = false" |
| 145 | + ></div> |
| 146 | + |
| 147 | + <div class="flex min-h-full items-center justify-center p-4 text-center sm:p-0"> |
| 148 | + <div |
| 149 | + x-show="open" |
| 150 | + x-transition:enter="ease-out duration-300" |
| 151 | + x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" |
| 152 | + x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100" |
| 153 | + x-transition:leave="ease-in duration-200" |
| 154 | + x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100" |
| 155 | + x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" |
| 156 | + class="relative transform overflow-hidden rounded-lg bg-white dark:bg-gray-800 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-4xl" |
| 157 | + x-on:click.stop |
| 158 | + > |
| 159 | + {{-- Header --}} |
| 160 | + <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 flex items-center justify-between"> |
| 161 | + <h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white truncate pr-4" id="modal-title-{{ $index }}"> |
| 162 | + {{ $fileTitle }} |
| 163 | + </h3> |
| 164 | + <button |
| 165 | + type="button" |
| 166 | + class="text-gray-400 hover:text-gray-500 focus:outline-none flex-shrink-0" |
| 167 | + x-on:click="open = false" |
| 168 | + > |
| 169 | + @svg('heroicon-o-x-mark', 'w-6 h-6') |
| 170 | + </button> |
| 171 | + </div> |
| 172 | + |
| 173 | + {{-- Content --}} |
| 174 | + <div class="px-4 py-5 sm:p-6"> |
| 175 | + <div class="w-full rounded-lg overflow-hidden border border-gray-200 dark:border-gray-700" style="max-height: 60vh;"> |
| 176 | + @switch($fileType) |
| 177 | + @case('image') |
| 178 | + <img |
| 179 | + src="{{ $fileUrl }}" |
| 180 | + alt="{{ $fileTitle }}" |
| 181 | + class="w-full h-auto object-contain bg-gray-100 dark:bg-gray-800" |
| 182 | + /> |
| 183 | + @break |
| 184 | + |
| 185 | + @case('video') |
| 186 | + <video |
| 187 | + controls |
| 188 | + class="w-full bg-gray-900" |
| 189 | + style="max-height: 60vh;" |
| 190 | + > |
| 191 | + <source src="{{ $fileUrl }}" type="video/{{ pathinfo($filePath, PATHINFO_EXTENSION) }}"> |
| 192 | + @lang('Your browser does not support the video tag.') |
| 193 | + </video> |
| 194 | + @break |
| 195 | + |
| 196 | + @case('audio') |
| 197 | + <div class="w-full p-8 bg-gray-50 dark:bg-gray-800"> |
| 198 | + <audio controls class="w-full"> |
| 199 | + <source src="{{ $fileUrl }}" type="audio/{{ pathinfo($filePath, PATHINFO_EXTENSION) }}"> |
| 200 | + @lang('Your browser does not support the audio tag.') |
| 201 | + </audio> |
| 202 | + </div> |
| 203 | + @break |
| 204 | + |
| 205 | + @case('pdf') |
| 206 | + <iframe |
| 207 | + src="{{ $fileUrl }}" |
| 208 | + class="w-full border-0" |
| 209 | + style="height: 60vh;" |
| 210 | + title="{{ $fileTitle }}" |
| 211 | + ></iframe> |
| 212 | + @break |
| 213 | + |
| 214 | + @case('text') |
| 215 | + <div class="w-full p-4 bg-gray-50 dark:bg-gray-800 overflow-auto font-mono text-sm" style="max-height: 60vh;"> |
| 216 | + @php |
| 217 | + $disk = \Illuminate\Support\Facades\Storage::disk($getDiskName()); |
| 218 | + $fileContent = ''; |
| 219 | + try { |
| 220 | + if ($disk->exists($filePath)) { |
| 221 | + $fileContent = $disk->get($filePath); |
| 222 | + } |
| 223 | + } catch (\Exception $e) { |
| 224 | + $fileContent = 'Unable to read file content.'; |
| 225 | + } |
| 226 | + @endphp |
| 227 | + <pre class="whitespace-pre-wrap break-words">{{ $fileContent }}</pre> |
| 228 | + </div> |
| 229 | + @break |
| 230 | + |
| 231 | + @default |
| 232 | + <div class="w-full p-8 bg-gray-50 dark:bg-gray-800 flex flex-col items-center justify-center"> |
| 233 | + @svg($fileIcon, 'w-16 h-16 text-gray-400 mb-4') |
| 234 | + <p class="text-gray-600 dark:text-gray-400">Preview not available</p> |
| 235 | + </div> |
| 236 | + @endswitch |
| 237 | + </div> |
| 238 | + </div> |
| 239 | + |
| 240 | + {{-- Footer --}} |
| 241 | + <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6 gap-2"> |
| 242 | + <a |
| 243 | + href="{{ $fileUrl }}" |
| 244 | + target="_blank" |
| 245 | + class="inline-flex w-full justify-center rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-primary-500 sm:ml-3 sm:w-auto" |
| 246 | + > |
| 247 | + @svg('heroicon-o-arrow-top-right-on-square', 'w-4 h-4 mr-1') |
| 248 | + @lang('Open') |
| 249 | + </a> |
| 250 | + @if($downloadable) |
| 251 | + <a |
| 252 | + href="{{ $fileUrl }}" |
| 253 | + target="_blank" |
| 254 | + download |
| 255 | + class="mt-3 inline-flex w-full justify-center rounded-md bg-white dark:bg-gray-800 px-3 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 sm:mt-0 sm:w-auto" |
| 256 | + > |
| 257 | + @svg('heroicon-o-arrow-down-tray', 'w-4 h-4 mr-1') |
| 258 | + @lang('Download') |
| 259 | + </a> |
| 260 | + @endif |
| 261 | + <button |
| 262 | + type="button" |
| 263 | + class="mt-3 inline-flex w-full justify-center rounded-md bg-white dark:bg-gray-800 px-3 py-2 text-sm font-semibold text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 sm:mt-0 sm:w-auto" |
| 264 | + x-on:click="open = false" |
| 265 | + > |
| 266 | + @lang('Close') |
| 267 | + </button> |
| 268 | + </div> |
| 269 | + </div> |
| 270 | + </div> |
| 271 | + </div> |
| 272 | + </div> |
| 273 | + @elseif($showAsLink) |
| 274 | + {{-- Simple link for non-previewable files --}} |
| 275 | + <a |
| 276 | + href="{{ $fileUrl }}" |
| 277 | + target="_blank" |
| 278 | + class="group flex items-center gap-3 p-3 rounded-lg bg-gray-50 dark:bg-gray-800 hover:bg-primary-50 dark:hover:bg-primary-900/20 border border-gray-200 dark:border-gray-700 hover:border-primary-200 dark:hover:border-primary-800 transition-all" |
| 279 | + > |
| 280 | + {{-- Icon --}} |
| 281 | + @svg($fileIcon, 'w-5 h-5 text-gray-400 group-hover:text-primary-500 flex-shrink-0') |
| 282 | + |
| 283 | + {{-- Filename --}} |
| 284 | + <span class="text-sm font-medium text-gray-900 dark:text-white truncate flex-1">{{ $fileTitle }}</span> |
| 285 | + |
| 286 | + @if($displayDate) |
| 287 | + {{-- Date --}} |
| 288 | + <span class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0">{{ $displayDate }}</span> |
| 289 | + @endif |
123 | 290 | </a> |
124 | 291 | @elseif($asModal) |
125 | 292 | {{-- Click opens modal --}} |
|
0 commit comments