Updated spells modal
This commit is contained in:
@@ -177,54 +177,13 @@ pub struct Range {
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Area {
|
pub struct Area {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub area_type: AreaType,
|
pub area_type: String,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub value: Option<i32>,
|
pub value: Option<i32>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub unit: Option<String>
|
pub unit: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum AreaType {
|
|
||||||
#[serde(rename = "cone")]
|
|
||||||
Cone,
|
|
||||||
#[serde(rename = "cube")]
|
|
||||||
Cube,
|
|
||||||
#[serde(rename = "cylinder")]
|
|
||||||
Cylinder,
|
|
||||||
#[serde(rename = "line")]
|
|
||||||
Line,
|
|
||||||
#[serde(rename = "sphere")]
|
|
||||||
Sphere
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl AreaType {
|
|
||||||
// pub fn to_string(&self) -> String {
|
|
||||||
// match self {
|
|
||||||
// AreaType::Cone => "cone".to_string(),
|
|
||||||
// AreaType::Cube => "cube".to_string(),
|
|
||||||
// AreaType::Cylinder => "cylinder".to_string(),
|
|
||||||
// AreaType::Line => "line".to_string(),
|
|
||||||
// AreaType::Sphere => "sphere".to_string()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl FromStr for AreaType {
|
|
||||||
// type Err = ();
|
|
||||||
|
|
||||||
// fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
// match s {
|
|
||||||
// "cone" => Ok(AreaType::Cone),
|
|
||||||
// "cube" => Ok(AreaType::Cube),
|
|
||||||
// "cylinder" => Ok(AreaType::Cylinder),
|
|
||||||
// "line" => Ok(AreaType::Line),
|
|
||||||
// "sphere" => Ok(AreaType::Sphere),
|
|
||||||
// _ => Err(())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Duration {
|
pub struct Duration {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
|||||||
@@ -22,6 +22,16 @@ export default function Page() {
|
|||||||
const [activeSpell, setActiveSpell] = useState<Spell | undefined>(undefined);
|
const [activeSpell, setActiveSpell] = useState<Spell | undefined>(undefined);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [searchName, setSearchName] = useState('');
|
const [searchName, setSearchName] = useState('');
|
||||||
|
const [includeCantrips, setIncludeCantrips] = useState(true);
|
||||||
|
const [includeLevel1, setIncludeLevel1] = useState(true);
|
||||||
|
const [includeLevel2, setIncludeLevel2] = useState(true);
|
||||||
|
const [includeLevel3, setIncludeLevel3] = useState(true);
|
||||||
|
const [includeLevel4, setIncludeLevel4] = useState(true);
|
||||||
|
const [includeLevel5, setIncludeLevel5] = useState(true);
|
||||||
|
const [includeLevel6, setIncludeLevel6] = useState(true);
|
||||||
|
const [includeLevel7, setIncludeLevel7] = useState(true);
|
||||||
|
const [includeLevel8, setIncludeLevel8] = useState(true);
|
||||||
|
const [includeLevel9, setIncludeLevel9] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getSpells({ levels: [0] }).then((s) => setCantrips(s.data));
|
getSpells({ levels: [0] }).then((s) => setCantrips(s.data));
|
||||||
@@ -54,6 +64,15 @@ export default function Page() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<hr />
|
<hr />
|
||||||
|
<SpellSection
|
||||||
|
title='Level 1'
|
||||||
|
spells={level1.filter((s) => s.name.toLowerCase().includes(searchName.toLowerCase()))}
|
||||||
|
onClick={(spell) => {
|
||||||
|
setActiveSpell(spell);
|
||||||
|
setIsOpen(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
{activeSpell && <SpellModal spell={activeSpell} isOpen={isOpen} onClose={() => setIsOpen(false)} />}
|
{activeSpell && <SpellModal spell={activeSpell} isOpen={isOpen} onClose={() => setIsOpen(false)} />}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export default function SpellModal({ spell, isOpen, onClose }: SpellModalProps)
|
|||||||
<span style={{ overflowWrap: 'break-word' }}>
|
<span style={{ overflowWrap: 'break-word' }}>
|
||||||
{spell.classes.map((c) => (
|
{spell.classes.map((c) => (
|
||||||
<span style={{ paddingRight: '0.6em', display: 'inline-block' }} className='link'>
|
<span style={{ paddingRight: '0.6em', display: 'inline-block' }} className='link'>
|
||||||
{capitalize(c)}
|
{parseText(c, true)}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
@@ -86,65 +86,74 @@ export default function SpellModal({ spell, isOpen, onClose }: SpellModalProps)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SpellDescription({ spell }: { spell: Spell }) {
|
function parseText(text: string, capitalizeFirst?: boolean) {
|
||||||
function parseText(text: string) {
|
const regex = /{@(.*?) (.*?)}/g;
|
||||||
const regex = /{@(.*?) (.*?)}/g;
|
const matches = text.matchAll(regex);
|
||||||
const matches = text.matchAll(regex);
|
const result = [];
|
||||||
const result = [];
|
let lastIndex = 0;
|
||||||
let lastIndex = 0;
|
for (const match of matches) {
|
||||||
for (const match of matches) {
|
const [full, type, name] = match;
|
||||||
const [full, type, name] = match;
|
result.push(text.slice(lastIndex, match.index));
|
||||||
result.push(text.slice(lastIndex, match.index));
|
if (match.index !== undefined) {
|
||||||
if (match.index !== undefined) {
|
if (type == 'dice') {
|
||||||
result.push(
|
result.push(
|
||||||
<span onClick={() => handleLink(type, name)} className='link'>
|
<span onClick={() => handleLink(type, name)} className='link'>
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
lastIndex = match.index + full.length;
|
} else if (type == 'scaledice') {
|
||||||
|
// scaledice format is {@scaledice 1d6|1-9|1d6|}. Parse this out into dice, levels, and dice again.
|
||||||
|
const [dice, levels] = name.split('|');
|
||||||
|
result.push(
|
||||||
|
<span onClick={() => handleLink('dice', dice)} className='link'>
|
||||||
|
{dice}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else if (type == 'bold') {
|
||||||
|
result.push(<span style={{ fontWeight: 'bold' }}>{name}</span>);
|
||||||
|
} else if (type == 'subclass') {
|
||||||
|
const [className, subclassName] = name.split('|');
|
||||||
|
result.push(
|
||||||
|
<span>
|
||||||
|
{capitalize(className)} ({capitalize(subclassName)})
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
result.push(<span>{capitalizeFirst ? capitalize(name) : name}</span>);
|
||||||
}
|
}
|
||||||
|
lastIndex = match.index + full.length;
|
||||||
}
|
}
|
||||||
result.push(text.slice(lastIndex));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
result.push(text.slice(lastIndex));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function handleLink(type: string, name: string) {
|
function handleLink(type: string, name: string) {
|
||||||
if (type == 'spell') {
|
if (type == 'spell') {
|
||||||
console.log(`Link to spell: ${name}`);
|
console.log(`Link to spell: ${name}`);
|
||||||
} else if (type == 'dice' || type == 'damage') {
|
} else if (type == 'dice') {
|
||||||
const rolls = rollDice(name);
|
const rolls = rollDice(name);
|
||||||
notifications.show({
|
notifications.show({
|
||||||
title: `Rolling ${name}`,
|
title: `Rolling ${name}`,
|
||||||
message: `${rolls.join(' + ')} = ${rolls.reduce((a, b) => a + b, 0)}`,
|
message: `${rolls.join(' + ')} = ${rolls.reduce((a, b) => a + b, 0)}`,
|
||||||
color: 'blue',
|
color: 'blue',
|
||||||
autoClose: 5000,
|
autoClose: 5000,
|
||||||
withCloseButton: false
|
withCloseButton: false
|
||||||
});
|
});
|
||||||
} else {
|
} else if (type == 'scaledice') {
|
||||||
console.error(`Unknown link type: ${type}`);
|
console.log(`Link to scaledice: ${name}`);
|
||||||
}
|
} else {
|
||||||
|
console.error(`Unknown link type: ${type}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function SpellDescription({ spell }: { spell: Spell }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{spell.description && (
|
{spell.description && (
|
||||||
<>
|
<>
|
||||||
{spell.description.entries.map((e) => (
|
{spell.description.entries.map((e) => (
|
||||||
// typeof e === 'string' ? (
|
|
||||||
// <p>{parseText(e)}</p>
|
|
||||||
// ) : (
|
|
||||||
// <>
|
|
||||||
// {e.list ? (
|
|
||||||
// <ul>
|
|
||||||
// {e.list.map((text) => (
|
|
||||||
// <li>{parseText(text)}</li>
|
|
||||||
// ))}
|
|
||||||
// </ul>
|
|
||||||
// ) : (
|
|
||||||
// <></>
|
|
||||||
// )}
|
|
||||||
// </>
|
|
||||||
// )
|
|
||||||
<>
|
<>
|
||||||
{e.text && <p>{parseText(e.text)}</p>}
|
{e.text && <p>{parseText(e.text)}</p>}
|
||||||
{e.list && (
|
{e.list && (
|
||||||
|
|||||||
Reference in New Issue
Block a user