All changes

This commit is contained in:
Andras Schmelczer 2026-03-14 21:36:00 +00:00
parent 593f380581
commit 49f7ec2f5a
60 changed files with 1783 additions and 679 deletions

View file

@ -3,7 +3,7 @@ import MapPage, { type ExportState } from './components/map/MapPage';
import PricingPage from './components/pricing/PricingPage';
import HomePage from './components/home/HomePage';
import LearnPage from './components/learn/LearnPage';
import AccountPage from './components/account/AccountPage';
import AccountPage, { SavedPage, InvitesPage } from './components/account/AccountPage';
import InvitePage from './components/invite/InvitePage';
import Header, { type Page } from './components/ui/Header';
import AuthModal from './components/ui/AuthModal';
@ -19,6 +19,7 @@ import { useTheme } from './hooks/useTheme';
import { useIsMobile } from './hooks/useIsMobile';
import { useAuth } from './hooks/useAuth';
import { useSavedSearches } from './hooks/useSavedSearches';
import { useSavedProperties } from './hooks/useSavedProperties';
declare global {
interface Window {
@ -34,6 +35,10 @@ function pageToPath(page: Page, inviteCode?: string): string {
return '/learn';
case 'pricing':
return '/pricing';
case 'saved':
return '/saved';
case 'invites':
return '/invites';
case 'account':
return '/account';
case 'invite':
@ -45,7 +50,8 @@ function pageToPath(page: Page, inviteCode?: string): string {
function pathToPage(pathname: string): { page: Page; inviteCode?: string } | null {
if (pathname === '/dashboard') return { page: 'dashboard' };
if (pathname === '/saved') return { page: 'account' };
if (pathname === '/saved') return { page: 'saved' };
if (pathname === '/invites') return { page: 'invites' };
if (pathname === '/learn') return { page: 'learn' };
if (pathname === '/pricing') return { page: 'pricing' };
if (pathname === '/account') return { page: 'account' };
@ -134,6 +140,7 @@ export default function App() {
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const savedSearches = useSavedSearches(user?.id ?? null);
const savedProperties = useSavedProperties(user?.id ?? null);
const [showSaveModal, setShowSaveModal] = useState(false);
useEffect(() => {
@ -207,15 +214,21 @@ export default function App() {
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const { fetchSearches } = savedSearches;
const { fetchProperties: fetchSavedProperties } = savedProperties;
useEffect(() => {
if (activePage === 'account') {
if (activePage === 'saved') {
fetchSearches();
fetchSavedProperties();
}
}, [activePage, fetchSearches]);
if (activePage === 'dashboard' && user) {
fetchSavedProperties();
}
}, [activePage, fetchSearches, fetchSavedProperties, user]);
const isAuthRequiredPage = activePage === 'account' || activePage === 'saved' || activePage === 'invites';
useEffect(() => {
if (authLoading) return;
if (activePage === 'account' && !user) {
if (isAuthRequiredPage && !user) {
setAuthModalTab('login');
setShowAuthModal(true);
navigateTo('home');
@ -223,10 +236,24 @@ export default function App() {
if (activePage === 'pricing' && (user?.subscription === 'licensed' || user?.isAdmin)) {
navigateTo('dashboard');
}
}, [activePage, user, authLoading, navigateTo]);
}, [activePage, isAuthRequiredPage, user, authLoading, navigateTo]);
const [exportState, setExportState] = useState<ExportState | null>(null);
if ((isScreenshotMode || isOgMode) && inviteCode) {
return (
<InvitePage
code={inviteCode}
user={null}
theme={theme}
screenshotMode
onLoginClick={() => {}}
onRegisterClick={() => {}}
onLicenseGranted={() => {}}
/>
);
}
if (isScreenshotMode) {
return (
<MapPage
@ -271,7 +298,7 @@ export default function App() {
onLogout={logout}
isMobile={isMobile}
/>
{user && !user.verified && !verificationDismissed && activePage === 'account' && (
{user && !user.verified && !verificationDismissed && isAuthRequiredPage && (
<VerificationBanner
email={user.email}
onRequestVerification={requestVerification}
@ -295,22 +322,34 @@ export default function App() {
/>
) : activePage === 'learn' ? (
<LearnPage />
) : activePage === 'account' && user ? (
<AccountPage
user={user}
onRefreshAuth={refreshAuth}
onRequestVerification={requestVerification}
) : activePage === 'saved' && user ? (
<SavedPage
searches={savedSearches.searches}
searchesLoading={savedSearches.loading}
onDeleteSearch={savedSearches.deleteSearch}
onOpenSearch={(params) => {
window.location.href = `/dashboard?${params}`;
}}
savedProperties={savedProperties.properties}
propertiesLoading={savedProperties.loading}
onDeleteProperty={savedProperties.deleteProperty}
onOpenProperty={(postcode) => {
window.location.href = `/dashboard?pc=${encodeURIComponent(postcode)}`;
}}
/>
) : activePage === 'invites' && user ? (
<InvitesPage user={user} />
) : activePage === 'account' && user ? (
<AccountPage
user={user}
onRefreshAuth={refreshAuth}
onRequestVerification={requestVerification}
/>
) : activePage === 'invite' && inviteCode ? (
<InvitePage
code={inviteCode}
user={user}
theme={theme}
onLoginClick={() => {
setAuthModalTab('login');
setShowAuthModal(true);
@ -340,6 +379,7 @@ export default function App() {
onExportStateChange={setExportState}
isMobile={isMobile}
initialTravelTime={urlState.travelTime}
initialPostcode={urlState.postcode}
user={user}
onLoginClick={() => {
setAuthModalTab('login');
@ -349,6 +389,10 @@ export default function App() {
setAuthModalTab('register');
setShowAuthModal(true);
}}
onSaveProperty={user ? savedProperties.saveProperty : undefined}
onUnsaveProperty={user ? savedProperties.deleteProperty : undefined}
isPropertySaved={user ? savedProperties.isPropertySaved : undefined}
getSavedPropertyId={user ? savedProperties.getSavedPropertyId : undefined}
/>
)}
{showAuthModal && (
@ -368,7 +412,7 @@ export default function App() {
<SaveSearchModal
onClose={() => setShowSaveModal(false)}
onSave={savedSearches.saveSearch}
onViewSearches={() => { setShowSaveModal(false); navigateTo('account'); }}
onViewSearches={() => { setShowSaveModal(false); navigateTo('saved'); }}
saving={savedSearches.saving}
error={savedSearches.error}
/>