Skip to content

Commit

Permalink
feat(asset dialog): Added search to the asset card dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
scottbenton committed Dec 2, 2023
1 parent 332fbc2 commit 46e3134
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 32 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Added the ability to copy rolls to the clipboard
- Added the ability to reroll rolls
- Added the ability to burn momentum to update rolls
- Added a search box to the asset card dialog to make find assets quicker

### Changes

Expand Down
12 changes: 10 additions & 2 deletions src/components/features/assets/AssetCard/AssetCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
Tooltip,
Typography,
} from "@mui/material";
import { ReactNode, useState } from "react";
import { ForwardedRef, ReactNode, forwardRef, useState } from "react";
import { Track } from "components/features/Track";
import { StoredAsset } from "types/Asset.type";
import { Asset, AssetAlterPropertiesConditionMeter } from "dataforged";
Expand Down Expand Up @@ -49,7 +49,10 @@ export interface AssetCardProps {
handleDeleteClick?: () => void;
}

export function AssetCard(props: AssetCardProps) {
function AssetCardComponent(
props: AssetCardProps,
ref: ForwardedRef<HTMLDivElement>
) {
const {
assetId,
storedAsset,
Expand Down Expand Up @@ -120,6 +123,7 @@ export function AssetCard(props: AssetCardProps) {
<>
<Card
variant={"outlined"}
ref={ref}
sx={{ height: "100%", display: "flex", flexDirection: "column", ...sx }}
>
<Box
Expand Down Expand Up @@ -359,3 +363,7 @@ export function AssetCard(props: AssetCardProps) {
</>
);
}

export const AssetCard = forwardRef<HTMLDivElement, AssetCardProps>(
AssetCardComponent
);
75 changes: 46 additions & 29 deletions src/components/features/assets/AssetCardDialog/AssetCardDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ import {
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Grid,
Tab,
Tabs,
} from "@mui/material";
import { useState } from "react";
import { assetGroups } from "data/assets";
import { useCallback, useState } from "react";
import { assetGroupMap, assetGroups } from "data/assets";
import { StoredAsset } from "types/Asset.type";
import { Asset } from "dataforged";
import { AssetCard } from "../AssetCard/AssetCard";
import { CreateCustomAsset } from "./CreateCustomAsset";
import { MarkdownRenderer } from "components/shared/MarkdownRenderer";
import { encodeDataswornId } from "functions/dataswornIdEncoder";
import { DialogTitleWithCloseButton } from "components/shared/DialogTitleWithCloseButton";
import { AssetCardSearch } from "./AssetCardSearch";
import { AssetCardDialogCard } from "./AssetCardDialogCard";

export interface AssetCardDialogProps {
open: boolean;
Expand All @@ -28,6 +29,11 @@ export interface AssetCardDialogProps {
showSharedAssetWarning?: boolean;
}

const groups: { name: string; id: string }[] = assetGroups.map((group) => ({
id: group.$id,
name: group.Title.Standard,
}));

export function AssetCardDialog(props: AssetCardDialogProps) {
const {
open,
Expand All @@ -37,7 +43,13 @@ export function AssetCardDialog(props: AssetCardDialogProps) {
showSharedAssetWarning,
} = props;

const [selectedTab, setSelectedTab] = useState(0);
const [selectedTabId, setSelectedTabId] = useState<string>(groups[0].id);
const [searchedAssetId, setSearchedAssetId] = useState<string>();
const handleSearch = useCallback((groupId: string, assetId: string) => {
setSelectedTabId(groupId);
setSearchedAssetId(assetId);
}, []);
const clearSearch = useCallback(() => setSearchedAssetId(undefined), []);

const onAssetSelect = (asset: Asset, isCustom?: boolean) => {
const inputs: { [key: string]: string } = {};
Expand Down Expand Up @@ -66,27 +78,39 @@ export function AssetCardDialog(props: AssetCardDialogProps) {
};

return (
<Dialog open={open} onClose={() => handleClose()} maxWidth={"md"} fullWidth>
<DialogTitle>Select an asset</DialogTitle>
<Dialog open={open} onClose={handleClose} maxWidth={"md"} fullWidth>
<DialogTitleWithCloseButton
onClose={handleClose}
actions={
<Box display={{ xs: "none", sm: "block" }}>
<AssetCardSearch handleSearch={handleSearch} />
</Box>
}
>
Select an asset
</DialogTitleWithCloseButton>
<DialogContent>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Box display={{ xs: "block", sm: "none" }}>
<AssetCardSearch handleSearch={handleSearch} />
</Box>
<Tabs
value={selectedTab}
onChange={(evt, value) => setSelectedTab(value)}
value={selectedTabId}
onChange={(evt, value) => setSelectedTabId(value)}
variant={"scrollable"}
scrollButtons={"auto"}
>
{Object.values(assetGroups).map((group, index) => (
<Tab label={group.Title.Standard} key={index} />
{groups.map((group, index) => (
<Tab label={group.name} value={group.id} key={index} />
))}
<Tab label={"custom"} />
<Tab label={"custom"} value={"custom"} />
</Tabs>
</Box>
<Box py={1}>
{selectedTab < assetGroups.length ? (
{selectedTabId !== "custom" ? (
<>
{showSharedAssetWarning &&
assetGroups[selectedTab].Usage.Shared && (
assetGroupMap[selectedTabId].Usage.Shared && (
<Alert severity={"warning"}>
<AlertTitle>Shared Assets</AlertTitle>
These assets are shared amongst characters playing together
Expand All @@ -96,25 +120,18 @@ export function AssetCardDialog(props: AssetCardDialogProps) {
</Alert>
)}
<MarkdownRenderer
markdown={assetGroups[selectedTab].Description}
markdown={assetGroupMap[selectedTabId].Description}
/>
<Grid container spacing={1} mt={2}>
{Object.values(assetGroups[selectedTab].Assets).map(
{Object.values(assetGroupMap[selectedTabId].Assets).map(
(asset, index) => (
<Grid item xs={12} sm={6} md={4} key={index}>
<AssetCard
assetId={asset.$id}
readOnly
showSharedIcon
actions={
<Button
color={"inherit"}
onClick={() => onAssetSelect(asset)}
disabled={loading}
>
Select
</Button>
}
<AssetCardDialogCard
asset={asset}
selectAsset={() => onAssetSelect(asset)}
loading={loading}
searched={asset.$id === searchedAssetId}
clearSearched={clearSearch}
/>
</Grid>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Asset } from "dataforged";
import { AssetCard } from "../AssetCard/AssetCard";
import { Button } from "@mui/material";
import { useEffect, useRef } from "react";

export interface AssetCardDialogCardProps {
asset: Asset;
selectAsset: () => void;
searched: boolean;
clearSearched: () => void;
loading?: boolean;
}

export function AssetCardDialogCard(props: AssetCardDialogCardProps) {
const { asset, selectAsset, searched, clearSearched, loading } = props;

const assetRef = useRef<HTMLDivElement | null>(null);

useEffect(() => {
if (searched) {
assetRef.current?.scrollIntoView({ behavior: "smooth" });
clearSearched();
}
}, [clearSearched, searched]);

return (
<AssetCard
ref={assetRef}
assetId={asset.$id}
readOnly
showSharedIcon
actions={
<Button color={"inherit"} onClick={selectAsset} disabled={loading}>
Select
</Button>
}
/>
);
}
37 changes: 37 additions & 0 deletions src/components/features/assets/AssetCardDialog/AssetCardSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Autocomplete, TextField } from "@mui/material";
import { assetGroups } from "data/assets";

export interface AssetCardSearchProps {
handleSearch: (groupId: string, assetId: string) => void;
}

const options = assetGroups
.flatMap((group) =>
Object.values(group.Assets).map((asset) => ({
groupId: group.$id,
groupName: group.Title.Standard,
assetId: asset.$id,
name: asset.Title.Standard,
}))
)
.sort((a, b) => a.groupName.localeCompare(b.groupName));

export function AssetCardSearch(props: AssetCardSearchProps) {
const { handleSearch } = props;

return (
<Autocomplete
options={options}
groupBy={(option) => option.groupName}
getOptionLabel={(option) => option.name}
onChange={(evt, val) => val && handleSearch(val.groupId, val.assetId)}
renderInput={(params) => (
<TextField
sx={{ mr: 2, minWidth: 200 }}
{...params}
placeholder="Search"
/>
)}
/>
);
}
4 changes: 3 additions & 1 deletion src/data/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
ironswornAssetCategories,
starforgedAssetCategories,
} from "./dataforged";
import type { Asset as DataforgedAsset } from "dataforged";
import type { AssetType, Asset as DataforgedAsset } from "dataforged";
import { GAME_SYSTEMS, GameSystemChooser } from "types/GameSystems.type";

const gameSystem = getSystem();
Expand All @@ -13,13 +13,15 @@ const assetCategories: GameSystemChooser<typeof ironswornAssetCategories> = {
};

// NEW ASSETS START HERE
export const assetGroupMap: { [key: string]: AssetType } = {};
export const assetMap: { [key: string]: DataforgedAsset } = {};
export const assetTypeLabels: { [key: string]: string } = {
"ironsworn/assets/role": "Role",
"starforged/assets/role": "Role",
};

Object.values(assetCategories[gameSystem]).forEach((category) => {
assetGroupMap[category.$id] = category;
assetTypeLabels[category.$id] = category.Title.Standard;
Object.values(category.Assets).forEach((asset) => {
assetMap[asset.$id] = asset;
Expand Down

0 comments on commit 46e3134

Please sign in to comment.