Files
rootandClaude Sonnet 5 7769d2038a Add favorite toggle to yoga poses
Exercises and workouts both have a favorite toggle; yoga poses had an
otherwise identical browse/filter UX but no way to favorite them - an
inconsistency rather than a deliberate omission. Mirrors the existing
exercise/workout favorite pattern exactly: a pivot table, a
belongsToMany on User, and a toggle button on the pose detail page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 12:04:50 +03:00

141 lines
9.7 KiB
PHP

<x-app-layout>
<section class="relative overflow-hidden">
<div class="absolute inset-0">
@php $img = $pose->url_png ?: $pose->url_svg ?: $pose->url_svg_alt; @endphp
@if($img)
<img src="{{ $img }}" alt="{{ $pose->english_name }}" class="h-full w-full object-contain bg-white">
@else
<div class="h-full w-full bg-gray-100 dark:bg-gray-800"></div>
@endif
<div class="absolute inset-0 bg-gradient-to-b from-indigo-900/40 via-indigo-800/30 to-transparent"></div>
</div>
<div class="relative mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12 sm:py-20">
<a href="{{ url()->previous() ?? route('yoga.index') }}" class="inline-flex items-center text-sm font-medium text-white/90 hover:text-white">&#8592; {{ __('app.yoga.back') }}</a>
<div class="mt-3 flex items-start justify-between gap-4">
<h1 class="text-3xl sm:text-5xl font-extrabold tracking-tight text-white drop-shadow">{{ $pose->english_name }}</h1>
@auth
@php $isFav = auth()->user()->hasFavoritedYogaPose($pose); @endphp
<form method="POST" action="{{ route('yoga.favorite', $pose) }}">
@csrf
<button type="submit" class="inline-flex items-center gap-2 rounded-full bg-white/90 px-3 py-1.5 text-sm font-semibold text-gray-900 shadow hover:bg-white">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="h-5 w-5 {{ $isFav ? 'text-rose-600' : 'text-gray-400' }}">
@if($isFav)
<path d="M11.645 20.91l-.007-.003-.022-.01a15.247 15.247 0 01-.383-.18 25.18 25.18 0 01-4.244-2.686C4.688 15.734 2.25 13.153 2.25 9.75 2.25 7.005 4.46 4.875 7.125 4.875c1.6 0 3.09.744 4.125 1.917a5.625 5.625 0 014.125-1.917c2.665 0 4.875 2.13 4.875 4.875 0 3.403-2.438 5.984-4.739 7.58a25.175 25.175 0 01-4.244 2.685 15.247 15.247 0 01-.383.18l-.022.01-.007.004-.003.001a.75.75 0 01-.592 0l-.003-.001z"/>
@else
<path fill-rule="evenodd" d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 6.01 4.01 4 6.5 4c1.74 0 3.41.81 4.5 2.09A6.004 6.004 0 0115.5 4C17.99 4 20 6.01 20 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" clip-rule="evenodd"/>
@endif
</svg>
<span>{{ $isFav ? 'Favorited' : 'Favorite' }}</span>
</button>
</form>
@endauth
</div>
<div class="mt-4 flex flex-wrap items-center gap-2">
@if($pose->category)
<span class="inline-flex items-center rounded-full bg-white/90 px-3 py-1 text-xs font-semibold text-gray-900 shadow">{{ $pose->category->name }}</span>
@endif
@if($pose->sanskrit_name)
<span class="inline-flex items-center rounded-full bg-emerald-100 text-emerald-700 px-2.5 py-1 text-xs font-semibold">Sanskrit: {{ $pose->sanskrit_name }}</span>
@endif
@if($pose->sanskrit_name_adapted)
<span class="inline-flex items-center rounded-full bg-sky-100 text-sky-700 px-2.5 py-1 text-xs font-semibold">{{ $pose->sanskrit_name_adapted }}</span>
@endif
</div>
</div>
</section>
<section class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-10">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8">
<div class="lg:col-span-8">
<div class="rounded-3xl overflow-hidden ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-6">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">{{ __('app.yoga.description') }}</h2>
<div class="prose prose-indigo dark:prose-invert max-w-none mt-3">
@php $desc = trim((string) $pose->description); @endphp
@if($desc !== '')
@foreach(preg_split('/\r?\n+/', $desc) as $line)
@if(trim($line) !== '')<p>{{ $line }}</p>@endif
@endforeach
@else
<p>{{ __('app.yoga.no_description') }}</p>
@endif
</div>
</div>
<div class="mt-6 rounded-3xl overflow-hidden ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-6">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">{{ __('app.yoga.benefits') }}</h2>
<div class="prose prose-indigo dark:prose-invert max-w-none mt-3">
@php $benef = trim((string) $pose->benefits); @endphp
@if($benef !== '')
@foreach(preg_split('/\r?\n+/', $benef) as $line)
@if(trim($line) !== '')<p>{{ $line }}</p>@endif
@endforeach
@else
<p>{{ __('app.yoga.no_benefits') }}</p>
@endif
</div>
</div>
</div>
<div class="lg:col-span-4">
<div class="rounded-2xl p-5 ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800">
<h3 class="text-sm font-semibold text-gray-900 dark:text-white">{{ __('app.yoga.pose_info') }}</h3>
<dl class="mt-3 space-y-2 text-sm text-gray-700 dark:text-gray-300">
@if($pose->translation_name)
<div class="flex justify-between"><dt>{{ __('app.yoga.translation') }}</dt><dd class="text-right ms-3">{{ $pose->translation_name }}</dd></div>
@endif
@if($pose->sanskrit_name)
<div class="flex justify-between"><dt>{{ __('app.yoga.sanskrit') }}</dt><dd class="text-right ms-3">{{ $pose->sanskrit_name }}</dd></div>
@endif
@if($pose->sanskrit_name_adapted)
<div class="flex justify-between"><dt>{{ __('app.yoga.sanskrit_adapted') }}</dt><dd class="text-right ms-3">{{ $pose->sanskrit_name_adapted }}</dd></div>
@endif
@if($pose->category)
<div class="flex justify-between"><dt>{{ __('app.yoga.category') }}</dt><dd class="text-right ms-3">{{ $pose->category->name }}</dd></div>
@endif
</dl>
<div class="mt-5">
<a href="{{ route('yoga.index') }}" class="inline-flex items-center rounded-xl bg-gradient-to-r from-fuchsia-600 to-indigo-600 px-4 py-2 text-sm font-semibold text-white shadow hover:from-fuchsia-500 hover:to-indigo-500">{{ __('app.yoga.browse_all') }}</a>
</div>
</div>
</div>
</div>
</section>
@isset($similarPoses)
<section class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 pb-12">
<div class="mt-8">
<div class="flex items-end justify-between gap-4 mb-4">
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">{{ __('app.yoga.similar') }}</h2>
<a href="{{ route('yoga.index') }}" class="text-sm font-semibold text-indigo-600 hover:text-indigo-500">{{ __('app.yoga.browse_all') }}</a>
</div>
@if($similarPoses->isEmpty())
<div class="rounded-2xl border border-dashed border-gray-300 dark:border-gray-700 p-6 text-center text-gray-600 dark:text-gray-300">{{ __('app.yoga.similar_none') }}</div>
@else
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
@foreach($similarPoses as $p)
<a href="{{ route('yoga.show', $p->slug) }}" class="group rounded-3xl overflow-hidden bg-white dark:bg-gray-800 ring-1 ring-gray-200 dark:ring-gray-700 shadow-sm hover:shadow-xl transition">
<div class="relative aspect-[16/9] overflow-hidden bg-white">
@php $img = $p->url_png ?: $p->url_svg ?: $p->url_svg_alt; @endphp
@if($img)
<img src="{{ $img }}" alt="{{ $p->english_name }}" class="h-full w-full object-contain transition-transform duration-500 group-hover:scale-105">
@else
<div class="h-full w-full flex items-center justify-center text-sm text-gray-500">{{ __('app.yoga.no_image') }}</div>
@endif
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
<div class="absolute bottom-3 left-3 inline-flex items-center rounded-full bg-white/90 px-3 py-1 text-xs font-semibold text-gray-900 shadow">{{ $p->english_name }}</div>
</div>
<div class="p-4">
<div class="mt-1 flex flex-wrap gap-2">
@if($p->category)
<span class="inline-flex items-center rounded-full px-2.5 py-1 text-xs font-medium bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-200">{{ $p->category->name }}</span>
@endif
</div>
</div>
</a>
@endforeach
</div>
@endif
</div>
</section>
@endisset
</x-app-layout>