feat: Auto-load saved user and remember last visited room

- JoinForm now pre-populates name/emoji from localStorage and shows
  a "Quick Join as [name]" button for returning users
- Home page shows "Rejoin /[room]" button when user has visited before
- Room slug saved to localStorage on every visit for quick rejoin

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-29 21:19:03 +01:00
parent 47dea7c9c3
commit 2284f94ee3
3 changed files with 78 additions and 2 deletions

View File

@ -46,6 +46,8 @@ export default function RoomPage() {
const stored = localStorage.getItem('rmaps_user');
if (stored) {
setCurrentUser(JSON.parse(stored));
// Save this as the last visited room
localStorage.setItem('rmaps_last_room', slug);
// Check if user had location sharing enabled for this room
const sharingPref = localStorage.getItem(`rmaps_sharing_${slug}`);
if (sharingPref === 'true') {
@ -61,6 +63,7 @@ export default function RoomPage() {
const handleJoin = (name: string, emoji: string) => {
const user = { name, emoji };
localStorage.setItem('rmaps_user', JSON.stringify(user));
localStorage.setItem('rmaps_last_room', slug);
setCurrentUser(user);
setNeedsJoin(false);
};

View File

@ -20,6 +20,7 @@ export default function HomePage() {
const [emoji, setEmoji] = useState('');
const [roomName, setRoomName] = useState('');
const [isLoaded, setIsLoaded] = useState(false);
const [lastRoom, setLastRoom] = useState<string | null>(null);
// Load saved user info from localStorage on mount
useEffect(() => {
@ -34,6 +35,11 @@ export default function HomePage() {
loadedEmoji = user.emoji;
}
}
// Load last visited room
const lastVisited = localStorage.getItem('rmaps_last_room');
if (lastVisited) {
setLastRoom(lastVisited);
}
} catch {
// Ignore parse errors
}
@ -53,6 +59,7 @@ export default function HomePage() {
// Store user info in localStorage for the session
localStorage.setItem('rmaps_user', JSON.stringify({ name, emoji }));
localStorage.setItem('rmaps_last_room', slug);
// Navigate to the room (will create it if it doesn't exist)
router.push(`/${slug}`);
@ -65,9 +72,16 @@ export default function HomePage() {
// Clean the slug
const cleanSlug = joinSlug.toLowerCase().replace(/[^a-z0-9-]/g, '');
localStorage.setItem('rmaps_last_room', cleanSlug);
router.push(`/${cleanSlug}`);
};
const handleRejoinLastRoom = () => {
if (!name.trim() || !lastRoom) return;
localStorage.setItem('rmaps_user', JSON.stringify({ name, emoji }));
router.push(`/${lastRoom}`);
};
return (
<main className="min-h-screen flex flex-col items-center justify-center p-4">
<div className="max-w-md w-full space-y-8">
@ -79,6 +93,23 @@ export default function HomePage() {
<p className="text-white/60">Find your friends at events</p>
</div>
{/* Quick Rejoin Card - show when user has saved info and last room */}
{isLoaded && name && lastRoom && (
<div className="room-panel rounded-2xl p-6">
<p className="text-white/60 text-sm text-center mb-4">Welcome back, {name}!</p>
<button
onClick={handleRejoinLastRoom}
className="btn-primary w-full text-lg py-3 flex items-center justify-center gap-2"
>
<span className="text-xl">{emoji}</span>
<span>Rejoin /{lastRoom}</span>
</button>
<p className="text-white/40 text-xs text-center mt-3">
Or create/join a different room below
</p>
</div>
)}
{/* Main Card */}
<div className="room-panel rounded-2xl p-6 space-y-6">
{/* User Setup */}

View File

@ -1,6 +1,6 @@
'use client';
import { useState } from 'react';
import { useState, useEffect } from 'react';
const EMOJIS = ['😀', '😎', '🤓', '🥳', '🦊', '🐱', '🐶', '🦄', '🌟', '🔥', '💜', '🎮'];
@ -11,7 +11,31 @@ interface JoinFormProps {
export default function JoinForm({ roomSlug, onJoin }: JoinFormProps) {
const [name, setName] = useState('');
const [emoji, setEmoji] = useState(EMOJIS[Math.floor(Math.random() * EMOJIS.length)]);
const [emoji, setEmoji] = useState('');
const [isLoaded, setIsLoaded] = useState(false);
// Load saved user info from localStorage
useEffect(() => {
let loadedEmoji = '';
try {
const stored = localStorage.getItem('rmaps_user');
if (stored) {
const user = JSON.parse(stored);
if (user.name) setName(user.name);
if (user.emoji) {
setEmoji(user.emoji);
loadedEmoji = user.emoji;
}
}
} catch {
// Ignore parse errors
}
// Set random emoji if none loaded
if (!loadedEmoji) {
setEmoji(EMOJIS[Math.floor(Math.random() * EMOJIS.length)]);
}
setIsLoaded(true);
}, []);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
@ -30,6 +54,24 @@ export default function JoinForm({ roomSlug, onJoin }: JoinFormProps) {
</p>
</div>
{/* Quick join option if user already has saved info */}
{isLoaded && name && (
<div className="mb-6 p-4 bg-rmaps-primary/10 border border-rmaps-primary/30 rounded-lg">
<p className="text-white/60 text-sm mb-3 text-center">Welcome back!</p>
<button
type="button"
onClick={() => onJoin(name.trim(), emoji)}
className="w-full btn-primary py-3 flex items-center justify-center gap-2"
>
<span className="text-xl">{emoji}</span>
<span>Join as {name}</span>
</button>
<p className="text-white/40 text-xs text-center mt-2">
Or customize below
</p>
</div>
)}
<form onSubmit={handleSubmit} className="space-y-4">
{/* Emoji picker */}
<div>