-
Notifications
You must be signed in to change notification settings - Fork 531
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip: most player modal pages tsx (no data/actions)
- Loading branch information
Showing
7 changed files
with
332 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export default function BanTab() { | ||
return <> | ||
Ban ban ban... | ||
</>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { Button } from "@/components/ui/button"; | ||
import { cn } from "@/lib/utils"; | ||
import { PlayerHistoryItem, PlayerModalSuccess } from "@shared/playerApiTypes"; | ||
|
||
|
||
|
||
type HistoryItemProps = { | ||
action: PlayerHistoryItem, | ||
permsDisableWarn: boolean, | ||
permsDisableBan: boolean, | ||
serverTime: number, | ||
} | ||
function HistoryItem({ action, permsDisableWarn, permsDisableBan, serverTime }: HistoryItemProps) { | ||
const isRevokeDisabled = ( | ||
!!action.revokedBy || | ||
(action.type == 'warn' && permsDisableWarn) || | ||
(action.type == 'ban' && permsDisableBan) | ||
); | ||
const actionDate = (new Date(action.ts * 1000)).toLocaleString(); | ||
|
||
let footerNote, borderColorClass, actionMessage; | ||
if (action.type == 'ban') { | ||
borderColorClass = 'border-destructive'; | ||
actionMessage = `BANNED by ${action.author}`; | ||
} else if (action.type == 'warn') { | ||
borderColorClass = 'border-warning'; | ||
actionMessage = `WARNED by ${action.author}`; | ||
} | ||
if (action.revokedBy) { | ||
borderColorClass = ''; | ||
footerNote = `Revoked by ${action.revokedBy}.`; | ||
} | ||
if (typeof action.exp == 'number') { | ||
const expirationDate = (new Date(action.exp * 1000)).toLocaleString(); | ||
footerNote = (action.exp < serverTime) ? `Expired at ${expirationDate}.` : `Expires at ${expirationDate}.`; | ||
} | ||
|
||
|
||
return ( | ||
<div className={cn('pl-2 border-l-4', borderColorClass)}> | ||
<div className="flex w-full justify-between"> | ||
<strong className="text-sm">{actionMessage}</strong> | ||
<small className="text-right text-xxs space-x-1"> | ||
<span className="font-mono">({action.id})</span> | ||
<span className="opacity-75">{actionDate}</span> | ||
<Button | ||
variant="outline" | ||
size='inline' | ||
disabled={isRevokeDisabled} | ||
onClick={() => { }} | ||
>Revoke</Button> | ||
</small> | ||
</div> | ||
<span className="text-sm">{action.reason}</span> | ||
{footerNote && <small className="block text-xxs opacity-75">{footerNote}</small>} | ||
</div> | ||
); | ||
} | ||
|
||
|
||
export default function HistoryTab() { | ||
return <div className="flex flex-col gap-1"> | ||
{exampleData.player.actionHistory.map((action) => ( | ||
<HistoryItem action={action} permsDisableWarn={false} permsDisableBan={false} serverTime={0} /> | ||
))} | ||
</div>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { txToast } from "@/components/TxToaster"; | ||
import { cn } from "@/lib/utils"; | ||
import { CopyIcon } from "lucide-react"; | ||
import { useState } from "react"; | ||
|
||
//DEBUG | ||
const exampleData = { | ||
ids: [], | ||
hwids: [], | ||
oldIds: [], | ||
oldHwids: [], | ||
} | ||
|
||
type IdsBlockProps = { | ||
title: string, | ||
emptyMessage: string, | ||
allIds: string[], | ||
currIds: string[], | ||
isSmaller?: boolean, | ||
} | ||
function IdsBlock({ title, emptyMessage, allIds, currIds, isSmaller }: IdsBlockProps) { | ||
const [hasCopiedIds, setHasCopiedIds] = useState(false); | ||
const displayCurrIds = currIds.sort((a, b) => a.localeCompare(b)); | ||
const displayOldIds = allIds.filter((id) => !currIds.includes(id)).sort((a, b) => a.localeCompare(b)); | ||
|
||
const handleCopyIds = () => { | ||
try { | ||
//Just to guarantee the correct visual order | ||
const arrToCopy = [...displayCurrIds, ...displayOldIds]; | ||
navigator.clipboard.writeText(arrToCopy.join('\n')); | ||
setHasCopiedIds(true); | ||
} catch (error) { | ||
txToast.error('Failed to copy to clipboard :('); | ||
} | ||
} | ||
|
||
return <div> | ||
<div className="flex justify-between items-center pb-1"> | ||
<h3 className="text-xl">{title}</h3> | ||
{hasCopiedIds ? ( | ||
<span className="text-sm text-success-inline">Copied!</span> | ||
) : ( | ||
<button onClick={handleCopyIds}> | ||
<CopyIcon className="h-4 text-secondary hover:text-primary" /> | ||
</button> | ||
)} | ||
</div> | ||
<p className={cn( | ||
"font-mono break-all whitespace-pre-wrap border rounded divide-y divide-border/50 tracking-wider text-muted-foreground", | ||
isSmaller ? "text-xxs leading-5" : "text-xs leading-6" | ||
)}> | ||
{displayCurrIds.length === 0 && <span className="block px-1 opacity-50 italic">{emptyMessage}</span>} | ||
{displayCurrIds.map((id) => ( | ||
<span className="block px-1 font-semibold">{id}</span> | ||
))} | ||
{displayOldIds.map((id) => ( | ||
<span className="block px-1 opacity-50">{id}</span> | ||
))} | ||
</p> | ||
</div> | ||
} | ||
|
||
|
||
export default function IdsTab() { | ||
return <div className="flex flex-col gap-4"> | ||
<IdsBlock | ||
title="Player Identifiers" | ||
emptyMessage="This player has no identifiers." | ||
allIds={exampleData.oldIds} | ||
currIds={exampleData.ids} | ||
/> | ||
<IdsBlock | ||
title="Player Hardware IDs" | ||
emptyMessage="This player has no hardware IDs." | ||
allIds={exampleData.oldHwids} | ||
currIds={exampleData.hwids} isSmaller | ||
/> | ||
</div>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import InlineCode from "@/components/InlineCode"; | ||
import { Button } from "@/components/ui/button"; | ||
import { Label } from "@/components/ui/label"; | ||
import { Textarea } from "@/components/ui/textarea"; | ||
import { cn } from "@/lib/utils"; | ||
|
||
|
||
function LogActionCounter({ type, count }: { type: 'Ban' | 'Warn', count: number }) { | ||
const pluralLabel = (count > 1) ? `${type}s` : type; | ||
if (count === 0) { | ||
return <span className={cn( | ||
'rounded-sm text-xs font-semibold px-1 py-[0.125rem] tracking-widest text-center inline-block', | ||
'bg-secondary text-secondary-foreground' | ||
)}> | ||
0 {type}s | ||
</span> | ||
} else { | ||
return <span className={cn( | ||
'rounded-sm text-xs font-semibold px-1 py-[0.125rem] tracking-widest text-center inline-block', | ||
type === 'Ban' ? 'bg-destructive text-destructive-foreground' : 'bg-warning text-warning-foreground' | ||
)}> | ||
{count} {pluralLabel} | ||
</span> | ||
} | ||
} | ||
|
||
function PlayerNotesBox() { | ||
return <> | ||
<Label htmlFor="playerNotes"> | ||
Notes: | ||
<span className="text-muted-foreground">Last modified by <InlineCode>tabarra</InlineCode> in October 18, 2003.</span> | ||
</Label> | ||
<Textarea | ||
placeholder="Type your notes about the player." | ||
id="playerNotes" | ||
className="w-full mt-1 bg-black/10 dark:bg-black/40" | ||
/> | ||
</> | ||
} | ||
|
||
export default function InfoTab() { | ||
return <div> | ||
<h3 className="text-xl pb-2">Player Information</h3> | ||
|
||
<dl className="pb-2"> | ||
<div className="py-0.5 grid grid-cols-3 gap-4 px-0"> | ||
<dt className="text-sm font-medium leading-6 text-muted-foreground">Session Time</dt> | ||
<dd className="text-sm leading-6 col-span-2 mt-0">5 hours, 43 minutes</dd> | ||
</div> | ||
<div className="py-0.5 grid grid-cols-3 gap-4 px-0"> | ||
<dt className="text-sm font-medium leading-6 text-muted-foreground">Play Time</dt> | ||
<dd className="text-sm leading-6 col-span-2 mt-0">18 days, 21 hours</dd> | ||
</div> | ||
<div className="py-0.5 grid grid-cols-3 gap-4 px-0"> | ||
<dt className="text-sm font-medium leading-6 text-muted-foreground">Joined</dt> | ||
<dd className="text-sm leading-6 col-span-2 mt-0">20 December 2022</dd> | ||
</div> | ||
<div className="py-0.5 grid grid-cols-3 gap-4 px-0"> | ||
<dt className="text-sm font-medium leading-6 text-muted-foreground">Whitelisted</dt> | ||
<dd className="text-sm leading-6 mt-0"> | ||
not yet | ||
</dd> | ||
<dd className="text-right"> | ||
<Button | ||
variant="outline" | ||
size='inline' | ||
style={{minWidth: '8ch'}} | ||
onClick={() => { }} | ||
>Add WL</Button> | ||
</dd> | ||
</div> | ||
<div className="py-0.5 grid grid-cols-3 gap-4 px-0"> | ||
<dt className="text-sm font-medium leading-6 text-muted-foreground">Log</dt> | ||
<dd className="text-sm leading-6 mt-0 space-x-2"> | ||
<LogActionCounter type="Ban" count={12} /> | ||
<LogActionCounter type="Warn" count={2} /> | ||
</dd> | ||
<dd className="text-right"> | ||
<Button | ||
variant="outline" | ||
size='inline' | ||
style={{minWidth: '8ch'}} | ||
onClick={() => { }} | ||
>View</Button> | ||
</dd> | ||
</div> | ||
</dl> | ||
|
||
<PlayerNotesBox /> | ||
</div>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.