initial index
This commit is contained in:
parent
62cc828d6a
commit
88015a98cd
21 changed files with 343 additions and 56 deletions
30
app/components/faction-bar.css.ts
Normal file
30
app/components/faction-bar.css.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import type { ComplexStyleRule } from "@vanilla-extract/css";
|
||||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
export const bar = style({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexDirection: "row",
|
||||
overflow: "hidden",
|
||||
borderRadius: "0.4rem",
|
||||
border: "2px solid #2d2d2d",
|
||||
});
|
||||
|
||||
const shared: ComplexStyleRule = {
|
||||
textAlign: "center",
|
||||
};
|
||||
|
||||
export const left = style({
|
||||
...shared,
|
||||
backgroundColor: "#991cba",
|
||||
});
|
||||
export const center = style({
|
||||
...shared,
|
||||
backgroundColor: "#1564cc",
|
||||
borderBottom: "1px solid #2d2d2d",
|
||||
});
|
||||
export const right = style({
|
||||
...shared,
|
||||
backgroundColor: "#d30101",
|
||||
});
|
32
app/components/faction-bar.tsx
Normal file
32
app/components/faction-bar.tsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { useMemo } from "react";
|
||||
import type { Population } from "~/utils/saerro";
|
||||
import { totalPopulation } from "~/utils/saerro";
|
||||
import * as styles from "./faction-bar.css";
|
||||
|
||||
export const FactionBar = ({
|
||||
population: { vs, nc, tr },
|
||||
}: {
|
||||
population: Population;
|
||||
}) => {
|
||||
const { vsPercent, ncPercent, trPercent } = useMemo(() => {
|
||||
const total = totalPopulation({ vs, nc, tr, total: 0 });
|
||||
return {
|
||||
vsPercent: Math.floor((vs / total) * 100) || 0,
|
||||
ncPercent: Math.floor((nc / total) * 100) || 0,
|
||||
trPercent: Math.floor((tr / total) * 100) || 0,
|
||||
};
|
||||
}, [vs, nc, tr]);
|
||||
return (
|
||||
<div className={styles.bar}>
|
||||
<div className={styles.left} style={{ flexGrow: vs + 1 }}>
|
||||
{vsPercent}%
|
||||
</div>
|
||||
<div className={styles.center} style={{ flexGrow: nc + 1 }}>
|
||||
{ncPercent}%
|
||||
</div>
|
||||
<div className={styles.right} style={{ flexGrow: tr + 1 }}>
|
||||
{trPercent}%
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
8
app/components/index-world-container.css.ts
Normal file
8
app/components/index-world-container.css.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
export const container = style({
|
||||
display: "flex",
|
||||
flexBasis: "100%",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "center",
|
||||
});
|
22
app/components/index-world-container.tsx
Normal file
22
app/components/index-world-container.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { useMemo } from "react";
|
||||
import type { Health, World } from "~/utils/saerro";
|
||||
import { IndexWorld } from "./index-world";
|
||||
import * as styles from "./index-world-container.css";
|
||||
|
||||
export const WorldContainer = ({
|
||||
worlds,
|
||||
health,
|
||||
}: {
|
||||
worlds: World[];
|
||||
health: Health;
|
||||
}) => (
|
||||
<div className={styles.container}>
|
||||
{worlds.map((world) => (
|
||||
<IndexWorld
|
||||
key={world.id}
|
||||
world={world}
|
||||
health={health.worlds.find((w) => world.name.toLowerCase() === w.name)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
70
app/components/index-world.css.ts
Normal file
70
app/components/index-world.css.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
export const container = style({
|
||||
background: "#333",
|
||||
flexBasis: "30%",
|
||||
margin: "0.5rem",
|
||||
});
|
||||
|
||||
export const header = style({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: "inherit",
|
||||
textDecoration: "none",
|
||||
transition: "background-color 0.2s ease-in-out",
|
||||
backgroundColor: "#222",
|
||||
":hover": {
|
||||
backgroundColor: "#383838",
|
||||
},
|
||||
});
|
||||
export const headerName = style({
|
||||
padding: "0.5rem",
|
||||
fontSize: "1.5rem",
|
||||
});
|
||||
export const headerDetailsLink = style({
|
||||
fontVariant: "small-caps",
|
||||
fontSize: "0.8rem",
|
||||
color: "#aaa",
|
||||
paddingRight: "0.5rem",
|
||||
});
|
||||
export const headerMarkers = style({
|
||||
fontSize: "0.8rem",
|
||||
flex: 1,
|
||||
fontWeight: "bold",
|
||||
color: "#aaa",
|
||||
});
|
||||
|
||||
export const circle = style({
|
||||
display: "inline-block",
|
||||
width: "0.4rem",
|
||||
height: "0.4rem",
|
||||
borderRadius: "50%",
|
||||
marginLeft: "0.2rem",
|
||||
});
|
||||
|
||||
export const details = style({
|
||||
padding: "0.5rem",
|
||||
});
|
||||
|
||||
export const population = style({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-evenly",
|
||||
});
|
||||
|
||||
export const popFaction = style({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
});
|
||||
|
||||
export const popImage = style({
|
||||
height: "1.5rem",
|
||||
marginRight: "0.5rem",
|
||||
});
|
||||
|
||||
export const totalPop = style({
|
||||
fontWeight: "bold",
|
||||
fontSize: "1.2rem",
|
||||
});
|
|
@ -1,18 +1,61 @@
|
|||
import { World } from "~/utils/saerro";
|
||||
import { Link } from "@remix-run/react";
|
||||
import { Health, totalPopulation, World } from "~/utils/saerro";
|
||||
import { humanTimeAgo } from "~/utils/strings";
|
||||
import { worlds } from "~/utils/worlds";
|
||||
import * as styles from "./index-world.css";
|
||||
import vsLogo from "~/images/vs-100.png";
|
||||
import ncLogo from "~/images/nc-100.png";
|
||||
import trLogo from "~/images/tr-100.png";
|
||||
import { FactionBar } from "./faction-bar";
|
||||
|
||||
export type IndexWorldProps = {
|
||||
world: World;
|
||||
health?: Health["worlds"][number];
|
||||
};
|
||||
|
||||
export const IndexWorld = ({ world }: IndexWorldProps) => {
|
||||
export const IndexWorld = ({ world, health }: IndexWorldProps) => {
|
||||
const { platform, location } = worlds[String(world.id || "default")];
|
||||
|
||||
const timeSinceLastEvent = humanTimeAgo(
|
||||
new Date().getTime() - new Date(health?.lastEvent || 0).getTime()
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>
|
||||
{world.name} (total: {world.population.total})
|
||||
</h1>
|
||||
<p>VS: {world.population.vs}</p>
|
||||
<p>NC: {world.population.nc}</p>
|
||||
<p>TR: {world.population.tr}</p>
|
||||
<div className={styles.container}>
|
||||
<Link to={`/worlds/${world.id}`} className={styles.header}>
|
||||
<div className={styles.headerName}>{world.name}</div>
|
||||
<div className={styles.headerMarkers}>
|
||||
[{location}] [{platform}]{" "}
|
||||
<div
|
||||
className={styles.circle}
|
||||
style={{
|
||||
backgroundColor: health?.status === "UP" ? "limegreen" : "red",
|
||||
}}
|
||||
title={`Status: ${health?.status} || Last event: ${timeSinceLastEvent}`}
|
||||
></div>
|
||||
</div>
|
||||
<div className={styles.headerDetailsLink}>DETAILS ⇨</div>
|
||||
</Link>
|
||||
<div className={styles.details}>
|
||||
<div className={styles.population}>
|
||||
<div className={styles.totalPop}>
|
||||
{totalPopulation(world.population)}
|
||||
</div>
|
||||
<div className={styles.popFaction}>
|
||||
<img className={styles.popImage} src={vsLogo} alt="VS" />{" "}
|
||||
{world.population.vs}
|
||||
</div>
|
||||
<div className={styles.popFaction}>
|
||||
<img className={styles.popImage} src={ncLogo} alt="NC" />{" "}
|
||||
{world.population.nc}
|
||||
</div>
|
||||
<div className={styles.popFaction}>
|
||||
<img className={styles.popImage} src={trLogo} alt="TR" />{" "}
|
||||
{world.population.tr}
|
||||
</div>
|
||||
</div>
|
||||
<FactionBar population={world.population} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue