Skip to content

Commit

Permalink
Add miscellaneous stats section with virtual list support (#31)
Browse files Browse the repository at this point in the history
* feat: add svelte-tiny-virtual-list dependency

* feat: add miscellaneous stats section and related components

* feat: enhance AdditionStat component with rarity color support

* feat: update Items component title style to be font-semibold

* feat: add styles for virtual list wrapper and inner components
  • Loading branch information
DarthGigi authored Nov 25, 2024
1 parent 36fc9d0 commit e936af2
Show file tree
Hide file tree
Showing 22 changed files with 518 additions and 12 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"svelte": "4.2.18",
"svelte-check": "^3.8.2",
"svelte-interactions": "^0.2.0",
"svelte-tiny-virtual-list": "^2.1.2",
"tailwind-merge": "^2.3.0",
"tailwindcss": "^3.4.4",
"tslib": "^2.6.3",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,11 @@
filter: url(#enchanted-glint) drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.4));
}
}

.virtual-list-wrapper {
@apply overflow-y-auto overflow-x-hidden;
}

.virtual-list-inner {
@apply overflow-hidden;
}
35 changes: 24 additions & 11 deletions src/lib/components/AdditionStat.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { RARITY_COLORS } from "$constants/items";
import { cn, flyAndScale } from "$lib/utils";
import { Tooltip } from "bits-ui";
Expand All @@ -7,24 +8,36 @@
export let subData: string | undefined = undefined;
export let asterisk: boolean = false;
export let maxed: boolean = false;
export let dataMaxed: boolean = false;
export let textRarityColor: string | undefined = undefined;
export let dataRarityColor: string | undefined = undefined;
export let subDataRarityColor: string | undefined = undefined;
let className: string | null | undefined = undefined;
export { className as class };
</script>

