v3 release #75

Merged
alekswilc merged 63 commits from v3 into main 2024-12-13 20:29:17 +01:00
11 changed files with 243 additions and 114 deletions
Showing only changes of commit 05c767b521 - Show all commits

View File

@ -5,7 +5,6 @@ import { Loader } from "./components/mini/loaders/PageLoader.tsx";
import { PageTitle } from "./components/mini/util/PageTitle.tsx";
import Chart from "./old/Chart.tsx";
import { Home } from "./pages/Home";
import Settings from "./old/Settings.tsx";
import Alerts from "./old/UiElements/Alerts.tsx";
import Buttons from "./old/UiElements/Buttons.tsx";
import DefaultLayout from "./layout/DefaultLayout";
@ -15,12 +14,17 @@ import { StationLeaderboard } from "./pages/leaderboard/StationsLeaderboard.tsx"
import { TrainLogs } from "./pages/logs/TrainLogs.tsx";
import { StationLogs } from "./pages/logs/StationLogs.tsx";
import { Profile } from "./pages/profile/Profile.tsx";
import { Log } from "./pages/log/Log.tsx";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import useColorMode from "./hooks/useColorMode.tsx";
function App()
{
const [ loading, setLoading ] = useState<boolean>(true);
const { pathname } = useLocation();
const [ theme ] = useColorMode();
useEffect(() =>
{
window.scrollTo(0, 0);
@ -34,105 +38,119 @@ function App()
return loading ? (
<Loader/>
) : (
<DefaultLayout>
<Routes>
<Route
index
element={
<>
<PageTitle title="simrail.alekswilc.dev | Home"/>
<Home/>
</>
}
/>
<Route
path="/leaderboard/trains"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Train Leaderboard"/>
<TrainLeaderboard/>
</>
}
/>
<>
<ToastContainer
position="bottom-right"
autoClose={ 1500 }
hideProgressBar={ false }
newestOnTop={ false }
closeOnClick
rtl={ false }
pauseOnHover
theme={ theme as "light" | "dark" }
/>
<DefaultLayout>
<Routes>
<Route
index
element={
<>
<PageTitle title="simrail.alekswilc.dev | Home"/>
<Home/>
</>
}
/>
<Route
path="/leaderboard/trains"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Train Leaderboard"/>
<TrainLeaderboard/>
</>
}
/>
<Route
path="/logs/trains"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Train logs"/>
<TrainLogs/>
</>
}
/>
<Route
path="/logs/trains"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Train logs"/>
<TrainLogs/>
</>
}
/>
<Route
path="/logs/stations"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Station logs"/>
<StationLogs/>
</>
}
/>
<Route
path="/logs/stations"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Station logs"/>
<StationLogs/>
</>
}
/>
<Route
path="/leaderboard/stations"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Stations Leaderboard"/>
<StationLeaderboard/>
</>
}
/>
<Route
path="/leaderboard/stations"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Stations Leaderboard"/>
<StationLeaderboard/>
</>
}
/>
<Route
path="/profile/:id"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Stations Leaderboard"/>
<Profile/>
</>
}
/>
<Route
path="/profile/:id"
element={
<>
<PageTitle title="simrail.alekswilc.dev | User Profile"/>
{/* page title is modified after API response */ }
<Profile/>
</>
}
/>
<Route
path="/settings"
element={
<>
<PageTitle title="Settings | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Settings/>
</>
}
/>
<Route
path="/chart"
element={
<>
<PageTitle title="Basic Chart | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Chart/>
</>
}
/>
<Route
path="/ui/alerts"
element={
<>
<PageTitle title="Alerts | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Alerts/>
</>
}
/>
<Route
path="/ui/buttons"
element={
<>
<PageTitle title="Buttons | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Buttons/>
</>
}
/>
</Routes>
</DefaultLayout>
<Route
path="/log/:id"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Log"/>
{/* page title is modified after API response */ }
<Log/>
</>
}
/>
<Route
path="/chart"
element={
<>
<PageTitle title="Basic Chart | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Chart/>
</>
}
/>
<Route
path="/ui/alerts"
element={
<>
<PageTitle title="Alerts | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Alerts/>
</>
}
/>
<Route
path="/ui/buttons"
element={
<>
<PageTitle title="Buttons | TailAdmin - Tailwind CSS Admin Dashboard Template"/>
<Buttons/>
</>
}
/>
</Routes>
</DefaultLayout>
</>
);
}

