Skip to content

Commit

Permalink
Release: v0.1.11
Browse files Browse the repository at this point in the history
Released dark mode.
  • Loading branch information
mayack committed Mar 2, 2025
1 parent 98672df commit 9b9c0e5
Show file tree
Hide file tree
Showing 18 changed files with 301 additions and 215 deletions.
45 changes: 11 additions & 34 deletions api/sargo/actions/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import { sargoClient } from '../client'
import { CONFIG } from '@/constants/config'
import type { User, UserAuthResponse } from '../interfaces/user'

export async function signIn(
formData: FormData
): Promise<{ success: boolean; error?: string }> {
export async function signIn(formData: FormData) {
const identifier = formData.get('identifier')
const password = formData.get('password')

Expand Down Expand Up @@ -45,7 +43,7 @@ export async function signIn(
value: JSON.stringify({
username: sargoResponse.user.username,
email: sargoResponse.user.email,
settings: sargoResponse.user.settings || CONFIG.units.default,
settings: sargoResponse.user.settings || CONFIG.settings.default,
}),
...CONFIG.api.tokens.sargoOptions.options,
})
Expand All @@ -55,10 +53,7 @@ export async function signIn(
console.error('SignIn Error:', error)
return {
success: false,
error:
error instanceof Error
? error.message
: 'Authentication failed. Please try again.',
error: error instanceof Error ? error.message : 'Authentication failed',
}
}
}
Expand All @@ -67,7 +62,6 @@ export async function signOut() {
const cookieStore = await cookies()

try {
// Delete all relevant cookies
const cookiesToDelete = [
CONFIG.api.tokens.polvo.key,
CONFIG.api.tokens.sargo.key,
Expand All @@ -85,20 +79,11 @@ export async function signOut() {
cookieStore.delete(cookieName)
}

// Log remaining cookies for debugging (optional)
const remainingCookies = cookiesToDelete.map((name) => ({
name,
exists: !!cookieStore.get(name),
}))
console.log('SignOut - Cookies status:', remainingCookies)

revalidatePath('/')
redirect('/auth/signin')
} catch (error) {
if (error instanceof Error && error.message.includes('NEXT_REDIRECT')) {
throw error // Let Next.js handle the redirect
}

if (error instanceof Error && error.message.includes('NEXT_REDIRECT'))
throw error
console.error('SignOut Error:', error)
redirect('/auth/signin')
}
Expand All @@ -108,22 +93,18 @@ export async function getCurrentUser(): Promise<User | null> {
const cookieStore = await cookies()
const jwt = cookieStore.get(CONFIG.api.tokens.sargo.key)?.value

if (!jwt) {
console.log('No JWT found')
return null
}
if (!jwt) return null

const optionsCookie = cookieStore.get(
CONFIG.api.tokens.sargoOptions.key
)?.value
if (optionsCookie) {
try {
const userOptions = JSON.parse(optionsCookie) as User
console.log('User options from cookie:', userOptions)
return {
username: userOptions.username || '',
email: userOptions.email || '',
settings: userOptions.settings || { units: CONFIG.units.default },
settings: userOptions.settings || CONFIG.settings.default,
}
} catch (error) {
console.error('Failed to parse sargoOptions cookie:', error)
Expand All @@ -132,31 +113,27 @@ export async function getCurrentUser(): Promise<User | null> {

try {
const freshUser = await sargoClient.getCurrentUser()
if (!freshUser) {
console.log('No fresh user data')
return null
}
console.log('Fresh user data:', freshUser)
if (!freshUser) return null
return {
username: freshUser.username || '',
email: freshUser.email || '',
settings: freshUser.settings || { units: CONFIG.units.default },
settings: freshUser.settings || CONFIG.settings.default,
}
} catch (error) {
console.error('Failed to fetch fresh user data:', error)
return null
}
}

export async function fetchSargoOptionsAction(sargoToken: string) {
export async function fetchSargoOptionsAction() {
const cookieStore = await cookies()
try {
const user = await sargoClient.getCurrentUser()
if (!user) throw new Error('No user data returned')
const options = {
username: user.username,
email: user.email,
settings: user.settings,
settings: user.settings || CONFIG.settings.default,
}
cookieStore.set({
name: CONFIG.api.tokens.sargoOptions.key,
Expand Down
102 changes: 91 additions & 11 deletions api/sargo/actions/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { revalidatePath } from 'next/cache'
import { sargoClient } from '@/api/sargo/client'
import { CONFIG } from '@/constants/config'
import { AppError, ErrorCode, HTTP_STATUS } from '@/utils/error'
import type { UserUnits } from '../interfaces/user'
import type { UserUnits, UserSettings } from '../interfaces/user'

export async function updateUsername(formData: FormData) {
const username = formData.get('username')
Expand Down Expand Up @@ -35,12 +35,14 @@ export async function updateUsername(formData: FormData) {
)?.value
const parsedOptions = optionsCookie
? JSON.parse(optionsCookie)
: { username: '', email: '', settings: CONFIG.units.default }
: { username: '', email: '', settings: CONFIG.settings.default }

const updatedCookieData = {
username,
email: parsedOptions.email,
settings: parsedOptions.settings,
}

cookieStore.set(
CONFIG.api.tokens.sargoOptions.key,
JSON.stringify(updatedCookieData),
Expand Down Expand Up @@ -100,7 +102,6 @@ export async function updatePassword(formData: FormData) {
}
}

// Type guard functions for validation
function isWindSpeedUnit(value: unknown): value is UserUnits['wind_speed'] {
return ['knots', 'mph', 'kph', 'mps'].includes(value as string)
}
Expand All @@ -113,6 +114,10 @@ function isTemperatureUnit(value: unknown): value is UserUnits['temperature'] {
return ['celsius', 'fahrenheit'].includes(value as string)
}

function isTheme(value: unknown): value is UserSettings['theme'] {
return ['light', 'dark', 'system'].includes(value as string)
}

export async function updateUnits(formData: FormData) {
const cookieStore = await cookies()
const jwt = cookieStore.get(CONFIG.api.tokens.sargo.key)?.value
Expand All @@ -124,13 +129,14 @@ export async function updateUnits(formData: FormData) {
)
}

// Validate form data
const windSpeed = formData.get('units.wind_speed')
const surfHeight = formData.get('units.surf_height')
const swellHeight = formData.get('units.swell_height')
const tideHeight = formData.get('units.tide_height')
const temperature = formData.get('units.temperature')

// Validate each field
// Validate each unit
if (!windSpeed || !isWindSpeedUnit(windSpeed)) {
throw new AppError(
`Invalid wind speed unit: ${windSpeed || 'missing'}`,
Expand Down Expand Up @@ -176,19 +182,31 @@ export async function updateUnits(formData: FormData) {
}

try {
await sargoClient.updateUserProfile({ settings: { units } })

// First get the current cookie data to get the most recent theme setting
const optionsCookie = cookieStore.get(
CONFIG.api.tokens.sargoOptions.key
)?.value
const parsedOptions = optionsCookie
const currentSettings = optionsCookie
? JSON.parse(optionsCookie)
: { username: '', email: '', settings: CONFIG.units.default }
: { username: '', email: '', settings: CONFIG.settings.default }

// Create updated settings preserving the current theme
const updatedSettings = {
units,
theme: currentSettings.settings.theme, // Use theme from cookie instead of fetching from server
}

// Update settings on the server
await sargoClient.updateUserProfile({ settings: updatedSettings })

// Update cookie with new settings while preserving other data
const updatedCookieData = {
username: parsedOptions.username,
email: parsedOptions.email,
settings: { units },
username: currentSettings.username,
email: currentSettings.email,
settings: updatedSettings,
}

// Set the updated cookie
cookieStore.set(
CONFIG.api.tokens.sargoOptions.key,
JSON.stringify(updatedCookieData),
Expand All @@ -206,3 +224,65 @@ export async function updateUnits(formData: FormData) {
)
}
}

export async function updateTheme(theme: string) {
if (!isTheme(theme)) {
throw new AppError(
`Invalid theme: ${theme}`,
ErrorCode.INVALID_PARAMETERS,
HTTP_STATUS.BAD_REQUEST
)
}

const cookieStore = await cookies()
const jwt = cookieStore.get(CONFIG.api.tokens.sargo.key)?.value
if (!jwt) {
throw new AppError(
'Unauthorized',
ErrorCode.AUTH_UNAUTHORIZED,
HTTP_STATUS.UNAUTHORIZED
)
}

try {
// Get current settings from cookie
const optionsCookie = cookieStore.get(
CONFIG.api.tokens.sargoOptions.key
)?.value
const currentSettings = optionsCookie
? JSON.parse(optionsCookie)
: { username: '', email: '', settings: CONFIG.settings.default }

// Create updated settings preserving the current units
const updatedSettings = {
units: currentSettings.settings.units, // Preserve current units
theme,
}

// Update settings on server
await sargoClient.updateUserProfile({ settings: updatedSettings })

// Update cookie with new settings while preserving other data
const updatedCookieData = {
username: currentSettings.username,
email: currentSettings.email,
settings: updatedSettings,
}

// Set the updated cookie
cookieStore.set(
CONFIG.api.tokens.sargoOptions.key,
JSON.stringify(updatedCookieData),
CONFIG.api.tokens.sargoOptions.options
)

return { success: true }
} catch (error) {
console.error('Update theme error:', error)
throw new AppError(
error instanceof Error ? error.message : 'Failed to update theme',
ErrorCode.SERVER_ERROR,
HTTP_STATUS.INTERNAL_SERVER_ERROR
)
}
}
9 changes: 7 additions & 2 deletions api/sargo/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { BaseApiClient } from '@/lib/baseApiClient'
import { CONFIG } from '@/constants/config'
import { cookies } from 'next/headers'
import { User, UserAuthResponse, UserUnits } from './interfaces/user'
import {
User,
UserAuthResponse,
UserSettings,
UserUnits,
} from './interfaces/user'
import { Spot, SpotResponse } from './interfaces/spot'

export class SargoClient extends BaseApiClient {
Expand Down Expand Up @@ -82,7 +87,7 @@ export class SargoClient extends BaseApiClient {

async updateUserProfile(data: {
username?: string
settings?: { units: UserUnits }
settings?: UserSettings
}): Promise<User> {
const headers = await this.getHeaders(
CONFIG.api.endpoints.sargo.user.update
Expand Down
1 change: 1 addition & 0 deletions api/sargo/interfaces/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface User {

export interface UserSettings {
units: UserUnits
theme: 'light' | 'dark' | 'system'
}

export interface UserUnits {
Expand Down
Loading

0 comments on commit 9b9c0e5

Please sign in to comment.