Skip to content

Commit

Permalink
Lint frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
nsychev committed Nov 14, 2024
1 parent cf5e623 commit a48a7cf
Show file tree
Hide file tree
Showing 31 changed files with 384 additions and 279 deletions.
4 changes: 4 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import stylistic from '@stylistic/eslint-plugin'

export default tseslint.config(
{ ignores: ['dist'] },
Expand All @@ -23,6 +24,7 @@ export default tseslint.config(
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
'@stylistic': stylistic
},
rules: {
...react.configs.recommended.rules,
Expand All @@ -32,6 +34,8 @@ export default tseslint.config(
'warn',
{ allowConstantExport: true },
],
...stylistic.configs['recommended-flat'].rules,
'@stylistic/semi': ['error', 'always']
},
},
)
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@stylistic/eslint-plugin": "^2.10.1",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
Expand Down
27 changes: 27 additions & 0 deletions frontend/pnpm-lock.yaml

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

66 changes: 37 additions & 29 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { useEffect, useState, useCallback, useRef } from 'react'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { Info, InfoHolder, WebSocketMessage } from './types'
import backendUrls from './util/backendUrls'
import Navbar from './components/Navbar'
import Footer from './components/Footer'
import Login from './pages/Login'
import Register from './pages/Register'
import VolunteerAccess from './pages/VolunteerAccess'
import ActiveBalloons from './pages/ActiveBalloons'
import { GlobalError } from './components/GlobalError'
import { useEffect, useState, useCallback, useRef } from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Info, InfoHolder, WebSocketMessage } from './types';
import backendUrls from './util/backendUrls';
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import Login from './pages/Login';
import Register from './pages/Register';
import VolunteerAccess from './pages/VolunteerAccess';
import ActiveBalloons from './pages/ActiveBalloons';
import { GlobalError } from './components/GlobalError';
import { Provider } from 'react-redux';
import { store } from './store/store';
import { useDispatch } from 'react-redux';
import { setContest } from './store/contestSlice';
import { updateBalloon, deleteBalloon, setBalloons } from './store/balloonsSlice';
import { WebSocketContext } from './contexts/WebSocketContext';
import DeliveredBalloons from './pages/DeliveredBalloons'
import VolunteerRating from './pages/VolunteerRating'
import Standings from './pages/Standings'
import ConnectionStatus from './components/ConnectionStatus'
import DeliveredBalloons from './pages/DeliveredBalloons';
import VolunteerRating from './pages/VolunteerRating';
import Standings from './pages/Standings';
import ConnectionStatus from './components/ConnectionStatus';

const RECONNECT_DELAY = 3000; // 3 seconds

