fix: adapt admin landings list for mobile layout

- Badges (active/inactive, gift) now wrap on narrow screens
- Action buttons move to a separate row on mobile (hidden/shown via sm:)
- Delete button pushed to the right on mobile for safety
- Reduced padding and gaps on small screens
- Desktop layout unchanged
This commit is contained in:
Fringg
2026-03-07 04:56:12 +03:00
parent 6d5c6fb9b3
commit b7c7decfd0

View File

@@ -115,7 +115,7 @@ function SortableLandingCard({
ref={setNodeRef} ref={setNodeRef}
style={style} style={style}
className={cn( className={cn(
'rounded-xl border bg-dark-800 p-4 transition-colors', 'rounded-xl border bg-dark-800 p-3 transition-colors sm:p-4',
isDragging isDragging
? 'border-accent-500/50 shadow-xl shadow-accent-500/20' ? 'border-accent-500/50 shadow-xl shadow-accent-500/20'
: landing.is_active : landing.is_active
@@ -123,50 +123,53 @@ function SortableLandingCard({
: 'border-dark-700/50 opacity-60', : 'border-dark-700/50 opacity-60',
)} )}
> >
<div className="flex items-start gap-3"> <div className="flex items-start gap-2 sm:gap-3">
{/* Drag handle */} {/* Drag handle */}
<button <button
{...attributes} {...attributes}
{...listeners} {...listeners}
className="mt-1 flex-shrink-0 cursor-grab touch-none rounded-lg p-2.5 text-dark-500 hover:bg-dark-700/50 hover:text-dark-300 active:cursor-grabbing sm:p-1.5" className="mt-0.5 flex-shrink-0 cursor-grab touch-none rounded-lg p-2 text-dark-500 hover:bg-dark-700/50 hover:text-dark-300 active:cursor-grabbing sm:mt-1 sm:p-1.5"
title={t('admin.tariffs.dragToReorder')} title={t('admin.tariffs.dragToReorder')}
> >
<GripIcon /> <GripIcon />
</button> </button>
{/* Content */} {/* Content + Actions wrapper */}
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="mb-1 flex items-center gap-2"> {/* Top row: title/slug + actions (desktop) */}
<div className="flex items-start justify-between gap-2">
<div className="min-w-0 flex-1">
<div className="mb-1 flex flex-wrap items-center gap-1.5 sm:gap-2">
<h3 className="truncate font-medium text-dark-100"> <h3 className="truncate font-medium text-dark-100">
{resolveLocaleDisplay(landing.title)} {resolveLocaleDisplay(landing.title)}
</h3> </h3>
<span className="rounded bg-dark-800 px-2 py-0.5 text-xs text-dark-400"> <span className="shrink-0 rounded bg-dark-800 px-2 py-0.5 text-xs text-dark-400">
{landing.slug} {landing.slug}
</span> </span>
{landing.is_active ? ( {landing.is_active ? (
<span className="rounded bg-success-500/20 px-2 py-0.5 text-xs text-success-400"> <span className="shrink-0 rounded bg-success-500/20 px-2 py-0.5 text-xs text-success-400">
{t('admin.landings.active')} {t('admin.landings.active')}
</span> </span>
) : ( ) : (
<span className="rounded bg-dark-600 px-2 py-0.5 text-xs text-dark-400"> <span className="shrink-0 rounded bg-dark-600 px-2 py-0.5 text-xs text-dark-400">
{t('admin.landings.inactive')} {t('admin.landings.inactive')}
</span> </span>
)} )}
{landing.gift_enabled && ( {landing.gift_enabled && (
<span className="rounded bg-accent-500/20 px-2 py-0.5 text-xs text-accent-400"> <span className="shrink-0 rounded bg-accent-500/20 px-1.5 py-0.5 text-xs text-accent-400">
<GiftIcon /> <GiftIcon />
</span> </span>
)} )}
</div> </div>
<div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-dark-400"> <div className="text-sm text-dark-400">
<span> <span>
{landing.purchase_stats.total} {t('admin.landings.purchases')} {landing.purchase_stats.total} {t('admin.landings.purchases')}
</span> </span>
</div> </div>
</div> </div>
{/* Actions */} {/* Actions: hidden on mobile, shown on desktop */}
<div className="flex items-center gap-2"> <div className="hidden shrink-0 items-center gap-1.5 sm:flex">
<button <button
onClick={onCopyUrl} onClick={onCopyUrl}
className="rounded-lg bg-dark-700 p-2 text-dark-300 transition-colors hover:bg-dark-600 hover:text-dark-100" className="rounded-lg bg-dark-700 p-2 text-dark-300 transition-colors hover:bg-dark-600 hover:text-dark-100"
@@ -174,7 +177,61 @@ function SortableLandingCard({
> >
<CopyIcon /> <CopyIcon />
</button> </button>
<button
onClick={onToggle}
className={cn(
'rounded-lg p-2 transition-colors',
landing.is_active
? 'bg-success-500/20 text-success-400 hover:bg-success-500/30'
: 'bg-dark-700 text-dark-400 hover:bg-dark-600',
)}
title={
landing.is_active ? t('admin.landings.inactive') : t('admin.landings.active')
}
>
{landing.is_active ? <CheckIcon /> : <XIcon />}
</button>
<button
onClick={onEdit}
className="rounded-lg bg-dark-700 p-2 text-dark-300 transition-colors hover:bg-dark-600 hover:text-dark-100"
title={t('admin.landings.edit')}
>
<EditIcon />
</button>
<button
onClick={onDelete}
className={cn(
'rounded-lg p-2 transition-colors',
isPendingDelete
? 'bg-error-500/20 text-error-400 ring-1 ring-error-500/30'
: 'bg-dark-700 text-dark-300 hover:bg-error-500/20 hover:text-error-400',
)}
title={
isPendingDelete
? t('admin.landings.deleteConfirm', {
title: resolveLocaleDisplay(landing.title),
})
: t('common.delete')
}
>
{isPendingDelete ? (
<span className="px-1 text-xs font-medium">{t('common.delete')}?</span>
) : (
<TrashIcon />
)}
</button>
</div>
</div>
{/* Actions: shown on mobile only */}
<div className="mt-2 flex items-center gap-1.5 sm:hidden">
<button
onClick={onCopyUrl}
className="rounded-lg bg-dark-700 p-2 text-dark-300 transition-colors hover:bg-dark-600 hover:text-dark-100"
title={t('admin.landings.copyUrl')}
>
<CopyIcon />
</button>
<button <button
onClick={onToggle} onClick={onToggle}
className={cn( className={cn(
@@ -187,7 +244,6 @@ function SortableLandingCard({
> >
{landing.is_active ? <CheckIcon /> : <XIcon />} {landing.is_active ? <CheckIcon /> : <XIcon />}
</button> </button>
<button <button
onClick={onEdit} onClick={onEdit}
className="rounded-lg bg-dark-700 p-2 text-dark-300 transition-colors hover:bg-dark-600 hover:text-dark-100" className="rounded-lg bg-dark-700 p-2 text-dark-300 transition-colors hover:bg-dark-600 hover:text-dark-100"
@@ -195,7 +251,7 @@ function SortableLandingCard({
> >
<EditIcon /> <EditIcon />
</button> </button>
<div className="flex-1" />
<button <button
onClick={onDelete} onClick={onDelete}
className={cn( className={cn(
@@ -206,7 +262,9 @@ function SortableLandingCard({
)} )}
title={ title={
isPendingDelete isPendingDelete
? t('admin.landings.deleteConfirm', { title: resolveLocaleDisplay(landing.title) }) ? t('admin.landings.deleteConfirm', {
title: resolveLocaleDisplay(landing.title),
})
: t('common.delete') : t('common.delete')
} }
> >
@@ -219,6 +277,7 @@ function SortableLandingCard({
</div> </div>
</div> </div>
</div> </div>
</div>
); );
} }