work
This commit is contained in:
parent
d62cc6f6a4
commit
aa391a8dba
99
src/app.pcss
99
src/app.pcss
@ -4,69 +4,46 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: rgb(253, 249, 246);
|
--background: 0 0% 100%;
|
||||||
--foreground: 25 67% 4%;
|
--foreground: 20 14.3% 4.1%;
|
||||||
--muted: 25 30% 95%;
|
--card: 0 0% 100%;
|
||||||
--muted-foreground: 25 2% 29%;
|
--card-foreground: 20 14.3% 4.1%;
|
||||||
--popover: 25 70% 98%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 25 67% 4%;
|
--popover-foreground: 20 14.3% 4.1%;
|
||||||
--card: 25 70% 98%;
|
--primary: 24.6 95% 53.1%;
|
||||||
--card-foreground: 25 67% 4%;
|
--primary-foreground: 60 9.1% 97.8%;
|
||||||
--border: 220 13% 91%;
|
--secondary: 60 4.8% 95.9%;
|
||||||
--input: 220 13% 91%;
|
--secondary-foreground: 24 9.8% 10%;
|
||||||
--primary: 25 31% 75%;
|
--muted: 60 4.8% 95.9%;
|
||||||
--primary-foreground: 25 31% 15%;
|
--muted-foreground: 25 5.3% 44.7%;
|
||||||
--secondary: 25 18% 90%;
|
--accent: 60 4.8% 95.9%;
|
||||||
--secondary-foreground: 25 18% 30%;
|
--accent-foreground: 24 9.8% 10%;
|
||||||
--accent: 25 23% 83%;
|
--destructive: 0 72.22% 50.59%;
|
||||||
--accent-foreground: 25 23% 23%;
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
--destructive: 13 96% 20%;
|
--border: 20 5.9% 90%;
|
||||||
--destructive-foreground: 13 96% 80%;
|
--input: 20 5.9% 90%;
|
||||||
--ring: 25 31% 75%;
|
--ring: 24.6 95% 53.1%;
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
font-size: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: 25 41% 2%;
|
--background: 20 14.3% 4.1%;
|
||||||
--foreground: 25 21% 98%;
|
--foreground: 60 9.1% 97.8%;
|
||||||
--muted: 25 30% 5%;
|
--card: 20 14.3% 4.1%;
|
||||||
--muted-foreground: 25 2% 71%;
|
--card-foreground: 60 9.1% 97.8%;
|
||||||
--popover: 25 41% 2%;
|
--popover: 20 14.3% 4.1%;
|
||||||
--popover-foreground: 25 21% 98%;
|
--popover-foreground: 60 9.1% 97.8%;
|
||||||
--card: 25 41% 2%;
|
--primary: 20.5 90.2% 48.2%;
|
||||||
--card-foreground: 25 21% 98%;
|
--primary-foreground: 60 9.1% 97.8%;
|
||||||
--border: 215 27.9% 16.9%;
|
--secondary: 12 6.5% 15.1%;
|
||||||
--input: 215 27.9% 16.9%;
|
--secondary-foreground: 60 9.1% 97.8%;
|
||||||
--primary: 25 31% 75%;
|
--muted: 12 6.5% 15.1%;
|
||||||
--primary-foreground: 25 31% 15%;
|
--muted-foreground: 24 5.4% 63.9%;
|
||||||
--secondary: 25 5% 14%;
|
--accent: 12 6.5% 15.1%;
|
||||||
--secondary-foreground: 25 5% 74%;
|
--accent-foreground: 60 9.1% 97.8%;
|
||||||
--accent: 25 11% 20%;
|
--destructive: 0 72.2% 50.6%;
|
||||||
--accent-foreground: 25 11% 80%;
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
--destructive: 13 96% 49%;
|
--border: 12 6.5% 15.1%;
|
||||||
--destructive-foreground: 0 0% 100%;
|
--input: 12 6.5% 15.1%;
|
||||||
--ring: 25 31% 75%;
|
--ring: 20.5 90.2% 48.2%;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Epica';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
src: url('/fonts/epica.otf');
|
|
||||||
}
|
|
||||||
|
|
||||||
.font-epica {
|
|
||||||
font-family: Epica ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrollbars-hidden::-webkit-scrollbar {
|
|
||||||
background: transparent; /* Chrome/Safari/Webkit */
|
|
||||||
width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrollbars-hidden {
|
|
||||||
scrollbar-width: none; /* Firefox */
|
|
||||||
-ms-overflow-style: none; /* IE 10+ */
|
|
||||||
}
|
}
|
@ -9,6 +9,7 @@
|
|||||||
superForm,
|
superForm,
|
||||||
} from "sveltekit-superforms";
|
} from "sveltekit-superforms";
|
||||||
import { zodClient } from "sveltekit-superforms/adapters";
|
import { zodClient } from "sveltekit-superforms/adapters";
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
|
|
||||||
@ -21,6 +22,7 @@
|
|||||||
},
|
},
|
||||||
onUpdated: ({form: f}) => {
|
onUpdated: ({form: f}) => {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
if(!f.errors) redirect(303, "/");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
superForm,
|
superForm,
|
||||||
} from "sveltekit-superforms";
|
} from "sveltekit-superforms";
|
||||||
import { zodClient } from "sveltekit-superforms/adapters";
|
import { zodClient } from "sveltekit-superforms/adapters";
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
|
|
||||||
@ -21,6 +22,7 @@
|
|||||||
},
|
},
|
||||||
onUpdated: ({form: f}) => {
|
onUpdated: ({form: f}) => {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
if(!f.errors) redirect(303, "/")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
import * as Drawer from '../ui/drawer';
|
import * as Drawer from '../ui/drawer';
|
||||||
import { Input } from '../ui/input';
|
import { Input } from '../ui/input';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatcher = createEventDispatcher();
|
||||||
let group_name = '';
|
let group_name = '';
|
||||||
|
|
||||||
async function createGroup() {
|
async function createGroup() {
|
||||||
@ -20,11 +22,12 @@
|
|||||||
).json();
|
).json();
|
||||||
|
|
||||||
if (!groups.success) return toast.error('Problem with creating group.');
|
if (!groups.success) return toast.error('Problem with creating group.');
|
||||||
|
dispatcher("created")
|
||||||
return toast.success('Group created.');
|
return toast.success('Group created.');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Drawer.Root>
|
<Drawer.Root open={false}>
|
||||||
<Drawer.Trigger asChild let:builder>
|
<Drawer.Trigger asChild let:builder>
|
||||||
<Button builders={[builder]} class="w-full rounded" variant="outline">
|
<Button builders={[builder]} class="w-full rounded" variant="outline">
|
||||||
<div class="flex flex-row justify-center items-center">
|
<div class="flex flex-row justify-center items-center">
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
<script>
|
<script>
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { ArrowLeft, PauseIcon, Play } from 'lucide-svelte';
|
import { ArrowLeft, PauseIcon, Play } from 'lucide-svelte';
|
||||||
import { createEventDispatcher, onMount } from 'svelte';
|
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||||
import {Progress} from '$lib/components/ui/progress';
|
import { Progress } from '$lib/components/ui/progress';
|
||||||
/** @type {string} */
|
import { isOpen, script, paused } from './state';
|
||||||
export let script;
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
|
||||||
/** @type {SpeechSynthesisUtterance} */
|
/** @type {SpeechSynthesisUtterance} */
|
||||||
let utterance;
|
let utterance;
|
||||||
let paused = false;
|
|
||||||
let progress = 0;
|
let progress = 0;
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
let wordIndex = 0;
|
let wordIndex = 0;
|
||||||
|
|
||||||
|
let text = $script;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {SpeechSynthesis}
|
* @type {SpeechSynthesis}
|
||||||
*/
|
*/
|
||||||
@ -23,13 +24,13 @@
|
|||||||
function ready() {
|
function ready() {
|
||||||
speechSynthesis.cancel();
|
speechSynthesis.cancel();
|
||||||
|
|
||||||
const text = script;
|
const text = $script;
|
||||||
const words = text.split(/\s+/);
|
const words = text.split(/\s+/);
|
||||||
utterance = new SpeechSynthesisUtterance(text);
|
utterance = new SpeechSynthesisUtterance(text);
|
||||||
utterance.addEventListener('boundary', (event) => {
|
utterance.addEventListener('boundary', (event) => {
|
||||||
if (event.name === 'word') {
|
if (event.name === 'word') {
|
||||||
console.log(words[wordIndex]);
|
console.log(words[wordIndex]);
|
||||||
document.querySelector(`span[data-index="${wordIndex}"]`)?.classList.add('text-black');
|
document.querySelector(`span[data-index="${wordIndex}"]`)?.classList.add('text-primary');
|
||||||
document.querySelector(`span[data-index="${wordIndex}"]`)?.scrollIntoView({
|
document.querySelector(`span[data-index="${wordIndex}"]`)?.scrollIntoView({
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
block: 'center',
|
block: 'center',
|
||||||
@ -42,7 +43,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
utterance.addEventListener('start', (event) => {
|
utterance.addEventListener('start', (event) => {
|
||||||
paused = false;
|
paused.set(false);
|
||||||
|
|
||||||
// const length = words.length;
|
// const length = words.length;
|
||||||
// const updateProgress = () => {
|
// const updateProgress = () => {
|
||||||
@ -54,13 +55,15 @@
|
|||||||
// updateProgress();
|
// updateProgress();
|
||||||
});
|
});
|
||||||
|
|
||||||
utterance.addEventListener('pause', () => {
|
utterance.onpause = () => {
|
||||||
paused = true;
|
paused.set(true);
|
||||||
});
|
console.log('pause');
|
||||||
|
};
|
||||||
|
|
||||||
utterance.addEventListener('resume', () => {
|
utterance.onresume = () => {
|
||||||
paused = false;
|
paused.set(false);
|
||||||
});
|
console.log('resume');
|
||||||
|
};
|
||||||
|
|
||||||
utterance.addEventListener('end', () => {
|
utterance.addEventListener('end', () => {
|
||||||
progress = 0;
|
progress = 0;
|
||||||
@ -71,23 +74,32 @@
|
|||||||
|
|
||||||
const pauseOrResumeUtterance = () => {
|
const pauseOrResumeUtterance = () => {
|
||||||
if (!speechSynthesis) return;
|
if (!speechSynthesis) return;
|
||||||
console.log('pause or resume');
|
|
||||||
if (!speechSynthesis.speaking) {
|
if (!speechSynthesis.speaking) {
|
||||||
ready();
|
ready();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (paused) {
|
if ($paused) {
|
||||||
console.log('resume');
|
|
||||||
speechSynthesis.resume();
|
speechSynthesis.resume();
|
||||||
|
paused.set(false);
|
||||||
} else {
|
} else {
|
||||||
console.log('pause');
|
|
||||||
speechSynthesis.pause();
|
speechSynthesis.pause();
|
||||||
|
paused.set(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (browser && 'speechSynthesis' in window) {
|
if (browser && 'speechSynthesis' in window) {
|
||||||
speechSynthesis = window.speechSynthesis;
|
speechSynthesis = window.speechSynthesis;
|
||||||
|
const unsubscribe = script.subscribe(v => {
|
||||||
|
text = v;
|
||||||
|
ready();
|
||||||
|
document.querySelectorAll(`span[data-index].text-primary`).forEach(e=>e.classList.remove('text-primary'));
|
||||||
|
wordIndex = 0;
|
||||||
|
progress = 0;
|
||||||
|
// speechSynthesis.pause();
|
||||||
|
// paused.set(true);
|
||||||
|
});
|
||||||
|
// onDestroy(unsubscribe);
|
||||||
} else {
|
} else {
|
||||||
alert(
|
alert(
|
||||||
'Sorry your browser <strong>does not support</strong> speech synthesis.<br>Try this in <a href="https://www.google.co.uk/intl/en/chrome/browser/canary.html">Chrome Canary</a>.'
|
'Sorry your browser <strong>does not support</strong> speech synthesis.<br>Try this in <a href="https://www.google.co.uk/intl/en/chrome/browser/canary.html">Chrome Canary</a>.'
|
||||||
@ -96,32 +108,35 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="absolute inset-0 flex h-full w-full bg-white">
|
<div class="absolute inset-0 flex flex-grow h-full w-full max-w-[100vw] bg-background {!$isOpen ? "hidden" : ""} z-50">
|
||||||
<div
|
<div
|
||||||
class="to-[hsl(rgb(253, 249, 246) / 1)] flex flex-col gap-16 bg-gradient-to-t from-orange-100 from-50% to-background to-80% p-10"
|
class="flex flex-col flex-grow gap-16 p-10 max-w-[100vw]"
|
||||||
>
|
>
|
||||||
<button on:click={() => dispatcher('close')}>
|
<button on:click={() => {
|
||||||
|
dispatcher('close')
|
||||||
|
isOpen.set(false);
|
||||||
|
}}>
|
||||||
<ArrowLeft class="h-8 w-8" />
|
<ArrowLeft class="h-8 w-8" />
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
class="text-container script scrollbars-hidden h-[80%] overflow-scroll text-2xl pb-8"
|
class="text-container script scrollbars-hidden h-[80%] w-full overflow-y-scroll break-words text-wrap pb-8 text-2xl"
|
||||||
style="line-height: 3rem; color:rgba(0,0,0,0.5)"
|
style="line-height: 3rem;"
|
||||||
>
|
>
|
||||||
{#each script.split(/\s+/) as word, i}
|
{#each text.split(/\s+/) as word, i}
|
||||||
<span data-index={i}>{word} </span>
|
<span data-index={i}>{word} </span>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<Progress class="w-full" max={script.length} value={progress} />
|
<Progress class="w-full" max={text.length} value={progress} />
|
||||||
<button
|
<Button
|
||||||
class="m-0 mx-auto flex aspect-square w-12 items-center justify-center rounded-full bg-white p-0"
|
class="m-0 mx-auto flex aspect-square w-12 items-center justify-center rounded-full p-0"
|
||||||
on:click={pauseOrResumeUtterance}
|
on:click={pauseOrResumeUtterance}
|
||||||
>
|
>
|
||||||
{#if paused}
|
{#if $paused}
|
||||||
<Play class="h-6 w-6" />
|
<Play class="h-6 w-6" />
|
||||||
{:else}
|
{:else}
|
||||||
<PauseIcon class="h-6 w-6" />
|
<PauseIcon class="h-6 w-6" />
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
5
src/lib/components/organisms/player/state.js
Normal file
5
src/lib/components/organisms/player/state.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
export const isOpen = writable(false);
|
||||||
|
export const script = writable("Hello world");
|
||||||
|
export const paused = writable(true);
|
@ -3,15 +3,19 @@
|
|||||||
|
|
||||||
import { Label } from "$lib/components/ui/label";
|
import { Label } from "$lib/components/ui/label";
|
||||||
import { Textarea } from "$lib/components/ui/textarea"
|
import { Textarea } from "$lib/components/ui/textarea"
|
||||||
|
import { toast } from "svelte-sonner";
|
||||||
|
|
||||||
export let text;
|
export let text;
|
||||||
|
export let title = "Your relay email";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label for="email">Your relay email</Label>
|
<Label for="email">{title}</Label>
|
||||||
<Textarea name="email" value={text} class="min-h-[1rem] h-[2.75rem] text-[1rem] text-center resize-none" readonly on:click={(e) => {
|
<Textarea name="email" value={text} class="min-h-[1rem] h-[2.75rem] text-[1rem] text-center resize-none" readonly on:click={(e) => {
|
||||||
e.target.select();
|
e.target.select();
|
||||||
navigator.clipboard.writeText(e.target.value);
|
navigator.clipboard.writeText(e.target.value);
|
||||||
e.target.unselect()
|
toast("Email coppied");
|
||||||
|
e.target.unselect();
|
||||||
}}/>
|
}}/>
|
||||||
|
<p class="text-sm text-muted-foreground">Subscribe to newsletters with this email in order to add them to your group.</p>
|
||||||
</div>
|
</div>
|
@ -13,7 +13,7 @@
|
|||||||
<DrawerOverlay />
|
<DrawerOverlay />
|
||||||
<DrawerPrimitive.Content
|
<DrawerPrimitive.Content
|
||||||
class={cn(
|
class={cn(
|
||||||
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border border-black bg-secondary",
|
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border border-black bg-background",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
|
|
||||||
export function generateId(length: number): string {
|
export function generateId(length: number, charset: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"): string {
|
||||||
var text = "";
|
var text = "";
|
||||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
for (var i = 0; i < length; i++)
|
for (var i = 0; i < length; i++)
|
||||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
text += charset.charAt(Math.floor(Math.random() * charset.length));
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import '../app.pcss';
|
import '../app.pcss';
|
||||||
import { Toaster } from '$lib/components/ui/sonner';
|
import { Toaster } from '$lib/components/ui/sonner';
|
||||||
|
import Player from '$lib/components/organisms/player/player.svelte';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Toaster />
|
|
||||||
<div class="max-w-xl mx-auto p-8 h-screen relative">
|
<div class="max-w-xl mx-auto p-8 h-screen relative">
|
||||||
|
<Player />
|
||||||
|
<Toaster />
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2,14 +2,13 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { Label } from '$lib/components/ui/label';
|
import { Label } from '$lib/components/ui/label';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
import Player from '$lib/components/organisms/player.svelte';
|
import Player from '$lib/components/organisms/player/player.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { PlayIcon, Loader, Plus, MailIcon, PlusIcon } from 'lucide-svelte';
|
import { PlayIcon, Loader, Plus, MailIcon, PlusIcon } from 'lucide-svelte';
|
||||||
import CreateGroup from '$lib/components/organisms/create-group.svelte';
|
import CreateGroup from '$lib/components/organisms/create-group.svelte';
|
||||||
|
import { isOpen, script } from '$lib/components/organisms/player/state';
|
||||||
|
|
||||||
let script = "";
|
|
||||||
|
|
||||||
let opened = false;
|
|
||||||
let groups = [];
|
let groups = [];
|
||||||
let pods = []
|
let pods = []
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
@ -21,16 +20,17 @@
|
|||||||
groups = res.groups;
|
groups = res.groups;
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if opened}
|
$: groups;
|
||||||
<Player script={script} on:close={() => opened=false} />
|
</script>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="flex gap-4 flex-col">
|
<div class="flex gap-4 flex-col">
|
||||||
<Label>Your Latest Podcasts</Label>
|
<Label>Your Latest Podcasts</Label>
|
||||||
{#each pods as pod}
|
{#each pods as pod}
|
||||||
<Button class="flex w-full flex-row justify-start rounded text-left" variant="secondary" on:click={() => opened = true}>
|
<Button class="flex w-full flex-row justify-start rounded text-left" variant="secondary" on:click={() => {
|
||||||
|
isOpen.set(true);
|
||||||
|
script.set(pod.script);
|
||||||
|
}}>
|
||||||
<div class="items-center justify-center rounded-lg p-2 pl-0">
|
<div class="items-center justify-center rounded-lg p-2 pl-0">
|
||||||
<PlayIcon class="h-4 w-4" />
|
<PlayIcon class="h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
@ -42,10 +42,10 @@
|
|||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<Label>Your Groups</Label>
|
<Label>Your Groups</Label>
|
||||||
<div class="overflow-x-scroll scrollbars-hidden">
|
<div class="scrollbars-hidden">
|
||||||
<CreateGroup />
|
<CreateGroup on:created={() => groups = [...groups]} />
|
||||||
{#each groups as group}
|
{#each groups as group}
|
||||||
<Button class="mt-4 flex w-full flex-row justify-start rounded text-left" variant="secondary">
|
<Button class="mt-4 flex w-full flex-row justify-start rounded text-left" variant="secondary" href="/group/{group.id}">
|
||||||
<div class="items-center justify-center rounded-lg p-2 pl-0">
|
<div class="items-center justify-center rounded-lg p-2 pl-0">
|
||||||
<MailIcon class="h-4 w-4" />
|
<MailIcon class="h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,6 @@ import { eq } from "drizzle-orm";
|
|||||||
* @type {import("@sveltejs/kit").RequestHandler}
|
* @type {import("@sveltejs/kit").RequestHandler}
|
||||||
*/
|
*/
|
||||||
export async function GET(event) {
|
export async function GET(event) {
|
||||||
console.log(event.locals.user.id)
|
|
||||||
const groups = await db.select().from(groupsTable).where(eq(groupsTable.userId, event.locals.user.id));
|
const groups = await db.select().from(groupsTable).where(eq(groupsTable.userId, event.locals.user.id));
|
||||||
|
|
||||||
return new Response(JSON.stringify({
|
return new Response(JSON.stringify({
|
||||||
@ -43,4 +42,21 @@ export async function POST(event) {
|
|||||||
success: true,
|
success: true,
|
||||||
group: groups[0]
|
group: groups[0]
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import("@sveltejs/kit").RequestHandler}
|
||||||
|
*/
|
||||||
|
export async function DELETE(event) {
|
||||||
|
const url = new URL(event.request.url);
|
||||||
|
const id = url.searchParams.get("id");
|
||||||
|
if(!id) return json({
|
||||||
|
succcess: false
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.delete(groupsTable).where(eq(groupsTable.id, id));
|
||||||
|
|
||||||
|
return json({
|
||||||
|
success: true
|
||||||
|
})
|
||||||
}
|
}
|
28
src/routes/group/[groupid]/+page.server.js
Normal file
28
src/routes/group/[groupid]/+page.server.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { db, groupsTable, podsTable, sourcesTable } from "$lib/db";
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
import { and, eq } from "drizzle-orm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import("./$types").PageServerLoad}
|
||||||
|
*/
|
||||||
|
export const load = async (event) => {
|
||||||
|
let groupInfo;
|
||||||
|
let sources;
|
||||||
|
let pods;
|
||||||
|
try {
|
||||||
|
groupInfo = await db.select().from(groupsTable).where(and(eq(groupsTable.userId, event.locals.user.id), eq(groupsTable.id, event.params.groupid)));
|
||||||
|
if(!groupInfo[0]) return redirect(303, "/")
|
||||||
|
|
||||||
|
sources = await db.select().from(sourcesTable).where(eq(sourcesTable.groupId, event.params.groupid));
|
||||||
|
pods = await db.select().from(podsTable).where(eq(podsTable.groupId, event.params.groupid));
|
||||||
|
} catch (err) {
|
||||||
|
return redirect(303, "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
group: groupInfo[0],
|
||||||
|
sources,
|
||||||
|
pods
|
||||||
|
};
|
||||||
|
}
|
57
src/routes/group/[groupid]/+page.svelte
Normal file
57
src/routes/group/[groupid]/+page.svelte
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<script>
|
||||||
|
import RelayEmail from '$lib/components/organisms/relay-email.svelte';
|
||||||
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
import { Label } from '$lib/components/ui/label';
|
||||||
|
import { isOpen, script } from '$lib/components/organisms/player/state';
|
||||||
|
|
||||||
|
import { MailIcon, PlayIcon } from 'lucide-svelte';
|
||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import("./$types").PageServerData}
|
||||||
|
*/
|
||||||
|
export let data;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<h1 class="text-lg">{data.group.name}</h1>
|
||||||
|
<Label>Your Latest Podcasts</Label>
|
||||||
|
<div class="flex overflow-x-scroll gap-3">
|
||||||
|
{#each data.pods as pod}
|
||||||
|
<Button
|
||||||
|
class="flex flex-row justify-start rounded text-left w-[15rem] max-w-sm"
|
||||||
|
variant="secondary"
|
||||||
|
on:click={() => {
|
||||||
|
isOpen.set(true);
|
||||||
|
script.set(pod.script);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="items-center justify-center rounded-lg p-2 pl-0">
|
||||||
|
<PlayIcon class="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-md">Your Daily Pod</h3>
|
||||||
|
<p class="text-sm text-muted-foreground">
|
||||||
|
{new Date(pod.date_created).toLocaleDateString('de')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<RelayEmail title="This group's email" text={data.group.email} />
|
||||||
|
|
||||||
|
<Label>Your Sources</Label>
|
||||||
|
<div class="scrollbars-hidden flex flex-col gap-4">
|
||||||
|
{#each data.sources as source}
|
||||||
|
<Button class="flex w-full flex-row justify-start rounded text-left" variant="secondary">
|
||||||
|
<div class="items-center justify-center rounded-lg p-2 pl-0">
|
||||||
|
<MailIcon class="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-md">{source.name}</h3>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user