Save workspace changes
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
{{-- Shim for legacy artwork card includes. Points to new web partial. --}}
|
||||
@include('web.partials._artwork_card')
|
||||
@@ -0,0 +1,17 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
use Illuminate\Support\Str;
|
||||
use Carbon\Carbon;
|
||||
use App\Services\LegacyService;
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
@include('legacy::home.featured')
|
||||
|
||||
@include('legacy::home.uploads')
|
||||
|
||||
@include('legacy::home.news')
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,46 @@
|
||||
{{-- Featured row --}}
|
||||
<div class="row featured-row">
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<div class="featured-card effect2">
|
||||
<div class="card-header">Featured Artwork</div>
|
||||
<div class="card-body text-center">
|
||||
<a href="/art/{{ data_get($featured, 'id') }}/{{ Str::slug(data_get($featured, 'name') ?? 'artwork') }}" class="thumb-link">
|
||||
@php
|
||||
$fthumb = data_get($featured, 'thumb_url') ?? data_get($featured, 'thumb');
|
||||
@endphp
|
||||
<img src="{{ $fthumb }}" class="img-responsive featured-img" alt="{{ data_get($featured, 'name') }}">
|
||||
</a>
|
||||
<div class="featured-title">{{ data_get($featured, 'name') }}</div>
|
||||
<div class="featured-author">by {{ data_get($featured, 'uname') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<div class="featured-card effect2">
|
||||
<div class="card-header">Featured by Members Vote</div>
|
||||
<div class="card-body text-center">
|
||||
<a href="/art/{{ data_get($memberFeatured, 'id') }}/{{ Str::slug(data_get($memberFeatured, 'name') ?? 'artwork') }}" class="thumb-link">
|
||||
@php
|
||||
$mthumb = data_get($memberFeatured, 'thumb_url') ?? data_get($memberFeatured, 'thumb');
|
||||
@endphp
|
||||
<img src="{{ $mthumb }}" class="img-responsive featured-img" alt="{{ data_get($memberFeatured, 'name') }}">
|
||||
</a>
|
||||
<div class="featured-title">{{ data_get($memberFeatured, 'name') }}</div>
|
||||
<div class="featured-author">by {{ data_get($memberFeatured, 'uname') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-sm-12">
|
||||
<div class="featured-card join-card effect2">
|
||||
<div class="card-header">Join to Skinbase World</div>
|
||||
<div class="card-body text-center">
|
||||
<a href="{{ route('register') }}" title="Join Skinbase">
|
||||
<img src="/gfx/sb_join.jpg" alt="Join SkinBase Community" class="img-responsive join-img center-block">
|
||||
</a>
|
||||
<div class="join-text">Join to Skinbase and be part of our great community! We have big collection of high quality Photography, Wallpapers and Skins for popular applications.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,84 @@
|
||||
{{-- News and forum columns --}}
|
||||
<div class="row news-row">
|
||||
<div class="col-sm-6">
|
||||
@php
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
@endphp
|
||||
@forelse ($forumNews as $item)
|
||||
<div class="panel panel-skinbase effect2">
|
||||
<div class="panel-heading"><h4 class="panel-title">{{ $item->topic }}</h4></div>
|
||||
<div class="panel-body">
|
||||
<div class="text-muted news-head">
|
||||
Written by {{ $item->uname }} on {{ Carbon::parse($item->post_date)->format('j F Y \@ H:i') }}
|
||||
</div>
|
||||
{!! Str::limit(strip_tags($item->preview ?? ''), 240, '...') !!}
|
||||
<br>
|
||||
<a class="clearfix btn btn-xs btn-info" href="{{ route('forum.thread.show', ['thread' => $item->topic_id, 'slug' => Str::slug($item->topic ?? '')]) }}" title="{{ strip_tags($item->topic) }}">More</a>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<p>No forum news available.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
@forelse ($ourNews as $news)
|
||||
<div class="panel panel-skinbase effect2">
|
||||
<div class="panel-heading"><h3 class="panel-title">{{ $news->headline }}</h3></div>
|
||||
<div class="panel-body">
|
||||
<div class="text-muted news-head">
|
||||
<i class="fa fa-user"></i> {{ $news->uname }}
|
||||
<i class="fa fa-calendar"></i> {{ Carbon::parse($news->create_date)->format('j F Y \@ H:i') }}
|
||||
<i class="fa fa-info"></i> {{ $news->category_name }}
|
||||
<i class="fa fa-info"></i> {{ $news->views }} reads
|
||||
<i class="fa fa-comment"></i> {{ $news->num_comments }} comments
|
||||
</div>
|
||||
|
||||
@if (!empty($news->picture))
|
||||
@php $nid = floor($news->news_id / 100); @endphp
|
||||
<div class="col-md-4">
|
||||
<img src="/archive/news/{{ $nid }}/{{ $news->picture }}" class="img-responsive" alt="{{ $news->headline }}">
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
{!! $news->preview !!}
|
||||
</div>
|
||||
@else
|
||||
{!! $news->preview !!}
|
||||
@endif
|
||||
|
||||
<a class="clearfix btn btn-xs btn-info text-white" href="/news/{{ $news->news_id }}/{{ Str::slug($news->headline ?? '') }}">More</a>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<p>No news available.</p>
|
||||
@endforelse
|
||||
|
||||
{{-- Site info --}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Info</strong></div>
|
||||
<div class="panel-body">
|
||||
<h4>Photography, Wallpapers and Skins... Thats Skinbase</h4>
|
||||
<p>Skinbase is the site dedicated to <strong>Photography</strong>, <strong>Wallpapers</strong> and <strong>Skins</strong> for <u>popular applications</u> for every major operating system like Windows, Mac OS X, Linux, iOS and Android</p>
|
||||
<em>Our members every day uploads new artworks to our site, so don't hesitate and check Skinbase frequently for updates. We also have forum where you can discuss with other members with anything.</em>
|
||||
<p>On the site toolbar you can click on Categories and start browsing our atwork (<i>photo</i>, <i>desktop themes</i>, <i>pictures</i>) and of course you can <u>download</u> them for free!</p>
|
||||
<p>We are also active on all major <b>social</b> sites, find us there too</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Latest forum activity --}}
|
||||
<div class="panel panel-default activity-panel">
|
||||
<div class="panel-heading"><strong>Latest Forum Activity</strong></div>
|
||||
<div class="panel-body">
|
||||
<div class="list-group effect2">
|
||||
@forelse ($latestForumActivity as $topic)
|
||||
<a class="list-group-item" href="{{ route('forum.thread.show', ['thread' => $topic->topic_id, 'slug' => Str::slug($topic->topic ?? '')]) }}">
|
||||
{{ $topic->topic }} <span class="badge badge-info">{{ $topic->numPosts }}</span>
|
||||
</a>
|
||||
@empty
|
||||
<p>No recent forum activity.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="gallery-grid">
|
||||
@foreach ($latestUploads as $upload)
|
||||
<div class="thumb-card effect2">
|
||||
@php
|
||||
$t = \App\Services\ThumbnailPresenter::present($upload, 'md');
|
||||
$card = [
|
||||
'id' => $t['id'] ?? null,
|
||||
'title' => $t['title'] ?? 'Artwork',
|
||||
'thumb' => $t['url'] ?? null,
|
||||
'thumb_srcset' => $t['srcset'] ?? null,
|
||||
];
|
||||
@endphp
|
||||
<x-artwork-card :art="$card" />
|
||||
</div>
|
||||
@endforeach
|
||||
</div> <!-- end .gallery-grid -->
|
||||
@@ -0,0 +1,97 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Interview</h1>
|
||||
<p>{{ $ar->headline ?? '' }}</p>
|
||||
<div style="location_bar">
|
||||
<a href="/interviews" class="btn btn-xs btn-default" title="List of all Interviews"><i class="fa fa-list fa-fw"></i> Interviews List</a>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h1 class="skinTitle">{{ $ar->headline }}</h1>
|
||||
<div>{!! $ar->tekst !!}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="skinTitle">User Comments</h2>
|
||||
|
||||
@foreach($comments as $comment)
|
||||
@php
|
||||
$local_date = date('j.F.y @ H:i:s', strtotime($comment->datum));
|
||||
$user_id = $comment->user_id ?? null;
|
||||
@endphp
|
||||
<table width="100%" cellspacing="1" cellpadding="1" class="MojText" border="0" style="background:#eee;">
|
||||
<tr>
|
||||
<td rowspan="3" valign="top" width="100" style="background:#fff">
|
||||
@if(!empty($comment->user_id) && !empty($comment->icon))
|
||||
<div align="center"><a href="/profile/{{ $comment->user_id }}"><img src="{{ \App\Support\AvatarUrl::forUser((int) $comment->user_id, null, 50) }}" width="50" height="50" border="0" alt="" /></a></div>
|
||||
@endif
|
||||
<br/>Posted by: <b><a href="/profile/{{ $comment->user_id ?? '' }}">{{ $comment->author }}</a></b><br/>
|
||||
Posts: {{ $postCounts[$comment->author] ?? 0 }}
|
||||
<div align="center"><img src="/gfx/member_stars/{{ $comment->user_type ?? 0 }}.jpg" title="" /></div>
|
||||
</td>
|
||||
<td valign="top" height="10" style="background:#eee"> {{ $local_date }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="50" style="background:#fff;padding-left:13px; padding-right:3px;">{!! $comment->tekst !!}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="bottom" align="center" height="10" style="background:#fff;">
|
||||
@if(!empty($comment->signature))
|
||||
{!! nl2br(e($comment->signature)) !!}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
@endforeach
|
||||
|
||||
@php
|
||||
$status = $_SESSION['web_login']['status'] ?? false;
|
||||
$user_type = $_SESSION['web_login']['user_type'] ?? 0;
|
||||
@endphp
|
||||
|
||||
@if(!$status || $user_type < 2)
|
||||
<h1>Please login first</h1>
|
||||
@else
|
||||
<h2 class="skinTitle">Write comment</h2>
|
||||
<form action="{{ url()->current() }}" method="post">
|
||||
@csrf
|
||||
<textarea name="comment" style="width:98%; height:215px;" class="textarea"></textarea><br />
|
||||
<input type="hidden" name="interview_id" value="{{ $ar->id }}">
|
||||
<input type="hidden" name="action" value="store">
|
||||
<button type="submit" class="btn btn-success">Submit</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div style="margin-left:4px; float:right;width:300px;border-left :dotted 1px #eee; padding-left:10px;">
|
||||
<br/><br/>
|
||||
@php \App\Banner::ShowBanner300x250(); @endphp
|
||||
<br/><br/>
|
||||
|
||||
@if(!empty($ar->username))
|
||||
@php $username = DB::table('users')->where('uname', $ar->username)->value('uname'); @endphp
|
||||
<div class="interviewGuy">{{ $username }} Gallery (random order):</div><br/>
|
||||
@foreach($artworks as $artwork)
|
||||
@php $nid = (int)($artwork->id / 100); @endphp
|
||||
<a href="/art/{{ $artwork->id }}/{{ \Illuminate\Support\Str::slug($artwork->name ?? '') }}">
|
||||
<img src="/files/archive/shots/{{ $nid }}/{{ $artwork->picture }}" alt="" style="max-width:100%;" />
|
||||
</a>
|
||||
<br/><br/>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,41 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">{{ $page_title ?? 'Interviews' }}</h1>
|
||||
<p>List of interviews and their authors.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
@php \App\Banner::ShowResponsiveAd(); @endphp
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<table class="table table-bordered table-striped">
|
||||
<tbody>
|
||||
@foreach($interviews as $interview)
|
||||
<tr>
|
||||
<td style="width:60px;">
|
||||
@if(!empty($interview->icon))
|
||||
<a href="/profile/{{ $interview->user_id }}/{{ \Illuminate\Support\Str::slug($interview->uname ?? '') }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $interview->user_id, null, 50) }}" width="50" height="50" alt="">
|
||||
</a>
|
||||
@else
|
||||
<img src="/gfx/avatar.jpg" alt="">
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<a href="/interview/{{ $interview->id }}/{{ \Illuminate\Support\Str::slug($interview->headline ?? '') }}">{{ $interview->headline }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,30 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Latest Artworks</h1>
|
||||
<p>List of recently uploaded Artworks - <strong>Skins</strong>, <strong>Photography</strong> and <strong>Wallpapers</strong>.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default uploads-panel effect2">
|
||||
<div class="panel-body">
|
||||
<div class="gallery-grid">
|
||||
@if($artworks)
|
||||
@foreach($artworks as $art)
|
||||
<x-artwork-card :art="$art" />
|
||||
@endforeach
|
||||
@else
|
||||
<p class="text-muted">No artworks found.</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
@if($artworks){{ $artworks->withQueryString()->links('pagination::bootstrap-4') }}@endif
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,64 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title, 'url' => route('legacy.latest_comments')],
|
||||
]);
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<x-nova-page-header
|
||||
section="Comments"
|
||||
:title="$page_title"
|
||||
icon="fa-comments"
|
||||
:breadcrumbs="$headerBreadcrumbs"
|
||||
description="List of artwork with latest comments received."
|
||||
headerClass="pb-6"
|
||||
/>
|
||||
|
||||
<div class="container-fluid legacy-page pt-8">
|
||||
|
||||
<div class="masonry">
|
||||
@foreach ($comments as $comment)
|
||||
<div class="masonry_item col-sm-6 col-md-4">
|
||||
<div class="comment_box effect3">
|
||||
<div class="cb_image">
|
||||
<a href="/profile/{{ $comment->commenter_id }}/{{ rawurlencode($comment->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $comment->commenter_id, null, 50) }}" width="50" height="50" class="comment_avatar" alt="{{ $comment->uname }}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="bubble_comment panel panel-skinbase">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">{{
|
||||
\Carbon\Carbon::parse($comment->datetime)->diffForHumans() }}
|
||||
</div>
|
||||
<h5 class="panel-title">Comment by: <a href="/profile/{{ $comment->commenter_id }}/{{ rawurlencode($comment->uname) }}">{{ $comment->uname }}</a></h5>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="comment_box_image">
|
||||
<a href="/art/{{ $comment->id }}/{{ $comment->artwork_slug }}">
|
||||
<img src="{{ $comment->thumb }}" alt="{{ $comment->name }}" class="img-thumbnail img-responsive">
|
||||
</a>
|
||||
</div>
|
||||
<div class="comment_text mt-2">
|
||||
{!! nl2br(e($comment->comment_description)) !!}
|
||||
</div>
|
||||
|
||||
@if (!empty($comment->signature))
|
||||
<div class="panel-footer comment-footer mt-2">
|
||||
{!! nl2br(e($comment->signature)) !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $comments->links('pagination::bootstrap-4') }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,66 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title, 'url' => route('legacy.monthly_commentators')],
|
||||
]);
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<x-nova-page-header
|
||||
section="Comments"
|
||||
:title="$page_title"
|
||||
icon="fa-ranking-star"
|
||||
:breadcrumbs="$headerBreadcrumbs"
|
||||
description="List of users who post the most comments in the current month."
|
||||
headerClass="pb-6"
|
||||
/>
|
||||
|
||||
<div class="container-fluid legacy-page pt-8">
|
||||
|
||||
<div class="container-main">
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-body">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Thumb</th>
|
||||
<th>Name</th>
|
||||
<th>Level</th>
|
||||
<th>Country</th>
|
||||
<th>Comments</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($rows as $row)
|
||||
<tr>
|
||||
<td width="50" class="text-center">
|
||||
<a href="/profile/{{ (int)$row->user_id }}/{{ rawurlencode($row->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $row->user_id, null, 32) }}" width="30" alt="{{ $row->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ (int)$row->user_id }}/{{ rawurlencode($row->uname) }}">{{ $row->uname }}</a>
|
||||
</td>
|
||||
<td width="100" class="text-center">
|
||||
<img src="/gfx/member_stars/{{ (int)$row->user_type }}.gif" alt="level">
|
||||
</td>
|
||||
<td width="100" class="text-center">
|
||||
@if (!empty($row->country_flag))
|
||||
<img width="20" title="{{ $row->country_name }}" src="/gfx/flags/{{ rawurlencode($row->country_flag) }}" alt="{{ $row->country_name }}">
|
||||
@endif
|
||||
</td>
|
||||
<td width="100" class="text-center">{{ (int)$row->num_comments }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $rows->withQueryString()->links('pagination::bootstrap-4') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,77 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="page-heading">
|
||||
<h1 class="page-header">{{ $news->headline ?? 'News' }}</h1>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-user"></i>
|
||||
<a href="/profile/{{ $news->user_id ?? '' }}/{{ Str::slug($news->uname ?? '') }}">{{ $news->uname ?? 'Unknown' }}</a>
|
||||
<i class="fa fa-calendar"></i>
|
||||
{{ date('j.F.y @ H:i:s', strtotime($news->create_date ?? now())) }}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<h1 class="panel-title" style="font-size:26px;color:#000;">{!! nl2br(e($news->headline ?? '')) !!}</h1>
|
||||
<br>
|
||||
<p>{!! html_entity_decode(stripslashes($news->content ?? '')) !!}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="lead">User Comments:</h3>
|
||||
|
||||
@foreach($comments as $ar)
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-user"></i>
|
||||
<a href="/profile/{{ $ar->user_id ?? '' }}/{{ Str::slug($ar->uname ?? '') }}">{{ $ar->uname ?? 'Unknown' }}</a>
|
||||
<i class="fa fa-calendar"></i>
|
||||
{{ date('j.F.y @ H:i:s', strtotime($ar->posted ?? now())) }}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@if(!empty($ar->icon))
|
||||
<div style="float:right;padding-left:20px;">
|
||||
<a href="/profile/{{ $ar->user_id ?? '' }}/{{ Str::slug($ar->uname ?? '') }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) ($ar->user_id ?? 0), null, 50) }}" width="50" height="50" alt="">
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div>{!! nl2br(e($ar->message ?? '')) !!}</div>
|
||||
|
||||
@if(!empty($ar->signature))
|
||||
<div class="label label-info">{!! nl2br(e($ar->signature)) !!}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
{{-- Comment form (legacy) --}}
|
||||
@php
|
||||
$status = $_SESSION['web_login']['status'] ?? false;
|
||||
$user_type = $_SESSION['web_login']['user_type'] ?? 0;
|
||||
@endphp
|
||||
|
||||
@if(!$status && $user_type < 2)
|
||||
<div class="alert alert-warning"><i class="fa fa-warning"></i> You have to login to write comment</div>
|
||||
@else
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-comment"></i> Write comment</div>
|
||||
<div class="panel-body">
|
||||
<form action="/news/{{ $news->news_id ?? '' }}/{{ Str::slug($news->headline ?? '') }}" method="post" class="form">
|
||||
@csrf
|
||||
<textarea name="comment" style="width:100%; height:215px;" class="tinymce"></textarea><br>
|
||||
<input type="hidden" name="news_id" value="{{ $news->news_id ?? '' }}">
|
||||
<input type="hidden" name="confirm" value="true">
|
||||
<button type="submit" class="btn btn-success">Post Comment</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,693 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$uname = $user->username ?? $user->name ?? 'Unknown';
|
||||
$displayName = $user->name ?? $uname;
|
||||
$avatarUrl = \App\Support\AvatarUrl::forUser((int) $user->id, $user->profile?->avatar_hash, 128);
|
||||
|
||||
$genderMap = [
|
||||
'M' => ['label' => 'Male', 'icon' => 'fa-mars', 'color' => 'text-blue-400'],
|
||||
'F' => ['label' => 'Female', 'icon' => 'fa-venus', 'color' => 'text-pink-400'],
|
||||
'X' => ['label' => 'N/A', 'icon' => 'fa-question', 'color' => 'text-gray-400'],
|
||||
];
|
||||
$genderCode = strtoupper((string) ($profile?->gender ?? 'X'));
|
||||
$gender = $genderMap[$genderCode] ?? $genderMap['X'];
|
||||
|
||||
$birthdate = null;
|
||||
if ($profile?->birthdate) {
|
||||
try {
|
||||
$bd = \Carbon\Carbon::parse($profile->birthdate);
|
||||
if ($bd->year > 1900) {
|
||||
$birthdate = $bd->format('F d, Y');
|
||||
}
|
||||
} catch (\Throwable) {}
|
||||
}
|
||||
|
||||
$website = $profile?->website ?? null;
|
||||
if ($website && !preg_match('#^https?://#i', $website)) {
|
||||
$website = 'https://' . $website;
|
||||
}
|
||||
|
||||
$about = $profile?->about ?? null;
|
||||
|
||||
$lastVisit = null;
|
||||
if ($user->last_visit_at) {
|
||||
try { $lastVisit = \Carbon\Carbon::parse($user->last_visit_at); } catch (\Throwable) {}
|
||||
}
|
||||
|
||||
$socialIcons = [
|
||||
'twitter' => ['icon' => 'fa-brands fa-x-twitter', 'label' => 'X / Twitter'],
|
||||
'deviantart' => ['icon' => 'fa-brands fa-deviantart', 'label' => 'DeviantArt'],
|
||||
'instagram' => ['icon' => 'fa-brands fa-instagram', 'label' => 'Instagram'],
|
||||
'behance' => ['icon' => 'fa-brands fa-behance', 'label' => 'Behance'],
|
||||
'artstation' => ['icon' => 'fa-solid fa-palette', 'label' => 'ArtStation'],
|
||||
'youtube' => ['icon' => 'fa-brands fa-youtube', 'label' => 'YouTube'],
|
||||
'website' => ['icon' => 'fa-solid fa-link', 'label' => 'Website'],
|
||||
];
|
||||
|
||||
$seoPage = max(1, (int) request()->query('page', 1));
|
||||
$seoBase = url()->current();
|
||||
$seoQ = request()->query(); unset($seoQ['page']);
|
||||
$seoUrl = fn(int $p) => $seoBase . ($p > 1
|
||||
? '?' . http_build_query(array_merge($seoQ, ['page' => $p]))
|
||||
: (count($seoQ) ? '?' . http_build_query($seoQ) : ''));
|
||||
$seoPrev = $seoPage > 1 ? $seoUrl($seoPage - 1) : null;
|
||||
$seoNext = (isset($artworks) && method_exists($artworks, 'nextPageUrl')) ? $artworks->nextPageUrl() : null;
|
||||
@endphp
|
||||
|
||||
@push('head')
|
||||
<link rel="canonical" href="{{ $seoUrl($seoPage) }}">
|
||||
@if($seoPrev)<link rel="prev" href="{{ $seoPrev }}">@endif
|
||||
@if($seoNext)<link rel="next" href="{{ $seoNext }}">@endif
|
||||
<meta name="robots" content="index,follow">
|
||||
<meta property="og:title" content="Profile: {{ e($uname) }} – Skinbase.org">
|
||||
<meta property="og:image" content="{{ $avatarUrl }}">
|
||||
<meta property="og:url" content="{{ $page_canonical ?? url()->current() }}">
|
||||
<style>
|
||||
.profile-hero-bg {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.profile-hero-bg::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(ellipse at 20% 50%, rgba(77,163,255,.12), transparent 60%),
|
||||
radial-gradient(ellipse at 80% 20%, rgba(224,122,33,.08), transparent 50%);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.nova-panel {
|
||||
background: var(--panel-dark);
|
||||
border: 1px solid var(--sb-line);
|
||||
border-radius: 0.75rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.nova-panel-header {
|
||||
padding: 0.65rem 1rem;
|
||||
border-bottom: 1px solid var(--sb-line);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.82rem;
|
||||
color: var(--sb-text);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.nova-panel-body { padding: 1rem; }
|
||||
.stat-item { text-align: center; padding: 0.5rem 0.75rem; }
|
||||
.stat-item .stat-value {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.stat-item .stat-label {
|
||||
font-size: 0.65rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--sb-muted);
|
||||
margin-top: 1px;
|
||||
}
|
||||
.profile-table td:first-child {
|
||||
color: var(--sb-muted);
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
padding-right: 0.75rem;
|
||||
padding-top: 0.45rem;
|
||||
padding-bottom: 0.45rem;
|
||||
}
|
||||
.profile-table td:last-child {
|
||||
color: var(--sb-text);
|
||||
font-size: 0.82rem;
|
||||
text-align: right;
|
||||
}
|
||||
.profile-table tr {
|
||||
border-bottom: 1px solid rgba(42,42,51,0.5);
|
||||
}
|
||||
.profile-table tr:last-child { border-bottom: none; }
|
||||
.profile-table td { vertical-align: middle; }
|
||||
.comment-avatar {
|
||||
width: 38px; height: 38px;
|
||||
border-radius: 50%; object-fit: cover; flex-shrink: 0;
|
||||
}
|
||||
.follower-avatar {
|
||||
width: 34px; height: 34px;
|
||||
border-radius: 50%; object-fit: cover;
|
||||
border: 1px solid var(--sb-line);
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.follower-avatar:hover { opacity: 0.85; }
|
||||
.fav-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
|
||||
gap: 4px;
|
||||
}
|
||||
.fav-grid a img {
|
||||
width: 100%; aspect-ratio: 1; object-fit: cover;
|
||||
border-radius: 4px; transition: opacity 0.2s;
|
||||
display: block;
|
||||
}
|
||||
.fav-grid a:hover img { opacity: 0.82; }
|
||||
.follow-btn { transition: all 0.2s ease; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
|
||||
{{-- ═══════════════════════════════════════════════════════════
|
||||
PROFILE HERO
|
||||
═══════════════════════════════════════════════════════════ --}}
|
||||
<div class="profile-hero-bg border-b border-[--sb-line]"
|
||||
@if(!empty($heroBgUrl))
|
||||
style="background: url('{{ $heroBgUrl }}') center/cover no-repeat;"
|
||||
@else
|
||||
style="background: linear-gradient(135deg, rgba(15,23,36,1) 0%, rgba(21,30,46,1) 50%, rgba(9,16,26,1) 100%);"
|
||||
@endif
|
||||
>
|
||||
{{-- Dark overlay so the content stays readable --}}
|
||||
@if(!empty($heroBgUrl))
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-[#0f1724]/95 via-[#0f1724]/80 to-[#0f1724]/60"></div>
|
||||
@endif
|
||||
<div class="relative z-10 max-w-screen-xl mx-auto px-4 py-8">
|
||||
<div class="flex flex-col sm:flex-row items-center sm:items-end gap-5">
|
||||
|
||||
{{-- Avatar --}}
|
||||
<div class="shrink-0">
|
||||
<img src="{{ $avatarUrl }}"
|
||||
alt="{{ e($uname) }}"
|
||||
class="w-24 h-24 sm:w-32 sm:h-32 rounded-full object-cover border-4 border-[--sb-line] shadow-lg">
|
||||
</div>
|
||||
|
||||
{{-- Name + meta --}}
|
||||
<div class="flex-1 text-center sm:text-left min-w-0">
|
||||
<h1 class="text-2xl sm:text-3xl font-bold text-white leading-tight truncate">
|
||||
{{ e($uname) }}
|
||||
</h1>
|
||||
@if($displayName && $displayName !== $uname)
|
||||
<p class="text-[--sb-muted] text-sm mt-0.5">{{ e($displayName) }}</p>
|
||||
@endif
|
||||
@if($countryName)
|
||||
<p class="text-[--sb-muted] text-sm mt-1 flex items-center justify-center sm:justify-start gap-1.5">
|
||||
@if($profile?->country_code)
|
||||
<img src="/gfx/flags/shiny/24/{{ rawurlencode($profile->country_code) }}.png"
|
||||
alt="{{ e($countryName) }}"
|
||||
class="w-5 h-auto rounded-sm inline-block"
|
||||
onerror="this.style.display='none'">
|
||||
@endif
|
||||
{{ e($countryName) }}
|
||||
</p>
|
||||
@endif
|
||||
@if($lastVisit)
|
||||
<p class="text-[--sb-muted] text-xs mt-1">
|
||||
<i class="fa-solid fa-clock fa-fw mr-1"></i>
|
||||
Last seen {{ $lastVisit->diffForHumans() }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Action buttons --}}
|
||||
<div class="shrink-0 flex flex-col gap-2 items-center sm:items-end">
|
||||
@if(!$isOwner)
|
||||
@auth
|
||||
<div x-data="{
|
||||
following: {{ $viewerIsFollowing ? 'true' : 'false' }},
|
||||
count: {{ (int) $followerCount }},
|
||||
loading: false,
|
||||
hovering: false,
|
||||
async toggle() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const r = await fetch('{{ route('profile.follow', ['username' => strtolower((string)$uname)]) }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const d = await r.json();
|
||||
if (r.ok) { this.following = d.following; this.count = d.follower_count; }
|
||||
} catch(e) {}
|
||||
this.loading = false;
|
||||
}
|
||||
}">
|
||||
<button @click="toggle" @mouseenter="hovering=true" @mouseleave="hovering=false" :disabled="loading" class="follow-btn inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border transition-all"
|
||||
:class="following
|
||||
? 'bg-green-500/10 border-green-500/40 text-green-400 hover:bg-red-500/10 hover:border-red-500/40 hover:text-red-400'
|
||||
: 'bg-[--sb-blue]/10 border-[--sb-blue]/40 text-[--sb-blue] hover:bg-[--sb-blue]/20'">
|
||||
<i class="fa-solid fa-fw"
|
||||
:class="loading ? 'fa-circle-notch fa-spin' : (following ? (hovering ? 'fa-user-minus' : 'fa-user-check') : 'fa-user-plus')"></i>
|
||||
<span x-text="following ? (hovering ? 'Unfollow' : 'Following') : 'Follow'"></span>
|
||||
<span class="text-xs opacity-60" x-text="'(' + count + ')'"></span>
|
||||
</button>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ route('login') }}"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border border-[--sb-blue]/40 text-[--sb-blue] hover:bg-[--sb-blue]/10 transition-all">
|
||||
<i class="fa-solid fa-user-plus fa-fw"></i> Follow
|
||||
<span class="text-xs opacity-60">({{ $followerCount }})</span>
|
||||
</a>
|
||||
@endauth
|
||||
@else
|
||||
<a href="{{ route('dashboard.profile') }}"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border border-[--sb-line] text-[--sb-text] hover:bg-white/5 transition-all">
|
||||
<i class="fa-solid fa-pen fa-fw"></i> Edit Profile
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ═══════════════════════════════════════════════════════════
|
||||
STATS STRIP
|
||||
═══════════════════════════════════════════════════════════ --}}
|
||||
<div class="bg-[--sb-panel2] border-b border-[--sb-line]">
|
||||
<div class="max-w-screen-xl mx-auto px-4">
|
||||
<div class="flex divide-x divide-[--sb-line] overflow-x-auto">
|
||||
@foreach([
|
||||
['value' => number_format($stats->uploads_count ?? 0), 'label' => 'Uploads', 'icon' => 'fa-cloud-arrow-up'],
|
||||
['value' => number_format($stats->downloads_received_count ?? 0),'label' => 'Downloads', 'icon' => 'fa-download'],
|
||||
['value' => number_format($stats->profile_views_count ?? 0), 'label' => 'Profile Views', 'icon' => 'fa-eye'],
|
||||
['value' => number_format($followerCount), 'label' => 'Followers', 'icon' => 'fa-users'],
|
||||
['value' => number_format($stats->following_count ?? 0), 'label' => 'Following', 'icon' => 'fa-user-check'],
|
||||
['value' => number_format($stats->awards_received_count ?? 0), 'label' => 'Awards', 'icon' => 'fa-trophy'],
|
||||
] as $si)
|
||||
<div class="stat-item flex-1 py-3">
|
||||
<div class="stat-value">{{ $si['value'] }}</div>
|
||||
<div class="stat-label">
|
||||
<i class="fa-solid {{ $si['icon'] }} fa-fw mr-0.5"></i>{{ $si['label'] }}
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ═══════════════════════════════════════════════════════════
|
||||
MAIN CONTENT
|
||||
═══════════════════════════════════════════════════════════ --}}
|
||||
<div class="max-w-screen-xl mx-auto px-4 py-6">
|
||||
<div class="flex flex-col lg:flex-row gap-5">
|
||||
|
||||
{{-- ─── LEFT COLUMN (artworks) ─── --}}
|
||||
<div class="flex-1 min-w-0 space-y-5">
|
||||
|
||||
{{-- Featured Artworks --}}
|
||||
@if(isset($featuredArtworks) && $featuredArtworks->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-star text-yellow-400 fa-fw"></i>
|
||||
Featured Artworks
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
@php $feat = $featuredArtworks->first() @endphp
|
||||
{{-- Main featured --}}
|
||||
<a href="/art/{{ $feat->id }}/{{ \Illuminate\Support\Str::slug($feat->name) }}"
|
||||
class="flex-1 group block min-w-0">
|
||||
<div class="overflow-hidden rounded-lg bg-black">
|
||||
<img src="{{ $feat->thumb }}"
|
||||
alt="{{ e($feat->name) }}"
|
||||
class="w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
||||
style="aspect-ratio:4/3;">
|
||||
</div>
|
||||
<h4 class="mt-2 text-sm font-medium text-white truncate">{{ e($feat->name) }}</h4>
|
||||
@if($feat->label)
|
||||
<p class="text-xs text-[--sb-muted]">{{ e($feat->label) }}</p>
|
||||
@endif
|
||||
@if($feat->featured_at)
|
||||
<p class="text-xs text-[--sb-muted] mt-0.5">
|
||||
<i class="fa-solid fa-calendar fa-fw"></i>
|
||||
Featured {{ \Carbon\Carbon::parse($feat->featured_at)->format('d M, Y') }}
|
||||
</p>
|
||||
@endif
|
||||
</a>
|
||||
{{-- Side featured (2nd & 3rd) --}}
|
||||
@if($featuredArtworks->count() > 1)
|
||||
<div class="md:w-44 space-y-2">
|
||||
@foreach($featuredArtworks->slice(1) as $sideArt)
|
||||
<a href="/art/{{ $sideArt->id }}/{{ \Illuminate\Support\Str::slug($sideArt->name) }}"
|
||||
class="block group">
|
||||
<div class="overflow-hidden rounded-md bg-black">
|
||||
<img src="{{ $sideArt->thumb }}"
|
||||
alt="{{ e($sideArt->name) }}"
|
||||
class="w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
||||
style="aspect-ratio:16/9;">
|
||||
</div>
|
||||
<p class="text-xs text-[--sb-muted] mt-1 truncate">{{ e($sideArt->name) }}</p>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Newest Artworks --}}
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-images fa-fw text-[--sb-blue]"></i>
|
||||
Newest Artworks
|
||||
<a href="{{ !empty($user->username) ? route('profile.gallery', ['username' => strtolower((string) $user->username)]) : url('/gallery/'.$user->id.'/'.\Illuminate\Support\Str::slug($uname)) }}"
|
||||
class="ml-auto text-xs text-[--sb-blue] hover:underline normal-case tracking-normal font-normal">
|
||||
View Gallery <i class="fa-solid fa-arrow-right fa-fw"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
@if(isset($artworks) && !$artworks->isEmpty())
|
||||
<div class="gallery-grid grid grid-cols-2 gap-4"
|
||||
data-nova-gallery
|
||||
data-gallery-type="profile"
|
||||
data-gallery-grid
|
||||
data-profile-id="{{ $user->id }}">
|
||||
@foreach($artworks as $art)
|
||||
<x-artwork-card :art="$art" />
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="hidden" data-gallery-skeleton-template aria-hidden="true">
|
||||
<x-skeleton.artwork-card />
|
||||
</div>
|
||||
<div class="hidden mt-6" data-gallery-skeleton></div>
|
||||
@else
|
||||
<p class="text-[--sb-muted] text-sm text-center py-8">
|
||||
<i class="fa-solid fa-image fa-2x mb-3 block opacity-20"></i>
|
||||
No artworks yet.
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Favourites --}}
|
||||
@if(isset($favourites) && $favourites->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-heart fa-fw text-pink-400"></i>
|
||||
Favourites
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
@foreach($favourites as $fav)
|
||||
<x-artwork-card :art="$fav" />
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>{{-- end left --}}
|
||||
|
||||
{{-- ─── RIGHT SIDEBAR ─── --}}
|
||||
<div class="lg:w-80 xl:w-96 shrink-0 space-y-4">
|
||||
|
||||
{{-- Profile Info --}}
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-id-card fa-fw text-[--sb-blue]"></i>
|
||||
Profile
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<table class="profile-table w-full">
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td>{{ e($uname) }}</td>
|
||||
</tr>
|
||||
@if($displayName && $displayName !== $uname)
|
||||
<tr><td>Real Name</td><td>{{ e($displayName) }}</td></tr>
|
||||
@endif
|
||||
<tr>
|
||||
<td>Gender</td>
|
||||
<td>
|
||||
<i class="fa-solid {{ $gender['icon'] }} fa-fw {{ $gender['color'] }}"></i>
|
||||
{{ $gender['label'] }}
|
||||
</td>
|
||||
</tr>
|
||||
@if($birthdate)
|
||||
<tr><td>Birthday</td><td>{{ $birthdate }}</td></tr>
|
||||
@endif
|
||||
@if($countryName)
|
||||
<tr>
|
||||
<td>Country</td>
|
||||
<td class="flex items-center justify-end gap-1.5">
|
||||
@if($profile?->country_code)
|
||||
<img src="/gfx/flags/shiny/24/{{ rawurlencode($profile->country_code) }}.png"
|
||||
alt="{{ e($countryName) }}"
|
||||
class="w-4 h-auto rounded-sm"
|
||||
onerror="this.style.display='none'">
|
||||
@endif
|
||||
{{ e($countryName) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@if($website)
|
||||
<tr>
|
||||
<td>Website</td>
|
||||
<td>
|
||||
<a href="{{ e($website) }}" rel="nofollow noopener" target="_blank"
|
||||
class="text-[--sb-blue] hover:underline text-xs inline-flex items-center gap-1">
|
||||
<i class="fa-solid fa-link fa-fw"></i>
|
||||
{{ e(parse_url($website, PHP_URL_HOST) ?? $website) }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@if($lastVisit)
|
||||
<tr>
|
||||
<td>Last Activity</td>
|
||||
<td class="text-[11px]">
|
||||
{{ $lastVisit->format('d.M.Y') }}
|
||||
<i class="fa-solid fa-clock fa-fw ml-1 opacity-60"></i>
|
||||
{{ $lastVisit->format('H:i') }}
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
<tr>
|
||||
<td>Member since</td>
|
||||
<td>{{ $user->created_at ? $user->created_at->format('M Y') : 'N/A' }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- About Me --}}
|
||||
@if($about)
|
||||
<div class="nova-panel" x-data="{ expanded: false }">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-quote-left fa-fw text-purple-400"></i>
|
||||
About Me
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="text-sm text-[--sb-text] leading-relaxed"
|
||||
:class="expanded ? '' : 'line-clamp-6'">
|
||||
{!! nl2br(e($about)) !!}
|
||||
</div>
|
||||
@if(strlen($about) > 300)
|
||||
<button @click="expanded = !expanded"
|
||||
class="mt-2 text-xs text-[--sb-blue] hover:underline">
|
||||
<span x-text="expanded ? '↑ Show less' : '↓ Read more'"></span>
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Statistics --}}
|
||||
@if($stats)
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-chart-bar fa-fw text-green-400"></i>
|
||||
Statistics
|
||||
</div>
|
||||
<div class="nova-panel-body p-0">
|
||||
<table class="profile-table w-full">
|
||||
@foreach([
|
||||
['Profile Views', number_format($stats->profile_views_count ?? 0), null],
|
||||
['Uploads', number_format($stats->uploads_count ?? 0), null],
|
||||
['Downloads', number_format($stats->downloads_received_count ?? 0), null],
|
||||
['Page Views', number_format($stats->artwork_views_received_count ?? 0), null],
|
||||
['Featured Works',number_format($stats->awards_received_count ?? 0), 'fa-star text-yellow-400'],
|
||||
] as [$label, $value, $iconClass])
|
||||
<tr>
|
||||
<td class="pl-4">{{ $label }}</td>
|
||||
<td class="pr-4">
|
||||
{{ $value }}
|
||||
@if($iconClass)<i class="fa-solid {{ $iconClass }} text-xs ml-1"></i>@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Social Links --}}
|
||||
@if(isset($socialLinks) && $socialLinks->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-share-nodes fa-fw text-[--sb-blue]"></i>
|
||||
Social Links
|
||||
</div>
|
||||
<div class="nova-panel-body flex flex-wrap gap-2">
|
||||
@foreach($socialLinks as $platform => $link)
|
||||
@php
|
||||
$si = $socialIcons[$platform] ?? ['icon' => 'fa-solid fa-link', 'label' => ucfirst($platform)];
|
||||
$href = str_starts_with($link->url, 'http') ? $link->url : ('https://' . $link->url);
|
||||
@endphp
|
||||
<a href="{{ e($href) }}" rel="nofollow noopener" target="_blank"
|
||||
class="inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs border border-[--sb-line] text-[--sb-text] hover:bg-white/5 hover:border-[--sb-blue]/40 transition-all">
|
||||
<i class="{{ $si['icon'] }} fa-fw"></i>
|
||||
{{ $si['label'] }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Recent Followers --}}
|
||||
@if(isset($recentFollowers) && $recentFollowers->isNotEmpty())
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-users fa-fw text-[--sb-blue]"></i>
|
||||
Followers
|
||||
<span class="ml-1 px-1.5 py-0.5 rounded text-xs bg-white/5 text-[--sb-muted]">
|
||||
{{ number_format($followerCount) }}
|
||||
</span>
|
||||
<a href="/following/{{ $user->id }}/{{ \Illuminate\Support\Str::slug($uname) }}"
|
||||
class="ml-auto text-xs text-[--sb-blue] hover:underline normal-case tracking-normal font-normal">
|
||||
All
|
||||
</a>
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
@foreach($recentFollowers as $follower)
|
||||
<a href="{{ $follower->profile_url }}" title="{{ e($follower->uname) }}">
|
||||
<img src="{{ $follower->avatar_url }}"
|
||||
alt="{{ e($follower->uname) }}"
|
||||
class="follower-avatar"
|
||||
onerror="this.src='{{ \App\Support\AvatarUrl::default() }}'">
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@elseif($followerCount > 0)
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-users fa-fw text-[--sb-blue]"></i>
|
||||
Followers
|
||||
<span class="ml-1 px-1.5 py-0.5 rounded text-xs bg-white/5 text-[--sb-muted]">
|
||||
{{ number_format($followerCount) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Profile Comments --}}
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-comments fa-fw text-orange-400"></i>
|
||||
Comments
|
||||
@if(isset($profileComments) && $profileComments->isNotEmpty())
|
||||
<span class="ml-1 px-1.5 py-0.5 rounded text-xs bg-white/5 text-[--sb-muted]">
|
||||
{{ $profileComments->count() }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
@if(!isset($profileComments) || $profileComments->isEmpty())
|
||||
<p class="text-[--sb-muted] text-xs text-center py-3">No comments yet.</p>
|
||||
@else
|
||||
<div class="space-y-4">
|
||||
@foreach($profileComments as $comment)
|
||||
<div class="flex gap-3">
|
||||
<a href="{{ $comment->author_profile_url }}" class="shrink-0">
|
||||
<img src="{{ $comment->author_avatar }}"
|
||||
alt="{{ e($comment->author_name) }}"
|
||||
class="comment-avatar"
|
||||
onerror="this.src='{{ \App\Support\AvatarUrl::default() }}'">
|
||||
</a>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<a href="{{ $comment->author_profile_url }}"
|
||||
class="text-xs font-semibold text-[--sb-text] hover:text-[--sb-blue] transition-colors">
|
||||
{{ e($comment->author_name) }}
|
||||
</a>
|
||||
<span class="text-[--sb-muted] text-[10px] ml-auto whitespace-nowrap">
|
||||
{{ \Carbon\Carbon::parse($comment->created_at)->diffForHumans() }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-xs text-[--sb-text] leading-relaxed break-words">
|
||||
{!! nl2br(e($comment->body)) !!}
|
||||
</p>
|
||||
@if(!empty($comment->author_signature))
|
||||
<p class="text-[--sb-muted] text-[10px] mt-1 italic border-t border-[--sb-line] pt-1 opacity-70">
|
||||
{!! nl2br(e($comment->author_signature)) !!}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Write Comment --}}
|
||||
@auth
|
||||
@if(auth()->id() !== $user->id)
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-header">
|
||||
<i class="fa-solid fa-pen fa-fw text-[--sb-blue]"></i>
|
||||
Write a Comment
|
||||
</div>
|
||||
<div class="nova-panel-body">
|
||||
@if(session('status') === 'Comment posted!')
|
||||
<div class="mb-3 px-3 py-2 rounded-lg bg-green-500/10 border border-green-500/30 text-green-400 text-xs">
|
||||
<i class="fa-solid fa-check fa-fw"></i> Comment posted!
|
||||
</div>
|
||||
@endif
|
||||
<form method="POST"
|
||||
action="{{ route('profile.comment', ['username' => strtolower((string)$uname)]) }}">
|
||||
@csrf
|
||||
<textarea name="body" rows="4" required minlength="2" maxlength="2000"
|
||||
placeholder="Write a comment for {{ e($uname) }}..."
|
||||
class="w-full bg-[--sb-bg] border border-[--sb-line] rounded-lg px-3 py-2 text-sm text-[--sb-text] placeholder:text-[--sb-muted]/60 resize-none focus:outline-none focus:border-[--sb-blue]/50 transition-colors"
|
||||
>{{ old('body') }}</textarea>
|
||||
@error('body')
|
||||
<p class="mt-1 text-xs text-red-400">{{ $message }}</p>
|
||||
@enderror
|
||||
<div class="mt-2 text-right">
|
||||
<button type="submit"
|
||||
class="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium bg-[--sb-blue]/90 hover:bg-[--sb-blue] text-white transition-colors">
|
||||
<i class="fa-solid fa-paper-plane fa-fw"></i>
|
||||
Post Comment
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="nova-panel">
|
||||
<div class="nova-panel-body text-center py-4">
|
||||
<p class="text-[--sb-muted] text-sm">
|
||||
<a href="{{ route('login') }}" class="text-[--sb-blue] hover:underline">Log in</a>
|
||||
to leave a comment.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endauth
|
||||
|
||||
</div>{{-- end right sidebar --}}
|
||||
|
||||
</div>{{-- end flex --}}
|
||||
</div>{{-- end container --}}
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
@endpush
|
||||
@@ -0,0 +1,63 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Received Comments</h1>
|
||||
<p>List of comments left on your uploaded artworks.</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="masonry">
|
||||
@foreach($comments as $comment)
|
||||
@php
|
||||
$author = $comment->user;
|
||||
$art = $comment->artwork;
|
||||
$created = optional($comment->created_at);
|
||||
@endphp
|
||||
|
||||
<div class="masonry_item col-sm-6 col-md-4">
|
||||
<div class="comment_box effect3">
|
||||
<div class="cb_image">
|
||||
<a href="/profile/{{ (int)($author->id ?? $author->user_id) }}/{{ rawurlencode($author->name ?? $author->uname ?? '') }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) ($author->id ?? $author->user_id), null, 50) }}" width="50" height="50" class="comment_avatar" alt="{{ $author->name ?? $author->uname ?? '' }}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="bubble_comment panel panel-skinbase">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">{{ $created ? $created->diffForHumans() . ' ago' : '' }}</div>
|
||||
<h5 class="panel-title">Comment by: <a href="/profile/{{ (int)($author->id ?? $author->user_id) }}/{{ rawurlencode($author->name ?? $author->uname ?? '') }}">{{ $author->name ?? $author->uname ?? '' }}</a></h5>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="comment_box_image">
|
||||
@if($art)
|
||||
<a href="/art/{{ $art->id }}/{{ Str::slug($art->name ?? '') }}">
|
||||
<img src="{{ $art->thumb }}" class="img-thumbnail img-responsive" alt="{{ $art->name }}">
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="comment_text">{!! nl2br(e($comment->content ?? $comment->description ?? '')) !!}</div>
|
||||
|
||||
@if(!empty($author->signature))
|
||||
<div class="panel-footer comment-footer">
|
||||
<p>{!! nl2br(e($author->signature)) !!}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@if($comments->hasPages())
|
||||
<div class="paginationMenu">
|
||||
{{ $comments->links() }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,82 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container legacy-page">
|
||||
<div class="page-header-wrap">
|
||||
<div class="clearfix">
|
||||
<h1 class="page-header" style="margin:0;display:inline-block">Artwork Statistics</h1>
|
||||
<span class="text-muted pull-right" style="margin-top:10px">
|
||||
Uploaded: {{ method_exists($artworks, 'total') ? $artworks->total() : $artworks->count() }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted" style="margin-top:6px;font-size:12px">Sort your uploads by popularity, downloads, comments, and date.</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default uploads-panel">
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-striped table-hover" style="margin-bottom:0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:90px" class="text-center">Thumbnail</th>
|
||||
<th>
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'name']) }}">Name</a>
|
||||
</th>
|
||||
<th style="width:110px" class="text-center">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'dls']) }}">Downloads</a>
|
||||
</th>
|
||||
<th style="width:95px" class="text-center">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'comments']) }}">Reviews</a>
|
||||
</th>
|
||||
<th style="width:180px">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'category']) }}">Section</a>
|
||||
</th>
|
||||
<th style="width:130px" class="text-center">
|
||||
<a href="{{ request()->fullUrlWithQuery(['sort' => 'date']) }}">Date</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($artworks as $art)
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<a href="/art/{{ (int) $art->id }}" title="View">
|
||||
<img
|
||||
src="{{ $art->thumb_url ?? 'https://files.skinbase.org/default/missing_md.webp' }}"
|
||||
@if(!empty($art->thumb_srcset)) srcset="{{ $art->thumb_srcset }}" @endif
|
||||
sizes="70px"
|
||||
alt="{{ $art->name ?? '' }}"
|
||||
class="img-thumbnail"
|
||||
style="width:70px;height:70px;object-fit:cover"
|
||||
>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/art/{{ (int) $art->id }}">{{ $art->name ?? '' }}</a>
|
||||
<div class="text-muted" style="font-size:12px">#{{ (int) $art->id }}</div>
|
||||
</td>
|
||||
<td class="text-center">{{ (int) ($art->dls ?? 0) }}</td>
|
||||
<td class="text-center">{{ (int) ($art->num_comments ?? 0) }}</td>
|
||||
<td>{{ $art->category_name ?? '' }}</td>
|
||||
<td class="text-center">
|
||||
@if(!empty($art->datum))
|
||||
{{ is_string($art->datum) ? date('d.m.Y', strtotime($art->datum)) : '' }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6">No artworks found.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="paginationMenu text-center">
|
||||
{{ $artworks->links('pagination::bootstrap-3') }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,79 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title ?? 'Today in History', 'url' => route('legacy.today_in_history')],
|
||||
]);
|
||||
|
||||
$galleryArtworks = collect(method_exists($artworks, 'items') ? $artworks->items() : [])->map(fn ($art) => [
|
||||
'id' => $art->id ?? null,
|
||||
'name' => $art->name ?? null,
|
||||
'slug' => $art->slug ?? null,
|
||||
'url' => $art->url ?? $art->art_url ?? null,
|
||||
'thumb' => $art->thumb_url ?? null,
|
||||
'thumb_url' => $art->thumb_url ?? null,
|
||||
'thumb_srcset' => $art->thumb_srcset ?? null,
|
||||
'uname' => $art->uname ?? '',
|
||||
'username' => $art->username ?? $art->uname ?? '',
|
||||
'avatar_url' => $art->avatar_url ?? null,
|
||||
'content_type_name' => $art->content_type_name ?? '',
|
||||
'content_type_slug' => $art->content_type_slug ?? '',
|
||||
'category_name' => $art->category_name ?? '',
|
||||
'category_slug' => $art->category_slug ?? '',
|
||||
'width' => $art->width ?? null,
|
||||
'height' => $art->height ?? null,
|
||||
])->values();
|
||||
|
||||
$galleryNextPageUrl = method_exists($artworks, 'nextPageUrl') ? $artworks->nextPageUrl() : null;
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<x-nova-page-header
|
||||
section="History"
|
||||
:title="$page_title ?? 'Today in History'"
|
||||
icon="fa-calendar-days"
|
||||
:breadcrumbs="$headerBreadcrumbs"
|
||||
:description="'Featured artworks uploaded on <span class="text-white/80 font-medium">' . e($todayLabel ?? now()->format('F j')) . '</span> in past years.'"
|
||||
headerClass="pb-6"
|
||||
/>
|
||||
|
||||
<section class="px-6 pt-8 md:px-10">
|
||||
@if ($artworks && $artworks->count())
|
||||
<div
|
||||
data-react-masonry-gallery
|
||||
data-artworks="{{ json_encode($galleryArtworks) }}"
|
||||
data-gallery-type="today-in-history"
|
||||
@if ($galleryNextPageUrl) data-next-page-url="{{ $galleryNextPageUrl }}" @endif
|
||||
data-limit="36"
|
||||
class="min-h-32"
|
||||
></div>
|
||||
@else
|
||||
<div class="rounded-xl border border-white/[0.06] bg-white/[0.02] px-8 py-12 text-center">
|
||||
<p class="text-white/40 text-sm">No featured artworks were found for {{ $todayLabel ?? now()->format('F j') }}.</p>
|
||||
<p class="text-white/25 text-xs mt-1">When historical features exist for this date, they will appear here.</p>
|
||||
</div>
|
||||
@endif
|
||||
</section>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
[data-nova-gallery] [data-gallery-grid] { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||
[data-nova-gallery].is-enhanced [data-gallery-grid] { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
[data-nova-gallery] [data-gallery-grid] { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
[data-nova-gallery].is-enhanced [data-gallery-grid] { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (min-width: 2600px) {
|
||||
[data-nova-gallery] [data-gallery-grid] { grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
||||
[data-nova-gallery].is-enhanced [data-gallery-grid] { grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
@vite('resources/js/entry-masonry-gallery.jsx')
|
||||
@endpush
|
||||
@@ -0,0 +1,117 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid legacy-page">
|
||||
<div class="effect2 page-header-wrap">
|
||||
<header class="page-heading">
|
||||
<h1 class="page-header">Top Members</h1>
|
||||
<p>Statistics of popular and active members at Skinbase</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>Most Active Members</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">Username</th>
|
||||
<th class="text-right">Uploads</th>
|
||||
<th class="text-right">Total Downloads</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topUsers as $u)
|
||||
<tr>
|
||||
<td width="80">
|
||||
<a href="/profile/{{ $u->user_id }}/{{ \Illuminate\Support\Str::slug($u->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $u->user_id, null, 32) }}" width="30" height="30" alt="{{ $u->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ $u->user_id }}/{{ \Illuminate\Support\Str::slug($u->uname) }}">{{ $u->uname }}</a>
|
||||
</td>
|
||||
<td class="text-right">{{ $u->uploads }}</td>
|
||||
<td class="text-right">{{ $u->total_downloads }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>Most Followed Members</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Thumb</th>
|
||||
<th>Name</th>
|
||||
<th>Followers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topFollowers as $f)
|
||||
<tr>
|
||||
<td width="60" align="center">
|
||||
<a href="/profile/{{ $f->user_id }}/{{ \Illuminate\Support\Str::slug($f->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $f->user_id, null, 32) }}" width="30" alt="{{ $f->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ $f->user_id }}/{{ \Illuminate\Support\Str::slug($f->uname) }}">{{ $f->uname }}</a>
|
||||
</td>
|
||||
<td align="center">{{ $f->num }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default effect2">
|
||||
<div class="panel-heading"><strong>Top Commentators</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Thumb</th>
|
||||
<th>Name</th>
|
||||
<th>Level</th>
|
||||
<th>Country</th>
|
||||
<th>Comments</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($topCommentators as $c)
|
||||
<tr>
|
||||
<td width="50" align="center">
|
||||
<a href="/profile/{{ $c->user_id }}/{{ \Illuminate\Support\Str::slug($c->uname) }}">
|
||||
<img src="{{ \App\Support\AvatarUrl::forUser((int) $c->user_id, null, 32) }}" width="30" alt="{{ $c->uname }}">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/profile/{{ $c->user_id }}/{{ \Illuminate\Support\Str::slug($c->uname) }}">{{ $c->uname }}</a>
|
||||
</td>
|
||||
<td width="100" align="center"><img src="/gfx/member_stars/{{ $c->user_type }}.gif" alt="level"></td>
|
||||
<td width="100" align="center">
|
||||
@if(!empty($c->country_flag))
|
||||
<img width="20" src="/gfx/flags/{{ rawurlencode($c->country_flag) }}" title="{{ $c->country_name }}">
|
||||
@endif
|
||||
</td>
|
||||
<td width="100" align="center">{{ $c->num_comments }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,79 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title, 'url' => route('legacy.top_favourites')],
|
||||
]);
|
||||
|
||||
$galleryArtworks = collect(method_exists($artworks, 'items') ? $artworks->items() : [])->map(fn ($art) => [
|
||||
'id' => $art->id ?? null,
|
||||
'name' => $art->name ?? null,
|
||||
'slug' => $art->slug ?? null,
|
||||
'url' => $art->url ?? null,
|
||||
'thumb' => $art->thumb_url ?? $art->thumb ?? null,
|
||||
'thumb_url' => $art->thumb_url ?? $art->thumb ?? null,
|
||||
'thumb_srcset' => $art->thumb_srcset ?? null,
|
||||
'uname' => $art->uname ?? '',
|
||||
'username' => $art->username ?? $art->uname ?? '',
|
||||
'avatar_url' => $art->avatar_url ?? null,
|
||||
'content_type_name' => $art->content_type_name ?? '',
|
||||
'content_type_slug' => $art->content_type_slug ?? '',
|
||||
'category_name' => $art->category_name ?? '',
|
||||
'category_slug' => $art->category_slug ?? '',
|
||||
'width' => $art->width ?? null,
|
||||
'height' => $art->height ?? null,
|
||||
'favourites' => (int) ($art->favourites ?? $art->num ?? 0),
|
||||
])->values();
|
||||
|
||||
$galleryNextPageUrl = method_exists($artworks, 'nextPageUrl') ? $artworks->nextPageUrl() : null;
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
<x-nova-page-header
|
||||
section="Favourites"
|
||||
:title="$page_title"
|
||||
icon="fa-heart"
|
||||
:breadcrumbs="$headerBreadcrumbs"
|
||||
description="Most popular artworks which users added in their favourites."
|
||||
headerClass="pb-6"
|
||||
/>
|
||||
|
||||
<section class="px-6 pt-8 md:px-10">
|
||||
@if ($artworks && $artworks->count())
|
||||
<div
|
||||
data-react-masonry-gallery
|
||||
data-artworks="{{ json_encode($galleryArtworks) }}"
|
||||
data-gallery-type="top-favourites"
|
||||
@if ($galleryNextPageUrl) data-next-page-url="{{ $galleryNextPageUrl }}" @endif
|
||||
data-limit="21"
|
||||
class="min-h-32"
|
||||
></div>
|
||||
@else
|
||||
<div class="rounded-xl border border-white/[0.06] bg-white/[0.02] px-8 py-12 text-center">
|
||||
<p class="text-white/40 text-sm">No artworks have been favourited yet.</p>
|
||||
<p class="text-white/25 text-xs mt-1">Once members start saving artworks, they will appear here.</p>
|
||||
</div>
|
||||
@endif
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
[data-nova-gallery] [data-gallery-grid] { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||
[data-nova-gallery].is-enhanced [data-gallery-grid] { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
[data-nova-gallery] [data-gallery-grid] { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
[data-nova-gallery].is-enhanced [data-gallery-grid] { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (min-width: 2600px) {
|
||||
[data-nova-gallery] [data-gallery-grid] { grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
||||
[data-nova-gallery].is-enhanced [data-gallery-grid] { grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
@vite('resources/js/entry-masonry-gallery.jsx')
|
||||
@endpush
|
||||
@@ -0,0 +1,368 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
|
||||
@php
|
||||
$birthDay = $birthDay ?? null;
|
||||
$birthMonth = $birthMonth ?? null;
|
||||
$birthYear = $birthYear ?? null;
|
||||
$avatarUserId = (int) ($user->id ?? auth()->id() ?? 0);
|
||||
$avatarHash = $user->icon
|
||||
?? optional(auth()->user())->profile->avatar_hash
|
||||
?? null;
|
||||
$currentAvatarUrl = !empty($avatarHash)
|
||||
? \App\Support\AvatarUrl::forUser($avatarUserId, $avatarHash, 128)
|
||||
: \App\Support\AvatarUrl::default();
|
||||
@endphp
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
.edit-profile-hero { position: relative; overflow: hidden; }
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
{{-- ── Hero background ──────────────────────────────────────────────── --}}
|
||||
<div class="edit-profile-hero border-b border-[--sb-line]"
|
||||
@if(!empty($heroBgUrl))
|
||||
style="background: url('{{ $heroBgUrl }}') center/cover no-repeat;"
|
||||
@else
|
||||
style="background: linear-gradient(135deg, rgba(15,23,36,1) 0%, rgba(21,30,46,1) 50%, rgba(9,16,26,1) 100%);"
|
||||
@endif
|
||||
>
|
||||
@if(!empty($heroBgUrl))
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-[#0f1724]/95 via-[#0f1724]/80 to-[#0f1724]/50"></div>
|
||||
@endif
|
||||
<div class="relative z-10 max-w-5xl mx-auto px-4 py-10 flex items-end gap-5">
|
||||
<img src="{{ $currentAvatarUrl }}"
|
||||
alt="Your avatar"
|
||||
class="w-20 h-20 rounded-full object-cover border-4 border-[--sb-line] shadow-lg shrink-0">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-white">Edit Profile</h1>
|
||||
<p class="text-sm text-[--sb-muted] mt-1">Manage your account settings</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="min-h-screen text-white py-12">
|
||||
|
||||
<!-- Container -->
|
||||
<div class="max-w-5xl mx-auto px-4">
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="mb-4 rounded-lg bg-red-700/10 border border-red-700/20 p-3 text-sm text-red-300">
|
||||
<div class="font-semibold mb-2">Please fix the following errors:</div>
|
||||
<ul class="list-disc pl-5 space-y-1">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!-- ================= Profile Card ================= -->
|
||||
<div class="bg-nova-800 rounded-xl shadow-lg p-8 mb-10">
|
||||
|
||||
<form method="POST" action="{{ route('profile.update') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
|
||||
<!-- LEFT COLUMN -->
|
||||
<div class="space-y-5">
|
||||
|
||||
<!-- Email -->
|
||||
<div>
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" name="email"
|
||||
class="form-input"
|
||||
value="{{ old('email', auth()->user()->email) }}">
|
||||
</div>
|
||||
|
||||
<!-- Username -->
|
||||
<div>
|
||||
<label class="form-label">Username</label>
|
||||
<input type="text" name="username"
|
||||
class="form-input"
|
||||
value="{{ old('username', auth()->user()->username) }}"
|
||||
readonly>
|
||||
</div>
|
||||
|
||||
<!-- Real Name -->
|
||||
<div>
|
||||
<label class="form-label">Real Name</label>
|
||||
<input type="text" name="name"
|
||||
class="form-input"
|
||||
value="{{ old('name', auth()->user()->name) }}">
|
||||
</div>
|
||||
|
||||
<!-- Homepage -->
|
||||
<div>
|
||||
<label class="form-label">Homepage</label>
|
||||
<input type="url" name="homepage"
|
||||
class="form-input"
|
||||
placeholder="https://"
|
||||
value="{{ old('homepage', auth()->user()->homepage ?? auth()->user()->website ?? '') }}">
|
||||
</div>
|
||||
|
||||
<!-- Birthday -->
|
||||
<div>
|
||||
<label class="form-label">Birthday</label>
|
||||
|
||||
<div class="grid grid-cols-3 gap-3">
|
||||
@php
|
||||
$currentYear = date('Y');
|
||||
$startYear = $currentYear - 100;
|
||||
$months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
||||
@endphp
|
||||
|
||||
<select name="day" class="form-input" aria-label="Day">
|
||||
<option value="">Day</option>
|
||||
@for($d = 1; $d <= 31; $d++)
|
||||
<option value="{{ $d }}" @if(intval(old('day', $birthDay)) == $d) selected @endif>{{ $d }}</option>
|
||||
@endfor
|
||||
</select>
|
||||
|
||||
<select name="month" class="form-input" aria-label="Month">
|
||||
<option value="">Month</option>
|
||||
@foreach($months as $idx => $m)
|
||||
@php $val = $idx + 1; @endphp
|
||||
<option value="{{ $val }}" @if(intval(old('month', $birthMonth)) == $val) selected @endif>{{ $m }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<select name="year" class="form-input" aria-label="Year">
|
||||
<option value="">Year</option>
|
||||
@for($y = $currentYear; $y >= $startYear; $y--)
|
||||
<option value="{{ $y }}" @if(intval(old('year', $birthYear)) == $y) selected @endif>{{ $y }}</option>
|
||||
@endfor
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gender -->
|
||||
<div>
|
||||
<label class="form-label">Gender</label>
|
||||
|
||||
<div class="flex gap-6 mt-2 text-soft">
|
||||
<label><input type="radio" name="gender" value="m" @if(old('gender', strtolower(auth()->user()->gender ?? '')) == 'm') checked @endif> Male</label>
|
||||
<label><input type="radio" name="gender" value="f" @if(old('gender', strtolower(auth()->user()->gender ?? '')) == 'f') checked @endif> Female</label>
|
||||
<label><input type="radio" name="gender" value="x" @if(old('gender', strtolower(auth()->user()->gender ?? '')) == 'x') checked @endif> N/A</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Country -->
|
||||
<div>
|
||||
<label class="form-label">Country</label>
|
||||
<input type="text" name="country"
|
||||
class="form-input"
|
||||
value="{{ old('country', auth()->user()->country ?? auth()->user()->country_code ?? '') }}">
|
||||
</div>
|
||||
|
||||
<!-- Preferences -->
|
||||
<div class="flex gap-6 text-soft">
|
||||
<label>
|
||||
<input type="checkbox" name="mailing" @if(old('mailing', auth()->user()->mlist ?? false)) checked @endif>
|
||||
Mailing List
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" name="notify" @if(old('notify', auth()->user()->friend_upload_notice ?? false)) checked @endif>
|
||||
Upload Notifications
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- RIGHT COLUMN -->
|
||||
<div class="space-y-5">
|
||||
|
||||
<!-- Avatar -->
|
||||
<div>
|
||||
<label class="form-label">Avatar</label>
|
||||
<div class="rounded-xl border border-sb-line bg-black/10 p-4">
|
||||
<div class="flex items-center gap-4">
|
||||
<img
|
||||
id="avatarPreviewImage"
|
||||
src="{{ $currentAvatarUrl }}"
|
||||
alt="{{ $user->name ?? $user->username ?? 'Avatar' }}"
|
||||
class="w-24 h-24 rounded-full object-cover ring-1 ring-white/10"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
>
|
||||
<div class="min-w-0 flex-1">
|
||||
<button
|
||||
type="button"
|
||||
id="avatarDropzone"
|
||||
class="w-full rounded-lg border border-dashed border-sb-line px-4 py-4 text-left hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-sb-blue/50"
|
||||
>
|
||||
<div class="text-sm text-white/90">Drag & drop a new avatar here</div>
|
||||
<div class="text-xs text-soft mt-1">or click to browse (JPG, PNG, WEBP)</div>
|
||||
<div id="avatarFileName" class="text-xs text-sb-muted mt-2 truncate">No file selected</div>
|
||||
</button>
|
||||
<input id="avatarInput" type="file" name="avatar" class="sr-only" accept="image/jpeg,image/png,image/webp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Emoticon -->
|
||||
<div>
|
||||
<label class="form-label">Emoticon</label>
|
||||
<input type="file" name="emoticon" class="form-file">
|
||||
</div>
|
||||
|
||||
<!-- Personal Picture -->
|
||||
<div>
|
||||
<label class="form-label">Personal Picture</label>
|
||||
<input type="file" name="photo" class="form-file">
|
||||
</div>
|
||||
|
||||
<!-- About -->
|
||||
<div>
|
||||
<label class="form-label">About Me</label>
|
||||
<textarea name="about" rows="4"
|
||||
class="form-textarea">{{ old('about', auth()->user()->about ?? auth()->user()->about_me ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<!-- Signature -->
|
||||
<div>
|
||||
<label class="form-label">Signature</label>
|
||||
<textarea name="signature" rows="3"
|
||||
class="form-textarea">{{ old('signature', auth()->user()->signature ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div>
|
||||
<label class="form-label">Description</label>
|
||||
<textarea name="description" rows="4"
|
||||
class="form-textarea">{{ old('description', auth()->user()->description ?? '') }}</textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Save Button -->
|
||||
<div class="mt-8 text-right">
|
||||
<button type="submit"
|
||||
class="btn-primary">
|
||||
Update Profile
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ================= PASSWORD CARD ================= -->
|
||||
<div class="bg-nova-800 rounded-xl shadow-lg p-8">
|
||||
|
||||
<h2 class="text-xl font-semibold mb-6">
|
||||
Change Password
|
||||
</h2>
|
||||
|
||||
<form method="POST" action="{{ route('profile.password') }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="space-y-5 max-w-md">
|
||||
|
||||
<div>
|
||||
<label class="form-label">Current Password</label>
|
||||
<input type="password" name="current_password"
|
||||
class="form-input">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="form-label">New Password</label>
|
||||
<input type="password" name="password"
|
||||
class="form-input">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="form-label">Repeat Password</label>
|
||||
<input type="password" name="password_confirmation"
|
||||
class="form-input">
|
||||
</div>
|
||||
|
||||
<button class="btn-secondary">
|
||||
Change Password
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
(() => {
|
||||
const input = document.getElementById('avatarInput');
|
||||
const dropzone = document.getElementById('avatarDropzone');
|
||||
const preview = document.getElementById('avatarPreviewImage');
|
||||
const fileName = document.getElementById('avatarFileName');
|
||||
if (!input || !dropzone || !preview || !fileName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatePreview = (file) => {
|
||||
if (!file || !file.type || !file.type.startsWith('image/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
preview.src = objectUrl;
|
||||
fileName.textContent = file.name;
|
||||
preview.onload = () => URL.revokeObjectURL(objectUrl);
|
||||
};
|
||||
|
||||
dropzone.addEventListener('click', () => input.click());
|
||||
|
||||
input.addEventListener('change', () => {
|
||||
const file = input.files && input.files[0] ? input.files[0] : null;
|
||||
if (file) {
|
||||
updatePreview(file);
|
||||
}
|
||||
});
|
||||
|
||||
['dragenter', 'dragover'].forEach((eventName) => {
|
||||
dropzone.addEventListener(eventName, (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
dropzone.classList.add('ring-2', 'ring-sb-blue/50');
|
||||
});
|
||||
});
|
||||
|
||||
['dragleave', 'drop'].forEach((eventName) => {
|
||||
dropzone.addEventListener(eventName, (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
dropzone.classList.remove('ring-2', 'ring-sb-blue/50');
|
||||
});
|
||||
});
|
||||
|
||||
dropzone.addEventListener('drop', (event) => {
|
||||
const file = event.dataTransfer && event.dataTransfer.files ? event.dataTransfer.files[0] : null;
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dt = new DataTransfer();
|
||||
dt.items.add(file);
|
||||
input.files = dt.files;
|
||||
updatePreview(file);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user