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
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lynn",
"version": "26.0.0",
"version": "27.0.0",
"private": true,
"dependencies": {
"@date-io/dayjs": "^2.16.0",
Expand All @@ -14,6 +14,8 @@
"dayjs": "^1.11.7",
"eorzea-time": "^3.0.0",
"i18next": "^25.2.1",
"i18next-browser-languagedetector": "^8.2.0",
"i18next-resources-to-backend": "^1.2.1",
"leaflet": "^1.9.4",
"leaflet-draw": "^1.0.4",
"lynn-eorzea-weather": "^3.3.0",
Expand Down
Binary file added public/assets/maps/markers/ocSoulShard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 19 additions & 17 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import './App.css';
import { Helmet } from 'react-helmet';
import React, { useEffect } from 'react';
import { I18nextProvider } from 'react-i18next';

import createTheme from '@mui/material/styles/createTheme';
import ThemeProvider from '@mui/material/styles/ThemeProvider';
Expand All @@ -10,6 +11,8 @@ import {
useParams,
} from 'react-router-dom';

import i18n from './i18n';

import MainPageComponent from './MainPageComponent';
import ForecastMainComponent from './forecast/ForecastMainComponent';
import BAMainComponent from './ba/BAMainComponent';
Expand Down Expand Up @@ -375,23 +378,22 @@ function App() {
});

return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<Helmet>
<title>FFXIV Field Operations Assistant - forays.info</title>
<meta name="description" content="A collection of tools for Final Fantasy XIV side content created by Lynn Kaneko @ Exodus" />
<meta property="og:title" content="forays.info" />
<meta property="og:url" content="https://forays.info/" />
<meta property="og:image" content="https://forays.info/logo.png" />
<meta property="og:description" content="A collection of tools for Final Fantasy XIV side content created by Lynn Kaneko @ Exodus" />
<meta property="og:site_name" content="forays.info" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="@reflexyui" />
</Helmet>
<RouterProvider router={router} />
</ThemeProvider>
</ColorModeContext.Provider>

<I18nextProvider i18n={i18n}>
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<Helmet>
<title>FFXIV Field Operations Assistant - forays.info</title>
<meta name="description" content="A collection of tools for Final Fantasy XIV side content created by Lynn Kaneko @ Exodus" />
<meta property="og:title" content="forays.info" />
<meta property="og:url" content="https://forays.info/" />
<meta property="og:image" content="https://forays.info/logo.png" />
<meta property="og:description" content="A collection of tools for Final Fantasy XIV side content created by Lynn Kaneko @ Exodus" />
<meta property="og:site_name" content="forays.info" />
</Helmet>
<RouterProvider router={router} />
</ThemeProvider>
</ColorModeContext.Provider>
</I18nextProvider>
);
}

Expand Down
9 changes: 5 additions & 4 deletions src/FooterComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import SvgIcon from '@mui/material/SvgIcon';
import Typography from '@mui/material/Typography';
import GitHubIcon from '@mui/icons-material/GitHub';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';

