Skip to content

Commit

Permalink
session page, make localisation actually local
Browse files Browse the repository at this point in the history
  • Loading branch information
danreeves committed Oct 23, 2023
1 parent fdd147f commit 2539590
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 42 deletions.
16 changes: 16 additions & 0 deletions app/data/gameplaySessions.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,19 @@ export async function saveGameplaySession(
) {
return await prisma.gameplaySession.create({ data: session })
}

export async function getGameplaySessions({
accountId,
characterId,
}: {
accountId: string
characterId: string
}) {
return await prisma.gameplaySession.findMany({
where: {
accountId,
characterId,
},
orderBy: [{ createdAt: "desc" }],
})
}
20 changes: 20 additions & 0 deletions app/hooks/locale.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { ReactNode } from "react"
import { createContext, useContext } from "react"

const LocaleContext = createContext<string>("")

export function LocaleProvider({
children,
locale,
}: {
children: ReactNode
locale: string
}) {
return (
<LocaleContext.Provider value={locale}>{children}</LocaleContext.Provider>
)
}

export default function useLocale() {
return useContext(LocaleContext)
}
72 changes: 50 additions & 22 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { authenticator } from "~/services/auth.server"
import { initJobs } from "~/jobs/index.server"
import { useRevalidateOnFocus } from "~/hooks/revalidateOnFocus"
import { ThemeProvider } from "./theme-provider"
import acceptLanguage from "accept-language-parser"
import { LocaleProvider } from "./hooks/locale"

// Sets up Cron singletons to perform timed jobs on the server
initJobs && initJobs()
Expand All @@ -35,36 +37,62 @@ export function meta() {
return [{ title: "Darkti.de - unofficial community tools" }]
}

function getLocale(request: Request): string {
const languages = acceptLanguage.parse(
request.headers.get("Accept-Language") as string,
)

if (!languages) {
return "en-us"
}

const firstLang = languages[0]

if (!firstLang) {
return "en-us"
}

if (!firstLang.region) {
return firstLang.code
}

return `${firstLang.code}-${firstLang.region.toLowerCase()}`
}

export let loader = async ({ request }: LoaderArgs) => {
const user = await authenticator.isAuthenticated(request)
return json({ user })
const locale = getLocale(request)

return json({ user, locale })
}

export default function App() {
const { user } = useLoaderData<typeof loader>()
const { user, locale } = useLoaderData<typeof loader>()

useRevalidateOnFocus()

return (
<html lang="en" className="h-screen" suppressHydrationWarning>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body className="h-screen">
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<Layout user={user} />
</ThemeProvider>
<Scripts />
<LiveReload />
</body>
</html>
<LocaleProvider locale={locale}>
<html lang="en" className="h-screen" suppressHydrationWarning>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body className="h-screen">
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<Layout user={user} />
</ThemeProvider>
<Scripts />
<LiveReload />
</body>
</html>
</LocaleProvider>
)
}
11 changes: 7 additions & 4 deletions app/routes/armoury.$character.$store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { titleCase } from "~/utils/titleCase"
import { ChevronsUp, Database } from "lucide-react"
import { Button } from "~/components/ui/button"
import { cn } from "~/lib/utils"
import useLocale from "~/hooks/locale"

