generated from hack4impact-calpoly/nextjs-app-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #47 from hack4impact-calpoly/33-create-announcemen…
…t-schema-and-create-announcement-page feat: added announcement schema and create announcement page
- Loading branch information
Showing
6 changed files
with
263 additions
and
2 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,80 @@ | ||
/** | ||
* @jest-environment jsdom | ||
*/ | ||
|
||
import React from "react"; | ||
import "@testing-library/jest-dom"; | ||
import { render, screen, fireEvent, waitFor } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import CreateAnnouncement from "@/app/createAnnouncement/page"; | ||
|
||
describe("CreateAnnouncement", () => { | ||
it("renders the form correctly", () => { | ||
render(<CreateAnnouncement />); | ||
|
||
expect(screen.getByText("New Message")).toBeInTheDocument(); | ||
expect(screen.getByLabelText("Send to")).toBeInTheDocument(); | ||
expect(screen.getByLabelText("Subject")).toBeInTheDocument(); | ||
expect(screen.getByLabelText("Message")).toBeInTheDocument(); | ||
expect(screen.getByRole("button", { name: /Send/i })).toBeInTheDocument(); | ||
expect(screen.getByRole("button", { name: /Cancel/i })).toBeInTheDocument(); | ||
}); | ||
|
||
it("updates form fields when user types", async () => { | ||
render(<CreateAnnouncement />); | ||
|
||
const recipientsInput = screen.getByPlaceholderText("Find recipients") as HTMLInputElement; | ||
const subjectInput = screen.getByPlaceholderText("Subject line here") as HTMLInputElement; | ||
const messageInput = screen.getByPlaceholderText("Type your message here...") as HTMLTextAreaElement; | ||
|
||
await userEvent.type(recipientsInput, "testUser"); | ||
await userEvent.type(subjectInput, "Meeting Update"); | ||
await userEvent.type(messageInput, "Hello everyone, please note the meeting time change."); | ||
|
||
expect(recipientsInput.value).toBe("testUser"); | ||
expect(subjectInput.value).toBe("Meeting Update"); | ||
expect(messageInput.value).toBe("Hello everyone, please note the meeting time change."); | ||
}); | ||
|
||
it("handles file selection correctly", () => { | ||
render(<CreateAnnouncement />); | ||
|
||
const fileInput = screen.getByLabelText(/Add attachment/i); | ||
const file = new File(["sample content"], "sample.txt", { type: "text/plain" }); | ||
|
||
fireEvent.change(fileInput, { target: { files: [file] } }); | ||
|
||
// Check if the file name appears correctly | ||
const attachmentText = screen.getByText("sample.txt"); | ||
expect(attachmentText).toBeInTheDocument(); | ||
}); | ||
|
||
it("handles form submission correctly", () => { | ||
const logSpy = jest.spyOn(console, "log").mockImplementation(); | ||
|
||
// Render the component | ||
render(<CreateAnnouncement />); | ||
|
||
const recipientsInput = screen.getByPlaceholderText(/Find recipients/i); | ||
const subjectInput = screen.getByPlaceholderText(/Subject line here/i); | ||
const messageTextarea = screen.getByPlaceholderText(/Type your message here/i); | ||
|
||
fireEvent.change(recipientsInput, { target: { value: "Test User" } }); | ||
fireEvent.change(subjectInput, { target: { value: "Test Subject" } }); | ||
fireEvent.change(messageTextarea, { target: { value: "Test Message" } }); | ||
|
||
// Simulate form submission | ||
const submitButton = screen.getByRole("button", { name: /Send/i }); | ||
fireEvent.click(submitButton); | ||
|
||
// Check if console.log was called with the correct form data | ||
expect(logSpy).toHaveBeenCalledWith("Submitted Data: ", { | ||
recipients: "Test User", | ||
subject: "Test Subject", | ||
message: "Test Message", | ||
attachment: null, | ||
}); | ||
|
||
logSpy.mockRestore(); | ||
}); | ||
}); |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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,153 @@ | ||
"use client"; | ||
|
||
import { useState } from "react"; | ||
import { | ||
Box, | ||
Button, | ||
FormControl, | ||
FormLabel, | ||
Input, | ||
Textarea, | ||
VStack, | ||
IconButton, | ||
HStack, | ||
useToast, | ||
Flex, | ||
Text, | ||
} from "@chakra-ui/react"; | ||
import { AttachmentIcon } from "@chakra-ui/icons"; | ||
|
||
const CreateAnnouncement = () => { | ||
type AnnouncementData = { | ||
recipients: string; | ||
subject: string; | ||
message: string; | ||
attachment: File | null; | ||
}; | ||
|
||
const [formData, setFormData] = useState<AnnouncementData>({ | ||
recipients: "", | ||
subject: "", | ||
message: "", | ||
attachment: null, // Make sure this is 'attachment' | ||
}); | ||
|
||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => { | ||
const { name, value } = e.target; | ||
setFormData((prev) => ({ | ||
...prev, | ||
[name]: value, | ||
})); | ||
}; | ||
|
||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
if (e.target.files && e.target.files[0]) { | ||
setFormData((prev) => ({ | ||
...prev, | ||
attachment: e.target.files![0], | ||
})); | ||
} | ||
}; | ||
|
||
const handleSubmit = () => { | ||
console.log("Submitted Data: ", formData); | ||
}; | ||
|
||
return ( | ||
<Box | ||
position="absolute" | ||
width="100vw" | ||
minHeight="100vh" | ||
bg="#F4F1E8" | ||
transform="translateX(-15rem)" | ||
pl="15rem" | ||
display="flex" | ||
alignItems="center" | ||
> | ||
<VStack spacing={7} align="start" p="50px" py="50px" width="100%" maxW="900px" mx="auto"> | ||
<Box fontSize="3xl" fontWeight="bold"> | ||
New Message | ||
</Box> | ||
<FormControl> | ||
<FormLabel fontWeight="bold">Send to</FormLabel> | ||
<Input | ||
name="recipients" | ||
placeholder="Find recipients" | ||
_placeholder={{ color: "#596435" }} | ||
value={formData.recipients} | ||
onChange={handleChange} | ||
bg="white" | ||
color="#596435" | ||
borderRadius="xl" | ||
py="23px" | ||
/> | ||
</FormControl> | ||
<FormControl> | ||
<FormLabel fontWeight="bold">Subject</FormLabel> | ||
<Input | ||
name="subject" | ||
placeholder="Subject line here" | ||
_placeholder={{ color: "#596435" }} | ||
value={formData.subject} | ||
onChange={handleChange} | ||
bg="white" | ||
borderRadius="xl" | ||
py="23px" | ||
/> | ||
</FormControl> | ||
<FormControl position="relative"> | ||
<FormLabel fontWeight="bold">Message</FormLabel> | ||
<Textarea | ||
name="message" | ||
placeholder="Type your message here..." | ||
_placeholder={{ color: "#596435" }} | ||
value={formData.message} | ||
onChange={handleChange} | ||
bg="#white" | ||
h="250px" | ||
pr="40px" // Space for icon | ||
color="#596435" | ||
borderRadius="xl" | ||
/> | ||
<Box position="absolute" top="35px" right="15px" display="flex" alignItems="center"> | ||
<label htmlFor="file-upload" style={{ display: "flex", alignItems: "center", cursor: "pointer" }}> | ||
<IconButton | ||
icon={<AttachmentIcon />} | ||
bg="transparent" | ||
color="black" | ||
aria-label="Upload file" | ||
_hover={{ color: "black" }} | ||
as="label" | ||
htmlFor="file-upload" | ||
mr="-6px" | ||
/> | ||
<Text fontSize="sm" color="black"> | ||
{formData.attachment ? formData.attachment.name : "Add attachment"} | ||
</Text> | ||
</label> | ||
</Box> | ||
<Input type="file" id="file-upload" display="none" onChange={handleFileChange} /> | ||
</FormControl> | ||
<HStack spacing={5}> | ||
<Button px="30px" fontWeight="normal" rounded="full" bg="#596435" color="white" onClick={handleSubmit}> | ||
Send | ||
</Button> | ||
<Button | ||
borderWidth="1.5px" | ||
fontWeight="normal" | ||
rounded="full" | ||
variant="outline" | ||
bg="white" | ||
borderColor="#596435" | ||
color="#596435" | ||
> | ||
Cancel | ||
</Button> | ||
</HStack> | ||
</VStack> | ||
</Box> | ||
// </Box> | ||
); | ||
}; | ||
|
||
export default CreateAnnouncement; |
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,18 @@ | ||
import mongoose, { Schema } from "mongoose"; | ||
|
||
export type IAnnouncement = { | ||
_id: string; | ||
volunteers: string[]; | ||
sender: string; | ||
dateSent: Date; | ||
message: string; | ||
}; | ||
|
||
const AnnouncementSchema = new Schema<IAnnouncement>({ | ||
volunteers: { type: [String], required: true }, | ||
sender: { type: String, required: true }, | ||
dateSent: { type: Date, required: true }, | ||
message: { type: String, required: true }, | ||
}); | ||
|
||
export default mongoose.models.Announcement || mongoose.model<IAnnouncement>("Announcement", AnnouncementSchema); |