Skip to content

Commit d3a9b32

Browse files
authored
feat: add basic party management
- feat: add party management page - refactor: add new className property - feat: add combobox component - feat: add party actions - refator: remove extra definition - refactor: improve custom filter - refactor: update access token - feat: create custom state - refactor: apply some optimizations - feat: add integration for claiming rewards - fix: add early return - feat: add utility type - refactor: run in parallel - refactor: use utility and add new response - feat: claim quest rewards - feat: add history initial layout - feat: add resources data - feat: add demo information - feat: add clamied rewards notifications - refactor: filter valid claims - feat: add note - refactor: claim rewards after kick - fix: increase min width
1 parent 2e70064 commit d3a9b32

File tree

55 files changed

+3266
-15
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3266
-15
lines changed

assets/images/currency/vbucks.png

-55.9 KB
Binary file not shown.

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8" />
55
<meta
66
http-equiv="Content-Security-Policy"
7-
content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'"
7+
content="default-src 'self' https://raw.githubusercontent.com; style-src 'self' 'unsafe-inline'; script-src 'self'"
88
/>
99
<title>Aerial Launcher</title>
1010
</head>

package-lock.json

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"@radix-ui/react-scroll-area": "^1.0.5",
4343
"@radix-ui/react-separator": "^1.0.3",
4444
"@radix-ui/react-slot": "^1.0.2",
45+
"@radix-ui/react-switch": "^1.0.3",
4546
"@radix-ui/react-tooltip": "^1.0.7",
4647
"@tanstack/react-router": "^1.29.2",
4748
"axios": "^1.6.8",