<Tooltip.Root group="additional-stats" openDelay={0} closeDelay={0}>
<Tooltip.Trigger class={cn(`my-0 flex items-center gap-1 text-sm font-bold text-text/60 data-[is-tooltip=false]:cursor-default`, { "text-maxed": maxed }, className)} data-is-tooltip={asterisk}>
<div class="capitalize">{text}:</div>
<span class={cn("-mr-0.5", maxed ? "text-gold" : "text-text")}
>{data}
{#if subData}
<span class="text-text/80"> {subData}</span>
{/if}
</span>
<Tooltip.Trigger asChild={!asterisk} class={cn(`my-0 flex items-center gap-1 font-bold text-text/60 data-[is-tooltip=false]:cursor-default`, { "text-maxed": maxed }, className)} data-is-tooltip={asterisk}>
<div class={!asterisk ? cn("my-0 flex items-center gap-1 font-bold text-text/60 data-[is-tooltip=false]:cursor-default", { "text-maxed": maxed }, className) : "contents"}>
<div style={textRarityColor ? `color: var(--§${RARITY_COLORS[textRarityColor]})` : ""} class="capitalize">
{text}:
</div>

<span class={cn("-mr-0.5", maxed || dataMaxed ? "text-gold" : "text-text")}>
<span style={dataRarityColor ? `color: var(--§${RARITY_COLORS[dataRarityColor]})` : ""}>
{data}
</span>

{#if asterisk}
*
{/if}
{#if subData}
<span class="text-text/80" style={subDataRarityColor ? `color: var(--§${RARITY_COLORS[subDataRarityColor]})` : ""}> {subData}</span>
{/if}
</span>

{#if asterisk}
*
{/if}
</div>
</Tooltip.Trigger>
{#if asterisk}
<Tooltip.Content class="z-50 rounded-lg bg-background-grey p-4" transition={flyAndScale} transitionConfig={{ y: 8, duration: 150 }} sideOffset={6} side="top" align="center">
Expand Down
2 changes: 1 addition & 1 deletion src/lib/layouts/stats/Items.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<div class="space-y-4">
{#if title}
<h3 class="text-2xl capitalize">{title}</h3>
<h3 class="text-2xl font-semibold capitalize">{title}</h3>
{/if}
{#if subtitle}
<h4 class="text-xl capitalize text-text">{subtitle}</h4>
Expand Down
2 changes: 2 additions & 0 deletions src/lib/layouts/stats/Main.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import Dungeons from "$lib/sections/stats/Dungeons.svelte";
import Inventory from "$lib/sections/stats/Inventory.svelte";
import Minions from "$lib/sections/stats/Minions.svelte";
import MiscSection from "$lib/sections/stats/MiscSection.svelte";
import Pets from "$lib/sections/stats/Pets.svelte";
import Rift from "$lib/sections/stats/Rift.svelte";
import SkillsSection from "$lib/sections/stats/SkillsSection.svelte";
Expand Down Expand Up @@ -42,6 +43,7 @@
<Collections />
<CrimsonIsle />
<Rift />
<MiscSection />
</main>

<svg xmlns="http://www.w3.org/2000/svg" height="0" width="0" style="position: fixed;">
Expand Down
43 changes: 43 additions & 0 deletions src/lib/sections/stats/MiscSection.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts">
import type { Stats as StatsType } from "$types/stats";
import { getContext, setContext } from "svelte";
import Auctions from "./misc/auctions.svelte";
import Claimed from "./misc/claimed.svelte";
import Damage from "./misc/damage.svelte";
import Dragons from "./misc/dragons.svelte";
import Endstone from "./misc/endstone.svelte";
import Essence from "./misc/essence.svelte";
import Gifts from "./misc/gifts.svelte";
import Jerry from "./misc/jerry.svelte";
import Kills from "./misc/kills.svelte";
import Mythological from "./misc/mythological.svelte";
import Pet from "./misc/pet.svelte";
import Potions from "./misc/potions.svelte";
import Races from "./misc/races.svelte";
import Uncategorized from "./misc/uncategorized.svelte";
import Upgrades from "./misc/upgrades.svelte";
const profile = getContext<StatsType>("profile");
setContext("misc", profile.misc);
console.log(profile.misc);
</script>

<h3 class="text-2xl capitalize">Miscellaneous</h3>

<Essence />
<!-- TODO: Essence Shop -->
<Kills />
<Races />
<Gifts />
<Jerry />
<Dragons />
<Endstone />
<Damage />
<Pet />
<Mythological />
<Potions />
<Upgrades />
<Auctions />
<Claimed />
<Uncategorized />
39 changes: 39 additions & 0 deletions src/lib/sections/stats/misc/auctions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Auctions Sold">
<div slot="text">
<AdditionStat text="Fees" data={format(misc.auctions.fees)} />
<AdditionStat text="Coins Earned" data={format(misc.auctions.gold_earned)} />
<AdditionStat text="Items Sold" data={format(misc.auctions.total_sold.total)} asterisk={true}>
{#each Object.entries(misc.auctions.total_sold) as [rarity, amount]}
{#if rarity !== "total"}
<AdditionStat text={rarity} data={amount} textRarityColor={rarity.toLowerCase()} />
{/if}
{/each}
</AdditionStat>
</div>
</Items>

<Items title="Auctions Bought">
<div slot="text">
<AdditionStat text="Bids" data={format(misc.auctions.bids)} />
<AdditionStat text="Highest Bid" data={format(misc.auctions.highest_bid)} />
<AdditionStat text="Won" data={format(misc.auctions.won)} />
<AdditionStat text="Coins Spent" data={format(misc.auctions.gold_spent)} />
<AdditionStat text="Items Bought" data={format(misc.auctions.total_bought.total)} asterisk={true}>
{#each Object.entries(misc.auctions.total_bought) as [rarity, amount]}
{#if rarity !== "total"}
<AdditionStat text={rarity} data={amount} textRarityColor={rarity.toLowerCase()} />
{/if}
{/each}
</AdditionStat>
</div>
</Items>
24 changes: 24 additions & 0 deletions src/lib/sections/stats/misc/claimed.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { formatDate, formatDistanceToNowStrict } from "date-fns";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Claimed Items">
<div slot="text">
{#each Object.entries(misc.claimed_items) as [item, time]}
<AdditionStat
text={item.replaceAll("_", " ")}
data={formatDistanceToNowStrict(time, {
addSuffix: true
})}
asterisk={true}>
{formatDate(time, "'Claimed on' dd MMMM yyyy 'at' HH:mm")}
</AdditionStat>
{/each}
</div>
</Items>
17 changes: 17 additions & 0 deletions src/lib/sections/stats/misc/damage.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Damage">
<div slot="text">
{#each Object.entries(misc.damage) as [text, data]}
<AdditionStat text={text.replaceAll("_", " ")} data={format(data.toFixed(3))} />
{/each}
</div>
</Items>
36 changes: 36 additions & 0 deletions src/lib/sections/stats/misc/dragons.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Dragons">
<div slot="text">
<AdditionStat text="Most Damage" data={format(misc.dragons.most_damage.best.toFixed(0))} asterisk={true}>
{#each Object.entries(misc.dragons.most_damage) as [text, data]}
{#if text !== "best"}
<AdditionStat {text} data={format(data.toFixed(0))} />
{/if}
{/each}
</AdditionStat>
<AdditionStat text="Fastest Kill" data={misc.dragons.fastest_kill.best} asterisk={true}>
{#each Object.entries(misc.dragons.fastest_kill) as [text, data]}
{#if text !== "best"}
<AdditionStat {text} {data} />
{/if}
{/each}
</AdditionStat>
<!-- TODO: Last Hits -->
<AdditionStat text="Deats" data={format(misc.dragons.deaths.total)} asterisk={true}>
{#each Object.entries(misc.dragons.deaths) as [text, data]}
{#if text !== "total"}
<AdditionStat {text} data={format(data)} />
{/if}
{/each}
</AdditionStat>
</div>
</Items>
17 changes: 17 additions & 0 deletions src/lib/sections/stats/misc/endstone.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Endstone Protector">
<div slot="text">
{#each Object.entries(misc.endstone_protector) as [text, data]}
<AdditionStat text={text.replaceAll("_", " ")} data={format(data)} />
{/each}
</div>
</Items>
29 changes: 29 additions & 0 deletions src/lib/sections/stats/misc/essence.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import Chip from "$lib/components/Chip.svelte";
import { cn } from "$lib/utils";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<div class="space-y-4">
<h3 class="text-xl font-semibold">Essence</h3>
<div class="flex flex-wrap gap-4">
{#each misc.essence as essence}
{@const hasUnlocked = essence.amount}
<Chip image={{ src: essence.texture }} class={cn("h-fit w-fit", { "opacity-50": !hasUnlocked })}>
<div class={cn("flex flex-col")}>
<div class="font-bold">
<span class="opacity-60">{essence.name}</span>
<div class="text-sm">
<span class="opacity-60">Amount:</span>
<span class="text-text">{format(essence.amount)}</span>
</div>
</div>
</div>
</Chip>
{/each}
</div>
</div>
17 changes: 17 additions & 0 deletions src/lib/sections/stats/misc/gifts.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Gifts">
<div slot="text">
{#each Object.entries(misc.gifts) as [text, data]}
<AdditionStat text={text.replaceAll("_", " ")} data={format(data)} />
{/each}
</div>
</Items>
17 changes: 17 additions & 0 deletions src/lib/sections/stats/misc/jerry.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import AdditionStat from "$lib/components/AdditionStat.svelte";
import Items from "$lib/layouts/stats/Items.svelte";
import type { Stats as StatsType } from "$types/stats";
import { format } from "numerable";
import { getContext } from "svelte";
const misc = getContext<StatsType["misc"]>("misc");
</script>

<Items title="Season of Jerry">
<div slot="text">
{#each Object.entries(misc.season_of_jerry) as [text, data]}
<AdditionStat text={text.replaceAll("_", " ")} data={format(data)} />
{/each}
</div>
</Items>
Loading

0 comments on commit e936af2

Please sign in to comment.