Fix mobile responsiveness across all pages

- PosPage: rooms list becomes horizontal scroll row on mobile instead of w-56 sidebar
- AvailabilityPage: edit panel stacks below grid on mobile (was fixed w-80 side panel)
- UsersPage roles tab: sidebar stacks above permissions on mobile
- All page containers: p-6 → p-4 md:p-6 (TariffsPage, DiscountsPage, MaintenancePage, ReportsPage, DynamicPricingPage, GuestsPage, LoyaltyPage)
- Stats grids: lg:grid-cols-4 → md:grid-cols-4 (GuestsPage, TariffsPage, DiscountsPage, MaintenancePage, ReportsPage, LoyaltyPage)
- Modal form grids: grid-cols-3 → grid-cols-1 sm:grid-cols-3, grid-cols-5 → grid-cols-3 sm:grid-cols-5, grid-cols-4 → grid-cols-2 sm:grid-cols-4
- PosPage modals: fixed w-80/w-96 → responsive w-[calc(100vw-2rem)] sm:w-80/96

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 00:27:43 +03:00
parent 91e58ff994
commit 2fc66d1e84
10 changed files with 62 additions and 35 deletions

View File

@@ -270,14 +270,41 @@ export function PosPage() {
<>
{/* ══════════════════════ TAB: main ══════════════════════ */}
{activeTab === 'main' && (
<div className="flex flex-1 overflow-hidden">
<div className="flex flex-col sm:flex-row flex-1 overflow-hidden">
{/* ── Left sidebar: Заезды (w-56) ── */}
<div className="w-56 flex flex-col border-r border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-800/50 shrink-0 overflow-hidden">
<div className="px-3 py-2 border-b border-slate-200 dark:border-slate-700">
{/* ── Заезды: horizontal scroll on mobile, sidebar on desktop ── */}
<div className="sm:w-56 flex-shrink-0 border-b sm:border-b-0 sm:border-r border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-800/50">
<div className="px-3 py-2 border-b border-slate-200 dark:border-slate-700 hidden sm:block">
<p className="text-[11px] font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">Заезды</p>
</div>
<div className="flex-1 overflow-y-auto p-2 space-y-1">
{/* Mobile: horizontal scroll row */}
<div className="flex sm:hidden gap-2 p-2 overflow-x-auto">
{MOCK_BALANCES.map(rb => {
const debt = Math.max(0, rb.totalAmount - rb.paidAmount)
const paid = debt === 0
const sel = selectedRoom?.roomId === rb.roomId
return (
<button
key={rb.roomId}
onClick={() => setSelectedRoom(rb)}
className={cn(
'shrink-0 rounded-lg px-3 py-1.5 border transition-all flex items-center gap-1.5',
sel
? 'border-brand-400 bg-brand-50 dark:bg-brand-900/20 dark:border-brand-600'
: 'border-slate-200 dark:border-slate-600 bg-white dark:bg-slate-800',
)}
>
<span className="text-xs font-bold text-slate-900 dark:text-slate-100">{rb.roomNumber}</span>
{paid
? <span className="text-[9px] font-semibold px-1 py-0.5 rounded-full bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300"></span>
: <span className="text-[9px] font-semibold px-1 py-0.5 rounded-full bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300 whitespace-nowrap">{formatCurrency(debt)}</span>
}
</button>
)
})}
</div>
{/* Desktop: vertical list */}
<div className="hidden sm:block flex-1 overflow-y-auto p-2 space-y-1">
{MOCK_BALANCES.map(rb => {
const debt = Math.max(0, rb.totalAmount - rb.paidAmount)
const paid = debt === 0
@@ -313,7 +340,7 @@ export function PosPage() {
</div>
{/* ── Center: payment form ── */}
<div className="flex-1 flex flex-col overflow-y-auto p-5 gap-5">
<div className="flex-1 flex flex-col overflow-y-auto p-4 sm:p-5 gap-5">
{selectedRoom ? (
<>
{/* Guest info */}
@@ -781,7 +808,7 @@ export function PosPage() {
{/* ── Receipt success overlay ── */}
{lastReceipt && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl p-8 w-80 text-center space-y-4">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl p-6 sm:p-8 w-[calc(100vw-2rem)] sm:w-80 text-center space-y-4">
<CheckCircle2 size={56} className="text-emerald-500 mx-auto" />
<div>
<p className="text-xl font-bold text-slate-900 dark:text-slate-100">Оплата принята</p>
@@ -815,7 +842,7 @@ export function PosPage() {
{/* ── Close shift confirmation modal ── */}
{closeConfirm && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl p-6 w-96 space-y-4">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl p-6 w-[calc(100vw-2rem)] sm:w-96 space-y-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center">
<Printer size={18} className="text-red-600" />