export default function FooterComponent({ includePadding = true }) {
const navigate = useNavigate();
const { t } = useTranslation('common');

return (
<Box width="100%">
<Stack
Expand All @@ -21,9 +24,7 @@ export default function FooterComponent({ includePadding = true }) {
alignItems="center"
>
<Typography variant="subtitle2" fontSize={12} maxWidth={600} textAlign="left">
FINAL FANTASY XIV © 2010 - 2025 SQUARE ENIX CO., LTD. FINAL FANTASY, FINAL FANTASY
XIV, and FFXIV are registered trademarks or trademarks of Square Enix Holdings Co.,
Ltd. All material used under license.
{t('footer.copyright')}
</Typography>
<Box flexGrow={1} />
<Stack direction="row">
Expand Down Expand Up @@ -72,7 +73,7 @@ export default function FooterComponent({ includePadding = true }) {
}}
>
<Typography variant="subtitle2" fontSize={12} pl={1} pr={1}>
{`Version ${process.env.REACT_APP_VERSION}`}
{t('footer.version', { ver: process.env.REACT_APP_VERSION })}
</Typography>
</Button>
</Stack>
Expand Down
75 changes: 37 additions & 38 deletions src/MainPageComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import Paper from '@mui/material/Paper';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { Helmet } from 'react-helmet';
import { useTranslation, Trans } from 'react-i18next';

export default function MainPageComponent() {
const { t } = useTranslation('common');

function getSiteName() {
const host = window.location.hostname;

Expand Down Expand Up @@ -84,46 +87,44 @@ export default function MainPageComponent() {
<Paper elevation={3}>
<Stack p={5} spacing={2}>
<Typography textAlign="left" fontSize={textSize}>
Welcome to
{' '}
{getSiteName()}
, a home for tools to help with Final Fantasy XIV side
content - including the Occult Crescent (Forked Tower), Eureka (The Baldesion
Arsenal), and Bozja (Delubrum Reginae Savage). Find out how to build and gather
materials for Lost Actions and Logos Actions, what to bring for The Baldesion
Arsenal or Delubrum Reginae Savage runs, when the next Cassie or Crab spawn is,
and more!
<Trans i18nKey="main.intro.p1" ns="common" values={{ sitename: getSiteName() }} />
</Typography>
<Typography textAlign="left" fontSize={textSize}>
Looking for a group to run Forked Tower, BA, or DRS with? Most of the content on this site
was designed for runs on
{' '}
<a
href="https://discord.gg/thehelplines"
target="_blank"
rel="noreferrer"
>
The Help Lines

</a>
{' '}
on Primal.
<Trans
i18nKey="main.intro.p2"
ns="common"
components={[
<a
href="https://discord.gg/thehelplines"
target="_blank"
rel="noreferrer"
>
The Help Lines
</a>,
]}
/>
</Typography>
<Typography textAlign="left" fontSize={textSize}>
Built by Lynn Kaneko @ Exodus. Issues/suggestions? You can reach out to me
on Discord (@lynnkaneko).
<Trans i18nKey="main.intro.p3" ns="common" />
</Typography>
<Typography textAlign="left" fontSize={textSize}>
Home page artwork by
{' '}
<a
href={pageTheme.imageCreditLink}
target="_blank"
rel="noreferrer"
>
{pageTheme.imageCredit}
!
</a>
<Trans
i18nKey="main.intro.p4"
ns="common"
components={[
<a
href={pageTheme.imageCreditLink}
target="_blank"
rel="noreferrer"
>
{pageTheme.imageCredit}
!
</a>,
]}
values={{
artist: pageTheme.imageCredit,
}}
/>
</Typography>
</Stack>
</Paper>
Expand All @@ -148,13 +149,11 @@ export default function MainPageComponent() {
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="@reflexyui" />
<title>
{getSiteName()}
{' '}
- FFXIV Field Operations Assistant
{t('main.header.title', { sitename: getSiteName() })}
</title>
</Helmet>
<Box>
<Typography variant="h3" fontWeight={700}>FFXIV Field Operations Assistant</Typography>
<Typography variant="h3" fontWeight={700}><Trans i18nKey="main.title" ns="common" /></Typography>
</Box>
<Box pl={5} sx={{ display: { xs: 'none', md: 'block' } }}>
<Stack direction="row">
Expand Down
76 changes: 57 additions & 19 deletions src/SettingsPopoverComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';

import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
Expand All @@ -8,16 +9,36 @@ import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import Stack from '@mui/material/Stack';
import ToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import Typography from '@mui/material/Typography';

import SettingsApplicationsIcon from '@mui/icons-material/SettingsApplications';
import {
FormControlLabel, Radio, RadioGroup,
} from '@mui/material';
import { changeLanguage } from './i18n';
import UniversalisRegionPicker from './UniversalisRegionPicker';

export default function SettingsPopoverComponent({ setColorMode }) {
const { t } = useTranslation('common');
const [open, setOpen] = React.useState(false);

/**
const getFlag = () => {
const language = localStorage.getItem('i18nextLng').substring(0, 2);

switch (language) {
case 'fr':
return '🇫🇷';
case 'de':
return '🇩🇪';
case 'jp':
return '🇯🇵';
default:
return '🇨🇦';
}
};
*/

const handleSettingsButtonClick = () => {
setOpen(true);
};
Expand All @@ -38,13 +59,15 @@ export default function SettingsPopoverComponent({ setColorMode }) {
onClick={(e) => handleSettingsButtonClick(e)}
>
<SettingsApplicationsIcon sx={{ color: 'white' }} />
{ /* <Typography fontWeight={600} fontSize={16}>{getFlag()}</Typography> */ }
<Box>
<Typography color="#fff" fontWeight={600} fontSize={16}>Settings</Typography>
<Typography color="#fff" fontWeight={600} fontSize={16}>{t('settings.title')}</Typography>
</Box>
</Stack>
);

const [theme, setTheme] = React.useState(localStorage.getItem('theme'));
const [language, setLanguage] = React.useState(localStorage.getItem('language') || 'en');

const handleThemeChange = useCallback((event, newTheme) => {
if (newTheme) {
Expand All @@ -54,40 +77,55 @@ export default function SettingsPopoverComponent({ setColorMode }) {
}
}, [localStorage, setTheme]);

const handleLanguageChange = useCallback((event, newLanguage) => {
if (newLanguage) {
setLanguage(newLanguage);
changeLanguage(newLanguage);
}
}, [setLanguage, changeLanguage]);

return (
<>
<Box flexGrow={1}>
{settingsButton}
</Box>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Settings</DialogTitle>
<DialogTitle>{t('settings.title')}</DialogTitle>
<DialogContent>
<DialogContentText>Site Theme</DialogContentText>
<ToggleButtonGroup
<DialogContentText>{t('settings.theme_title')}</DialogContentText>
<RadioGroup
row
value={theme}
exclusive
onChange={handleThemeChange}
>
<ToggleButton value="light">
Light
</ToggleButton>
<ToggleButton value="dark">
Dark
</ToggleButton>
<ToggleButton value="system">
System
</ToggleButton>
</ToggleButtonGroup>
<DialogContentText pt={2}>Universalis Region</DialogContentText>
<FormControlLabel value="light" control={<Radio />} label={t('settings.themes.light')} />
<FormControlLabel value="dark" control={<Radio />} label={t('settings.themes.dark')} />
<FormControlLabel value="system" control={<Radio />} label={t('settings.themes.system')} />
</RadioGroup>

<DialogContentText pt={2}>{t('settings.language_title')}</DialogContentText>

<RadioGroup
row
value={language}
onChange={handleLanguageChange}
>
<FormControlLabel value="en" control={<Radio />} label="🇨🇦 English" />
<FormControlLabel value="fr" control={<Radio />} disabled label="🇫🇷 Français" />
<FormControlLabel value="de" control={<Radio />} label="🇩🇪 Deutsch" />
<FormControlLabel value="jp" control={<Radio />} disabled label="🇯🇵 日本語" />
</RadioGroup>

<DialogContentText pt={2}>{t('settings.universalis_region_title')}</DialogContentText>
<UniversalisRegionPicker />
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>
Close
{t('common.close')}
</Button>
</DialogActions>
</Dialog>
</>

);
}
Loading
Loading