Improve alert timer
This commit is contained in:
parent
8b5ceaf599
commit
2314da4763
2 changed files with 141 additions and 57 deletions
|
@ -99,7 +99,15 @@ export const contBars = style({
|
||||||
export const contBarTitle = style({
|
export const contBarTitle = style({
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
fontSize: "0.7rem",
|
fontSize: "0.7rem",
|
||||||
padding: "0.2rem 0.5rem",
|
padding: "0.15rem",
|
||||||
|
lineHeight: 0.8,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const barSeparator = style({
|
||||||
|
height: "0.5rem",
|
||||||
|
width: "100%",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const contCircle = style({
|
export const contCircle = style({
|
||||||
|
@ -145,6 +153,24 @@ export const alertCont = style({
|
||||||
animation: `${alertFade} 1s ease-in-out 4 alternate`,
|
animation: `${alertFade} 1s ease-in-out 4 alternate`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const alertDotBlink = keyframes({
|
||||||
|
from: {
|
||||||
|
backgroundColor: "#ff2d2d",
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
backgroundColor: "#662929",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const alertDot = style({
|
||||||
|
display: "inline-block",
|
||||||
|
height: "0.5rem",
|
||||||
|
width: "0.5rem",
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "#ff2d2d",
|
||||||
|
animation: `${alertDotBlink} var(--speed) ease-in-out infinite alternate`,
|
||||||
|
});
|
||||||
|
|
||||||
export const nextCont = style({
|
export const nextCont = style({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { FactionBar } from "./faction-bar";
|
||||||
import type { MetagameWorld } from "~/utils/metagame";
|
import type { MetagameWorld } from "~/utils/metagame";
|
||||||
import type { PopulationWorld } from "~/utils/population";
|
import type { PopulationWorld } from "~/utils/population";
|
||||||
import { c } from "~/utils/classes";
|
import { c } from "~/utils/classes";
|
||||||
|
import { ReactFragment, useEffect, useState } from "react";
|
||||||
|
|
||||||
export type IndexWorldProps = {
|
export type IndexWorldProps = {
|
||||||
metagame: MetagameWorld;
|
metagame: MetagameWorld;
|
||||||
|
@ -67,64 +68,10 @@ export const IndexWorld = ({ metagame, population }: IndexWorldProps) => {
|
||||||
return a.alert && !b.alert ? -1 : b.alert && !a.alert ? 1 : 0;
|
return a.alert && !b.alert ? -1 : b.alert && !a.alert ? 1 : 0;
|
||||||
})
|
})
|
||||||
.map((zone) => {
|
.map((zone) => {
|
||||||
let {
|
|
||||||
name,
|
|
||||||
colors: [upper, lower],
|
|
||||||
} = zones[zone.id];
|
|
||||||
return worldId !== 19 ? (
|
return worldId !== 19 ? (
|
||||||
<div
|
<Continent key={zone.id} zone={zone} />
|
||||||
key={zone.id}
|
|
||||||
className={c(styles.continent, zone.alert && styles.alertCont)}
|
|
||||||
>
|
|
||||||
<div className={styles.contName}>
|
|
||||||
<div
|
|
||||||
className={styles.contCircle}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--upper-color": upper,
|
|
||||||
"--lower-color": lower,
|
|
||||||
} as any
|
|
||||||
}
|
|
||||||
></div>
|
|
||||||
<div>{name}</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.contBars}>
|
|
||||||
<div>
|
|
||||||
<div className={styles.contBarTitle}>TERRITORY CONTROL</div>
|
|
||||||
<FactionBar population={zone.territory} />
|
|
||||||
</div>
|
|
||||||
{zone.alert && (
|
|
||||||
<div>
|
|
||||||
<div className={styles.contBarTitle}>
|
|
||||||
{snakeCaseToTitleCase(
|
|
||||||
zone.alert.alert_type
|
|
||||||
).toUpperCase()}{" "}
|
|
||||||
ALERT PROGRESS | STARTED{" "}
|
|
||||||
{humanTimeAgo(
|
|
||||||
Date.now() -
|
|
||||||
new Date(zone.alert.start_time).getTime(),
|
|
||||||
true
|
|
||||||
).toUpperCase()}{" "}
|
|
||||||
AGO
|
|
||||||
</div>
|
|
||||||
<FactionBar population={zone.alert.percentages} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div key={zone.id} className={styles.contName}>
|
<JaegerContinent key={zone.id} zone={zone} />
|
||||||
<div
|
|
||||||
className={styles.contCircle}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--upper-color": upper,
|
|
||||||
"--lower-color": lower,
|
|
||||||
} as any
|
|
||||||
}
|
|
||||||
></div>
|
|
||||||
<div>{name}</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{worldId !== 19 && (
|
{worldId !== 19 && (
|
||||||
|
@ -148,3 +95,114 @@ export const IndexWorld = ({ metagame, population }: IndexWorldProps) => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const JaegerContinent = ({ zone }: { zone: MetagameWorld["zones"][0] }) => {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
colors: [upper, lower],
|
||||||
|
} = zones[zone.id];
|
||||||
|
return (
|
||||||
|
<div key={zone.id} className={styles.contName}>
|
||||||
|
<div
|
||||||
|
className={styles.contCircle}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--upper-color": upper,
|
||||||
|
"--lower-color": lower,
|
||||||
|
} as any
|
||||||
|
}
|
||||||
|
></div>
|
||||||
|
<div>{name}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const endTime = (alert: Required<MetagameWorld["zones"][0]>["alert"]) => {
|
||||||
|
const alertDurationMins = alert.alert_type !== "sudden_death" ? 90 : 15;
|
||||||
|
return new Date(alert.start_time).getTime() + alertDurationMins * 60 * 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Continent = ({ zone }: { zone: MetagameWorld["zones"][0] }) => {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
colors: [upper, lower],
|
||||||
|
} = zones[zone.id];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={zone.id} className={c(styles.continent)}>
|
||||||
|
<div className={styles.contName}>
|
||||||
|
<div
|
||||||
|
className={styles.contCircle}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--upper-color": upper,
|
||||||
|
"--lower-color": lower,
|
||||||
|
} as any
|
||||||
|
}
|
||||||
|
></div>
|
||||||
|
<div>{name}</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.contBars}>
|
||||||
|
<div>
|
||||||
|
<div className={styles.contBarTitle}>TERRITORY CONTROL</div>
|
||||||
|
<FactionBar population={zone.territory} />
|
||||||
|
</div>
|
||||||
|
{zone.alert && (
|
||||||
|
<>
|
||||||
|
<div className={styles.barSeparator}></div>
|
||||||
|
<div>
|
||||||
|
<div className={styles.contBarTitle}>
|
||||||
|
<div>
|
||||||
|
{snakeCaseToTitleCase(zone.alert.alert_type).toUpperCase()}{" "}
|
||||||
|
ALERT PROGRESS
|
||||||
|
</div>{" "}
|
||||||
|
<div>
|
||||||
|
<TimeLeft alert={zone.alert} />{" "}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<FactionBar population={zone.alert.percentages} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeLeftString = (alert: MetagameWorld["zones"][0]["alert"]) => {
|
||||||
|
if (alert) {
|
||||||
|
const time = endTime(alert) - Date.now();
|
||||||
|
if (time < 2000) {
|
||||||
|
return <>JUST ENDED</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const speed = time < 1000 * 60 * 15 ? "1s" : "4s";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{humanTimeAgo(time, true).toUpperCase()} LEFT{" "}
|
||||||
|
<div
|
||||||
|
className={styles.alertDot}
|
||||||
|
style={{ "--speed": speed } as any}
|
||||||
|
></div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const TimeLeft = ({ alert }: { alert: MetagameWorld["zones"][0]["alert"] }) => {
|
||||||
|
const [timeLeft, setTimeLeft] = useState(timeLeftString(alert));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (alert) {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setTimeLeft(timeLeftString(alert));
|
||||||
|
}, 1000);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, [alert]);
|
||||||
|
|
||||||
|
return <>{timeLeft}</>;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue