Skip to content

Commit

Permalink
Finish dream log implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
bombies committed Oct 26, 2023
1 parent 6b59e5b commit 1bac732
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ const CurrentDreamsContainer: FC = () => {
)), [dreams.data, endOfToday, startOfToday])

return (
<div className="w-3/4">
<div className="flex flex-col">
<h2 className="text-4xl phone:text-2xl font-semibold mb-8 phone:mb-4 tablet:text-center">Today - {startOfToday.toLocaleDateString("en-US", {
dateStyle: "medium"
})}
</h2>
<div className="bg-primary/20 rounded-3xl py-6 px-4 phone:p-3 w-[36rem] tablet:w-full tablet:self-center flex flex-col gap-y-6">
<div className="bg-primary/20 rounded-3xl py-6 px-4 phone:p-3 w-[36rem] tablet:w-[24rem] phone:w-[20rem] tablet:self-center flex flex-col gap-y-6 phone:gap-y-3">
<LogDreamCard/>
{dreamCards}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ const DreamCard: FC<Props> = ({dream}) => {
return (
<Fragment>
<Card classNames={{
header: "bg-secondary",
body: "bg-secondary",
footer: "bg-secondary",
header: "bg-[#0C0015] pt-6 px-8 pb-0",
body: "bg-[#0C0015] px-8 pt-4",
footer: "bg-[#0C0015] px-8",
}}>
<CardHeader className="flex justify-between">
<h2>{dream.title}</h2>
<p>
<h2 className="text-3xl tablet:text-xl font-semibold whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[80%] phone:max-w-[50%]">{dream.title}</h2>
<p className="text-subtext text-lg self-end">
{new Date(dream.createdAt.toString()).toLocaleTimeString("en-US", {
timeStyle: 'short'
})}
</p>
</CardHeader>
<CardBody>
<p>
<p className="mb-4 text-subtext max-w-[85%] overflow-hidden whitespace-nowrap overflow-ellipsis">
{dream.description.substring(0, Math.min(dream.description.length, 100))}
</p>
</CardBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ const AddCharacterForm: FC<Props> = ({onSuccess}) => {
}

return (
<form onSubmit={handleSubmit(onSubmit)}>
<form
onSubmit={handleSubmit(onSubmit)}
name="add_dream_character_form"
id="add_dream_character_form"
>
<div className="space-y-6">
<Input
isRequired
Expand All @@ -85,6 +89,7 @@ const AddCharacterForm: FC<Props> = ({onSuccess}) => {
isLoading={isCreating}
isDisabled={isCreating}
type="submit"
form="add_dream_character_form"
color="primary"
variant="shadow"
>Create Character</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,34 @@ import {Chip} from "@nextui-org/chip";
import {SelectItem} from "@nextui-org/react";
import {DreamCharactersState} from "@/app/(site)/(internal)/dashboard/components/dreams/hooks/useDreamCharacters";
import {UseFormRegister} from "react-hook-form";
import AddCharacterModal from "@/app/(site)/(internal)/dashboard/components/dreams/forms/characters/AddCharacterModal";
import PlusIcon from "@/app/(site)/components/icons/PlusIcon";

type Props = {
register?: UseFormRegister<any>,
characters: DreamCharactersState
characters: DreamCharactersState,
isDisabled?: boolean,
onModalOpen?: () => void,
}

const DreamCharacterSelect: FC<Props> = ({characters, register}) => {
const DreamCharacterSelect: FC<Props> = ({onModalOpen, isDisabled, characters, register}) => {
const [modalOpen, setModalOpen] = useState(false)

return (
<Fragment>
<AddCharacterModal
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
/>
<div className="flex gap-4 mb-2">
<label className="text-lg phone:text-medium text-[#EAE0FF] self-center">Dream Characters</label>
<Button
color="cta"
size="sm"
onPress={() => setModalOpen(true)}
startContent={<PlusIcon width={20} />}
onPress={onModalOpen}
isDisabled={isDisabled}
startContent={<PlusIcon width={20}/>}
>
Add New Character
</Button>
</div>
<Select
isDisabled={isDisabled}
aria-label="Dream Characters"
register={register}
id="characters"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,32 @@ import {Chip} from "@nextui-org/chip";
import {SelectItem} from "@nextui-org/react";
import {UseFormRegister} from "react-hook-form";
import {DreamTagsState} from "@/app/(site)/(internal)/dashboard/components/dreams/hooks/useDreamTags";
import AddTagModal from "@/app/(site)/(internal)/dashboard/components/dreams/forms/tags/AddTagModal";
import PlusIcon from "@/app/(site)/components/icons/PlusIcon";

type Props = {
register?: UseFormRegister<any>,
tags: DreamTagsState
tags: DreamTagsState,
isDisabled?: boolean,
onModalOpen?: () => void
}

const DreamTagSelect: FC<Props> = ({tags, register}) => {
const [modalOpen, setModalOpen] = useState(false)

const DreamTagSelect: FC<Props> = ({onModalOpen, isDisabled, tags, register}) => {
return (
<Fragment>
<AddTagModal
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
/>
<div className="flex gap-4 mb-2">
<label className="text-lg phone:text-medium text-[#EAE0FF] self-center">Dream Tags</label>
<Button
color="cta"
size="sm"
onPress={() => setModalOpen(true)}
onPress={onModalOpen}
startContent={<PlusIcon width={20} />}
isDisabled={isDisabled}
>
Add New Tag
</Button>
</div>
<Select
isDisabled={isDisabled}
aria-label="Dream Tags"
register={register}
id="tags"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import {FC, useCallback} from "react";
import {FC, Fragment, useCallback, useState} from "react";
import {SubmitHandler, useForm} from "react-hook-form";
import {PostDreamDto} from "@/app/api/me/dreams/dreams.dto";
import Input from "@/app/(site)/components/Input";
Expand All @@ -12,6 +12,14 @@ import DreamTagSelect from "@/app/(site)/(internal)/dashboard/components/dreams/
import {Divider} from "@nextui-org/divider";
import PencilIcon from "@/app/(site)/components/icons/PencilIcon";
import CloseIcon from "@/app/(site)/components/icons/CloseIcon";
import axios from "axios";
import useSWRMutation from "swr/mutation";
import {Dream} from "@prisma/client";
import {handleAxiosError} from "@/utils/client-utils";
import {useSession} from "next-auth/react";
import toast from "react-hot-toast";
import AddTagModal from "@/app/(site)/(internal)/dashboard/components/dreams/forms/tags/AddTagModal";
import AddCharacterModal from "@/app/(site)/(internal)/dashboard/components/dreams/forms/characters/AddCharacterModal";

type FormProps = Omit<PostDreamDto, 'tags' | 'characters'> & {
tags?: string[] | string
Expand All @@ -20,79 +28,160 @@ type FormProps = Omit<PostDreamDto, 'tags' | 'characters'> & {

type Props = {
onForget?: () => void;
onCreate?: (dream: Dream) => void;
}

const LogDreamForm: FC<Props> = ({onForget}) => {
const {characters, tags} = useDreamsData()
type CreateDreamArgs = {
arg: {
dto: PostDreamDto
}
}

const CreateDream = () => {
const mutator = (url: string, {arg}: CreateDreamArgs) => axios.post<Dream | null>(url, arg.dto)
return useSWRMutation('/api/me/dreams', mutator)
}

const LogDreamForm: FC<Props> = ({onCreate, onForget}) => {
const {data: session} = useSession()
const [addTagModalOpen, setAddTagModalOpen] = useState(false)
const [addCharacterModalOpen, setAddCharacterModalOpen] = useState(false)
const {characters, tags, dreams} = useDreamsData()
const {register, handleSubmit} = useForm<FormProps>()
const {trigger: createDream, isMutating: dreamIsCreating} = CreateDream()

const handleDreamCreation = useCallback(async (dto: PostDreamDto) => (
createDream({dto})
.then(res => {
const dream = res.data!!
if (onCreate)
onCreate(dream)
return dream
})
.catch(handleAxiosError)
), [createDream, onCreate])

const onSubmit: SubmitHandler<FormProps> = useCallback(async ({
tags: dataTags,
characters: dataCharacters,
...data
}) => {
if (!session?.user)
return

const onSubmit: SubmitHandler<FormProps> = useCallback(({tags, characters, ...data}) => {
const mutableData: PostDreamDto = {...data}
if (typeof tags === "string")
mutableData.tags = tags.split(",")
if (typeof characters === "string")
mutableData.characters = characters.split(",")
console.log(mutableData)
}, [])
if (typeof dataTags === "string")
mutableData.tags = dataTags.split(",")
if (typeof dataCharacters === "string")
mutableData.characters = dataCharacters.split(",")

const {tags: tagIds, characters: characterIds, comments, ...dreamData} = mutableData
// In case there's ever a need to include the tags and such in the optimistic data
// const tagObjects = tagIds && tags.data.filter(tag => tagIds.some(id => id === tag.id))
// const characterObjects = characterIds && characters.data.filter(character => characterIds.some(id => id === character.id))

await toast.promise(dreams.optimisticData
.addOptimisticData(
() => handleDreamCreation(mutableData),
{
id: '',
userId: session.user.id,
...dreamData,
comments: comments ?? null,
createdAt: new Date(),
updatedAt: new Date()
}
), {
loading: "Creating new dream log...",
success: "Successfully logged your dream!",
error: "Could not log your dream!"
}
)
}, [dreams.optimisticData, handleDreamCreation, session?.user])

return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-6">
<Input
isRequired
register={register}
id="title"
label="Dream Title"
labelPlacement="outside"
placeholder="Enter a fancy title for your special dream!"
maxLength={500}
/>
<TextArea
isRequired
register={register}
id="description"
label="Your Dream"
labelPlacement="outside"
placeholder="Tell your tale..."
maxLength={5000}
/>
<DreamTagSelect
register={register}
tags={tags}
/>
<DreamCharacterSelect
register={register}
characters={characters}
/>
<Input
register={register}
id="comments"
label="Dream Comments"
labelPlacement="outside"
placeholder="Anything you'd like to add?"
maxLength={100}
/>
<Divider/>
<div className="flex justify-end pr-6 phone:p-0 phone:justify-center gap-4">
<Button
type="submit"
color="cta"
startContent={<PencilIcon width={20} />}
>Log Dream</Button>
<Button
variant="bordered"
color="danger"
startContent={<CloseIcon width={20} />}
onPress={() => {
if (onForget)
onForget()
}}
>
Forget It
</Button>
<Fragment>
<AddTagModal
isOpen={addTagModalOpen}
onClose={() => setAddTagModalOpen(false)}
/>
<AddCharacterModal
isOpen={addCharacterModalOpen}
onClose={() => setAddCharacterModalOpen(false)}
/>
<form
name="dream_log_form"
id="dream_log_form"
onSubmit={handleSubmit(onSubmit)}
>
<div className="space-y-6">
<Input
isRequired
register={register}
id="title"
label="Dream Title"
labelPlacement="outside"
placeholder="Enter a fancy title for your special dream!"
maxLength={500}
isDisabled={dreamIsCreating}
/>
<TextArea
isRequired
register={register}
id="description"
label="Your Dream"
labelPlacement="outside"
placeholder="Tell your tale..."
maxLength={5000}
isDisabled={dreamIsCreating}
/>
<DreamTagSelect
register={register}
tags={tags}
isDisabled={dreamIsCreating}
onModalOpen={() => setAddTagModalOpen(true)}
/>
<DreamCharacterSelect
register={register}
characters={characters}
isDisabled={dreamIsCreating}
onModalOpen={() => setAddCharacterModalOpen(true)}
/>
<Input
register={register}
id="comments"
label="Dream Comments"
labelPlacement="outside"
placeholder="Anything you'd like to add?"
maxLength={100}
isDisabled={dreamIsCreating}
/>
<Divider/>
<div className="flex justify-end pr-6 phone:p-0 phone:justify-center gap-4">
<Button
type="submit"
form="dream_log_form"
color="cta"
startContent={<PencilIcon width={20}/>}
isLoading={dreamIsCreating}
isDisabled={dreamIsCreating}
>Log Dream</Button>
<Button
variant="bordered"
color="danger"
startContent={<CloseIcon width={20}/>}
onPress={() => {
if (onForget)
onForget()
}}
isDisabled={dreamIsCreating}
>
Forget It
</Button>
</div>
</div>
</div>
</form>
</form>
</Fragment>
)
}

Expand Down
Loading

0 comments on commit 1bac732

Please sign in to comment.