Skip to content

Commit

Permalink
feat: add tooltips in assembly member chart (#127)
Browse files Browse the repository at this point in the history
* feat: add tooltips in assembly member chart

* fix: remove unused optional chaining
  • Loading branch information
greatng authored Oct 20, 2024
1 parent 6e73800 commit 3cf8aae
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 9 deletions.
17 changes: 17 additions & 0 deletions src/components/Assemblies/AssemblyTooltip.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import type { TooltipProp } from './shared';
export let tooltipProp: TooltipProp | null = null;
</script>

{#if tooltipProp}
<div
style:left="{tooltipProp.x}px"
style:top="{tooltipProp.y}px"
class="label-01 absolute z-10 flex min-w-max flex-col
rounded-sm bg-[#393939] p-3 text-center text-white"
>
<div class="font-semibold">{tooltipProp.title}</div>
<div>{tooltipProp.additional}</div>
</div>
{/if}
33 changes: 30 additions & 3 deletions src/components/Assemblies/CabinetRole.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,48 @@
<script lang="ts">
import type { CabinetSeat } from './shared';
import type { AssemblyMember } from '$lib/datasheets/assembly-member';
import AssemblyTooltip from './AssemblyTooltip.svelte';
import type { CabinetSeat, TooltipProp } from './shared';
export let cabinets: CabinetSeat[];
export let role: CabinetSeat['role'];
let tooltipProp: TooltipProp | null = null;
const showTooltip = (event: MouseEvent, member: AssemblyMember) => {
const name = `${member.firstname} ${member.lastname}`;
tooltipProp = {
title: name,
additional: member.assemblyRole.role,
x: event.layerX,
y: event.layerY + 20
};
};
const hideTooltip = () => {
tooltipProp = null;
};
</script>

<div class="role">
<p class="heading-compact-01">{role}</p>
<div class="group-dot">
{#each cabinets.find((c) => role === c.role)?.parties || [] as party}
{#each Array.from({ length: party.count || 0 }, (_, i) => i) as _}
<span class="dot" style="background-color: {party.color || '#8D8D8D'};"></span>
{#each party?.members ?? [] as member}
<div
role="tooltip"
class="dot"
style="background-color: {party.color || '#8D8D8D'};"
on:mouseenter={(e) => showTooltip(e, member)}
on:mouseleave={hideTooltip}
></div>
{/each}
{/each}
</div>
</div>

<AssemblyTooltip {tooltipProp}></AssemblyTooltip>

<style lang="scss">
.group-dot {
display: flex;
Expand Down
29 changes: 25 additions & 4 deletions src/components/Assemblies/SeatChart.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<script lang="ts">
import { onMount } from 'svelte';
import * as d3 from 'd3';
import type { PartySeat } from './shared';
import type { PartySeat, TooltipProp } from './shared';
import AssemblyTooltip from './AssemblyTooltip.svelte';
interface Point {
x: number;
y: number;
color: string;
title?: string;
additional?: string;
}
interface LineCalculator {
Expand All @@ -21,6 +23,7 @@
let outterRadius = 0;
let circleDiameter = outterRadius / 2 / lineAmounts.length;
let gap = 0;
let tooltipProp: TooltipProp | null = null;
const getIndexOfLine = (lineCals: LineCalculator[]) => {
const filledPercents = lineCals.map((lineCal) => lineCal.count / lineCal.total);
Expand All @@ -43,10 +46,13 @@
let index = getIndexOfLine(lineCals);
let line = lineCals[index];
let radius = outterRadius - index * circleDiameter - index * gap;
const name = `${party?.members?.[i].firstname} ${party?.members?.[i].lastname}`;
points.push({
x: radius * Math.cos((line.count / (line.total - 1)) * Math.PI + Math.PI),
y: radius * Math.sin((line.count / (line.total - 1)) * Math.PI + Math.PI),
color: party.color
color: party.color,
additional: party.name,
title: name
});
lineCals[index].count++;
}
Expand Down Expand Up @@ -87,7 +93,11 @@
.attr('cy', value.y + outterRadius + circleDiameter)
.attr('r', circleDiameter / 2)
.attr('fill', value.color)
.attr('class', 'seat');
.attr('class', 'seat')
.on('mouseover', (e) => setTooltipProperty(value, e))
.on('mouseout', () => {
tooltipProp = null;
});
});
};
Expand All @@ -100,6 +110,15 @@
);
};
const setTooltipProperty = (value: Point, event: MouseEvent): void => {
tooltipProp = {
title: value.title ?? '',
additional: value.additional ?? '',
x: event.pageX,
y: event.pageY + 20
};
};
onMount(() => {
redraw();
Expand All @@ -126,3 +145,5 @@
class="transition-[height] duration-500 ease-in-out"
/>
</div>

<AssemblyTooltip {tooltipProp}></AssemblyTooltip>
10 changes: 8 additions & 2 deletions src/components/Assemblies/SummaryTotal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
if (foundParty) {
foundParty.count += party.count;
} else {
acc.push({ name: party.name, count: party.count, color: party.color });
acc.push({
name: party.name,
count: party.count,
color: party.color,
members: party.members
});
}
return acc;
}, []);
Expand Down Expand Up @@ -60,7 +65,8 @@
return {
name: group.name,
count: group.total,
color: getSenateColorByTitle(group.name)
color: getSenateColorByTitle(group.name),
members: group.senateMembers
};
});
};
Expand Down
9 changes: 9 additions & 0 deletions src/components/Assemblies/shared.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { AssemblyMember } from '$lib/datasheets/assembly-member';
import type { MemberGroup } from '../../routes/assemblies/[id]/+page.server';

export interface PartySelected {
Expand Down Expand Up @@ -47,6 +48,7 @@ export interface PartySeat {
name: string;
color: string;
count: number;
members?: AssemblyMember[];
}

export interface CabinetSeat {
Expand All @@ -66,3 +68,10 @@ export const getSenateColorByTitle = (title: string) => {
return '#A8A8A8';
}
};

export type TooltipProp = {
title: string;
additional: string;
x: number;
y: number;
};
2 changes: 2 additions & 0 deletions src/routes/assemblies/[id]/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface Summary {
export interface MemberGroup {
name: string;
total: number;
senateMembers?: AssemblyMember[];
parties?: (Pick<Party, 'name' | 'color'> & { count: number; members?: AssemblyMember[] })[];
}

Expand Down Expand Up @@ -93,6 +94,7 @@ export async function load({ params }) {
total: group.subgroups.reduce((sum, subGroup) => sum + subGroup.members.length, 0)
}
: {
senateMembers: group.members,
total: group.members.length
})
}));
Expand Down

0 comments on commit 3cf8aae

Please sign in to comment.