-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
367 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<script lang="ts"> | ||
import { clickoutside } from '$/utils/hooks/click-outside'; | ||
import { base } from '$app/paths'; | ||
import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from '@steeze-ui/heroicons'; | ||
import { Icon } from '@steeze-ui/svelte-icon'; | ||
import type { LayoutData } from './$types'; | ||
export let data: LayoutData; | ||
let practiceListOpen: boolean = false; | ||
</script> | ||
|
||
<div class="flex h-screen w-screen flex-col"> | ||
<header class="flex h-[60px] w-screen flex-row items-center"> | ||
<span class="ml-8 font-jazz text-2xl font-bold"> JazzyDalpeng / Jazz Guitar Practice</span> | ||
</header> | ||
<div class="flex basis-full flex-col items-center justify-center"> | ||
<slot /> | ||
</div> | ||
<nav class="relative h-[60px] w-screen"> | ||
<div class="flex h-full flex-row items-center justify-between"> | ||
{#if data.pages.previous} | ||
<a | ||
href={`${base}/practice/${data.category}/${data.pages.previous.slug}`} | ||
class="mr-8 flex h-full cursor-pointer select-none flex-row items-center gap-4 text-indigo-400 transition duration-200 hover:text-indigo-600 active:text-indigo-800" | ||
> | ||
<Icon class="h-[30px] w-auto" src={ChevronLeft} theme="solid" /> | ||
<span | ||
class="invisible whitespace-nowrap text-black hover:text-indigo-600 active:text-indigo-800 lg:visible" | ||
>{data.pages.previous.title}</span | ||
> | ||
</a> | ||
{:else} | ||
<div | ||
class="mr-8 flex h-full select-none flex-row items-center gap-4 text-gray-300 transition duration-200" | ||
> | ||
<Icon class="h-[30px] w-auto" src={ChevronLeft} theme="solid" /> | ||
</div> | ||
{/if} | ||
{#if data.pages.next} | ||
<a | ||
href={`${base}/practice/${data.category}/${data.pages.next.slug}`} | ||
class="ml-8 flex h-full cursor-pointer select-none flex-row items-center gap-4 text-indigo-400 transition duration-200 hover:text-indigo-600 active:text-indigo-800" | ||
> | ||
<span | ||
class="invisible whitespace-nowrap text-black hover:text-indigo-600 active:text-indigo-800 lg:visible" | ||
>{data.pages.next.title}</span | ||
> | ||
<Icon class="h-[30px] w-auto" src={ChevronRight} theme="solid" /> | ||
</a> | ||
{:else} | ||
<div | ||
class="ml-8 flex h-full select-none flex-row items-center gap-4 text-gray-300 transition duration-200" | ||
> | ||
<Icon class="h-[30px] w-auto" src={ChevronRight} theme="solid" /> | ||
</div> | ||
{/if} | ||
</div> | ||
<button | ||
class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" | ||
on:click={() => (practiceListOpen = !practiceListOpen)} | ||
> | ||
<div | ||
use:clickoutside | ||
on:clickoutside={() => (practiceListOpen = false)} | ||
class="absolute -top-[30px] left-[50%] h-[40px] w-auto -translate-x-[50%]" | ||
> | ||
<Icon | ||
class="opacity-25% hover:opacity-100% h-[20px] w-auto cursor-pointer transition-opacity" | ||
src={practiceListOpen ? ChevronDown : ChevronUp} | ||
theme="mini" | ||
/> | ||
{#if practiceListOpen} | ||
<div | ||
class="absolute bottom-full left-1/2 max-h-80 w-80 -translate-x-1/2 -translate-y-[1rem] rounded bg-gray-500 p-4" | ||
> | ||
{#each data.routes[data.category] as route} | ||
<div class="text-start"> | ||
<a href={`${base}/practice/${data.category}/${route.slug}`}> | ||
{route.title} | ||
</a> | ||
</div> | ||
{/each} | ||
</div> | ||
{/if} | ||
</div> | ||
<p class="whitespace-nowrap">{data.pages.current.title}</p> | ||
</button> | ||
</nav> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { base } from '$app/paths'; | ||
import { redirect } from '@sveltejs/kit'; | ||
import { routes, type PracticeRoute, type PracticeRouteCategory } from '../data'; | ||
import type { LayoutLoad } from './$types'; | ||
|
||
export const load: LayoutLoad = (data) => { | ||
const { category, slug } = data.params; | ||
|
||
if (category !== 'core' && category !== 'custom') { | ||
redirect(303, `${base}/practice`); | ||
} | ||
|
||
const currentCategoryRoutes = routes[category]; | ||
const currentPageIndex = currentCategoryRoutes.findIndex((route) => route.slug === slug); | ||
if (currentPageIndex === -1) { | ||
redirect(303, `${base}/practice/${category}/${routes[category][0].slug}`); | ||
} | ||
|
||
const pages: { | ||
previous?: PracticeRoute; | ||
current: PracticeRoute; | ||
next?: PracticeRoute; | ||
} = { | ||
previous: currentPageIndex - 1 >= 0 ? currentCategoryRoutes[currentPageIndex - 1] : undefined, | ||
current: currentCategoryRoutes[currentPageIndex], | ||
next: | ||
currentPageIndex < currentCategoryRoutes.length - 1 | ||
? currentCategoryRoutes[currentPageIndex + 1] | ||
: undefined | ||
}; | ||
|
||
return { routes, category: category as PracticeRouteCategory, pages }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
category |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
slug |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
hi | ||
<script> | ||
import { base } from '$app/paths'; | ||
</script> | ||
|
||
<a href={`${base}/practice`}>????</a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
import type { Practice } from '$/lib/practice/types'; | ||
import { TUNE } from '$/utils/music/pitch'; | ||
|
||
export interface PracticeRoute { | ||
title: string; | ||
slug: string; | ||
practice: Practice; | ||
} | ||
|
||
export type PracticeRouteCategory = 'core' | 'custom'; | ||
export interface PracticeRoutes extends Record<PracticeRouteCategory, PracticeRoute[]> {} | ||
|
||
export const routes: PracticeRoutes = { | ||
core: [ | ||
{ | ||
title: 'Major Scale', | ||
slug: 'major-scale', | ||
practice: { | ||
tempo: { | ||
bpm: 120, | ||
beatPerBar: 4, | ||
signatureUnit: 4 | ||
}, | ||
guitar: { | ||
tuning: TUNE.standard | ||
}, | ||
scores: [ | ||
{ | ||
positions: [ | ||
{ line: 6, fret: 8 }, | ||
{ line: 6, fret: 10 }, | ||
{ line: 5, fret: 7 }, | ||
{ line: 5, fret: 8 }, | ||
{ line: 5, fret: 10 }, | ||
{ line: 4, fret: 7 }, | ||
{ line: 4, fret: 9 }, | ||
{ line: 4, fret: 10 }, | ||
{ line: 3, fret: 7 }, | ||
{ line: 3, fret: 9 }, | ||
{ line: 3, fret: 10 }, | ||
{ line: 2, fret: 8 }, | ||
{ line: 2, fret: 10 }, | ||
{ line: 1, fret: 7 }, | ||
{ line: 1, fret: 8 }, | ||
{ line: 1, fret: 10 }, | ||
{ line: 6, fret: 7 } | ||
], | ||
notes: [ | ||
{ position: 0, time: { start: 0, duration: 0.0625 } }, | ||
{ position: 1, time: { start: 0.0625, duration: 0.0625 } }, | ||
{ position: 2, time: { start: 0.125, duration: 0.0625 } }, | ||
{ position: 3, time: { start: 0.1875, duration: 0.0625 } }, | ||
{ position: 4, time: { start: 0.25, duration: 0.0625 } }, | ||
{ position: 5, time: { start: 0.3125, duration: 0.0625 } }, | ||
{ position: 6, time: { start: 0.375, duration: 0.0625 } }, | ||
{ position: 7, time: { start: 0.4375, duration: 0.0625 } }, | ||
{ position: 8, time: { start: 0.5, duration: 0.0625 } }, | ||
{ position: 9, time: { start: 0.5625, duration: 0.0625 } }, | ||
{ position: 10, time: { start: 0.625, duration: 0.0625 } }, | ||
{ position: 11, time: { start: 0.6875, duration: 0.0625 } }, | ||
{ position: 12, time: { start: 0.75, duration: 0.0625 } }, | ||
{ position: 13, time: { start: 0.8125, duration: 0.0625 } }, | ||
{ position: 14, time: { start: 0.875, duration: 0.0625 } }, | ||
{ position: 15, time: { start: 0.9375, duration: 0.0625 } }, | ||
{ position: 14, time: { start: 1, duration: 0.0625 } }, | ||
{ position: 13, time: { start: 1.0625, duration: 0.0625 } }, | ||
{ position: 12, time: { start: 1.125, duration: 0.0625 } }, | ||
{ position: 11, time: { start: 1.1875, duration: 0.0625 } }, | ||
{ position: 10, time: { start: 1.25, duration: 0.0625 } }, | ||
{ position: 9, time: { start: 1.3125, duration: 0.0625 } }, | ||
{ position: 8, time: { start: 1.375, duration: 0.0625 } }, | ||
{ position: 7, time: { start: 1.4375, duration: 0.0625 } }, | ||
{ position: 6, time: { start: 1.5, duration: 0.0625 } }, | ||
{ position: 5, time: { start: 1.5625, duration: 0.0625 } }, | ||
{ position: 4, time: { start: 1.625, duration: 0.0625 } }, | ||
{ position: 3, time: { start: 1.6875, duration: 0.0625 } }, | ||
{ position: 2, time: { start: 1.75, duration: 0.0625 } }, | ||
{ position: 1, time: { start: 1.8125, duration: 0.0625 } }, | ||
{ position: 0, time: { start: 1.875, duration: 0.0625 } }, | ||
{ position: 16, time: { start: 1.9375, duration: 0.0625 } }, | ||
{ position: 0, time: { start: 2, duration: 0.0625 } } | ||
], | ||
boards: [ | ||
{ | ||
title: 'C line 1', | ||
fingers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], | ||
time: { start: 0 } | ||
}, | ||
{ | ||
title: 'C line 2', | ||
fingers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], | ||
time: { start: 15 / 16 } | ||
} | ||
], | ||
fretRange: { | ||
start: 5, | ||
end: 11, | ||
visibility: 'all' | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
{ | ||
title: 'Rhythm Test', | ||
slug: 'rhythm-test', | ||
practice: { | ||
tempo: { | ||
bpm: 120, | ||
beatPerBar: 4, | ||
signatureUnit: 4 | ||
}, | ||
guitar: { | ||
tuning: TUNE.standard | ||
}, | ||
scores: [ | ||
{ | ||
positions: [ | ||
{ line: 5, fret: 3 }, | ||
{ line: 6, fret: 3 }, | ||
{ line: 1, fret: 'open' }, | ||
{ line: 2, fret: 1 }, | ||
{ line: 3, fret: 'open' } | ||
], | ||
notes: [ | ||
{ position: 0, time: { start: 0, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 1 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 1 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 1 / 4, duration: 1 / 4 } }, | ||
{ position: 1, time: { start: 2 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 3 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 3 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 3 / 4, duration: 1 / 4 } }, | ||
{ position: 0, time: { start: 4 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 5 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 5 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 5 / 4, duration: 1 / 4 } }, | ||
{ position: 1, time: { start: 6 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 7 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 7 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 7 / 4, duration: 1 / 4 } }, | ||
{ position: 0, time: { start: 8 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 9 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 9 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 9 / 4, duration: 1 / 4 } }, | ||
{ position: 1, time: { start: 10 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 11 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 11 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 11 / 4, duration: 1 / 4 } }, | ||
{ position: 0, time: { start: 12 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 13 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 13 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 13 / 4, duration: 1 / 4 } }, | ||
{ position: 1, time: { start: 14 / 4, duration: 1 / 4 } }, | ||
{ position: 2, time: { start: 15 / 4, duration: 1 / 4 } }, | ||
{ position: 3, time: { start: 15 / 4, duration: 1 / 4 } }, | ||
{ position: 4, time: { start: 15 / 4, duration: 1 / 4 } } | ||
], | ||
boards: [ | ||
{ | ||
title: 'C line 1', | ||
fingers: [0, 2, 3, 4], | ||
time: { start: 0 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [1, 2, 3, 4], | ||
time: { start: 1 / 2 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [0, 2, 3, 4], | ||
time: { start: 2 / 2 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [1, 2, 3, 4], | ||
time: { start: 3 / 2 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [0, 2, 3, 4], | ||
time: { start: 4 / 2 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [1, 2, 3, 4], | ||
time: { start: 5 / 2 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [0, 2, 3, 4], | ||
time: { start: 6 / 2 } | ||
}, | ||
{ | ||
title: 'C line 1', | ||
fingers: [1, 2, 3, 4], | ||
time: { start: 7 / 2 } | ||
} | ||
], | ||
fretRange: { | ||
start: 0, | ||
end: 12, | ||
visibility: 'all' | ||
} | ||
} | ||
] | ||
} | ||
} | ||
], | ||
custom: [] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { Action, ActionReturn } from 'svelte/action'; | ||
|
||
export const clickoutside: Action< | ||
Element, | ||
unknown, | ||
{ 'on:clickoutside'?: (event: CustomEvent<MouseEvent>) => any } | ||
> = (node) => { | ||
const handleClick = (event: MouseEvent) => { | ||
const target = event.target as HTMLElement; | ||
if (!event.target) { | ||
return; | ||
} | ||
if (node && !node.contains(target) && !event.defaultPrevented) { | ||
node.dispatchEvent(new CustomEvent('clickoutside', { detail: CustomEvent<MouseEvent> })); | ||
} | ||
}; | ||
|
||
document.addEventListener('click', handleClick, true); | ||
|
||
return { | ||
destroy() { | ||
document.removeEventListener('click', handleClick, true); | ||
} | ||
}; | ||
}; |