Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/layouts/navbar/navbar.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function NavbarLayout(): JSX.Element {
{!isVisible && (
<button
onClick={() => onToggleNavbar()}
className="fixed z-50 bottom-0 left-1/2 -translate-x-1/2 px-10 py-2.5 bg-white/[0.05] backdrop-blur-[40px] backdrop-saturate-[180%] border-t border-x border-white/10 rounded-t-3xl shadow-[0_-10px_30px_rgba(0,0,0,0.5)] transition-all hover:bg-white/[0.08]"
className="fixed z-50 bottom-0 left-1/2 -translate-x-1/2 px-10 py-2.5 bg-white/[0.05] backdrop-blur-[40px] backdrop-saturate-[180%] border-t border-x border-white/10 rounded-t-3xl shadow-[0_-0px_30px_rgba(0,0,0,0.3)] transition-all hover:bg-white/[0.08]"
>
<div className="w-10 h-1 rounded-full bg-white/30" />
</button>
Expand All @@ -123,7 +123,7 @@ export function NavbarLayout(): JSX.Element {
: '-bottom-32 opacity-0 scale-95 pointer-events-none'
}`}
>
<nav className="relative flex items-center gap-1 p-1.5 bg-white/[0.02] backdrop-blur-[60px] backdrop-saturate-[180%] border border-white/[0.08] rounded-[2.5rem] shadow-[0_20px_40px_rgba(0,0,0,0.4)] before:absolute before:inset-0 before:rounded-[2.5rem] before:bg-gradient-to-b before:from-white/[0.1] before:to-transparent before:pointer-events-none">
<nav className="relative flex items-center gap-1 p-1.5 bg-white/[0.02] backdrop-blur-md border border-white/[0.08] rounded-[2.5rem]">
<button
onClick={() => onToggleNavbar()}
className="relative z-10 p-2 transition-colors cursor-pointer text-white/20 hover:text-white/40"
Expand Down
6 changes: 1 addition & 5 deletions src/layouts/widgets/weather/current/current-box.weather.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import { WiCloudy, WiHumidity } from 'react-icons/wi'

interface CurrentWeatherBoxProps {
fetchedWeather: FetchedWeather | null
enabledShowName: boolean
temperatureUnit: keyof typeof unitsFlag
}

export function CurrentWeatherBox({
fetchedWeather,
enabledShowName,
temperatureUnit,
}: CurrentWeatherBoxProps) {
return (
Expand Down Expand Up @@ -40,9 +38,7 @@ export function CurrentWeatherBox({
<div className="relative z-10 flex items-center justify-between py-1">
<div className="flex flex-col gap-1.5">
<span className="text-xs font-medium text-muted drop-shadow-lg">
{enabledShowName
? cleanCityName(fetchedWeather?.city?.fa || '')
: '🏠'}
{cleanCityName(fetchedWeather?.city?.fa || '')}
</span>

<span className="flex items-baseline gap-1.5 text-4xl font-bold leading-none text-base-content drop-shadow-lg">
Expand Down
87 changes: 0 additions & 87 deletions src/layouts/widgets/weather/weather-setting.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useRef, useState, useEffect } from 'react'
import { getFromStorage, setToStorage } from '@/common/storage'
import { callEvent } from '@/common/utils/call-event'
import { SectionPanel } from '@/components/section-panel'
import { ToggleSwitch } from '@/components/toggle-switch.component'
import { SelectCity } from '@/layouts/setting/tabs/general/components/select-city'
import { WidgetSettingWrapper } from '@/layouts/widgets-settings/widget-settings-wrapper'
import type { WeatherSettings } from './weather.interface'
Expand All @@ -16,13 +14,6 @@ export function WeatherSetting() {
})
const isInitialLoad = useRef(true)

function updateWeatherSettings(key: keyof WeatherSettings, value: any) {
setSetting((per) => ({
...per,
[key]: value,
}))
}

useEffect(() => {
async function load() {
const settingFromStorage = await getFromStorage('weatherSettings')
Expand All @@ -44,84 +35,6 @@ export function WeatherSetting() {
return (
<WidgetSettingWrapper>
<SelectCity key={'selectCity'} />
<SectionPanel title="تنظیمات نمایش" size="sm">
<div className="flex flex-col space-y-4">
{/* Temperature Unit */}
<div className="flex flex-col space-y-2">
<div className="flex items-center justify-between">
<label
htmlFor="tempUnit"
className={'text-sm font-medium text-content'}
>
واحد دما
</label>
<div className="flex overflow-hidden border rounded-md border-white/10">
{[
{
value: 'metric',
label: '°C',
persianName: 'سلسیوس',
},
{
value: 'imperial',
label: '°F',
persianName: 'فارنهایت',
},
{
value: 'standard',
label: 'K',
persianName: 'کلوین',
},
].map((option) => (
<button
key={option.value}
className={`px-3 py-1.5 min-w-[40px] text-sm font-medium transition cursor-pointer ${
setting.temperatureUnit === option.value
? 'bg-blue-600 text-white'
: 'bg-base-200'
}`}
onClick={() =>
updateWeatherSettings(
'temperatureUnit',
option.value as any
)
}
>
<span className="ml-1">{option.persianName}</span>
<span>({option.label})</span>
</button>
))}
</div>
</div>
<div className={'text-xs font-light text-right text-muted'}>
{setting.temperatureUnit === 'metric' &&
'واحد سلسیوس در بیشتر کشورهای جهان استفاده می‌شود'}
{setting.temperatureUnit === 'imperial' &&
'واحد فارنهایت بیشتر در آمریکا استفاده می‌شود'}
{setting.temperatureUnit === 'standard' &&
'واحد کلوین در محاسبات علمی استفاده می‌شود'}
</div>
</div>

<div className="flex items-center justify-between">
<div>
<p className={'text-sm text-content'}>نمایش نام شهر</p>
<div className={'text-xs font-light text-muted'}>
نمایش یا عدم نمایش نام شهر در بالای ویجت
</div>
</div>
<ToggleSwitch
enabled={setting.enableShowName}
onToggle={() =>
updateWeatherSettings(
'enableShowName',
!setting.enableShowName
)
}
/>
</div>
</div>
</SectionPanel>
</WidgetSettingWrapper>
)
}
59 changes: 17 additions & 42 deletions src/layouts/widgets/weather/weather.layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import { getFromStorage, setToStorage } from '@/common/storage'
import { callEvent, listenEvent } from '@/common/utils/call-event'
import { listenEvent } from '@/common/utils/call-event'
import type {
FetchedForecast,
FetchedWeather,
Expand All @@ -13,9 +13,6 @@ import { useAuth } from '@/context/auth.context'
import { RequireAuth } from '@/components/auth/require-auth'
import { useGetWeatherByLatLon } from '@/services/hooks/weather/getWeatherByLatLon'
import { useGetForecastWeatherByLatLon } from '@/services/hooks/weather/getForecastWeatherByLatLon'
import { Button } from '@/components/button/button'
import { WidgetTabKeys } from '@/layouts/widgets-settings/constant/tab-keys'
import Analytics from '@/analytics'

export function WeatherLayout() {
const { isAuthenticated, user } = useAuth()
Expand All @@ -30,7 +27,9 @@ export function WeatherLayout() {
refetchInterval: 0,
units: weatherSettings?.temperatureUnit,
useAI: weatherSettings?.useAI,
enabled: isAuthenticated && user?.city?.id != null,
lat: user?.city?.id ? undefined : 35.696111,
lon: user?.city?.id ? undefined : 51.423056,
enabled: isAuthenticated,
})

const {
Expand All @@ -40,8 +39,10 @@ export function WeatherLayout() {
} = useGetForecastWeatherByLatLon({
count: 6,
units: weatherSettings?.temperatureUnit,
enabled: isAuthenticated && user?.city?.id != null,
enabled: isAuthenticated,
refetchInterval: 0,
lat: user?.city?.id ? undefined : 35.696111,
lon: user?.city?.id ? undefined : 51.423056,
})

useEffect(() => {
Expand Down Expand Up @@ -107,50 +108,24 @@ export function WeatherLayout() {
}
}, [user?.city?.id, isAuthenticated, refetchWeather, refetchForecast])

const onClickSetCity = () => {
callEvent('openWidgetsSettings', {
tab: WidgetTabKeys.weather_settings,
})
Analytics.event('weather_set_city_clicked')
}

if (!weatherSettings) return null

return (
<WidgetContainer>
<RequireAuth mode="preview">
{!user?.city?.id ? (
<div className="flex flex-col items-center justify-center w-full h-full p-4 text-center rounded-2xl">
<div className="mb-4 text-4xl">🌤️</div>
<p className="mb-4 text-sm leading-relaxed text-muted">
به‌دلیل تغییرات، لازم است شهر خود را دوباره در تنظیمات ویجت
انتخاب کنید
</p>
<Button
size="md"
isPrimary={true}
className="px-6 py-2 font-medium text-white transition-colors rounded-2xl"
onClick={onClickSetCity}
>
تنظیم شهر
</Button>
</div>
) : (
<div className="flex flex-col w-full h-full gap-2 py-1">
<CurrentWeatherBox
enabledShowName={weatherSettings.enableShowName}
fetchedWeather={weatherState || null}
<div className="flex flex-col w-full h-full gap-2 py-1">
<CurrentWeatherBox
fetchedWeather={weatherState || null}
temperatureUnit={weatherSettings.temperatureUnit}
/>

<div className="flex justify-between gap-0.5 px-1 rounded-2xl bg-base-200/40">
<Forecast
temperatureUnit={weatherSettings.temperatureUnit}
forecast={forecastWeather}
/>

<div className="flex justify-between gap-0.5 px-1 rounded-2xl bg-base-200/40">
<Forecast
temperatureUnit={weatherSettings.temperatureUnit}
forecast={forecastWeather}
/>
</div>
</div>
)}
</div>
</RequireAuth>
</WidgetContainer>
)
Expand Down
29 changes: 16 additions & 13 deletions src/services/hooks/weather/getForecastWeatherByLatLon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,34 @@ import type {
FetchedForecast,
TemperatureUnit,
} from '../../../layouts/widgets/weather/weather.interface'

async function fetchForecastWeatherByLatLon(
count?: number,
interface Options {
refetchInterval: number | null
count?: number
units?: TemperatureUnit
enabled: boolean
lat?: number
lon?: number
}
async function fetchForecastWeatherByLatLon(
options: Options
): Promise<FetchedForecast[]> {
const client = await getMainClient()

const response = await client.get<FetchedForecast[]>('/weather/forecast', {
params: {
...(count !== null && { count }),
...(units !== null && { units }),
...(options.count !== null && { count: options.count }),
...(options.units !== null && { units: options.units }),
...(options.lat !== null && { lat: options.lat }),
...(options.lon !== null && { lon: options.lon }),
},
})
return response.data
}

export function useGetForecastWeatherByLatLon(options: {
refetchInterval: number | null
count?: number
units?: TemperatureUnit
enabled: boolean
}) {
export function useGetForecastWeatherByLatLon(options: Options) {
return useQuery({
queryKey: ['ForecastGetWeatherByLatLon'],
queryFn: () => fetchForecastWeatherByLatLon(options.count, options.units),
queryKey: ['ForecastGetWeatherByLatLon', options],
queryFn: () => fetchForecastWeatherByLatLon(options),
refetchInterval: options.refetchInterval || false,
enabled: options.enabled,
})
Expand Down
17 changes: 9 additions & 8 deletions src/services/hooks/weather/getWeatherByLatLon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { getMainClient } from '@/services/api'
import type { FetchedWeather } from '../../../layouts/widgets/weather/weather.interface'

type units = 'standard' | 'metric' | 'imperial'
async function fetchWeatherByLatLon(
units?: units,
useAI?: boolean
): Promise<FetchedWeather> {
async function fetchWeatherByLatLon(op: GetWeatherByLatLon): Promise<FetchedWeather> {
const client = await getMainClient()

const response = await client.get<FetchedWeather>('/weather/current', {
params: {
units,
useAI,
lat: op.lat,
lon: op.lon,
units: op.units,
useAI: op.useAI,
},
})
return response.data
Expand All @@ -24,11 +23,13 @@ type GetWeatherByLatLon = {
useAI?: boolean
refetchInterval: number | null
enabled: boolean
lat?: number
lon?: number
}
export function useGetWeatherByLatLon(options: GetWeatherByLatLon) {
return useQuery({
queryKey: ['getWeatherByLatLon'],
queryFn: () => fetchWeatherByLatLon(options.units, options.useAI),
queryKey: ['getWeatherByLatLon', options],
queryFn: () => fetchWeatherByLatLon(options),
refetchInterval: options?.refetchInterval || false,
enabled: options.enabled,
staleTime: ms('5m'),
Expand Down