Plan/Plan/react/dashboard/src/components/cards/common/FirstMomentsCard.js

156 lines
6.6 KiB
JavaScript

import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {Card} from "react-bootstrap";
import CardHeader from "../CardHeader";
import {faChevronLeft, faChevronRight, faHandHoldingHeart} from "@fortawesome/free-solid-svg-icons";
import {fetchFirstMoments, fetchPlayersOnlineGraph} from "../../../service/serverService";
import {CardLoader} from "../../navigation/Loader";
import XRangeGraph from "../../graphs/XRangeGraph";
import {Link} from "react-router-dom";
import {tooltip} from "../../../util/graphs";
import {useTranslation} from "react-i18next";
import Graph from "../../graphs/Graph";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {useDataRequest} from "../../../hooks/dataFetchHook";
import {useMetadata} from "../../../hooks/metadataHook";
import {ErrorViewBody} from "../../../views/ErrorView";
import FormattedTime from "../../text/FormattedTime";
const dayMs = 24 * 60 * 60 * 1000;
const FirstMomentsCard = ({identifier}) => {
const {t} = useTranslation();
const {timeZoneOffsetMinutes, networkMetadata} = useMetadata();
const [selectedDay, setSelectedDay] = useState(1648760400000); //Date.now())
const {data: playersOnline, loadingError} = useDataRequest(fetchPlayersOnlineGraph, [identifier]);
const [sessionPlots, setSessionPlots] = useState([]);
const loadData = useCallback(async () => {
const startOfDay = selectedDay - (selectedDay + timeZoneOffsetMinutes * 60 * 1000) % dayMs;
const endOfDay = startOfDay + dayMs;
const {
data: loaded,
error
} = await fetchFirstMoments(startOfDay, endOfDay, networkMetadata?.servers.find(s => s.serverUUID === identifier));
console.log(loaded);
const sessionsByPlayer = {};
if (loaded?.data) {
for (const session of loaded.data.sessionList) {
const player = session.player_name;
if (!sessionsByPlayer[player]) sessionsByPlayer[player] = [];
sessionsByPlayer[player].push(session);
}
}
const sessionPlots = [];
let i = 1;
for (const entry of Object.entries(sessionsByPlayer)) {
sessionPlots.push({
name: entry[1][0].player_name,
uuid: entry[1][0].player_uuid,
points: entry[1].map(session => {
const start = session.startMillis;
const end = session.endMillis;
return {x: start, x2: end, color: session.first_session ? '#4caf50' : '#4ab4de'};
}).sort((a, b) => a.x - b.x > 0 ? 1 : -1),
playtime: entry[1].reduce((partialSum, session) => partialSum + session.endMillis - session.startMillis, 0)
})
i++;
}
setSessionPlots(sessionPlots.sort((a, b) => a.points[0].x - b.points[0].x > 0 ? 1 : -1));
}, [selectedDay, setSessionPlots, identifier]);
useEffect(() => {
loadData()
}, [loadData]);
const playersOnlineOptions = useMemo(() => {
if (!playersOnline || !sessionPlots?.length) return {};
const startOfDay = selectedDay + timeZoneOffsetMinutes;
const endOfDay = startOfDay + dayMs;
return {
yAxis: {
title: {
text: ''
},
opposite: true,
softMax: 1,
softMin: 0
},
xAxis: {
visible: false,
type: 'datetime',
min: startOfDay,
max: endOfDay
},
title: {text: ''},
legend: {
enabled: false
},
time: {
timezoneOffset: 0
},
series: [{
name: t('html.label.playersOnline'),
type: 'spline',
tooltip: tooltip.zeroDecimals,
data: playersOnline ? playersOnline.playersOnline : [],
color: "#90b7f3",
yAxis: 0
}]
}
}, [playersOnline, t, sessionPlots]);
if (!sessionPlots) return <CardLoader/>;
return (
<Card>
<CardHeader icon={faHandHoldingHeart} color="light-green" label={"First moments"}>
<div className={"float-end"}>
<span style={{marginRight: '0.5rem'}}>on {new Date(selectedDay).toISOString().split("T")[0]}</span>
<button style={{marginRight: '0.5rem'}} onClick={() => setSelectedDay(selectedDay - dayMs)}>
<FontAwesomeIcon icon={faChevronLeft}/></button>
<button onClick={() => setSelectedDay(selectedDay + dayMs)}>
<FontAwesomeIcon icon={faChevronRight}/>
</button>
</div>
</CardHeader>
{/*<ExtendableCardBody id={"card-body-first-moments"} style={{marginTop: "-0.5rem"}}>*/}
{/* <Filter index={0} filter={filter} setFilterOptions={setFilterOptions}/>*/}
{/*</ExtendableCardBody>*/}
<div style={{overflowY: "scroll", maxHeight: "700px"}}>
<table className={"table table-striped"}>
<thead>
<tr style={{position: 'sticky', top: 0, backgroundColor: "white", zIndex: 1}}>
<td>Players Online</td>
<td>
{loadingError && <ErrorViewBody error={loadingError}/>}
{!loadingError &&
<Graph id={"players-online-graph"} options={playersOnlineOptions} className={''}
style={{height: "100px"}}/>}
</td>
<td>-</td>
</tr>
<tr style={{position: 'sticky', top: "7.8rem", backgroundColor: "white", zIndex: 1}}>
<th>Player</th>
<th>Sessions</th>
<th>Playtime</th>
</tr>
</thead>
<tbody>
{sessionPlots.map((plot, i) => <tr key={plot.name}>
<td><Link to={`/player/${plot.uuid}`}>{plot.name}</Link></td>
<td style={{padding: 0}}><XRangeGraph id={`xrange-${plot.uuid}`} pointsByAxis={[plot]}
height={"60px"}/>
</td>
<td><FormattedTime timeMs={plot.playtime}/></td>
</tr>)}
</tbody>
</table>
</div>
</Card>
)
};
export default FirstMomentsCard