View File

@ -18,11 +18,11 @@ export const LoadError = () =>
</div>
<div className="w-full">
<h5 className="mb-3 font-semibold text-[#B45454]">
{ t("contentloader.error.header") }
{ t("content_loader.error.header") }
</h5>
<ul>
<li className="leading-relaxed text-[#CD5D5D]">
{ t("contentloader.error.description") }
{ t("content_loader.error.description") }
</li>
<li className="leading-relaxed text-[#CD5D5D]">
<div className="pt-4">
@ -30,12 +30,12 @@ export const LoadError = () =>
<div className="mb-7.5 flex flex-wrap gap-4">
<Link
className="inline-flex items-center justify-center rounded-md bg-primary py-2 px-8 text-center font-medium text-white hover:bg-opacity-70 lg:px-6 xl:px-8"
to="https://git.alekswilc.dev/simrail/simrail.alekswilc.dev/issues/new">{ t("contentloader.error.report") }</Link>
to="https://git.alekswilc.dev/simrail/simrail.alekswilc.dev/issues/new">{ t("content_loader.error.report") }</Link>
<Link
className="inline-flex items-center justify-center rounded-md bg-primary py-2 px-8 text-center font-medium text-white hover:bg-opacity-70 lg:px-6 xl:px-8"
to="#"
onClick={ () => window.location.reload() }>{ t("contentloader.error.refresh") }</Link>
onClick={ () => window.location.reload() }>{ t("content_loader.error.refresh") }</Link>
</div>
</div>

View File

