Added ui
This commit is contained in:
91
ui/src/app/spells/page.tsx
Normal file
91
ui/src/app/spells/page.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
'use client';
|
||||
|
||||
import { getSpells } from '@/api/spells';
|
||||
import { Spell } from '@/api/spells.types';
|
||||
import SpellModal from '@/components/SpellModal';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import './spells.css';
|
||||
import { Box, TextInput } from '@mantine/core';
|
||||
import { AiOutlineVerticalAlignTop } from 'react-icons/ai';
|
||||
|
||||
export default function Page() {
|
||||
const [cantrips, setCantrips] = useState<Spell[]>([]);
|
||||
const [level1, setLevel1] = useState<Spell[]>([]);
|
||||
const [level2, setLevel2] = useState<Spell[]>([]);
|
||||
const [level3, setLevel3] = useState<Spell[]>([]);
|
||||
const [level4, setLevel4] = useState<Spell[]>([]);
|
||||
const [level5, setLevel5] = useState<Spell[]>([]);
|
||||
const [level6, setLevel6] = useState<Spell[]>([]);
|
||||
const [level7, setLevel7] = useState<Spell[]>([]);
|
||||
const [level8, setLevel8] = useState<Spell[]>([]);
|
||||
const [level9, setLevel9] = useState<Spell[]>([]);
|
||||
const [activeSpell, setActiveSpell] = useState<Spell | undefined>(undefined);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [searchName, setSearchName] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
getSpells({ levels: [0] }).then((s) => setCantrips(s.data));
|
||||
getSpells({ levels: [1] }).then((s) => setLevel1(s.data));
|
||||
getSpells({ levels: [2] }).then((s) => setLevel2(s.data));
|
||||
getSpells({ levels: [3] }).then((s) => setLevel3(s.data));
|
||||
getSpells({ levels: [4] }).then((s) => setLevel4(s.data));
|
||||
getSpells({ levels: [5] }).then((s) => setLevel5(s.data));
|
||||
getSpells({ levels: [6] }).then((s) => setLevel6(s.data));
|
||||
getSpells({ levels: [7] }).then((s) => setLevel7(s.data));
|
||||
getSpells({ levels: [8] }).then((s) => setLevel8(s.data));
|
||||
getSpells({ levels: [9] }).then((s) => setLevel9(s.data));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box style={{ width: '60%', margin: 'auto' }}>
|
||||
<h1>Spells</h1>
|
||||
<TextInput
|
||||
label='Search by name'
|
||||
placeholder='Acid Splash...'
|
||||
onChange={(e) => setSearchName(e.target.value)}
|
||||
style={{ width: '25%' }}
|
||||
/>
|
||||
<SpellSection
|
||||
title='Cantrips'
|
||||
spells={cantrips.filter((s) => s.name.toLowerCase().includes(searchName.toLowerCase()))}
|
||||
onClick={(spell) => {
|
||||
setActiveSpell(spell);
|
||||
setIsOpen(true);
|
||||
}}
|
||||
/>
|
||||
<hr />
|
||||
{activeSpell && <SpellModal spell={activeSpell} isOpen={isOpen} onClose={() => setIsOpen(false)} />}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function SpellSection({ title, spells, onClick }: { title: string; spells: Spell[]; onClick: (spell: Spell) => void }) {
|
||||
const isBrowser = () => typeof window !== 'undefined'; //The approach recommended by Next.js
|
||||
|
||||
function scrollToTop() {
|
||||
if (!isBrowser()) return;
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<h2>{title}</h2>
|
||||
<ul>
|
||||
{spells.map((spell) => (
|
||||
<li
|
||||
key={spell.id}
|
||||
className='link spell-item'
|
||||
style={{ width: 'fit-content' }}
|
||||
onClick={() => onClick(spell)}
|
||||
>
|
||||
{spell.name}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', color: 'gray' }} onClick={scrollToTop}>
|
||||
<span style={{ paddingRight: '0.2em' }}>Back to top</span>
|
||||
<AiOutlineVerticalAlignTop />
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user