Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setlist and songUpdates #14

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions app/components/forms/song/SongForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@ const SongForm = forwardRef<
</div>
))}
</div>
<label>
<h2>Additional Information</h2>
<label>
Runtime in seconds
<Input
name="runtime"
defaultValue={song.runtime}
type="number"
title="RunTime (seconds)"
aria-label="RunTime in seconds"
className="text-xl w-full bg-inherit py-1 outline-none hover:cursor-text resize-none"
/>
</label>
<Textarea
name="notes"
placeholder="Notes"
defaultValue={song.notes}
className="text-xl w-full bg-inherit py-1 outline-none hover:cursor-text resize-none"
/>
</label>
{/* <button
type="submit"
className="bg-stone-200 px-5 py-2 rounded-md text-stone-800 mt-4"
Expand Down
15 changes: 14 additions & 1 deletion app/db/setlist.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@ export async function getSetlists() {
});
}

export async function getSetlistsByUserId(userId: number) {
return await prisma.setlist.findMany({
where: { authorId: userId },
include: {
songs: {
select: {
id: true,
},
},
},
});
}

export async function createSetlist(
data?: Pick<Setlist, "name" | "description">
data?: Pick<Setlist, "name" | "description" | "authorId">
) {
return await prisma.setlist.create({
data: { ...data },
Expand Down
2 changes: 1 addition & 1 deletion app/db/song.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export async function updateSong({
data,
}: {
id: Song["id"];
data: Pick<Song, "title" | "attribution" | "stanzas">;
data: Pick<Song, "title" | "attribution" | "stanzas" | "runtime" | "notes">;
}) {
return await prisma.song.update({ where: { id: +id }, data });
}
18 changes: 18 additions & 0 deletions app/helpers/formatRunTime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import formatRunTime from "./formatRunTime";

describe("returns appropriate conversions", () => {
test("expected format", () => {
const actual = formatRunTime(185);
expect(actual).toBe("3 min. 5 sec.");
});

test("expected format", () => {
const actual = formatRunTime(60);
expect(actual).toBe("1 min. 0 sec.");
});

test("expected format", () => {
const actual = formatRunTime(30);
expect(actual).toBe("30 sec.");
});
});
12 changes: 12 additions & 0 deletions app/helpers/formatRunTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* formats the runtime in seconds to US-EN format.
*/
export const formatRunTime = (runtime: number) => {
if (runtime < 60) return `${runtime} sec.`;
let min = runtime / 60;
min = ~~min;
const remSec = runtime % 60;
return `${min} min. ${remSec} sec.`;
};

export default formatRunTime;
10 changes: 7 additions & 3 deletions app/routes/__app/setlists/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { Setlist } from "@prisma/client";
import { Link } from "@remix-run/react";
import type { LoaderArgs } from "@remix-run/node";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { Button } from "~/components/Button";
import { Search } from "~/components/Search";
import { getSetlists } from "~/db/setlist.db";
import { useSearch } from "~/lib/useSearch";
import { requireAuthentication } from "~/utils/auth.server";
import { getSetlistsByUserId } from "~/db/setlist.db";

export async function loader() {
const setlists = await getSetlists();
export async function loader({ request }: LoaderArgs) {
const user = await requireAuthentication(request);

const setlists = await getSetlistsByUserId(user.id);
return typedjson({
setlists,
});
Expand Down
4 changes: 4 additions & 0 deletions app/routes/__app/setlists/new.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ import { redirect } from "@remix-run/node";
import { typedjson } from "remix-typedjson";
import { createSetlist, setQRCode } from "~/db/setlist.db";
import { formDataToJson } from "~/helpers/formDataToJson";
import { currentAuthedUser } from "~/utils/auth.server";

export async function action({ request }: ActionArgs) {
const user = await currentAuthedUser(request);
if (!user) return redirect("/");
const formData = formDataToJson(await request.formData());
if (!formData.name) return;

try {
const setlist = await createSetlist({
name: formData.name as string,
description: formData?.description as string,
authorId: user.id as number,
});
await setQRCode(setlist, request);
return redirect(`/setlists`);
Expand Down
7 changes: 3 additions & 4 deletions app/routes/__app/songs/$id/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,17 @@ export async function action({ request }: ActionArgs) {
const formDataAsJson = formDataToJson(
await request.formData()
) as unknown as ISong;
const id = formDataAsJson.id;
const title = formDataAsJson.title;
const attribution = formDataAsJson.attribution;
const { notes, runtime, title, attribution, id } = formDataAsJson;
const stanzas = JSON.stringify(formDataAsJson.stanzas);

try {
const updatedSong = await updateSong({
id,
data: {
title,
attribution,
stanzas,
notes,
runtime: +runtime,
},
});
return typedjson({ ...updatedSong });
Expand Down
16 changes: 16 additions & 0 deletions app/routes/__app/songs/$id/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { Button } from "~/components/Button";
import { Stanza } from "~/components/Stanza";
import { getSong } from "~/db/song.db";
import { formatRunTime } from "~/helpers/formatRunTime";

export async function loader({ params }: LoaderArgs) {
if (!params.id) throw new Response("Not Found", { status: 404 });
Expand Down Expand Up @@ -87,12 +88,27 @@ export default function () {
<p className="text-xl w-full bg-inherit py-1 outline-none hover:cursor-text resize-none text-stone-500">
{song.attribution}
</p>
<p className="text-xl w-full bg-inherit py-1 outline-none hover:cursor-text resize-none text-stone-500">
Run Time: {formatRunTime(song.runtime)}
</p>
</div>
<div className="space-y-7">
{song.stanzas.map((stanza) => (
<Stanza stanza={stanza} key={stanza.id} />
))}
</div>
<div>
<h2>Notes</h2>
<p className="text-xl w-full bg-inherit py-1 outline-none hover:cursor-text resize-none text-stone-500">
{song.notes}
</p>
{/* <h2>Public domain status</h2>
<p className="text-xl w-full bg-inherit py-1 outline-none hover:cursor-text resize-none text-stone-500">
{song.claimedPublicDomain
? "This song is considered in the public domain"
: "This song is not part of the public domain. Contact the writer, label, composer for use rights."}
</p> */}
</div>
</div>
</div>
</div>
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"db:deploy": "npx prisma migrate deploy",
"db:push": "npx prisma db push",
"db:reset": "rm -r prisma/data.db && npm run db:push",
"db:hard-refresh": "rm -r prisma/data.db && npm run db:push && npm run db:seed",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm down to just add the seed command to db:reset if you want?

"db:seed": "npx prisma db seed",
"db:studio": "npx prisma studio -p 7777 --browser none",
"dev": "concurrently \"npm run dev:css\" \"remix dev\"",
Expand Down Expand Up @@ -41,6 +42,7 @@
"debounce": "^1.2.1",
"dotenv-cli": "^6.0.0",
"fuse.js": "^6.6.2",
"moment": "^2.28.0",
"qrcode": "^1.5.1",
"qs": "^6.11.0",
"react": "^18.2.0",
Expand Down
56 changes: 29 additions & 27 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ datasource db {
}

model User {
id Int @id @default(autoincrement())
email String @unique
id Int @id @default(autoincrement())
email String @unique
name String?
// role Role @default(USER)
songs Song[]
profile Profile?
oAuthProvider String?
oAuthId String?
setlists Setlist[]
}

model Profile {
Expand All @@ -29,41 +30,42 @@ model Profile {
}

model Song {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
attribution String @default("")
stanzas String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
categories Category[] //# @relation(references: [id])
Setlist Setlist? @relation(fields: [setlistId], references: [id])
setlistId String?
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
attribution String @default("")
stanzas String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
// time in seconds for the length of song
runtime Int @default(185) // bonus points if you know the reference
notes String @default("")
claimedPublicDomain Boolean @default(false)
categories Category[] //# @relation(references: [id])
setlists Setlist[] // @relation(fields: [setlistId], references: [id])
}

model Category {
id Int @id @default(autoincrement())
name String
songs Song[] //@relation(references: [id])
songs Song[] // @relation(references: [id])

setlists Setlist[]
}

model Setlist {
id String @id @default(uuid())
name String @default("")
description String @default("")
// Json type not supported in SQLite
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

qrcode String @default("")

songs Song[]
Category Category? @relation(fields: [categoryId], references: [id])
categoryId Int?
id String @id @default(uuid())
name String @default("")
description String @default("")
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
qrcode String @default("")
songs Song[]
categories Category[]
}

// enum Role {
Expand Down
22 changes: 22 additions & 0 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { PrismaClient } from "@prisma/client";

import { createMockSong } from "@/test/factories/song.factory";

const prisma = new PrismaClient();
async function main() {
const keith = await prisma.user.upsert({
Expand All @@ -25,6 +28,25 @@ async function main() {
name: "Keith Full Auth Flow",
},
});
await prisma.category.create({ data: { name: "Sea Shanties" } });
await prisma.category.create({ data: { name: "New American Americana" } });
await prisma.category.create({ data: { name: "Folk" } });
await prisma.category.create({ data: { name: "Protest" } });
await prisma.category.create({
data: { name: "Really makes you go hmmmmm." },
});
await prisma.category.create({
data: { name: "Really makes you go hummmmm." },
});
const mockedSong = createMockSong();
await prisma.song.create({
data: {
...mockedSong,
id: 1,
authorId: 3,
},
});
// await prisma.category.upsert
console.log({ keith, drew, keithFullAuth });
}
main()
Expand Down