let storeSlugToType: Record<string, "credits" | "marks"> = {
exchange: "credits",
Expand Down Expand Up @@ -328,6 +329,7 @@ const raritySymbol = ["0", "Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ"]

export default function Exchange() {
let navigation = useNavigation()
let locale = useLocale()
let { offers, wallet } = useLoaderData<typeof loader>()

return (
Expand Down Expand Up @@ -370,7 +372,8 @@ export default function Exchange() {
<div className="flex h-full place-items-start ml-auto text-sm font-medium leading-none mb-4 text-amber-500">
<div className="flex items-center">
<Database className="mr-1 h-4 w-4" aria-hidden="true" />
{wallet.balance.amount.toLocaleString()} {wallet.balance.type}
{wallet.balance.amount.toLocaleString(locale)}{" "}
{wallet.balance.type}
</div>
</div>
) : null}
Expand Down Expand Up @@ -524,9 +527,9 @@ export default function Exchange() {
<Database className="h-4 w-4" aria-hidden="true" />
{offer.purchased
? "Purchased"
: `Buy for ${offer.price.amount.amount.toLocaleString()} ${
offer.price.amount.type
}`}
: `Buy for ${offer.price.amount.amount.toLocaleString(
locale,
)} ${offer.price.amount.type}`}
</Button>
</div>
</div>
Expand Down
8 changes: 6 additions & 2 deletions app/routes/armoury.$character.contracts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getAccountWallet,
} from "~/services/darktide.server"
import { twMerge } from "tailwind-merge"
import useLocale from "~/hooks/locale"

export async function action({ params, request }: ActionArgs) {
let { character: characterId } = zx.parseParams(params, {
Expand Down Expand Up @@ -161,6 +162,7 @@ function timeUntil(date: number) {
export default function Contracts() {
let data = useLoaderData<typeof loader>()
let navigation = useNavigation()
let locale = useLocale()

let [timeLeft, setTimeLeft] = useState(
timeUntil(parseInt(data?.refreshTime ?? "0", 10)),
Expand Down Expand Up @@ -190,12 +192,14 @@ export default function Contracts() {
<div className="flex flex-row gap-4">
<div className="flex items-center">
<CircleStackIcon className="mr-1 h-4 w-4" aria-hidden />{" "}
{data.wallet?.credits?.balance.amount.toLocaleString() ?? "--"}{" "}
{data.wallet?.credits?.balance.amount.toLocaleString(locale) ??
"--"}{" "}
credits
</div>
<div className="flex items-center">
<Square2StackIcon className="mr-1 h-4 w-4" aria-hidden />{" "}
{data.wallet?.marks?.balance.amount.toLocaleString() ?? "--"} marks
{data.wallet?.marks?.balance.amount.toLocaleString(locale) ?? "--"}{" "}
marks
</div>
</div>
</div>
Expand Down
113 changes: 113 additions & 0 deletions app/routes/armoury.$character.sessions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Link, useLoaderData } from "@remix-run/react"
import type { LoaderArgs } from "@remix-run/server-runtime"
import { json } from "@remix-run/server-runtime"
import { z } from "zod"
import { zx } from "zodix"
import { getAuthToken } from "~/data/authtoken.server"
import { authenticator } from "~/services/auth.server"
import { getCharacterStats } from "~/services/darktide.server"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "~/components/ui/table"
import { zipObjectDeep, get, orderBy } from "lodash-es"
import { is, record, string } from "valibot"
import { getGameplaySessions } from "~/data/gameplaySessions.server"
import useLocale from "~/hooks/locale"

type Stats = { typePath: string[]; value: Record<string, number> }[]
function zipStats(stats: Stats) {
return zipObjectDeep(
stats.map((stat) => stat.typePath.join(".")),
stats.map((stat) => stat.value),
)
}

function explodeKeyTable(keyTable: unknown): Record<string, unknown>[] {
let result = []

if (is(record(string()), keyTable)) {
for (let key in keyTable) {
let value = keyTable[key]
let row: Record<string, unknown> = { value }

let otherCols = key.split("|")
if (Array.isArray(otherCols) && otherCols.length) {
for (let col of otherCols) {
let [key, val] = col.split(":")
if (key) {
row[key] = val
}
}
}

result.push(row)
}
}

return result
}

export async function loader({ params, request }: LoaderArgs) {
let { character: characterId } = zx.parseParams(params, {
character: z.string(),
})
let user = await authenticator.isAuthenticated(request, {
failureRedirect: "/login",
})

let auth = await getAuthToken(user.id)

let gameplaySessions = await getGameplaySessions({
accountId: auth.sub,
characterId,
})

return json({
sessions: gameplaySessions.map((s) => {
return { id: s.sessionId, createdAt: s.createdAt }
}),
})
}

export default function Statistics() {
let { sessions } = useLoaderData<typeof loader>()
let locale = useLocale()

return (
<div className="max-w-7xl mx-auto flex gap-4 pb-4 flex-wrap">
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Ended at</TableHead>
<TableHead>Session</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{sessions.map((session) => {
return (
<TableRow key={session.id}>
<TableCell className="p-0">
<Link className="p-4 flex object-cover" to={session.id}>
{new Date(session.createdAt).toLocaleString(locale)}
</Link>
</TableCell>
<TableCell className="p-0">
<Link className="p-4 flex object-cover" to={session.id}>
{session.id}
</Link>
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</div>
</div>
)
}
8 changes: 4 additions & 4 deletions app/routes/armoury.$character.statistics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
TableRow,
} from "~/components/ui/table"
import { zipObjectDeep, get, orderBy } from "lodash-es"
import { isRecord } from "~/utils/isRecord"
import { is, record, string, unknown } from "valibot"

type Stats = { typePath: string[]; value: Record<string, number> }[]
function zipStats(stats: Stats) {
Expand All @@ -28,7 +28,7 @@ function zipStats(stats: Stats) {
function explodeKeyTable(keyTable: unknown): Record<string, unknown>[] {
let result = []

if (isRecord(keyTable)) {
if (is(record(string(), unknown()), keyTable)) {
for (let key in keyTable) {
let value = keyTable[key]
let row: Record<string, unknown> = { value }
Expand Down Expand Up @@ -76,7 +76,7 @@ export async function loader({ params, request }: LoaderArgs) {
)
let m = "mission" in mission ? mission.mission : {}
let justMissions = {}
if (isRecord(m)) {
if (is(record(string(), unknown()), m)) {
justMissions = { ...m }
if ("playtime" in justMissions) {
delete justMissions.playtime
Expand Down Expand Up @@ -215,7 +215,7 @@ function AutoTable({
{rows.map((row, i) => (
<TableRow key={i}>
{cols.map((col) => (
<TableCell key={col.key}>{row[col.key]}</TableCell>
<TableCell key={col.key}>{String(row[col.key])}</TableCell>
))}
</TableRow>
))}
Expand Down
1 change: 1 addition & 0 deletions app/routes/armoury.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ let charLinks = [
{ link: "requisitorium", label: "Requisitorium" },
{ link: "contracts", label: "Contracts" },
{ link: "statistics", label: "Statistics" },
{ link: "sessions", label: "History" },
]

export let loader = async ({ request, params }: LoaderArgs) => {
Expand Down
Loading

0 comments on commit 2539590

Please sign in to comment.