Skip to content

Commit

Permalink
feat: add scoreboard table formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
muffn committed Jan 5, 2025
1 parent f831c09 commit fbf91f5
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 152 deletions.
85 changes: 85 additions & 0 deletions src/components/mdx/Scoreboard.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
---

<table class='w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400'>
<slot />
</table>

<script>
const addClasses = (element: HTMLElement, classes: string[]) => {
classes.forEach((className) => {
element.classList.add(className)
})
}

const styleTableRows = (rows: NodeListOf<HTMLTableRowElement>) => {
rows.forEach((row, index) => {
addClasses(row, ['p-0', 'even:bg-gray-100', 'dark:bg-gray-800'])
if (index === 0) {
styleHeaderRow(row)
} else {
styleDataRow(row)
}
})
}

const styleHeaderRow = (row: HTMLTableRowElement) => {
addClasses(row, [
'text-xs',
'text-gray-700',
'uppercase',
'bg-gray-100',
'dark:bg-gray-500',
'dark:text-gray-400'
])
const headers = row.querySelectorAll('th')
headers.forEach((header) => {
addClasses(header, ['p-4']) // Add padding to table headers
})
styleTableCells(headers, ['text-center'], [1])
}

const styleDataRow = (row: HTMLTableRowElement) => {
addClasses(row, ['bg-white', 'border-b', 'dark:border-gray-700'])
const cells = row.querySelectorAll('td')
styleTableCells(cells, ['text-center'], [1])
}

const styleTableCells = (
cells: NodeListOf<HTMLElement>,
classesToAdd: string[],
excludeIndices: number[] = []
) => {
if (cells.length >= 7) {
for (let i = 0; i < cells.length; i++) {
if (!excludeIndices.includes(i)) {
addClasses(cells[i], classesToAdd)
}
}
colorCellValue(cells[6])
}
}

const colorCellValue = (cell: HTMLElement) => {
const value = cell.innerText.trim()
if (value.startsWith('+')) {
addClasses(cell, ['text-green-500'])
} else if (value.startsWith('-')) {
addClasses(cell, ['text-red-500'])
}
}

const copyBlock = () => {
const tableBlock = document.querySelectorAll('table')
tableBlock.forEach((table) => {
const rows = table.querySelectorAll('tr')
if (rows.length > 0 && rows[0].children.length === 8) {
styleTableRows(rows)
}
})
}

copyBlock() // initial load
document.addEventListener('astro:after-swap', copyBlock) // re-run after each page change
</script>
8 changes: 1 addition & 7 deletions src/content/page/Community.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,4 @@ Blabla!

> *Hier könnte dein Zitat stehen!*\
> \
> Test!
| Tabellen | Verrückt? |
| ------------- | ------------ |
| Kurze Tabelle | Ja |
| Lange Tabelle | Ein bisschen |
| Keine Tabelle | Nein |
> Test!
7 changes: 7 additions & 0 deletions src/content/page/Liga.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ title: Liga
---

Hier wird bald mehr zu der Liga stehen!

