mirror of
https://github.com/mue/mue.git
synced 2026-07-19 06:54:10 +02:00
feat(LocationSearch): add LocationSearch component for improved location input
This commit is contained in:
@@ -13,7 +13,21 @@ import { getWeather } from './api/getWeather.js';
|
||||
import './weather.scss';
|
||||
|
||||
const WeatherWidget = memo(() => {
|
||||
const [location, setLocation] = useState(localStorage.getItem('location') || 'London');
|
||||
const [location, setLocation] = useState(() => {
|
||||
const stored = localStorage.getItem('location');
|
||||
if (!stored) return 'London';
|
||||
|
||||
// Try parsing as new JSON format
|
||||
try {
|
||||
const parsed = JSON.parse(stored);
|
||||
if (parsed && typeof parsed === 'object') {
|
||||
return parsed;
|
||||
}
|
||||
} catch {
|
||||
// Legacy string format
|
||||
}
|
||||
return stored;
|
||||
});
|
||||
const [done, setDone] = useState(false);
|
||||
const [weatherData, setWeatherData] = useState({});
|
||||
|
||||
@@ -57,10 +71,14 @@ const WeatherWidget = memo(() => {
|
||||
return <WeatherSkeleton weatherType={weatherType} />;
|
||||
}
|
||||
|
||||
// Get display name from location (handles both object and string formats)
|
||||
const locationDisplay =
|
||||
typeof location === 'object' ? location.displayName || location.name : location;
|
||||
|
||||
if (!weatherData.weather) {
|
||||
return (
|
||||
<div className="weather">
|
||||
<span className="loc">{location}</span>
|
||||
<span className="loc">{locationDisplay}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -87,7 +105,7 @@ const WeatherWidget = memo(() => {
|
||||
amount: `${formatNumber(weatherData.weather.feels_like)}${weatherData.temp_text}`,
|
||||
})}
|
||||
</span>
|
||||
<span className="loc">{location}</span>
|
||||
<span className="loc">{locationDisplay}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,19 @@ export const getWeather = async (location) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(variables.constants.API_URL + `/weather?city=${location}`);
|
||||
// Build URL based on location type
|
||||
let url;
|
||||
if (typeof location === 'object' && location.lat && location.lon) {
|
||||
// New format: use coordinates (preferred)
|
||||
url = `${variables.constants.API_URL}/weather?lat=${location.lat}&lon=${location.lon}`;
|
||||
} else {
|
||||
// Legacy format: use city name string
|
||||
const cityName =
|
||||
typeof location === 'object' ? location.displayName || location.name : location;
|
||||
url = `${variables.constants.API_URL}/weather?city=${encodeURIComponent(cityName)}`;
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('Weather API response not ok:', response.status, response.statusText);
|
||||
|
||||
@@ -1,59 +1,19 @@
|
||||
import { useCallback } from 'react';
|
||||
import { MdAutoAwesome } from 'react-icons/md';
|
||||
import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Layout/Settings';
|
||||
import { useLocalStorageState } from 'utils/useLocalStorageState';
|
||||
import { Radio, Dropdown, Checkbox } from 'components/Form/Settings';
|
||||
import { Radio, Dropdown, Checkbox, LocationSearch } from 'components/Form/Settings';
|
||||
import variables from 'config/variables';
|
||||
|
||||
const useWeatherSettings = () => {
|
||||
const [location, setLocation] = useLocalStorageState('location', '');
|
||||
const [windSpeed, setWindSpeed] = useLocalStorageState('windspeed', 'true');
|
||||
|
||||
const showReminder = useCallback(() => {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
localStorage.setItem('showReminder', true);
|
||||
}, []);
|
||||
|
||||
const changeLocation = (e) => {
|
||||
localStorage.removeItem('currentWeather');
|
||||
setLocation(e.target.value);
|
||||
showReminder();
|
||||
};
|
||||
|
||||
const getAutoLocation = useCallback(() => {
|
||||
setLocation(variables.getMessage('modals.main.loading'));
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
async (position) => {
|
||||
const data = await (
|
||||
await fetch(
|
||||
`${variables.constants.API_URL}/gps?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}`,
|
||||
)
|
||||
).json();
|
||||
setLocation(data[0].name);
|
||||
showReminder();
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
},
|
||||
);
|
||||
}, [setLocation, showReminder]);
|
||||
|
||||
return {
|
||||
location,
|
||||
windSpeed: windSpeed !== 'true',
|
||||
setWindSpeed,
|
||||
changeLocation,
|
||||
getAutoLocation,
|
||||
};
|
||||
};
|
||||
|
||||
const WeatherOptions = () => {
|
||||
const { location, windSpeed, setWindSpeed, changeLocation, getAutoLocation } =
|
||||
useWeatherSettings();
|
||||
const { windSpeed, setWindSpeed } = useWeatherSettings();
|
||||
const weatherType = localStorage.getItem('weatherType');
|
||||
const WEATHER_SECTION = 'modals.main.settings.sections.weather';
|
||||
|
||||
@@ -81,26 +41,12 @@ const WeatherOptions = () => {
|
||||
<Row>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.location`)} />
|
||||
<Action>
|
||||
<div className="text-field-container">
|
||||
<div className="text-field">
|
||||
<div className="text-field-header">
|
||||
<label className="text-field-label">
|
||||
{variables.getMessage(`${WEATHER_SECTION}.location`)}
|
||||
</label>
|
||||
<span className="text-field-reset" onClick={getAutoLocation}>
|
||||
<MdAutoAwesome />
|
||||
{variables.getMessage(`${WEATHER_SECTION}.auto`)}
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
className="text-field-input"
|
||||
value={location}
|
||||
onChange={changeLocation}
|
||||
placeholder="London"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<LocationSearch
|
||||
label={variables.getMessage(`${WEATHER_SECTION}.location`)}
|
||||
name="location"
|
||||
category="weather"
|
||||
placeholder="London"
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user