Skip to content

Commit 8d7fd4a

Browse files
committed
feat: implement chat background
1 parent 558fca2 commit 8d7fd4a

File tree

9 files changed

+183
-4
lines changed

9 files changed

+183
-4
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {getConversationById} from "@/lib/conversation";
2+
import {NextResponse} from "next/server";
3+
import {db} from "@/lib/db";
4+
5+
export async function PATCH(
6+
req: Request,
7+
{ params }: { params: { conversationId: string } }
8+
) {
9+
try{
10+
const conversation = await getConversationById(params.conversationId);
11+
const { imageUrl } = await req.json();
12+
13+
if(!conversation) {
14+
return new NextResponse("Conversation is missing", { status: 400 });
15+
}
16+
17+
const newConversation = await db.conversation.update({
18+
where: {
19+
id: conversation.id,
20+
},
21+
data: {
22+
Background: imageUrl,
23+
}
24+
})
25+
26+
return NextResponse.json(newConversation);
27+
} catch (error) {
28+
console.log("[CONVERSATION_NOTIFICATION_PATCH]", error);
29+
return new NextResponse("Internal Error", { status: 500 });
30+
}
31+
}

components/chat/chat-header.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {DatePicker} from "@/components/ui/date-picker";
1010
import * as React from "react";
1111
import {Input} from "@/components/ui/input";
1212
import {Conversation} from "@prisma/client";
13+
import {ChatImageButton} from "@/components/chat/chat-image-button";
1314

