Skip to content

Commit 7efcf7f

Browse files
committed
Update .gitignore, refactor Header component for type safety, and adjust API URLs in context files
1 parent 2c48154 commit 7efcf7f

File tree

13 files changed

+219
-163
lines changed

13 files changed

+219
-163
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ lerna-debug.log*
99
MaddonsManager.github.io.code-workspace
1010
.react-router/
1111

12+
.env
13+
.env.production
14+
.env.development
1215
node_modules
1316
dist
1417
dist-ssr

src/components/Header/Header.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface HeaderProps {
99
const Header = ({ data }: HeaderProps) => {
1010
const { pathname } = useLocation()
1111

12-
const getPageLabel = () => {
12+
const getPageLabel = (): string | undefined => {
1313
const allNavItems = [...siteConfig.navItems, ...siteConfig.navItemsAccord]
1414
return allNavItems.find((item) => item.href.toLowerCase() === pathname.toLowerCase())?.label
1515
}

src/components/ItemList/ItemList.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Card, CardBody, Image, Button, Tooltip, Chip, Avatar, Divider } from "@heroui/react"
1+
import { Card, CardBody, Image, Button, Tooltip, Chip, Avatar, Divider } from '@heroui/react'
22
import { AnimatePresence } from 'framer-motion'
33
import { classIcon } from '@/utils/classIcon'
44
import { FlameIcon, GroupIcon } from '@/assets/Icons'
@@ -16,7 +16,7 @@ const ItemList = ({ data, onOpenDetails, handleCopyToClipboard, itemToShow }: It
1616
<AnimatePresence>
1717
{data.slice(0, itemToShow).map((item: StringItems) => (
1818
<div
19-
key={`${item.uuid}-${item.title}`}
19+
key={`${item.file_name}-${item.title}`}
2020
className="transition-transform duration-300 ease-in-out hover:scale-105"
2121
>
2222
<Card
@@ -67,7 +67,7 @@ const ItemList = ({ data, onOpenDetails, handleCopyToClipboard, itemToShow }: It
6767
item.class.map((className: string, index: number) => (
6868
<Chip
6969
avatar={
70-
className === 'ALL' ? (
70+
className === 'All' ? (
7171
<GroupIcon />
7272
) : (
7373
<Avatar

src/components/ProfilesDetails/ProfilesDetails.tsx

+13-26
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import {
99
Chip,
1010
Image,
1111
Avatar
12-
} from "@heroui/react"
12+
} from '@heroui/react'
1313
import ReactMarkdown from 'react-markdown'
1414
import { classIcon, roleIcon } from '@/utils/classIcon'
1515
import remarkGfm from 'remark-gfm'
1616
import rehypeRaw from 'rehype-raw'
1717
import hljs from 'highlight.js'
1818
import { useEffect } from 'react'
19+
import { GroupIcon } from '@/assets/Icons'
1920

2021
interface ProfilesDetailsProps {
2122
data: any
@@ -67,10 +68,14 @@ const ProfilesDetails = ({ data, isOpen, onOpenChange }: ProfilesDetailsProps) =
6768
{data.class.map((className: string, index: number) => (
6869
<Chip
6970
avatar={
70-
<Avatar
71-
name={data.title}
72-
src={classIcon[className]}
73-
/>
71+
className === 'All' ? (
72+
<GroupIcon />
73+
) : (
74+
<Avatar
75+
name={data.title}
76+
src={classIcon[className]}
77+
/>
78+
)
7479
}
7580
key={index}
7681
color="warning"
@@ -107,38 +112,20 @@ const ProfilesDetails = ({ data, isOpen, onOpenChange }: ProfilesDetailsProps) =
107112
<Divider className="my-2" />
108113
<div className="flex items-center justify-between">
109114
<p className=" text-white/60">95.1k Downloads - 141.9k views</p>
110-
<p className="text-sm text-gray-500">
111-
Last updated: {data.lastUpdate}
112-
</p>
113-
<p className="text-sm text-gray-500">version: {data.version}</p>
115+
<p className="text-sm text-gray-500">Last updated:</p>
116+
<p className="text-sm text-gray-500">version: </p>
114117
</div>
115118
<Divider className="my-2" />
116119
<h2 className="text-lg font-extrabold">Description</h2>
117120
<article className="markdown-body p-1 !bg-transparent">
118121
<ReactMarkdown
119122
remarkPlugins={[remarkGfm]}
120123
rehypePlugins={[rehypeRaw]}
124+
className="text-default-900 gap-4 w-auto p-4 mx-auto flex-col lg:flex-row rounded-md"
121125
>
122126
{data.md}
123127
</ReactMarkdown>
124128
</article>
125-
<div className="flex justify-center p-4 ">
126-
<Image
127-
shadow="md"
128-
alt={data.title}
129-
radius="sm"
130-
src={data.logo}
131-
className="max-w-[500px] max-h-[500px]"
132-
/>
133-
</div>
134-
<div className="flex flex-col items-start justify-center p-4">
135-
<h2 className="text-lg font-extrabold">Changelogs</h2>
136-
{data.changelog.map((changelog: string, index: number) => (
137-
<p key={index} className="block my-2 text-justify">
138-
{changelog}
139-
</p>
140-
))}
141-
</div>
142129
</DrawerBody>
143130
<DrawerFooter>
144131
<Button color="primary" onPress={onClose}>

src/components/Searcher/Searcher.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Autocomplete, AutocompleteItem } from "@heroui/react"
1+
import { Autocomplete, AutocompleteItem } from '@heroui/react'
22
import { SearchIcon } from '@/assets/Icons'
33

44
interface SearcherProps {
@@ -14,7 +14,7 @@ const SearchAddon = ({ searchTerm, setSearchTerm, valueName }: SearcherProps) =>
1414
isVirtualized
1515
selectedKey={searchTerm}
1616
onSelectionChange={(key) => setSearchTerm(key as string)}
17-
defaultItems={valueName.map((name) => ({ key: name, name: name }))}
17+
defaultItems={valueName.map((title) => ({ key: title, title: title }))}
1818
startContent={<SearchIcon className="w-4 h-4" />}
1919
size="md"
2020
className="w-full font-bold text-default-900"
@@ -46,8 +46,8 @@ const SearchAddon = ({ searchTerm, setSearchTerm, valueName }: SearcherProps) =>
4646
}}
4747
>
4848
{(item) => (
49-
<AutocompleteItem key={item.key} textValue={item.name}>
50-
{item.name}
49+
<AutocompleteItem key={item.key} textValue={item.title}>
50+
{item.title}
5151
</AutocompleteItem>
5252
)}
5353
</Autocomplete>

src/context/AddonsContext.tsx

+30-33
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@ import { createContext, FC, ReactNode, useContext } from 'react'
22
import { useQuery } from '@tanstack/react-query'
33
import { AddonsDataState } from '@/types'
44

5-
const urls: { [key: string]: string } = {
6-
LichKing: 'https://raw.githubusercontent.com/PentSec/wowAddonsAPI/main/LK/lichking.json',
7-
Cataclysm: 'https://raw.githubusercontent.com/PentSec/wowAddonsAPI/main/Cata/cataclysm.json',
8-
Pandaria: 'https://raw.githubusercontent.com/PentSec/wowAddonsAPI/main/Panda/pandaria.json'
9-
}
5+
const jsonUrl =
6+
'https://raw.githubusercontent.com/PentSec/MaddonsManager/refs/heads/main/API/Maddons.json'
107

118
interface AddonsContextValue {
12-
data: AddonsDataState
9+
data: AddonsDataState[]
1310
isPending: boolean
1411
error: string | null
1512
}
@@ -24,41 +21,41 @@ export const useAddonsContext = (): AddonsContextValue => {
2421
return context
2522
}
2623

27-
const fetchAddons = async (key: string) => {
28-
const response = await fetch(urls[key]).then((res) => res.json())
29-
return response
24+
const fetchAddons = async (url: string) => {
25+
const response = await fetch(url)
26+
const jsonData = await response.json()
27+
return Promise.all(
28+
jsonData.map(async (item: AddonsDataState) => {
29+
const mdUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/refs/heads/main/API/Addons/${item.file_name}/post.md`
30+
const logoUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/refs/heads/main/API/Addons/${item.file_name}/${item.file_name}.webp`
31+
const zipUrl = `https://github.com/PentSec/MaddonsManager/raw/refs/heads/main/API/Addons/${item.file_name}/${item.file_name}.zip`
32+
33+
const [md] = await Promise.all([
34+
fetch(mdUrl).then((res) => {
35+
if (!res.ok) throw new Error(`Failed to fetch md for ${item.file_name}`)
36+
return res.text()
37+
})
38+
])
39+
40+
return { ...item, md, logo: logoUrl, zip: zipUrl }
41+
})
42+
)
3043
}
3144

3245
export const AddonsProvider: FC<{ children: ReactNode }> = ({ children }) => {
33-
const lichKingQuery = useQuery({
34-
queryKey: ['lichKing'],
35-
queryFn: () => fetchAddons('LichKing'),
36-
refetchOnWindowFocus: false
37-
})
38-
const cataclysmQuery = useQuery({
39-
queryKey: ['cataclysm'],
40-
queryFn: () => fetchAddons('Cataclysm'),
41-
refetchOnWindowFocus: false
42-
})
43-
const pandariaQuery = useQuery({
44-
queryKey: ['pandaria'],
45-
queryFn: () => fetchAddons('Pandaria'),
46+
const { data, isPending, error } = useQuery({
47+
queryKey: ['addons'],
48+
queryFn: () => fetchAddons(jsonUrl),
4649
refetchOnWindowFocus: false
4750
})
4851

49-
const data: AddonsDataState = {
50-
LichKing: lichKingQuery.data || [],
51-
Cataclysm: cataclysmQuery.data || [],
52-
Pandaria: pandariaQuery.data || []
53-
}
54-
55-
const isPending = lichKingQuery.isPending || cataclysmQuery.isPending || pandariaQuery.isPending
56-
57-
const error = lichKingQuery.error || cataclysmQuery.error || pandariaQuery.error
58-
5952
return (
6053
<AddonsContext.Provider
61-
value={{ data, isPending, error: error ? (error as Error).message : null }}
54+
value={{
55+
data: data || [],
56+
isPending,
57+
error: error ? (error as Error).message : null
58+
}}
6259
>
6360
{children}
6461
</AddonsContext.Provider>

src/context/ElvUIContext.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createContext, useContext, FC, ReactNode } from 'react'
22
import { StringItems } from '@/types'
33
import { useQuery } from '@tanstack/react-query'
44

5-
const jsonUrl = 'https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/ElvUI/ElvUI.json'
5+
const jsonUrl = 'https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/ElvUI.json'
66

77
interface ElvUIContextValue {
88
data: StringItems[]
@@ -25,17 +25,17 @@ const fetchElvUIWithContent = async (url: string): Promise<StringItems[]> => {
2525
const jsonData = await response.json()
2626
return Promise.all(
2727
jsonData.map(async (item: StringItems) => {
28-
const txtUrl = `https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/ElvUI/${item.uuid}/${item.uuid}.txt`
29-
const logoUrl = `https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/ElvUI/${item.uuid}/${item.logo}`
30-
const mdUrl = `https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/ElvUI/${item.uuid}/${item.uuid}.md`
28+
const txtUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/ElvUI/${item.file_name}/${item.file_name}.txt`
29+
const logoUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/ElvUI/${item.file_name}/${item.file_name}.webp`
30+
const mdUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/ElvUI/${item.file_name}/post.md`
3131

3232
const [content, md] = await Promise.all([
3333
fetch(txtUrl).then((res) => {
34-
if (!res.ok) throw new Error(`Failed to fetch txt for ${item.uuid}`)
34+
if (!res.ok) throw new Error(`Failed to fetch txt for ${item.file_name}`)
3535
return res.text()
3636
}),
3737
fetch(mdUrl).then((res) => {
38-
if (!res.ok) throw new Error(`Failed to fetch md for ${item.uuid}`)
38+
if (!res.ok) throw new Error(`Failed to fetch md for ${item.file_name}`)
3939
return res.text()
4040
})
4141
])

src/context/WeakAurasContext.tsx

+4-5
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { createContext, FC, ReactNode, useContext } from 'react'
22
import { useQuery } from '@tanstack/react-query'
33
import { StringItems } from '@/types'
44

5-
const jsonUrl =
6-
'https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/WeakAuras/WeakAuras.json'
5+
const jsonUrl = 'https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/WeakAuras.json'
76

87
interface WeakAurasContextValue {
98
data: StringItems[]
@@ -26,9 +25,9 @@ const fetchWeakAurasWithContent = async (url: string): Promise<StringItems[]> =>
2625
const jsonData = await response.json()
2726
return Promise.all(
2827
jsonData.map(async (item: any) => {
29-
const txtUrl = `https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/WeakAuras/${item.uuid}/${item.uuid}.txt`
30-
const logoUrl = `https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/WeakAuras/${item.uuid}/${item.logo}`
31-
const mdUrl = `https://raw.githubusercontent.com/PentSec/wowAddonsAPI/develop/WeakAuras/${item.uuid}/${item.uuid}.md`
28+
const txtUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/WeakAuras/${item.file_name}/${item.file_name}.txt`
29+
const logoUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/WeakAuras/${item.file_name}/${item.file_name}.webp`
30+
const mdUrl = `https://raw.githubusercontent.com/PentSec/MaddonsManager/main/API/WeakAuras/${item.file_name}/post.md`
3231

3332
const [content, md] = await Promise.all([
3433
fetch(txtUrl).then((res) => (res.ok ? res.text() : null)),

src/hook/useFilterAddons.ts

+16-26
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,35 @@
11
import { useState, useMemo } from 'react'
22
import { AddonsData, AddonsDataState } from '@/types'
33

4-
const useFilterAddons = (data: AddonsDataState | null, onOpen: (isOpen: boolean) => void) => {
4+
const useFilterAddons = (data: AddonsDataState[], onOpen: () => void) => {
55
const [searchTerm, setSearchTerm] = useState<string | null>(null)
66
const [version, setVersion] = useState<string | null>(null)
77
const [selectedType, setSelectedType] = useState<string | null>(null)
88
const [isSelectAddon, setIsSelectAddon] = useState<AddonsData | null>(null)
99

1010
const combinedData = useMemo(() => {
11-
if (!data) return []
12-
const allData = [...data.LichKing, ...data.Cataclysm, ...data.Pandaria]
13-
return version === null ? allData : data[version] || []
14-
}, [data, version])
11+
if (!data || data.length === 0) return []
12+
return Array.from(new Set(data.flatMap((item) => item.expansion)))
13+
}, [data])
1514

1615
const addonTypes = useMemo(() => {
17-
return combinedData && combinedData.length > 0
18-
? Array.from(new Set(combinedData.map((addon) => addon.addonType)))
19-
: []
20-
}, [combinedData])
16+
return Array.from(new Set(data.flatMap((item) => item.tags)))
17+
}, [data])
2118

2219
const filteredData = useMemo(() => {
23-
return (
24-
combinedData?.filter((addon) => {
25-
const matchesSearch = searchTerm
26-
? addon.name.toLowerCase().includes(searchTerm.toLowerCase())
27-
: true
28-
const matchesType = selectedType ? addon.addonType === selectedType : true
29-
return matchesSearch && matchesType
30-
}) || []
31-
)
32-
}, [combinedData, searchTerm, selectedType])
33-
34-
const handleDownload = async (githubRepo: string) => {
35-
const mainUrl = `${githubRepo}/archive/refs/heads/main.zip`
36-
window.open(mainUrl)
37-
}
20+
return data.filter((item) => {
21+
const matchesSearch = searchTerm
22+
? item.title.toLowerCase().includes(searchTerm.toLowerCase())
23+
: true
24+
const matchesType = selectedType ? item.tags.includes(selectedType) : true
25+
const matchesExpansion = version ? item.expansion.includes(version) : true
26+
return matchesSearch && matchesType && matchesExpansion
27+
})
28+
}, [data, searchTerm, selectedType, version])
3829

3930
const handleOpenDetails = (addon: AddonsData) => {
4031
setIsSelectAddon(addon)
41-
onOpen(true)
32+
onOpen()
4233
}
4334

4435
return {
@@ -51,7 +42,6 @@ const useFilterAddons = (data: AddonsDataState | null, onOpen: (isOpen: boolean)
5142
addonTypes,
5243
filteredData,
5344
combinedData,
54-
handleDownload,
5545
handleOpenDetails,
5646
isSelectAddon
5747
}

0 commit comments

Comments
 (0)