@ -13,8 +13,8 @@ export const StationTable = ({ stations, error }: { stations: TLeaderboardRecord
return (
<>
{ error === 2 && <WarningAlert title={ t("contentloader.notfound.header") }
description={ t("contentloader.notfound.description") }/> }
{ error === 2 && <WarningAlert title={ t("content_loader.notfound.header") }
description={ t("content_loader.notfound.description") }/> }
{ error === 0 && <ContentLoader/> }
{ error === 1 && <div
className="rounded-sm border border-stroke bg-white px-5 pt-6 pb-2.5 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5 xl:pb-1">

View File

@ -11,8 +11,8 @@ export const TrainTable = ({ trains, error }: { trains: TLeaderboardRecord[], er
return (
<>
{ error === 2 && <WarningAlert title={ t("contentloader.notfound.header") }
description={ t("contentloader.notfound.description") }/> }
{ error === 2 && <WarningAlert title={ t("content_loader.notfound.header") }
description={ t("content_loader.notfound.description") }/> }
{ error === 0 && <ContentLoader/> }
{ error === 1 && <div
className="rounded-sm border border-stroke bg-white px-5 pt-6 pb-2.5 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5 xl:pb-1">

View File

@ -0,0 +1,89 @@
import { useTranslation } from "react-i18next";
import { TLogStationData } from "../../../types/log.ts";
import dayjs from "dayjs";
import { toast } from "react-toastify";
export const StationLog = ({ data }: { data: TLogStationData }) =>
{
const copyLink = () =>
{
void navigator.clipboard.writeText(location.href);
toast.success("Skopiowano link do schowka!");
};
const report = () =>
{
toast.info("Do schowka skopiowano dane wyjścia z posterunku, możesz ich użyć do wysłania na kanale #multiplayer-help-requests na oficjalnym serwerze Discord gry simrail.", {
autoClose: 5000,
});
void navigator.clipboard.writeText(`;user: \`${ data.userUsername }\`\n;steam: \`${ data.userSteamId }\`\n;left: <t:${ data.leftDate }>${ data.joinedDate ? `\n;joined: <t:${ data.joinedDate }>` : "" }\n;station: \`${ data.stationName }\`\n;link: ${ location.href }\n\n`);
};
const { t } = useTranslation();
return <div
className="overflow-hidden rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark">
<div className="px-4 pt-6 text-center lg:pb-8 xl:pb-11.5">
<div
className="mx-auto w-full max-w-30 rounded-full bg-white/20 p-1 backdrop-blur sm:h-44 sm:max-w-44 sm:p-3">
<div className="relative drop-shadow-2">
<img className="rounded-full" src={ data.userAvatar } alt="profile"/>
</div>
</div>
<div className="mt-4">
<h3 className="mb-1.5 text-2xl font-semibold text-black dark:text-white">
{ data.userUsername }
</h3>
{/*<div*/ }
{/* className="mx-auto mt-4.5 mb-5.5 grid max-w-94 grid-cols-2 rounded-md border border-stroke py-2.5 shadow-1 dark:border-strokedark dark:bg-[#37404F]">*/ }
{/* <div*/ }
{/* className="flex flex-col items-center justify-center gap-1 border-r border-stroke px-4 dark:border-strokedark xsm:flex-row">*/ }
{/* <span className="font-semibold text-black dark:text-white">*/ }
{/* { Math.floor(data.player.trainDistance / 1000) }km*/ }
{/* </span>*/ }
{/* <span className="text-sm text-wrap">{ t("profile.stats.distance") }</span>*/ }
{/* </div>*/ }
{/* <div*/ }
{/* className="flex flex-col items-center justify-center gap-1 border-r border-stroke px-4 dark:border-strokedark xsm:flex-row">*/ }
{/* <span className="font-semibold text-black dark:text-white">*/ }
{/* { Math.floor(data.player.dispatcherTime / 3600000) }h*/ }
{/* </span>*/ }
{/* <span className="text-sm text-wrap">{ t("profile.stats.time") }</span>*/ }
{/* </div>*/ }
{/*</div>*/ }
</div>
</div>
<div className="bg-white px-5 pt-6 pb-5 shadow-default dark:bg-boxdark sm:px-7.5">
<div className="flex flex-col sm:flex-row sm:flex-wrap sm:justify-end">
<div className="flex flex-col">
<h1 className="text-xl text-black dark:text-white pb-5">{ t("log.station.header") }</h1>
<p>{ t("log.station.server", { server: data.server.toUpperCase() }) }</p>
<p>{ t("log.station.station", { name: data.stationName, short: data.stationShort }) }</p>
{ data.joinedDate &&
<p>{ t("log.station.joined", { date: dayjs(data.joinedDate).format("DD/MM/YYYY HH:mm") }) }</p> }
<p>{ t("log.station.left", { date: dayjs(data.leftDate).format("DD/MM/YYYY HH:mm") }) }</p>
{ data.joinedDate &&
<p>{ t("log.station.spent", { date: dayjs.duration(data.leftDate - data.joinedDate).format("H[h] m[m]") }) }</p> }
</div>
<div className="flex flex-col gap-5 mt-5 sm:mt-0 sm:ml-auto">
<a
onClick={ report }
className="cursor-pointer inline-flex items-center justify-center rounded-md bg-meta-7 py-4 px-10 text-center font-medium text-white hover:bg-opacity-90 lg:px-8 xl:px-10"
>
Zgłoś
</a>
<a
onClick={ copyLink }
className="cursor-pointer inline-flex items-center justify-center rounded-md bg-primary py-4 px-10 text-center font-medium text-white hover:bg-opacity-90 lg:px-8 xl:px-10"
>
Kopiuj link
</a>
</div>
</div>
</div>
</div>;
};

View File

@ -15,8 +15,8 @@ export const StationTable = ({ stations, error }: {
return (
<>
{ error === 2 && <WarningAlert title={ t("contentloader.notfound.header") }
description={ t("contentloader.notfound.description") }/> }
{ error === 2 && <WarningAlert title={ t("content_loader.notfound.header") }
description={ t("content_loader.notfound.description") }/> }
{ error === 0 && <ContentLoader/> }
{ error === 1 && <div

View File

@ -15,8 +15,8 @@ export const TrainTable = ({ trains, error }: {
return (
<>
{ error === 2 && <WarningAlert title={ t("contentloader.notfound.header") }
description={ t("contentloader.notfound.description") }/> }
{ error === 2 && <WarningAlert title={ t("content_loader.notfound.header") }
description={ t("content_loader.notfound.description") }/> }
{ error === 0 && <ContentLoader/> }
{ error === 1 && <div
className="rounded-sm border border-stroke bg-white px-5 pt-6 pb-2.5 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5 xl:pb-1">

View File

@ -3,7 +3,7 @@ import useLocalStorage from "./useLocalStorage";
const useColorMode = () =>
{
const [ colorMode, setColorMode ] = useLocalStorage("color-theme", "light");
const [ colorMode, setColorMode ] = useLocalStorage<"light" | "dark">("color-theme", "light");
useEffect(() =>
{

View File

@ -48,10 +48,10 @@
"search": "Wpisz, aby wyszukać",
"station": "Stacja"
},
"contentloader": {
"content_loader": {
"error": {
"header": "Błąd ładowania strony",
"description": "Sprawdź swoje połączenie z internetem i odśwież strone",
"description": "Sprawdź swoje połączenie z internetem i odśwież stronę",
"report": "Zgłoś błąd",
"refresh": "Odśwież"
},
@ -83,9 +83,27 @@
"description": "Profil gracza nie został znaleziony lub posiada on prywatny profil steam."
},
"blacklist": {
"title": "Nie można wyświetlic profilu",
"title": "Nie można wyświetlić profilu",
"description": "Profil tego gracza został zablokowany."
}
}
},
"log": {
"errors": {
"title": "Nie znaleziono rekordu",
"description": "Ten rekord nie został znaleziony."
},
"blacklist": {
"title": "Nie można wyświetlić rekordu",
"description": "Rekord został zablokowany."
},
"station": {
"header": "Wyjście z posterunku",
"server": "Serwer: {{server}}",
"station": "Stacja: {{name}} - {{short}}",
"joined": "Data wejścia: {{date}}",
"left": "Data wyjścia: {{date}}",
"spent": "Spędzony czas: {{date}}"
}
}
}

View File

@ -81,7 +81,8 @@ export const Home: React.FC = () =>
i18nKey={ t("home.footer.thanks") }
components={ {
bahu: <Link className="color-orchid" to={ "https://bahu.pro/" }/>,
simrailelite: <Link className="color-orchid" to={ "https://bahu.pro/" }/>,
simrailelite: <Link className="color-orchid"
to={ "https://discord.gg/yDhy3pDrVr" }/>,
} }
/></p>
<p>{ t("home.footer.license") } <Link className="color-orchid"

View File

@ -5,6 +5,7 @@ import { ContentLoader } from "../../components/mini/loaders/ContentLoader.tsx";
import { WarningAlert } from "../../components/mini/alerts/Warning.tsx";
import { ProfileCard } from "../../components/pages/profile/Profile.tsx";
import { useTranslation } from "react-i18next";
import { PageTitle } from "../../components/mini/util/PageTitle.tsx";
export const Profile = () =>
{
@ -29,7 +30,6 @@ export const Profile = () =>
case 200:
setError(1);
setData(data.data);
console.log(data.data.steam);
break;
}
});
@ -42,12 +42,15 @@ export const Profile = () =>
{/* LOADING */ }
{ error === 0 && <ContentLoader/> }
{/* NOT FOUND */ }
{ error === 2 && <PageTitle title={ `simrail.alekswilc.dev | Profile not found` }/> }
{ error === 2 && <WarningAlert title={ t("profile.errors.notfound.title") }
description={ t("profile.errors.notfound.description") }/> }
{/* BLACKLISTED PROFILE */ }
{ error === 3 && <PageTitle title={ `simrail.alekswilc.dev | Blacklisted profile` }/> }
{ error === 3 && <WarningAlert title={ t("profile.errors.blacklist.title") }
description={ t("profile.errors.blacklist.description") }/> }
{/* SUCCESS */ }
{ error === 1 && <PageTitle title={ `simrail.alekswilc.dev | ${ data.steam.personname }'s profile` }/> }
{ error === 1 && <ProfileCard data={ data }/> }
</>
);