1415
interface ChatHeaderProps {
1516
name: string;
@@ -35,6 +36,7 @@ export const ChatHeader = ({
3536
{name}
3637
</p>
3738
<div className="ml-auto flex items-center">
39+
<ChatImageButton conversationId={conversation?.id}/>
3840
<Input placeholder="Поиск по сообщениям"
3941
value={searchMessage}
4042
onChange={(e) => setSearchMessage(e.target.value)}

components/chat/chat-image-button.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"use client";
2+
3+
import qs from "query-string";
4+
import { usePathname, useRouter, useSearchParams } from "next/navigation";
5+
import { PictureInPicture } from "lucide-react";
6+
7+
8+
import { ActionTooltip } from "@/components/action-tooltip";
9+
import axios from "axios";
10+
import {useEffect, useState} from "react";
11+
import {useModal} from "@/hooks/use-modal-store";
12+
13+
interface ChatImageButtonProps {
14+
conversationId?: string;
15+
}
16+
17+
export const ChatImageButton = ({conversationId}: ChatImageButtonProps) => {
18+
const { onOpen } = useModal();
19+
20+
const Icon = PictureInPicture;
21+
const tooltipLabel = "Фон чата" ;
22+
23+
return (
24+
<ActionTooltip side="bottom" label={tooltipLabel}>
25+
<button onClick={() => onOpen("chatImage", {conversationId: conversationId})} className="hover:opacity-75 transition mr-4">
26+
<Icon className="h-6 w-6 text-zinc-500 dark:text-zinc-400" />
27+
</button>
28+
</ActionTooltip>
29+
)
30+
}

components/chat/conver-chat-messages.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import {ElementRef, Fragment, useEffect, useRef} from "react";
44
import {format} from "date-fns";
5-
import {Member, Message, User} from "@prisma/client";
5+
import {Conversation, Member, Message, User} from "@prisma/client";
66
import {Loader2, ServerCrash} from "lucide-react";
77

88
import {useChatQuery} from "@/hooks/use-chat-query";
@@ -20,6 +20,7 @@ const DATE_FORMAT = "d MMM yyyy, HH:mm";
2020
interface ChatMessagesProps {
2121
name: string;
2222
member: ExtendedUser;
23+
conversation: Conversation;
2324
chatId: string;
2425
apiUrl: string;
2526
socketUrl: string;
@@ -36,6 +37,7 @@ export const ConverChatMessages = ({
3637
member,
3738
chatId,
3839
apiUrl,
40+
conversation,
3941
socketUrl,
4042
socketQuery,
4143
paramKey,
@@ -93,7 +95,7 @@ export const ConverChatMessages = ({
9395
</div>)
9496
}
9597

96-
return (<div ref={chatRef} className="flex-1 flex flex-col py-4 overflow-y-auto">
98+
return (<div ref={chatRef} style={{backgroundImage: `url(${conversation.Background})`}} className="flex-1 flex flex-col py-4 overflow-y-auto">
9799
{!hasNextPage && <div className="flex-1"/>}
98100
{!hasNextPage && (<ChatWelcome
99101
type={type}

components/chat/conver-wrapper.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const ConverWrapper = ({currentMember, otherMember, conversation}: ChatWr
3737
member={currentMember}
3838
name={otherMember.name}
3939
chatId={conversation.id}
40+
conversation={conversation}
4041
type="conversation"
4142
apiUrl="/api/direct-messages"
4243
paramKey="conversationId"
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
"use client";
2+
3+
import axios from "axios";
4+
import * as z from "zod";
5+
import { zodResolver } from "@hookform/resolvers/zod";
6+
import { useForm } from "react-hook-form";
7+
8+
import {
9+
Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,
10+
} from "@/components/ui/dialog";
11+
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
12+
import { Input } from "@/components/ui/input";
13+
import { Button } from "@/components/ui/button";
14+
import { FileUpload } from "@/components/files/file-upload";
15+
import { useRouter } from "next/navigation";
16+
import { useModal } from "@/hooks/use-modal-store";
17+
import { useEffect, useState } from "react";
18+
import { Department } from "@prisma/client";
19+
20+
const formSchema = z.object({
21+
imageUrl: z.string()
22+
});
23+
24+
export const ChatImageModal = () => {
25+
const { isOpen, onClose, type , data} = useModal();
26+
const [departments, setDepartments] = useState<Department[]>([]);
27+
const router = useRouter();
28+
29+
const isModalOpen = isOpen && type === "chatImage";
30+
31+
const form = useForm({
32+
resolver: zodResolver(formSchema), defaultValues: {
33+
imageUrl: "",
34+
}
35+
});
36+
37+
const isLoading = form.formState.isSubmitting;
38+
39+
const onSubmit = async (values: z.infer<typeof formSchema>) => {
40+
try {
41+
await axios.patch(`/api/conversation/${data.conversationId}`, values);
42+
43+
form.reset();
44+
router.refresh();
45+
onClose();
46+
} catch (error) {
47+
console.log(error);
48+
}
49+
}
50+
51+
useEffect(() => {
52+
const fetchDepartments = async () => {
53+
try {
54+
const response = await axios.get('/api/departments');
55+
setDepartments(response.data);
56+
} catch (error) {
57+
console.log(error);
58+
}
59+
};
60+
fetchDepartments();
61+
}, []);
62+
63+
const handleClose = () => {
64+
form.reset();
65+
onClose();
66+
}
67+
68+
return (
69+
<Dialog open={isModalOpen} onOpenChange={handleClose}>
70+
<DialogContent className="bg-white text-black p-0 overflow-hidden">
71+
<DialogHeader className="pt-8 px-6">
72+
<DialogTitle className="text-2xl text-center font-bold">
73+
Настройте чат
74+
</DialogTitle>
75+
<DialogDescription className="text-center text-zinc-500">
76+
Настройте фон чата
77+
</DialogDescription>
78+
</DialogHeader>
79+
<Form {...form}>
80+
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
81+
<div className="space-y-8 px-6">
82+
<div className="flex items-center justify-center text-center">
83+
<FormField
84+
control={form.control}
85+
name="imageUrl"
86+
render={({ field }) => (
87+
<FormItem>
88+
<FormControl>
89+
<FileUpload
90+
endpoint="serverImage"
91+
value={field.value}
92+
onChange={field.onChange}
93+
/>
94+
</FormControl>
95+
</FormItem>
96+
)}
97+
/>
98+
</div>
99+
</div>
100+
<DialogFooter className="bg-gray-100 px-6 py-4">
101+
<Button disabled={isLoading}>
102+
Сохранить
103+
</Button>
104+
</DialogFooter>
105+
</form>
106+
</Form>
107+
</DialogContent>
108+
</Dialog>
109+
);
110+
}

components/modals/create-server-modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"use client";
1+
"use client";
22

33
import axios from "axios";
44
import * as z from "zod";

components/providers/modal-provider.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {DeleteMessageModal} from "@/components/modals/delete-message-modal";
1616
import {EditProfileModal} from "@/components/modals/edit-profile-modal";
1717
import {ForwardMessageModal} from "@/components/modals/forward-message-modal";
1818
import {CreateServerAdminModal} from "@/components/modals/create-server-admin-modal";
19+
import {ChatImageModal} from "@/components/modals/chat-image-modal";
1920

2021
export const ModalProvider = () => {
2122
const [isMounted, setIsMounted] = useState(false);
@@ -44,6 +45,7 @@ export const ModalProvider = () => {
4445
<DeleteMessageModal />
4546
<EditProfileModal />
4647
<ForwardMessageModal/>
48+
<ChatImageModal/>
4749
</>
4850
)
4951
}

hooks/use-modal-store.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { create } from "zustand";
33

44
export type ModalType = "createServer" | "createServerAdmin" | "invite" | "editServer" | "members" | "createChannel"
55
| "leaveServer" | "deleteServer" | "deleteChannel" | "editChannel" | "messageFile" | "deleteMessage"
6-
| "editProfile" | "forwardMessage";
6+
| "editProfile" | "forwardMessage" | "chatImage";
77

88
interface ModalData {
99
user?: User;
1010
server?: Server;
1111
channel?: Channel;
1212
message?: Message;
13+
conversationId?: string;
1314
channelType?: ChannelType;
1415
apiUrl?: string;
1516
query?: Record<string, any>;

0 commit comments

Comments
 (0)