v3 release #75

Merged
alekswilc merged 63 commits from v3 into main 2024-12-13 20:29:17 +01:00
60 changed files with 93 additions and 242 deletions
Showing only changes of commit cc72fee712 - Show all commits

View File

@ -68,14 +68,14 @@ export class LeaderboardRoute {
const records = await MProfile.aggregate(filter)
.sort({ dispatcherTime: -1 })
.limit(10)
res.render('leaderboard/index.ejs', {
records,
dayjs,
msToTime,
type: 'station',
q: req.query.q,
...GitUtil.getData(),
});
res.json(
new SuccessResponseBuilder<{ records: Omit<IProfile, '_id' | '__v'>[] }>()
.setCode(200)
.setData({ records: records.map(x => removeProperties<Omit<IProfile, '_id' | '__v'>>(x, ['_id', '__v'])) })
.toJSON()
);
})
return app;

View File

@ -10,6 +10,7 @@
},
"dependencies": {
"apexcharts": "^3.41.0",
"dayjs": "^1.11.13",
"flatpickr": "^4.6.13",
"headlessui": "^0.0.0",
"i18next": "^23.15.1",

View File

@ -12,7 +12,8 @@ import Alerts from './pages/UiElements/Alerts';
import Buttons from './pages/UiElements/Buttons';
import DefaultLayout from './layout/DefaultLayout';
import "./i18n";
import { TrainLogs } from './pages/Logs.tsx';
import { TrainLeaderboard } from './pages/leaderboard/TrainLeaderboard.tsx';
import { StationLeaderboard } from './pages/leaderboard/StationsLeaderboard.tsx';
function App() {
@ -42,11 +43,20 @@ function App() {
}
/>
<Route
path="/logs/trains"
path="/leaderboard/trains"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Train Logs" />
<TrainLogs />
<PageTitle title="simrail.alekswilc.dev | Train Leaderboard" />
<TrainLeaderboard />
</>
}
/>
<Route
path="/leaderboard/stations"
element={
<>
<PageTitle title="simrail.alekswilc.dev | Stations Leaderboard" />
<StationLeaderboard />
</>
}
/>

View File

@ -1,127 +0,0 @@
import { BRAND } from '../../types/brand';
import BrandOne from '../../images/brand/brand-01.svg';
import BrandTwo from '../../images/brand/brand-02.svg';
import BrandThree from '../../images/brand/brand-03.svg';
import BrandFour from '../../images/brand/brand-04.svg';
import BrandFive from '../../images/brand/brand-05.svg';
const brandData: BRAND[] = [
{
logo: BrandOne,
name: 'Google',
visitors: 3.5,
revenues: '5,768',
sales: 590,
conversion: 4.8,
},
{
logo: BrandTwo,
name: 'Twitter',
visitors: 2.2,
revenues: '4,635',
sales: 467,
conversion: 4.3,
},
{
logo: BrandThree,
name: 'Github',
visitors: 2.1,
revenues: '4,290',
sales: 420,
conversion: 3.7,
},
{
logo: BrandFour,
name: 'Vimeo',
visitors: 1.5,
revenues: '3,580',
sales: 389,
conversion: 2.5,
},
{
logo: BrandFive,
name: 'Facebook',
visitors: 3.5,
revenues: '6,768',
sales: 390,
conversion: 4.2,
},
];
const TableOne = () => {
return (
<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">
<h4 className="mb-6 text-xl font-semibold text-black dark:text-white">
Top Channels
</h4>
<div className="flex flex-col">
<div className="grid grid-cols-3 rounded-sm bg-gray-2 dark:bg-meta-4 sm:grid-cols-5">
<div className="p-2.5 xl:p-5">
<h5 className="text-sm font-medium uppercase xsm:text-base">
Source
</h5>
</div>
<div className="p-2.5 text-center xl:p-5">
<h5 className="text-sm font-medium uppercase xsm:text-base">
Visitors
</h5>
</div>
<div className="p-2.5 text-center xl:p-5">
<h5 className="text-sm font-medium uppercase xsm:text-base">
Revenues
</h5>
</div>
<div className="hidden p-2.5 text-center sm:block xl:p-5">
<h5 className="text-sm font-medium uppercase xsm:text-base">
Sales
</h5>
</div>
<div className="hidden p-2.5 text-center sm:block xl:p-5">
<h5 className="text-sm font-medium uppercase xsm:text-base">
Conversion
</h5>
</div>
</div>
{brandData.map((brand, key) => (
<div
className={`grid grid-cols-3 sm:grid-cols-5 ${
key === brandData.length - 1
? ''
: 'border-b border-stroke dark:border-strokedark'
}`}
key={key}
>
<div className="flex items-center gap-3 p-2.5 xl:p-5">
<div className="flex-shrink-0">
<img src={brand.logo} alt="Brand" />
</div>
<p className="hidden text-black dark:text-white sm:block">
{brand.name}
</p>
</div>
<div className="flex items-center justify-center p-2.5 xl:p-5">
<p className="text-black dark:text-white">{brand.visitors}K</p>
</div>
<div className="flex items-center justify-center p-2.5 xl:p-5">
<p className="text-meta-3">${brand.revenues}</p>
</div>
<div className="hidden items-center justify-center p-2.5 sm:flex xl:p-5">
<p className="text-black dark:text-white">{brand.sales}</p>
</div>
<div className="hidden items-center justify-center p-2.5 sm:flex xl:p-5">
<p className="text-meta-5">{brand.conversion}%</p>
</div>
</div>
))}
</div>
</div>
);
};
export default TableOne;

View File

@ -1,14 +1,14 @@
import toast from 'react-hot-toast';
import dataJSON from '../../public/data.json';
const createToast=(title: string, msg: string, type: number)=>{toast.custom((t) => (
//TODO: rewrite
const createToast = (title: string, msg: string, type: number) => {
toast.custom((t) => (
<div
className={`${
t.visible ? 'animate-enter' : 'animate-leave'
className={`${t.visible ? 'animate-enter' : 'animate-leave'
}
max-w-md w-full ${type=='0'?"bg-[#04b20c]":type=='1'?"bg-[#eab90f]":"bg-[#e13f32]"} shadow-lg rounded-lg pointer-events-auto flex ring-1 ring-black ring-opacity-5`}
max-w-md w-full ${type === 0 ? "bg-[#04b20c]" : type === 1 ? "bg-[#eab90f]" : "bg-[#e13f32]"} shadow-lg rounded-lg pointer-events-auto flex ring-1 ring-black ring-opacity-5`}
>
<div className="flex-1 w-0 p-4 ">
<div className="flex items-start">
@ -50,7 +50,8 @@ const createToast=(title: string, msg: string, type: number)=>{toast.custom((t)
</div>
</div>
))};
))
};
// let dataJSON: any;
// let headers = new Headers();
// headers.append('Access-Control-Allow-Origin', 'http://127.0.0.1:8000');
@ -73,8 +74,7 @@ if (alertSettings){
const value = isNaN(parseFloat(alertSetting.value)) ? alertSetting.value : parseFloat(alertSetting.value);
const para = alertSetting.criterion < 2 ? "delta_" + alertSetting.para : alertSetting.para;
if (alertSetting.id == "ALL") {
Object.keys(dataJSON).map((id:string)=>
{
Object.keys(dataJSON).map((id: string) => {
const condition = alertSetting.criterion == '0' ? value <= -1 * dataJSON[id][para] :
alertSetting.criterion == '1' || alertSetting.criterion == '3' ? value >= dataJSON[id][para] :
alertSetting.criterion == '2' ? value <= dataJSON[id][para] :
@ -109,4 +109,3 @@ if (alertSettings){
}
export default fireToast;

View File

@ -27,4 +27,7 @@ i18n
defaultNS: "translation",
});
export { i18n };

View File

@ -29,5 +29,13 @@
"stations": "Stacje",
"trains": "Pociągi",
"leaderboard": "Tablica wyników"
},
"leaderboard": {
"user": "Użytkownik",
"time": "Czas",
"distance": "Dystans",
"points": "Punkty",
"profile": "Otwórz profil",
"actions": "Akcje"
}
}

View File

@ -6,6 +6,15 @@ import './css/style.css';
import './css/satoshi.css';
import 'flatpickr/dist/flatpickr.min.css';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime.js';
import duration from 'dayjs/plugin/duration.js';
dayjs.extend(duration)
dayjs.extend(relativeTime);
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<Router>

View File

@ -1,21 +0,0 @@
import TableOne from '../components/Tables/TableOne';
import TableThree from '../components/Tables/TableThree';
import TableTwo from '../components/Tables/TableTwo';
import { TTrainRecord } from '../types/train.ts';
const trains: TTrainRecord[] = {"success":true,"data":{"records":[{"id":"16b54f4a-0826-4005-b67d-2ab57d74ffeb","steam":"76561199101984415","steamName":"tomsobczak35","trainTime":4841000336,"trainPoints":572048,"trainDistance":8066546,"dispatcherTime":0,"trainStats":{"Pendolino (ED250)":{"distance":8066546,"score":572048,"time":4841000336}}},{"id":"a9050fd0-f3cd-45c9-8087-44948da79b00","steam":"76561198258359953","steamName":"Kashameister.","trainTime":4838762785,"trainPoints":353232,"trainDistance":10274248,"dispatcherTime":0,"trainStats":{"EU07":{"distance":10274248,"score":353232,"time":4838762785}}},{"id":"2a08cadb-bacb-494a-8d09-0ef1870f1057","steam":"76561198200906855","steamName":"Nesto Ash Leo","trainTime":4411743671,"trainPoints":110438,"trainDistance":4412798,"dispatcherTime":0,"trainStats":{"EP08":{"distance":4412798,"score":110438,"time":4411743671}}},{"id":"23de2c57-84da-4845-b901-a40b6b5e1261","steam":"76561199065951587","steamName":"Pablo","trainTime":3021172809,"trainPoints":55277,"trainDistance":429106,"dispatcherTime":250586,"trainStats":{"EN96":{"distance":429106,"score":55277,"time":3021172809}},"dispatcherStats":{"Korytów":{"time":22064},"Olszamowice":{"time":221137},"Dąbrowa Górnicza":{"time":7385}}},{"id":"b44b2b4b-476a-4e52-b612-573d5c5eea78","steam":"76561198356160006","steamName":"Marcion","trainTime":9571588,"dispatcherTime":0,"trainStats":{"Pendolino (ED250)":{"distance":303450,"score":9856,"time":9571588}},"trainDistance":303450,"trainPoints":9856},{"id":"3ee1f655-8329-4c83-96ae-bcf162d31f78","steam":"76561199465955782","steamName":"Bolek","trainTime":14441779,"dispatcherTime":0,"trainStats":{"Pendolino (ED250)":{"distance":402970,"score":9740,"time":14441779}},"trainDistance":402970,"trainPoints":9740},{"id":"c3731119-72b0-47c4-a047-70315e595d01","steam":"76561198048854814","steamName":"Night King_UA","trainTime":9537157,"dispatcherTime":0,"trainStats":{"Pendolino (ED250)":{"distance":302954,"score":9686,"time":9537157}},"trainDistance":302954,"trainPoints":9686},{"id":"a88f7594-844b-47e1-b657-d6c0be2d021a","steam":"76561198886710784","steamName":"LIPTON2315","trainTime":10820008,"dispatcherTime":0,"trainStats":{"EP08":{"distance":240000,"score":0,"time":9860788},"Pendolino (ED250)":{"distance":22693,"score":9320,"time":959220}},"trainDistance":262693,"trainPoints":9320},{"id":"42b5c7f0-3af4-4305-aca7-6462e5bf134b","steam":"76561198067997310","steamName":"Gladicek","trainTime":8042564,"dispatcherTime":0,"trainStats":{"EU07":{"distance":97165,"score":0,"time":4419762},"Traxx (E186)":{"distance":5704,"score":4483,"time":873122},"EN57":{"distance":27186,"score":4696,"time":2262371},"EN96":{"distance":3506,"score":0,"time":487309}},"trainDistance":133561,"trainPoints":9179},{"id":"31a65828-3e87-4123-b8c7-c2604375e5a4","steam":"76561198859961880","steamName":"mpapa","trainTime":15313091,"dispatcherTime":0,"trainStats":{"EP08":{"distance":110491,"score":4463,"time":13036616},"Dragon2 (E6ACTa, E6ACTadb)":{"distance":924,"score":0,"time":321162},"Pendolino (ED250)":{"distance":59999,"score":2750,"time":1955313}},"trainDistance":171414,"trainPoints":7213}]},"code":200}.data.records;
export const TrainLogs = () => {
return (
<>
<div className="flex flex-col gap-10">
<TableOne />
<TableTwo />
<TableThree />
</div>
</>
);
};

View File

@ -1,15 +1,15 @@
import TableOne from '../components/Tables/TableOne';
import TableThree from '../components/Tables/TableThree';
import TableTwo from '../components/Tables/TableTwo';
// import TableOne from '../components/Tables/TableOne';
// import TableThree from '../components/Tables/TableThree';
// import TableTwo from '../components/Tables/TableTwo';
const Tables = () => {
return (
<>
<div className="flex flex-col gap-10">
<TableOne />
{/* <TableOne />
<TableTwo />
<TableThree />
<TableThree /> */}
</div>
</>
);

View File

@ -1,31 +0,0 @@
export interface TTrainResponse {
success: boolean;
data: TTrainData;
code: number;
}
export interface TTrainData {
records: TTrainRecord[];
}
export interface TTrainRecord {
id: string;
steam: string;
steamName: string;
trainTime: number;
trainPoints: number;
trainDistance: number;
dispatcherTime: number;
trainStats: { [key: string]: TTrainStat };
dispatcherStats?: { [key: string]: TDispatcherStat };
}
export interface TDispatcherStat {
time: number;
}
export interface TTrainStat {
distance: number;
score: number;
time: number;
}

View File

@ -1150,7 +1150,7 @@ csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
dayjs@^1.11.12:
dayjs@^1.11.12, dayjs@^1.11.13:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==