added message file upload for image and pdf
This commit is contained in:
parent
e0162c2d5e
commit
fa641dc3a1
@ -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]"/>
|
||||||
|
@ -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}
|
||||||
|
114
components/modals/message-file-modal.tsx.tsx
Normal file
114
components/modals/message-file-modal.tsx.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
@ -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/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user