diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..3bb32f46
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,22 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/).
+
+## [1.0.0-alpha.1] - 2024-08-26
+
+### Added
+
+### Changed
+- Changed minimum character limit input field for adding new ideation https://github.com/chingu-x/chingu-dashboard/issues/171
+- Removed character count from password input https://github.com/chingu-x/chingu-dashboard/issues/173
+- Changed arrow direction of accordion in agenda section in sprints page https://github.com/chingu-x/chingu-dashboard/issues/187
+
+### Fixed
+- Fixed typo in placeholder text in new ideation form https://github.com/chingu-x/chingu-dashboard/issues/181
+- Fixed issue with saving meeting notes https://github.com/chingu-x/chingu-dashboard/issues/186
+- Fixed start meeting link https://github.com/chingu-x/chingu-dashboard/issues/188
+- Fixed display of date in error message in create meeting page when selecting a meeting time https://github.com/chingu-x/chingu-dashboard/issues/189
+- Fixed issue with weekly checkin widget displaying "due today" text in 1st week of voyage https://github.com/chingu-x/chingu-dashboard/issues/190
diff --git a/src/app/(main)/dashboard/components/Calendar/Calendar.test.tsx b/src/app/(main)/dashboard/components/Calendar/Calendar.test.tsx
new file mode 100644
index 00000000..f920887a
--- /dev/null
+++ b/src/app/(main)/dashboard/components/Calendar/Calendar.test.tsx
@@ -0,0 +1,27 @@
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import { configureStore } from "@reduxjs/toolkit";
+import { format } from "date-fns";
+import Calendar from "./Calendar";
+import { rootReducer } from "@/store/store";
+
+describe("Calendar Component", () => {
+ // not the best test. maybe refactor to e2e test later
+ it("displays the month and year on a single line", () => {
+ const store = configureStore({
+ reducer: rootReducer,
+ });
+
+ const { getByText } = render(
+
+
+ ,
+ );
+
+ const currentDate = new Date();
+ const formattedDate = format(currentDate, "MMMM y");
+ const monthYearElement = getByText(formattedDate);
+
+ expect(monthYearElement.closest("div")).toHaveClass("whitespace-nowrap");
+ });
+});
diff --git a/src/app/(main)/dashboard/components/Calendar/Calendar.tsx b/src/app/(main)/dashboard/components/Calendar/Calendar.tsx
index a6cbfaef..de2c5b63 100644
--- a/src/app/(main)/dashboard/components/Calendar/Calendar.tsx
+++ b/src/app/(main)/dashboard/components/Calendar/Calendar.tsx
@@ -50,7 +50,7 @@ export default function Calendar({
{/* CALENDAR */}
-
+
{/* CALENDAR CONTROLS */}
{
- const dayOfWeek = getDay(userDate);
+ const currentSprintEndDate = sprintsData.voyage.sprints.find(
+ (sprint) => sprint.number === currentSprintNumber,
+ )?.endDate;
- if (dayOfWeek >= 2 && dayOfWeek <= 6) {
- return "";
- } else if (dayOfWeek === 0) {
- return "Pending Submission";
- } else if (dayOfWeek === 1) {
- return "Due today";
+ if (currentSprintEndDate) {
+ const currentSprintEndDateInUserTimezone = convertStringToDate(
+ currentSprintEndDate,
+ timezone,
+ );
+
+ if (isSameDay(userDate, currentSprintEndDateInUserTimezone)) {
+ return "Due today";
+ } else if (
+ isSameDay(
+ userDate,
+ sub(currentSprintEndDateInUserTimezone, { days: 1 }),
+ )
+ ) {
+ return "Pending Submission";
+ }
}
return "";
diff --git a/src/app/(main)/my-voyage/[teamId]/ideation/components/IdeationForm.tsx b/src/app/(main)/my-voyage/[teamId]/ideation/components/IdeationForm.tsx
index cc2f2624..12e46f4c 100644
--- a/src/app/(main)/my-voyage/[teamId]/ideation/components/IdeationForm.tsx
+++ b/src/app/(main)/my-voyage/[teamId]/ideation/components/IdeationForm.tsx
@@ -28,7 +28,7 @@ const validationSchema = z.object({
title: validateTextInput({
inputName: "Title",
required: true,
- minLen: 10,
+ minLen: 3,
maxLen: 50,
}),
description: validateTextInput({
@@ -315,7 +315,7 @@ export default function IdeationForm() {
;
-interface NotesProps {
- data?: string;
-}
-
-export default function Notes({ data }: NotesProps) {
+export default function Notes() {
+ const [data, setData] = useState();
const dispatch = useAppDispatch();
const params = useParams<{
sprintNumber: string;
@@ -41,6 +38,14 @@ export default function Notes({ data }: NotesProps) {
Number(params.meetingId),
];
+ const {
+ voyage: { sprints },
+ } = useSprint();
+
+ useEffect(() => {
+ setData(sprints[sprintNumber - 1].teamMeetings[0].notes);
+ }, [sprints, sprintNumber]);
+
const {
register,
handleSubmit,
diff --git a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Planning.tsx b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Planning.tsx
index 75f602b8..9ab2fb24 100644
--- a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Planning.tsx
+++ b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Planning.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { z } from "zod";
import { type SubmitHandler, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -18,7 +18,7 @@ import {
editSection,
type EditSectionBody,
} from "@/myVoyage/sprints/sprintsService";
-import { useAppDispatch } from "@/store/hooks";
+import { useAppDispatch, useSprint } from "@/store/hooks";
import { onOpenModal } from "@/store/features/modal/modalSlice";
const validationSchema = z.object({
@@ -34,11 +34,8 @@ const validationSchema = z.object({
export type ValidationSchema = z.infer;
-interface PlanningProps {
- data?: Section;
-}
-
-export default function Planning({ data }: PlanningProps) {
+export default function Planning() {
+ const [data, setData] = useState();
const dispatch = useAppDispatch();
const params = useParams<{
sprintNumber: string;
@@ -50,6 +47,18 @@ export default function Planning({ data }: PlanningProps) {
Number(params.meetingId),
];
+ const {
+ voyage: { sprints },
+ } = useSprint();
+
+ useEffect(() => {
+ setData(
+ sprints[sprintNumber - 1].teamMeetings[0].formResponseMeeting?.find(
+ (form) => form.form.id === Number(Forms.planning),
+ ),
+ );
+ }, [sprints, sprintNumber]);
+
const goal = data?.responseGroup.responses.find(
(response) => response.question.id === Number(PlanningQuestions.goal),
)?.text;
diff --git a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Review.tsx b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Review.tsx
index ac4b0254..f6c4a709 100644
--- a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Review.tsx
+++ b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Review.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { z } from "zod";
import { type SubmitHandler, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -19,7 +19,7 @@ import {
editSection,
} from "@/myVoyage/sprints/sprintsService";
import { onOpenModal } from "@/store/features/modal/modalSlice";
-import { useAppDispatch } from "@/store/hooks";
+import { useAppDispatch, useSprint } from "@/store/hooks";
const validationSchema = z.object({
what_right: validateTextInput({
@@ -38,11 +38,8 @@ const validationSchema = z.object({
export type ValidationSchema = z.infer;
-interface ReviewProps {
- data?: Section;
-}
-
-export default function Review({ data }: ReviewProps) {
+export default function Review() {
+ const [data, setData] = useState();
const dispatch = useAppDispatch();
const params = useParams<{
sprintNumber: string;
@@ -54,6 +51,18 @@ export default function Review({ data }: ReviewProps) {
Number(params.meetingId),
];
+ const {
+ voyage: { sprints },
+ } = useSprint();
+
+ useEffect(() => {
+ setData(
+ sprints[sprintNumber - 1].teamMeetings[0].formResponseMeeting?.find(
+ (form) => form.form.id === Number(Forms.review),
+ ),
+ );
+ }, [sprints, sprintNumber]);
+
const what_right = data?.responseGroup.responses.find(
(response) => response.question.id === Number(ReviewQuestions.what_right),
)?.text;
diff --git a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/SectionBase.tsx b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/SectionBase.tsx
index 3d7b7a51..8518ccb0 100644
--- a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/SectionBase.tsx
+++ b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/SectionBase.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { AnimatePresence, type Variants, motion } from "framer-motion";
import {
ChevronDownIcon,
@@ -58,6 +58,10 @@ export default function SectionBase({
setIsLoading: setEditMeetingLoading,
} = useServerAction(editMeeting);
+ useEffect(() => {
+ if (isAdded) setIsOpen(true);
+ }, [isAdded]);
+
const handleAddSection = async () => {
if (id !== Number(Forms.notes)) {
const [res, error] = await addSectionAction({
@@ -174,10 +178,10 @@ export default function SectionBase({
aria-expanded={isOpen}
aria-controls={`accordion-panel-${title}`}
type="button"
- onClick={handleToggle}
+ onClick={() => handleToggle()}
aria-label={`close ${title} panel`}
>
-
+
)}
{isAdded && !isOpen && (
@@ -191,10 +195,10 @@ export default function SectionBase({
aria-expanded={isOpen}
aria-controls={`accordion-panel-${title}`}
type="button"
- onClick={handleToggle}
+ onClick={() => handleToggle()}
aria-label={`open ${title} panel`}
>
-
+
)}
diff --git a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Sections.tsx b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Sections.tsx
index 70f3d2f7..2a64b3e2 100644
--- a/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Sections.tsx
+++ b/src/app/(main)/my-voyage/[teamId]/sprints/components/sections/Sections.tsx
@@ -37,21 +37,21 @@ export default function Sections({
title: "notes",
icon: ,
isAdded: notes !== null,
- children: ,
+ children: ,
},
{
id: Forms.planning,
title: "sprint planning",
icon: ,
isAdded: planning !== undefined,
- children: ,
+ children: ,
},
{
id: Forms.review,
title: "retrospective & review",
icon: ,
isAdded: review !== undefined,
- children: ,
+ children: ,
},
];
diff --git a/src/components/inputs/TextInput.tsx b/src/components/inputs/TextInput.tsx
index 86d8b4ed..2ac47c45 100644
--- a/src/components/inputs/TextInput.tsx
+++ b/src/components/inputs/TextInput.tsx
@@ -57,7 +57,7 @@ const TextInput = React.forwardRef(
function handleOnChange(e: ChangeEvent) {
// Max length suggestion message
- if (maxLength) {
+ if (maxLength && e.target.type !== "password") {
const currentLength = e.target.value.length;
if (currentLength > 0) {
setCurrentSuggestion(
diff --git a/src/store/store.ts b/src/store/store.ts
index 85aefece..e3cdd6ee 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -34,7 +34,8 @@ const persistConfig = {
whitelist: ["ideation", "sprint"],
};
-const rootReducer = combineReducers({
+// Root reducer should be used as import directly only for tests
+export const rootReducer = combineReducers({
modal: modalReducer,
auth: authReducer,
user: userReducer,
diff --git a/src/stories/components/Modal.stories.tsx b/src/stories/components/Modal.stories.tsx
index c09467b6..5ad97ba9 100644
--- a/src/stories/components/Modal.stories.tsx
+++ b/src/stories/components/Modal.stories.tsx
@@ -128,7 +128,7 @@ export const WithFormInsideWithVerticalScroll: Story = {
({
message: `The meeting should be between ${format(
minDate,
- "MMM d k:mm (zzz)",
+ "MMM d H:mm (zzz)",
{
timeZone: timezone,
},
- )} and ${format(maxDate, "MMM d k:mm (zzz)", {
+ )} and ${format(maxDate, "MMM d H:mm (zzz)", {
timeZone: timezone,
})}`,
}),