| # | Spieler | Spiele | S | U | N | D | Punkte |
| - | ----------------- | ------ | -- | - | - | --- | ------ |
| 1 | Max Mustermann | 15 | 11 | 3 | 1 | +34 | 32 |
| 2 | Maxine Musterfrau | 14 | 10 | 1 | 3 | +25 | 23 |
| 3 | John Doe | 14 | 7 | 5 | 2 | -10 | 14 |
| 4 | Johnine Doine | 0 | 0 | 0 | 0 | 0 | 0 |
3 changes: 2 additions & 1 deletion src/pages/community.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getPageByTitle } from '../utils/post'
import Code from '../components/mdx/Code.astro'
import ImageGallery from '../components/ImageGallery.astro'
import ImageEmbed from '@/components/mdx/ImageEmbed'
import Scoreboard from '@/components/mdx/Scoreboard'
const title = 'Community'
const page = await getPageByTitle(title)
Expand All @@ -21,7 +22,7 @@ const { Content } = await page.render()
<div>
<article class='max-w-full w-full'>
<div class='prose prose-lg md:prose-xl dark:prose-invert mb-12 min-w-full'>
<Content components={{ pre: Code, ImageEmbed }} />
<Content components={{ pre: Code, table: Scoreboard, ImageEmbed }} />
</div>
</article>
<!-- image gallery -->
Expand Down
3 changes: 2 additions & 1 deletion src/pages/hobby-starter.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import BaseLayout from '@/layouts/BaseLayout'
import { getPageByTitle } from '../utils/post'
import Code from '../components/mdx/Code.astro'
import ImageEmbed from '@/components/mdx/ImageEmbed'
import Scoreboard from '../components/mdx/Scoreboard.astro'
const title = 'Hobby Starter'
const page = await getPageByTitle(title)
Expand All @@ -20,7 +21,7 @@ const { Content } = await page.render()
<div>
<article class='max-w-full w-full'>
<div class='prose prose-lg md:prose-xl dark:prose-invert mb-12 min-w-full'>
<Content components={{ pre: Code, ImageEmbed }} />
<Content components={{ pre: Code, table: Scoreboard, ImageEmbed }} />
</div>
</article>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/pages/kontakt.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getPageByTitle } from '../utils/post'
import Code from '../components/mdx/Code.astro'
import ImageEmbed from '@/components/mdx/ImageEmbed'
import Team from '../components/Team.astro'
import Scoreboard from '../components/mdx/Scoreboard.astro'
const title = 'Kontakt'
const page = await getPageByTitle(title)
Expand Down Expand Up @@ -46,7 +47,7 @@ const dummyTeam = [
<div>
<article class='max-w-full w-full'>
<div class='prose prose-lg md:prose-xl dark:prose-invert mb-12 min-w-full'>
<Content components={{ pre: Code, ImageEmbed }} />
<Content components={{ pre: Code, table: Scoreboard, ImageEmbed }} />
</div>
</article>
</div>
Expand Down
151 changes: 9 additions & 142 deletions src/pages/liga.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import BaseLayout from '@/layouts/BaseLayout'
import { getPageByTitle } from '../utils/post'
import Code from '../components/mdx/Code.astro'
import ImageEmbed from '@/components/mdx/ImageEmbed'
import ImageGallery from '../components/ImageGallery.astro'
import Scoreboard from '@/components/mdx/Scoreboard'
const title = 'Liga'
const page = await getPageByTitle(title)
Expand All @@ -13,156 +15,21 @@ if (!page) {
}
const { Content } = await page.render()
type Player = {
rank: number
name: string
games: number
wins: number
draws: number
losses: number
difference: number
points: number
}
type Props = {
players: Player[]
}
const players: Player[] = [
{
rank: 1,
name: 'Max Mustermann',
games: 15,
wins: 11,
draws: 3,
losses: 1,
difference: 34,
points: 32
},
{
rank: 2,
name: 'John Doe',
games: 15,
wins: 7,
draws: 4,
losses: 4,
difference: 8,
points: 25
},
{
rank: 3,
name: 'Joanna Doe',
games: 15,
wins: 3,
draws: 1,
losses: 11,
difference: -15,
points: 10
},
{
rank: 4,
name: 'Alice Smith',
games: 15,
wins: 10,
draws: 2,
losses: 3,
difference: 20,
points: 32
},
{
rank: 5,
name: 'Bob Brown',
games: 15,
wins: 8,
draws: 5,
losses: 2,
difference: 10,
points: 29
},
{
rank: 6,
name: 'Charlie Davis',
games: 15,
wins: 6,
draws: 6,
losses: 3,
difference: 5,
points: 24
}
]
---

<BaseLayout title={page.data.title}>
<TitlePage title={page.data.title} />
<div>
<article class='max-w-full w-full'>
<div class='prose prose-lg md:prose-xl dark:prose-invert mb-12 min-w-full'>
<Content components={{ pre: Code, ImageEmbed }} />
<Content components={{ pre: Code, table: Scoreboard, ImageEmbed }} />
</div>
</article>
</div>

<div class='relative overflow-x-auto rounded-xl border-8 border-gray-100 dark:border-gray-700'>
<table class='w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400'>
<thead
class='text-xs text-gray-700 uppercase bg-gray-100 dark:bg-gray-700 dark:text-gray-400'
>
<tr>
<th scope='col' class='pl-2 pb-2 text-center'>#</th>
<th scope='col' class='pl-2 pb-2'>Spieler</th>
<th scope='col' class='px-0 pb-2 text-center'>
<span class='hidden sm:inline'>Spiele</span>
<span class='sm:hidden'>Sp</span>
</th>
<th scope='col' class='px-0 pb-2 text-center'>S</th>
<th scope='col' class='px-0 pb-2 text-center'>U</th>
<th scope='col' class='px-0 pb-2 text-center'>N</th>
<th scope='col' class='px-0 pb-2 text-center w-1'>D</th>
<th scope='col' class='px-0 pb-2 text-center w-9 sm:w-20'>
<span class='hidden sm:inline'>Punkte</span>
<span class='sm:hidden'>Pt</span>
</th>
</tr>
</thead>
<tbody>
{
players.map((player) => (
<tr
class={`bg-white border-b dark:bg-gray-800 dark:border-gray-700 ${player.rank % 2 === 0 ? 'even:bg-gray-100' : ''}`}
>
<th
scope='row'
class='pl-2 py-2 font-medium text-gray-900 whitespace-nowrap dark:text-white text-center'
>
{player.rank}
</th>
<td class='pl-2 py-2'>{player.name}</td>
<td class='px-0 py-2 text-center'>{player.games}</td>
<td class='px-0 py-2 text-center'>{player.wins}</td>
<td class='px-0 py-2 text-center'>{player.draws}</td>
<td class='px-0 py-2 text-center'>{player.losses}</td>
<td class='px-0 py-2 text-center' data-value={player.difference}>
{player.difference}
</td>
<td class='px-0 py-2 text-center'>{player.points}</td>
</tr>
))
}
</tbody>
</table>
<!-- image gallery -->
{
page.data.galleryImages && page.data.galleryImages.length > 0 && (
<ImageGallery images={page.data.galleryImages} />
)
}
</div>
</BaseLayout>
<script>
document.addEventListener('DOMContentLoaded', () => {
const cells = document.querySelectorAll('td[data-value]')
cells.forEach((cell) => {
const value = parseInt(cell.getAttribute('data-value'), 10)
if (value > 0) {
cell.classList.add('text-green-700')
} else if (value < 0) {
cell.classList.add('text-red-500')
}
})
})
</script>
1 change: 1 addition & 0 deletions src/pages/post/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Disqus from '@/components/Disqus'
import { disqusConfig } from '@/data/disqus.config'
import ImageGallery from '../../components/ImageGallery.astro'
import ImageEmbed from '@/components/mdx/ImageEmbed'
import Scoreboard from '@/components/mdx/Scoreboard'
const posts = await getCollection('blog')
export async function getStaticPaths() {
Expand Down

0 comments on commit fbf91f5

Please sign in to comment.