added message file upload for image and pdf

This commit is contained in:
Bob Burningham 2023-10-26 19:48:25 -07:00
parent e0162c2d5e
commit fa641dc3a1
5 changed files with 147 additions and 3 deletions

View File

@ -14,6 +14,7 @@ import {
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Plus, Smile } from "lucide-react"; import { Plus, Smile } from "lucide-react";
import { useModal } from "@/hooks/use-modal-store";
interface ChatInputProps { interface ChatInputProps {
apiUrl: string; apiUrl: string;
@ -32,6 +33,8 @@ export const ChatInput = ({
name, name,
type type
}: ChatInputProps) => { }: ChatInputProps) => {
const { onOpen } = useModal();
const form = useForm<z.infer<typeof formSchema>>({ const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema), resolver: zodResolver(formSchema),
defaultValues: { defaultValues: {
@ -66,7 +69,7 @@ export const ChatInput = ({
<div className="relative p-4 pb-6"> <div className="relative p-4 pb-6">
<button <button
type="button" type="button"
onClick={() => {}} onClick={() => onOpen("messageFile", { apiUrl, query})}
className="absolute top-7 left-8 h-[24px] w-[24px] bg-zinc-500 dark:bg-zinc-400 hover:bg-zinc-600 dark:hover:bg-zinc-300 transition rounded-full p-1 flex items-center justify-center" className="absolute top-7 left-8 h-[24px] w-[24px] bg-zinc-500 dark:bg-zinc-400 hover:bg-zinc-600 dark:hover:bg-zinc-300 transition rounded-full p-1 flex items-center justify-center"
> >
<Plus className="text-white dark:text-[#313338]"/> <Plus className="text-white dark:text-[#313338]"/>

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import { X } from "lucide-react"; import { FileIcon, X } from "lucide-react";
import Image from "next/image"; import Image from "next/image";
import { UploadDropzone } from "@/lib/uploadthing"; import { UploadDropzone } from "@/lib/uploadthing";
@ -40,6 +40,29 @@ export const FileUpload = ({
) )
} }
if (value && fileType === "pdf") {
return (
<div className="relative flex items-center p-2 mt-2 rounded-md bg-background/10">
<FileIcon className="h-10 w-10 fill-indigo-200 stroke-indigo-400 "/>
<a
href={value}
target="_blank"
rel="noopener noreferrer"
className="ml-2 text-sm text-indigo-500 dark:text-indigo-400 hover:underline"
>
{value}
</a>
<button
onClick={() => onChange("")}
className="bg-rose-500 text-white p-1 rounded-full absolute -top-2 -right-2 shadow-sm"
type="button"
>
<X className="h-4 w-4" />
</button>
</div>
)
}
return ( return (
<UploadDropzone <UploadDropzone
endpoint={endpoint} endpoint={endpoint}

View File

@ -0,0 +1,114 @@
"use client";
import axios from "axios";
import qs from "query-string";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import{
Form,
FormControl,
FormField,
FormItem,
} from "@/components/ui/form";
import { Button } from "@/components/ui/button";
import { FileUpload } from "@/components/file-upload";
import { useRouter } from "next/navigation";
import { useModal } from "@/hooks/use-modal-store";
const formSchema = z.object({
fileUrl: z.string().min(1, {
message: "Attachment is required",
}),
});
export const MessageFileModal = () => {
const {isOpen, onClose, type, data} = useModal();
const router = useRouter();
const isModalOpen = isOpen && type === "messageFile";
const { apiUrl, query } = data;
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
fileUrl: "",
}
});
const handleClose = () => {
form.reset();
onClose();
}
const isLoading = form.formState.isSubmitting;
const onSubmit = async (values: z.infer<typeof formSchema>) => {
try {
const url = qs.stringifyUrl({
url: apiUrl || "",
query,
})
await axios.post(url, {...values, content: values.fileUrl,});
form.reset();
router.refresh();
handleClose();
} catch (error) {
console.error(error);
}
}
return (
<Dialog open={isModalOpen} onOpenChange={handleClose}>
<DialogContent className="bg-white text-black p-0 overflow-hidden">
<DialogHeader className="pt-8 px-6">
<DialogTitle className="text-2xl text-center">
Add an attachment
</DialogTitle>
<DialogDescription className="text-center text-zinc-500">
Send a file as a message
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<div className="space-y-8 px-6">
<div className="flex items-center justify-center text-center">
<FormField
control={form.control}
name="fileUrl"
render={({ field }) => (
<FormItem>
<FormControl>
<FileUpload
endpoint="messageFile"
value={field.value}
onChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
</div>
</div>
<DialogFooter className="bg-gray-100 px-6 py-4">
<Button variant={"primary"} disabled={isLoading}>
Send
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
)
}

View File

@ -11,6 +11,7 @@ import { LeaveServerModal } from "@/components/modals/leave-server-modal";
import { DeleteServerModal } from "@/components/modals/delete-server-modal"; import { DeleteServerModal } from "@/components/modals/delete-server-modal";
import { DeleteChannelModal } from "@/components/modals/delete-channel-modal"; import { DeleteChannelModal } from "@/components/modals/delete-channel-modal";
import { EditChannelModal } from "@/components/modals/edit-channel-modal"; import { EditChannelModal } from "@/components/modals/edit-channel-modal";
import { MessageFileModal } from "@/components/modals/message-file-modal.tsx";
export const ModalProvider = () => { export const ModalProvider = () => {
const [isMounted, setIsMounted] = useState(false); const [isMounted, setIsMounted] = useState(false);
@ -34,6 +35,7 @@ export const ModalProvider = () => {
<DeleteServerModal/> <DeleteServerModal/>
<DeleteChannelModal/> <DeleteChannelModal/>
<EditChannelModal/> <EditChannelModal/>
<MessageFileModal/>
</> </>
) )
} }

View File

@ -2,12 +2,14 @@
import { Channel, ChannelType, Server } from "@prisma/client"; import { Channel, ChannelType, Server } from "@prisma/client";
import { create } from "zustand"; import { create } from "zustand";
export type ModalType = "createServer" | "invite" | "editServer" | "members" | "createChannel" | "leaveServer" | "deleteServer" | "deleteChannel" | "editChannel"; export type ModalType = "createServer" | "invite" | "editServer" | "members" | "createChannel" | "leaveServer" | "deleteServer" | "deleteChannel" | "editChannel" | "messageFile";
interface ModalData { interface ModalData {
server?: Server; server?: Server;
channel?: Channel channel?: Channel
channelType?: ChannelType; channelType?: ChannelType;
apiUrl?: string;
query?: Record<string, any>;
} }
interface ModalStore { interface ModalStore {