Expand All @@ -32,7 +32,8 @@ function AppContent() {
const setTokenWithStorage = useCallback((newToken: string | null) => {
if (newToken) {
localStorage.setItem('token', newToken);
} else {
}
else {
localStorage.removeItem('token');
}
setToken(newToken);
Expand All @@ -41,15 +42,18 @@ function AppContent() {
const fetchInfo = useCallback(async () => {
try {
const response = await fetch(backendUrls.getInfo(), {
headers: token ? {
Authorization: `Bearer ${token}`
} : undefined
headers: token
? {
Authorization: `Bearer ${token}`,
}
: undefined,
});
const data = await response.json() as Info;
setInfo({ ...data, status: 'success' })
} catch (exc) {
console.error('Error fetching info:', exc)
setInfo(prevInfo => ({ ...prevInfo, status: 'error' }))
setInfo({ ...data, status: 'success' });
}
catch (exc) {
console.error('Error fetching info:', exc);
setInfo(prevInfo => ({ ...prevInfo, status: 'error' }));
}
}, [token]);

Expand All @@ -59,7 +63,7 @@ function AppContent() {

const createWebSocket = useCallback(() => {
const websocket = new WebSocket(
`${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}${backendUrls.eventStream()}`
`${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}${backendUrls.eventStream()}`,
);

websocket.onopen = () => {
Expand All @@ -85,7 +89,7 @@ function AppContent() {

websocket.onmessage = (event: MessageEvent<string>) => {
const message = JSON.parse(event.data) as WebSocketMessage;

if ('type' in message) {
switch (message.type) {
case 'contestUpdated':
Expand All @@ -98,7 +102,8 @@ function AppContent() {
dispatch(deleteBalloon(message.runId));
break;
}
} else {
}
else {
// Handle initial State
const state = message;
dispatch(setContest(state.contest));
Expand Down Expand Up @@ -152,9 +157,12 @@ function AppContent() {
<Route path="/access" element={<VolunteerAccess infoHolder={infoHolder} />} />
<Route path="/login" element={<Login infoHolder={infoHolder} />} />
<Route path="/register" element={<Register infoHolder={infoHolder} />} />
<Route path="*" element={
<GlobalError title="404" message="Такой страницы не существует." />
} />
<Route
path="*"
element={
<GlobalError title="404" message="Такой страницы не существует." />
}
/>
</Routes>
<Footer infoHolder={infoHolder} />
</WebSocketContext.Provider>
Expand Down
58 changes: 33 additions & 25 deletions frontend/src/components/BalloonList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import ProblemBox from './ProblemBox';
import { useContestMaps } from '../hooks/useContestMaps';

const BalloonRow = ({ balloon, problem, team, actions }: {
balloon: Balloon;
problem: Problem;
team: Team;
actions: (balloon: Balloon) => React.ReactNode;
balloon: Balloon
problem: Problem
team: Team
actions: (balloon: Balloon) => React.ReactNode
}) => {
const actionContent = actions(balloon);

const content = useMemo(() => (
<div className="balloon-row">
<ProblemBox problem={problem} />
Expand All @@ -25,33 +25,41 @@ const BalloonRow = ({ balloon, problem, team, actions }: {
};

const BalloonList = ({ title, balloons, contest, actions }: {
title: string;
balloons: Balloon[];
contest: Contest;
actions: (balloon: Balloon) => React.ReactNode;
title: string
balloons: Balloon[]
contest: Contest
actions: (balloon: Balloon) => React.ReactNode
}) => {
const { problemsMap, teamMap } = useContestMaps(contest);

if (balloons.length === 0) {
return null;
}

return <>
<h2>{title} ({balloons.length})</h2>
<div className="balloon-list">
{balloons.map(balloon => {
return (
<BalloonRow
key={balloon.runId}
balloon={balloon}
problem={problemsMap[balloon.problemId]}
team={teamMap[balloon.teamId]}
actions={actions}
/>
);
})}
</div>
</>;
return (
<>
<h2>
{title}
{' '}
(
{balloons.length}
)
</h2>
<div className="balloon-list">
{balloons.map((balloon) => {
return (
<BalloonRow
key={balloon.runId}
balloon={balloon}
problem={problemsMap[balloon.problemId]}
team={teamMap[balloon.teamId]}
actions={actions}
/>
);
})}
</div>
</>
);
};

export default BalloonList;
6 changes: 3 additions & 3 deletions frontend/src/components/ConnectionStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useWebSocket } from '../contexts/WebSocketContext';
import { useState, useEffect } from 'react';
import { InfoHolder } from '../types';

const ConnectionStatus = ({ infoHolder } : { infoHolder: InfoHolder}) => {
const ConnectionStatus = ({ infoHolder }: { infoHolder: InfoHolder }) => {
const ws = useWebSocket();
const [connectionState, setConnectionState] = useState<number>();

Expand Down Expand Up @@ -39,8 +39,8 @@ const ConnectionStatus = ({ infoHolder } : { infoHolder: InfoHolder}) => {
if (connectionState === WebSocket.CLOSED || connectionState === WebSocket.CLOSING) {
return <div className="connection-status lost" role="alert">Соединение потеряно. Переподключение...</div>;
}

return null;
};

export default ConnectionStatus;
export default ConnectionStatus;
15 changes: 10 additions & 5 deletions frontend/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ const Footer = ({ infoHolder }: { infoHolder: InfoHolder }) => {

return (
<footer>
{infoHolder.info?.login && <>
<span>Вы вошли как <strong>{infoHolder.info.login}</strong> </span>
<a onClick={handleLogout}>Выйти</a>
</>}
{infoHolder.info?.login && (
<>
<span>
Вы вошли как
<strong>{infoHolder.info.login}</strong>
</span>
<a onClick={handleLogout}>Выйти</a>
</>
)}
<span>
<a href="https://github.com/nsychev/balloons-reborn" target="_blank" rel="noopener noreferrer">Open&nbsp;source</a>
</span>
Expand All @@ -23,4 +28,4 @@ const Footer = ({ infoHolder }: { infoHolder: InfoHolder }) => {
);
};

export default Footer;
export default Footer;
4 changes: 2 additions & 2 deletions frontend/src/components/GlobalError.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
interface GlobalErrorProps {
title: string;
message: string;
title: string
message: string
}

export function GlobalError({ title, message }: GlobalErrorProps) {
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/components/HallSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ const HallSelector = () => {

return (
<div className="hall-dropdown" ref={dropdownRef}>
<span
className="hall-dropdown-toggle"
<span
className="hall-dropdown-toggle"
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-haspopup="true"
Expand All @@ -44,8 +44,8 @@ const HallSelector = () => {
</span>
{isOpen && (
<ul className="hall-dropdown-menu" role="menu">
<li
className={!selectedHall ? 'active' : ''}
<li
className={!selectedHall ? 'active' : ''}
onClick={() => handleSelect(null)}
>
Все холлы
Expand All @@ -56,7 +56,9 @@ const HallSelector = () => {
className={selectedHall === hall ? 'active' : ''}
onClick={() => handleSelect(hall)}
>
Холл {hall}
Холл
{' '}
{hall}
</li>
))}
</ul>
Expand All @@ -65,4 +67,4 @@ const HallSelector = () => {
);
};

export default HallSelector;
export default HallSelector;
Loading

0 comments on commit a48a7cf

Please sign in to comment.