-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pano): add create post form with modal route ux (#638)
Add modal based UX for pano post creation. Uses [parallel routes] and "[intercepting routes]" patterns from next.js to render a modal if we go to `/post/create` route from application using a link, and render the form directly if user lands on that route directly by either clicking to that link from somewhere else, or reloading at that route. _(an example implementation from next.js: https://github.com/vercel-labs/nextgram)_ https://github.com/kamp-us/monorepo/assets/1783869/e56072c3-a938-4cc6-b228-bee5d11d9349 ### Checklist - [ ] discord username: `umut` - [ ] Closes #613 - [ ] A descriptive and understandable title: The PR title should clearly describe the nature and purpose of the changes. The PR title should be the first thing displayed when the PR is opened. And it should follow the semantic commit rules, and should include the app/package/service name in the title. For example, a title like "docs(@kampus-apps/pano): Add README.md" can be used. - [ ] Related file selection: Only relevant files should be touched and no other files should be affected. - [ ] I ran `npx turbo run` at the root of the repository, and build was successful. - [ ] I installed the npm packages using `npm install --save-exact <package>` so my package is pinned to a specific npm version. Leave empty if no package was installed. Leave empty if no package was installed with this PR. [parallel routes]: https://nextjs.org/docs/app/building-your-application/routing/parallel-routes [intercepting routes]: https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes
- Loading branch information
Showing
19 changed files
with
774 additions
and
151 deletions.
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,19 @@ | ||
"use client"; | ||
|
||
import { useRouter } from "next/navigation"; | ||
|
||
import { Dialog, DialogContent } from "@kampus/ui"; | ||
|
||
import { CreatePanoPostForm } from "~/app/pano/CreatePanoPostForm"; | ||
|
||
export default function CreatePost({ searchParams }: { searchParams: { conn: string } }) { | ||
const router = useRouter(); | ||
|
||
return ( | ||
<Dialog open onOpenChange={() => router.back()}> | ||
<DialogContent className="sm:max-w-[425px]"> | ||
<CreatePanoPostForm connectionID={searchParams.conn} onCompleted={() => router.back()} /> | ||
</DialogContent> | ||
</Dialog> | ||
); | ||
} |
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,3 @@ | ||
export default function Default() { | ||
return null; | ||
} |
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,3 @@ | ||
export default function Default() { | ||
return null; | ||
} |
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,143 @@ | ||
"use client"; | ||
|
||
import { graphql, useMutation } from "react-relay"; | ||
import { z } from "zod"; | ||
|
||
import { | ||
Button, | ||
Form, | ||
FormControl, | ||
FormDescription, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
Input, | ||
Textarea, | ||
useForm, | ||
} from "@kampus/ui"; | ||
|
||
const mutation = graphql` | ||
mutation CreatePanoPostFormMutation( | ||
$title: String! | ||
$content: String | ||
$url: String | ||
$connections: [ID!]! | ||
) { | ||
createPanoPost(input: { url: $url, title: $title, content: $content }) { | ||
edge @prependEdge(connections: $connections) { | ||
cursor | ||
node { | ||
...PostItem_post | ||
} | ||
} | ||
error { | ||
... on UserError { | ||
message | ||
} | ||
} | ||
} | ||
} | ||
`; | ||
|
||
const formSchema = z.object({ | ||
title: z.string().min(5, { message: "Başlık en az 5 karakterden oluşmalıdır" }), | ||
url: z.string().url({ message: "URL duzgun degil" }), | ||
content: z.string().optional(), | ||
}); | ||
|
||
type FormSchema = z.infer<typeof formSchema>; | ||
|
||
interface Props { | ||
connectionID?: string; | ||
onCompleted?: () => void; | ||
} | ||
|
||
export function CreatePanoPostForm(props: Props) { | ||
const [commit, isInFlight] = useMutation(mutation); | ||
|
||
const form = useForm(formSchema, { | ||
defaultValues: { | ||
title: "", | ||
url: "", | ||
content: "", | ||
}, | ||
}); | ||
|
||
const onSubmit = (values: FormSchema) => { | ||
commit({ | ||
variables: { | ||
title: values.title, | ||
url: values.url, | ||
content: values.content, | ||
connections: [props.connectionID].filter(Boolean), | ||
}, | ||
onError: (error) => { | ||
console.error(error); | ||
}, | ||
onCompleted: () => { | ||
props.onCompleted?.(); | ||
}, | ||
}); | ||
}; | ||
|
||
const onCancel = () => { | ||
props.onCompleted?.(); | ||
}; | ||
|
||
return ( | ||
<Form {...form}> | ||
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */} | ||
<form className="flex flex-col gap-2" onSubmit={form.handleSubmit(onSubmit)}> | ||
<FormField | ||
control={form.control} | ||
name="url" | ||
render={(props) => ( | ||
<FormItem> | ||
<FormLabel>URL</FormLabel> | ||
<FormControl> | ||
<Input placeholder="https://ornek.com" {...props.field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="title" | ||
render={(props) => ( | ||
<FormItem> | ||
<FormLabel>Başlık</FormLabel> | ||
<FormControl> | ||
<Input placeholder="Ornek baslik" {...props.field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={form.control} | ||
name="content" | ||
render={(props) => ( | ||
<FormItem> | ||
<FormLabel>Icerik</FormLabel> | ||
<FormControl> | ||
<Textarea placeholder="Ornek hakkindaki dusuncelerim .." {...props.field} /> | ||
</FormControl> | ||
<FormDescription>Eklemek istediklerini ekleyebilirsin ..</FormDescription> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<div className="flex justify-end gap-1.5"> | ||
<Button onClick={onCancel} variant="outline" type="reset"> | ||
Iptal | ||
</Button> | ||
<Button type="submit" disabled={isInFlight}> | ||
Gonder | ||
</Button> | ||
</div> | ||
</form> | ||
</Form> | ||
); | ||
} |
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
Oops, something went wrong.