- △ Norwegian ExplorerFjellområder
+
+ {/* Logoen tar brukeren tilbake til forsiden. Det er en knapp, men ser ut som før (kun pekermus). */}
+ {onHome
+ ?
+ : △ Norwegian Explorer}Fjellområder
OPPDAG NORGE TIL FOTS
{checking ? 'Velkommen tilbake.' : mode === 'login' ? 'Logg inn for å utforske.' : 'Opprett din profil.'}
Lagre favoritter og finn registrerte turruter fra hele Norge.
@@ -67,17 +72,29 @@ export function AuthGate({ onAuthenticated }: { onAuthenticated: () => void }) {
export default function Profile({ selected, onSelectRoute, disabled, onLogout }: { selected: SelectedRoute | null, onSelectRoute: (route: SelectedRoute) => void, disabled: boolean, onLogout?: () => void }) {
const [user, setUser] = useState(null)
- const [mode, setMode] = useState<'login'|'register'>('login')
+ const [mode, setMode] = useState<'login' | 'register'>('login')
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [message, setMessage] = useState('')
const [busy, setBusy] = useState(false)
const [loadingProfile, setLoadingProfile] = useState(true)
const token = localStorage.getItem(TOKEN_KEY)
+ const [municipalities, setMunicipalities] = useState([])
+ const loggedIn = Boolean(user)
+
+ // Kommunelisten til «Mitt sted» hentes først når brukeren er logget inn
+ useEffect(() => {
+ if (!loggedIn) return
+ const controller = new AbortController()
+ void graphQL('query{areas{municipalities{code name}}}', {}, controller.signal)
+ .then(data => setMunicipalities(data.areas.municipalities))
+ .catch(() => undefined)
+ return () => controller.abort()
+ }, [loggedIn])
useEffect(() => {
if (!token || disabled) return
- void graphQL('query($token:String!){me(token:$token){username email phone avatar favorites{id name number createdAt}}}', { token })
+ void graphQL('query($token:String!){me(token:$token){username email phone avatar homeMunicipality{code name} favorites{id name number createdAt}}}', { token })
.then(data => { setUser(data.me); if (!data.me) { localStorage.removeItem(TOKEN_KEY); onLogout?.() } })
.catch(() => setMessage('Kunne ikke hente profilen. Oppdater siden for å prøve igjen.'))
.finally(() => setLoadingProfile(false))
@@ -87,7 +104,7 @@ export default function Profile({ selected, onSelectRoute, disabled, onLogout }:
event.preventDefault(); setBusy(true); setMessage('')
try {
const mutation = mode === 'login' ? 'login' : 'register'
- const data = await graphQL(`mutation($username:String!,$password:String!){${mutation}(username:$username,password:$password){token user{username email phone avatar favorites{id name number createdAt}}}}`, { username, password })
+ const data = await graphQL(`mutation($username:String!,$password:String!){${mutation}(username:$username,password:$password){token user{username email phone avatar homeMunicipality{code name} favorites{id name number createdAt}}}}`, { username, password })
localStorage.setItem(TOKEN_KEY, data[mutation].token); setUser(data[mutation].user); setPassword('')
} catch (error) { setMessage(error instanceof Error ? error.message : 'Noe gikk galt.') }
finally { setBusy(false) }
@@ -98,7 +115,7 @@ export default function Profile({ selected, onSelectRoute, disabled, onLogout }:
if (!currentToken || !selected?.id) return
setBusy(true); setMessage('')
try {
- const data = await graphQL('mutation($token:String!,$routeId:ID!){toggleFavorite(token:$token,routeId:$routeId){username email phone avatar favorites{id name number createdAt}}}', { token: currentToken, routeId: selected.id })
+ const data = await graphQL('mutation($token:String!,$routeId:ID!){toggleFavorite(token:$token,routeId:$routeId){username email phone avatar homeMunicipality{code name} favorites{id name number createdAt}}}', { token: currentToken, routeId: selected.id })
setUser(data.toggleFavorite)
} catch (error) { setMessage(error instanceof Error ? error.message : 'Noe gikk galt.') }
finally { setBusy(false) }
@@ -117,7 +134,7 @@ export default function Profile({ selected, onSelectRoute, disabled, onLogout }:
setBusy(true); setMessage('')
const form = new FormData(event.currentTarget)
try {
- const data = await graphQL('mutation($token:String!,$email:String,$phone:String,$avatar:String){updateProfile(token:$token,email:$email,phone:$phone,avatar:$avatar){username email phone avatar favorites{id name number createdAt}}}', {
+ const data = await graphQL('mutation($token:String!,$email:String,$phone:String,$avatar:String){updateProfile(token:$token,email:$email,phone:$phone,avatar:$avatar){username email phone avatar homeMunicipality{code name} favorites{id name number createdAt}}}', {
token: currentToken, email: String(form.get('email') || ''), phone: String(form.get('phone') || ''), avatar: user.avatar || '',
})
setUser(data.updateProfile); setMessage('Profilen er lagret.')
@@ -125,6 +142,18 @@ export default function Profile({ selected, onSelectRoute, disabled, onLogout }:
finally { setBusy(false) }
}
+ // Lagrer stedet brukeren vil se turforslag fra på forsiden. Lagres med en gang det velges.
+ async function saveHomeMunicipality(code: string) {
+ const currentToken = localStorage.getItem(TOKEN_KEY)
+ if (!currentToken) return
+ setBusy(true); setMessage('')
+ try {
+ const data = await graphQL('mutation($token:String!,$code:String){setHomeMunicipality(token:$token,code:$code){username email phone avatar homeMunicipality{code name} favorites{id name number createdAt}}}', { token: currentToken, code })
+ setUser(data.setHomeMunicipality); setMessage('Stedet er lagret.')
+ } catch (error) { setMessage(error instanceof Error ? error.message : 'Noe gikk galt.') }
+ finally { setBusy(false) }
+ }
+
function chooseAvatar(event: ChangeEvent) {
const file = event.target.files?.[0]
if (!file) return
@@ -156,12 +185,18 @@ export default function Profile({ selected, onSelectRoute, disabled, onLogout }:
{user.avatar && }
+
{selected?.id && }
{message &&
{message}
}
Favoritter ({user.favorites.length})
- {user.favorites.length === 0 ?
Du har ikke lagret noen ruter ennå.
:
{user.favorites.map(item => )}
}
+ {user.favorites.length === 0 ?
Du har ikke lagret noen ruter ennå.
:
{user.favorites.map(item => )}
}
}
diff --git a/src/graphql.ts b/src/graphql.ts
index 5539adf..9f1e609 100644
--- a/src/graphql.ts
+++ b/src/graphql.ts
@@ -16,3 +16,6 @@ export async function graphql(query: string, variables: Record