feat(admin): refine header layout and logo placement

- Left-align logo across breakpoints; remove duplicate centered/mobile blocks
- Add date separator and spacing; keep header compact and readable

fix(admin): prevent category badge overlap in grid

- Move badge to top-left; make non-interactive; constrain width to avoid checkbox collisions

chore(docker): support ADMIN_PASSWORD in docker-compose

- Allow setting initial admin password via env for easier provisioning

chore(backend): normalize EOF newline in set-admin-password.js

Refs: admin-header-layout, category-badge-overlap, docker-admin-password
This commit is contained in:
2025-09-15 14:23:35 +02:00
parent eb3751cb52
commit d64e7d08de
4 changed files with 17 additions and 22 deletions
+1 -1
View File
@@ -36,4 +36,4 @@ async function setAdminPassword() {
} }
} }
setAdminPassword(); setAdminPassword();
+1
View File
@@ -11,6 +11,7 @@ services:
- JWT_SECRET=${JWT_SECRET} - JWT_SECRET=${JWT_SECRET}
- ADMIN_USERNAME=${ADMIN_USERNAME:-admin} - ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
- ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com} - ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- DATABASE_CLIENT=pg - DATABASE_CLIENT=pg
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME} - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
- DB_TYPE=postgresql - DB_TYPE=postgresql
+12 -18
View File
@@ -71,35 +71,29 @@ export const AdminHeader: React.FC<AdminHeaderProps> = ({ onMenuClick }) => {
<header className="sticky top-0 z-30 bg-white border-b border-neutral-200"> <header className="sticky top-0 z-30 bg-white border-b border-neutral-200">
<div className="px-4 sm:px-6 lg:px-8"> <div className="px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16"> <div className="flex items-center justify-between h-16">
{/* Left side - Menu button and Date */} {/* Left side - Menu button, Logo, and Date */}
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<button <button
onClick={onMenuClick} onClick={onMenuClick}
className="lg:hidden text-neutral-500 hover:text-neutral-700" className="lg:hidden text-neutral-500 hover:text-neutral-700"
> >
<Menu className="w-6 h-6" /> <Menu className="w-6 h-6" />
</button> </button>
{/* Date display - hidden on small screens */} {/* PicPeak logo - sticky to the left on all sizes */}
<div className="hidden xl:block"> <div className="flex items-center gap-2">
<img src="/picpeak-kamera-transparent.png" alt="PicPeak" className="h-8 w-auto object-contain" />
<span className="text-xl sm:text-2xl" style={{ fontFamily: 'Poppins, sans-serif', fontWeight: 600, color: '#145346' }}>PicPeak</span>
</div>
{/* Date display - hidden on smaller screens */}
<div className="hidden xl:block pl-3 border-l border-neutral-200 ml-1">
<p className="text-base text-neutral-700"> <p className="text-base text-neutral-700">
{format(new Date(), 'PPPP')} {format(new Date(), 'PPPP')}
</p> </p>
</div> </div>
</div> </div>
{/* Center - Logo and PicPeak text - hidden on small screens to prevent overlap */}
<div className="hidden lg:flex absolute left-1/2 transform -translate-x-1/2 items-center gap-3">
<img src="/picpeak-kamera-transparent.png" alt="PicPeak" className="h-10 w-auto object-contain" />
<span className="text-2xl" style={{ fontFamily: 'Poppins, sans-serif', fontWeight: 600, color: '#145346' }}>PicPeak</span>
</div>
{/* Mobile Logo - shown only on small screens */}
<div className="flex lg:hidden items-center gap-2 mx-auto">
<img src="/picpeak-kamera-transparent.png" alt="PicPeak" className="h-8 w-auto object-contain" />
<span className="text-xl" style={{ fontFamily: 'Poppins, sans-serif', fontWeight: 600, color: '#145346' }}>PicPeak</span>
</div>
{/* Right side actions */} {/* Right side actions */}
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{/* Language Selector */} {/* Language Selector */}
@@ -253,4 +247,4 @@ export const AdminHeader: React.FC<AdminHeaderProps> = ({ onMenuClick }) => {
/> />
</header> </header>
); );
}; };
@@ -248,10 +248,10 @@ export const AdminPhotoGrid: React.FC<AdminPhotoGridProps> = ({
</div> </div>
</div> </div>
{/* Category Badge */} {/* Category Badge - move to top-left and prevent overlap with select checkbox */}
{photo.category_name && ( {photo.category_name && (
<div className="absolute right-2" style={{ top: (selectedPhotos.has(photo.id) || isSelectionMode) ? '40px' : '8px' }}> <div className="absolute left-2 top-2 pointer-events-none">
<span className="px-2 py-1 text-xs font-medium bg-white/90 text-neutral-700 rounded"> <span className="px-2 py-1 text-xs font-medium bg-white/90 text-neutral-700 rounded max-w-[70%] whitespace-nowrap overflow-hidden text-ellipsis">
{photo.category_name} {photo.category_name}
</span> </span>
</div> </div>