src/components/account-list/hooks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function useAccountList() {
2727
const tags = getGroupTagsByAccountId(account.accountId)
2828

2929
if (checkIfCustomDisplayNameIsValid(account.customDisplayName)) {
30-
_keys.push(account.customDisplayName as string)
30+
_keys.push(account.customDisplayName)
3131
}
3232

3333
if (provider !== '') {

src/components/menu/history.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import type { RewardsNotification } from '../../types/notifications'
2+
3+
import { repositoryAssetsURL } from '../../config/about/links'
4+
5+
import { ScrollArea } from '../ui/scroll-area'
6+
7+
import { useClaimedRewards } from '../../hooks/stw-operations/claimed-rewards'
8+
9+
import { useGetAccounts } from '../../hooks/accounts'
10+
11+
import { parseResource } from '../../lib/parsers/resources'
12+
import { parseDisplayName } from '../../lib/utils'
13+
14+
export function HistoryMenu() {
15+
const { data } = useClaimedRewards()
16+
const dataOrderByDesc = data.toReversed()
17+
18+
return (
19+
<ScrollArea className="h-full max-h-[calc(100vh-3.5rem)]">
20+
{dataOrderByDesc.length > 0 ? (
21+
<>
22+
<div className="border-l-4 italic mb-4 mt-2 pl-2 py-1 text-muted-foreground">
23+
Note: this is a temporal history
24+
</div>
25+
<div className="flex-1 pb-6 [&_img]:pointer-events-none [&_img]:select-none">
26+
{dataOrderByDesc.map((item, index) => (
27+
<div
28+
className="border-b py-3 space-y-5 text-foreground/90 last:border-b-0"
29+
key={index}
30+
>
31+
<RewardSection data={item} />
32+
</div>
33+
))}
34+
</div>
35+
</>
36+
) : (
37+
<div className="flex items-center justify-center text-muted-foreground min-h-[calc(100vh-3.5rem)]">
38+
Claimed Reward History
39+
</div>
40+
)}
41+
</ScrollArea>
42+
)
43+
}
44+
45+
function RewardSection({ data }: { data: Array<RewardsNotification> }) {
46+
const { accountList } = useGetAccounts()
47+
48+
return data.map((item, index) => (
49+
<div key={index}>
50+
<div className="font-bold mb-2 break-all">
51+
{parseDisplayName(accountList[item.accountId])}:
52+
</div>
53+
<ul
54+
className="space-y-1"
55+
key={index}
56+
>
57+
<RewardItems rewards={item.rewards} />
58+
<AccoladesItem accolades={item.accolades} />
59+
</ul>
60+
</div>
61+
))
62+
}
63+
64+
function RewardItems({ rewards }: Pick<RewardsNotification, 'rewards'>) {
65+
const rawItems = Object.entries(rewards)
66+
const items = rawItems.map(([key, quantity]) =>
67+
parseResource({ key, quantity })
68+
)
69+
70+
return items.map((item, index) => (
71+
<li key={index}>
72+
<figure className="flex gap-1 items-center">
73+
<img
74+
src={item.imgUrl}
75+
className="size-6"
76+
alt={item.name}
77+
/>
78+
<figcaption className="break-all">
79+
{Intl.NumberFormat('en-US').format(item.quantity)} &times;{' '}
80+
{item.name}
81+
</figcaption>
82+
</figure>
83+
</li>
84+
))
85+
}
86+
87+
function AccoladesItem({
88+
accolades,
89+
}: Pick<RewardsNotification, 'accolades'>) {
90+
return (
91+
<li>
92+
<figure className="flex gap-1 items-center">
93+
<img
94+
src={`${repositoryAssetsURL}/images/brxp.png`}
95+
className="size-6"
96+
alt="Accolades"
97+
/>
98+
<figcaption className="break-all">
99+
{Intl.NumberFormat('en-US').format(
100+
accolades.totalMissionXPRedeemed +
101+
accolades.totalQuestXPRedeemed
102+
)}{' '}
103+
&times; Accolades
104+
</figcaption>
105+
</figure>
106+
</li>
107+
)
108+
}

src/components/menu/sidebar.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,23 @@ export function SidebarMenu({
7070
<div
7171
className={cn(
7272
'px-3 py-2 text-muted-foreground',
73-
'[&_.item-account-management>a]:flex'
73+
'[&_.item-stw-operations>a]:flex'
7474
)}
7575
>
7676
<ul className="list-disc ml-5">
77-
<li className="item-account-management">
77+
<li className="item-stw-operations">
78+
<Link
79+
to="/stw-operations/party"
80+
className={currentClassNameHover}
81+
activeProps={{
82+
className: cn(activeClassName),
83+
}}
84+
onClick={goToPage}
85+
>
86+
Party
87+
</Link>
88+
</li>
89+
<li className="item-stw-operations">
7890
<Link
7991
to="/stw-operations/save-quests"
8092
className={currentClassNameHover}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { useState } from 'react'
2+
3+
export type ComboboxOption = {
4+
label: string
5+
value: string
6+
keywords: Array<string>
7+
}
8+
9+
export type ComboboxProps = {
10+
className?: string
11+
emptyText?: string
12+
isMulti?: boolean
13+
options: Array<ComboboxOption>
14+
placeholder?: string
15+
placeholderSearch?: string
16+
value?: Array<ComboboxOption>
17+
customFilter?: (
18+
value: string,
19+
search: string,
20+
keywords?: Array<string>
21+
) => number
22+
onChange?: (values: Array<ComboboxOption>) => void
23+
}
24+
25+
export function useData({
26+
isMulti = false,
27+
options,
28+
value,
29+
onChange,
30+
}: Pick<ComboboxProps, 'isMulti' | 'options' | 'value' | 'onChange'>) {
31+
const [open, setOpen] = useState(false)
32+
const [__values, __setValues] = useState<Array<ComboboxOption>>([])
33+
34+
const currentValues = value ?? __values
35+
36+
const selectedName = isMulti
37+
? currentValues.length > 1
38+
? `${currentValues.length} selected`
39+
: currentValues[0]?.label
40+
: options.find((item) => item.value === currentValues[0]?.value)?.label
41+
42+
const __onChange = (value: string) => {
43+
const current = options.find((item) => item.value === value)
44+
const hasItem = currentValues.find((item) => item.value === value)
45+
const update = (values: Array<ComboboxOption>) => {
46+
__setValues(values)
47+
onChange?.(values)
48+
}
49+
50+
if (!current) {
51+
return
52+
}
53+
54+
if (!isMulti) {
55+
update(hasItem ? [] : [current])
56+
57+
return
58+
}
59+
60+
const newValues = hasItem
61+
? currentValues.filter((item) => item.value !== value)
62+
: current
63+
? [...currentValues, current]
64+
: currentValues
65+
66+
update(newValues)
67+
}
68+
69+
return {
70+
currentValues,
71+
open,
72+
selectedName,
73+
74+
setOpen,
75+
__onChange,
76+
}
77+
}

0 commit comments

Comments
 (0)