Skip to content

Commit

Permalink
Merge pull request #230 from wizelineacademy/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
pedroalonsoms authored Jun 14, 2024
2 parents b0d7096 + 27736f3 commit 0680557
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 30 deletions.
36 changes: 27 additions & 9 deletions app/(base)/pcp/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import ArticleIcon from "@/components/icons/ArticleIcon";
import Link from "next/link";
import ChevronRightIcon from "@/components/icons/ChevronRightIcon";
import Loader from "@/components/Loader";
import toast from "react-hot-toast";
import { RulerTask, RulerResource } from "@/types/types";

const statusOptions = [
Expand Down Expand Up @@ -258,6 +259,7 @@ const PCPTasks = ({
queryClient.invalidateQueries({
queryKey: ["tasks-history", projectId],
});
toast.success("Task status updated successfully");

const tasks = queryClient.getQueryData<SelectPipTask[]>([
"tasks",
Expand All @@ -269,6 +271,9 @@ const PCPTasks = ({
setProgressPercentage((doneTasks / totalTasks) * 100);
}
},
onError: () => {
toast.error("Error updating task status");
},
});

return (
Expand All @@ -277,6 +282,7 @@ const PCPTasks = ({
<div className="mx-auto flex justify-between">
<h3 className="text-3xl font-medium text-black">Tasks</h3>
<button
data-testid="show-task-history"
className="cursor-pointer self-center text-sm text-graySubtitle"
onClick={openDialog}
>
Expand Down Expand Up @@ -330,6 +336,17 @@ const PCPTasksDialogContent = ({ projectId }: { projectId: number }) => {

const { mutateAsync } = useMutation({
mutationFn: updateTask,
onSuccess: () => {
console.log("success");
queryClient.invalidateQueries({ queryKey: ["tasks", projectId] });
queryClient.invalidateQueries({
queryKey: ["tasks-history", projectId],
});
toast.success("Task status updated successfully");
},
onError: () => {
toast.error("Error updating task status");
},
});

if (tasksHistoryQuery.data && typeof tasksHistoryQuery.data === "string") {
Expand All @@ -349,7 +366,7 @@ const PCPTasksDialogContent = ({ projectId }: { projectId: number }) => {
};

return (
<div>
<div data-testid="pcp-task-history">
{tasksHistoryQuery.data.map((sprint) => (
<div key={sprint.id}>
{sprint.scheduledAt && (
Expand Down Expand Up @@ -386,6 +403,7 @@ const PCPTasksDialogContent = ({ projectId }: { projectId: number }) => {
<Menu as="div" className="relative inline-block text-left">
<div className="flex items-center">
<Menu.Button
data-testid={``}
className={`h-6 w-6 transform cursor-pointer rounded-full border ${currentStatusOption.color} outline-${currentStatusOption.color} transition-all duration-200 ease-in-out hover:scale-110`}
>
<span className="sr-only">Change status</span>
Expand All @@ -406,12 +424,6 @@ const PCPTasksDialogContent = ({ projectId }: { projectId: number }) => {
newStatus:
option.value as typeof task.status,
});
await queryClient.invalidateQueries({
queryKey: ["tasks", projectId],
});
await queryClient.invalidateQueries({
queryKey: ["tasks-history", projectId],
});
}}
>
<span
Expand Down Expand Up @@ -465,17 +477,22 @@ const PCPTask = ({
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button
data-testid="task-status-button"
className={`h-6 w-6 transform cursor-pointer rounded-full border ${selectedStatus.color} outline-${selectedStatus.color} transition-all duration-200 ease-in-out hover:scale-110`}
>
<span className="sr-only">Change status</span>
</Menu.Button>
</div>
<Menu.Items className="absolute right-0 mt-2 w-44 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<Menu.Items
data-testid="task-status-options"
className="absolute right-0 mt-2 w-44 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div className="py-1">
{statusOptions.map((option) => (
<Menu.Item key={option.value}>
{({ active }) => (
<button
data-testid={option.value}
className={`${
active ? "bg-gray-100" : ""
} group flex w-full items-center px-4 py-2 text-sm text-gray-700`}
Expand Down Expand Up @@ -607,6 +624,7 @@ const PCPResource = ({ resource }: { resource: SelectPipResource }) => {
</p>
<button className="mx-auto w-fit rounded-full bg-primary px-7 py-1 text-xs font-medium text-white">
<Link
data-testid="resource-link"
target="_blank"
href={`https://www.google.com/search?q=${resource.title}`}
>
Expand Down Expand Up @@ -645,7 +663,7 @@ const PCPResourcesDialogContent = ({ projectId }: { projectId: number }) => {
};

return (
<div>
<div data-testid="pcp-resource-history">
{resourcesHistoryQuery.data.map((sprint) => (
<div key={sprint.id}>
{sprint.scheduledAt && (
Expand Down
9 changes: 8 additions & 1 deletion app/(base)/projects/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from "@mantine/core";
import { Employee } from "@/types/types";
import toast from "react-hot-toast";
import Loader from "@/components/Loader";

const CreateProject = () => {
const router = useRouter();
Expand Down Expand Up @@ -146,11 +147,17 @@ const CreateProject = () => {
);
};

if (employeesQuery.isLoading) return <div>Loading...</div>;
if (employeesQuery.isLoading)
return (
<div className="flex h-[80dvh] w-full">
<Loader />
</div>
);
if (employeesQuery.isError) return <div>Error loading employees.</div>;

return (
<>
{isLoading && <p>Creando proyecto</p>}
<div className="mx-28 my-6">
<h3 className="text-4xl font-medium">Project Creation</h3>
<form action={handleForm} className="mt-4">
Expand Down
20 changes: 20 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,23 @@
.emotion-box:has(.emotion-circle:hover) .emotion-circle:not(:hover) {
transform: scale(0.9);
}

.loader {
width: 25px;
height: 25px;
border: 3px solid #bdbdbd;
border-bottom-color: #6640d5;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}

@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
5 changes: 3 additions & 2 deletions components/ComboBoxSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useQuery } from "@tanstack/react-query";
import { searchUsers } from "@/services/user";
import SearchBar from "./SearchBar";
import UserProfileButton from "./UserProfileButton";
import Spinner from "./Spinner";

interface Person {
id: number;
Expand Down Expand Up @@ -60,8 +61,8 @@ const ComboBoxSearch = () => {
className="absolute z-10 mt-1 max-h-52 w-full overflow-auto rounded-md border border-gray-300 bg-white p-2 shadow-lg empty:hidden"
>
{isLoading ? (
<div className="relative cursor-default select-none px-4 py-2 text-gray-700">
Loading...
<div className="flex w-full py-2">
<Spinner />
</div>
) : people.length === 0 && query !== "" ? (
<div className="relative cursor-default select-none px-4 py-2 text-gray-700">
Expand Down
2 changes: 1 addition & 1 deletion components/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default async function ProjectCard({
<Link
data-testid={`project-${id}-link`}
href={`/projects/${id}`}
className="flex h-9 w-9 items-center justify-center rounded-full bg-primary"
className="flex h-9 w-9 items-center justify-center rounded-full bg-primary hover:bg-primary-dark"
>
<ChevronRightIcon size="h-6 w-6" color="white" />
</Link>
Expand Down
5 changes: 5 additions & 0 deletions components/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Spinner = () => {
return <span className="loader mx-auto" />;
};

export default Spinner;
1 change: 1 addition & 0 deletions components/modals/DraggableUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const DraggableUser = ({ user, times = 0 }: DraggableUserProps) => {
<Draggable
id={`base-${user.userId}`}
data={user}
data-testid="draggable-user"
setIsDragging={setIsDragging}
>
{isDragging ? (
Expand Down
1 change: 1 addition & 0 deletions components/modals/SprintDropRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const SprintDropRow = ({
</div>
{colors.map((color, index) => (
<SprintDropRowBox
data-testid={`droppable-box-${index}`}
key={index}
index={index}
color={color}
Expand Down
5 changes: 3 additions & 2 deletions components/modals/SprintSurvey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ const SprintSurvey = ({
onSuccess: () => {
router.refresh();
queryClient.invalidateQueries({ queryKey: ["notifications"] });
toast.success("Encuesta enviada exitosamente!");
toast.success("Survey submitted!");
},
onError: () => {
toast.error("Error al enviar la encuesta");
toast.error("Error submitting the survey.");
},
});

Expand Down Expand Up @@ -210,6 +210,7 @@ const SprintSurvey = ({
leaveTo="opacity-0"
>
<Dialog.Panel
data-testid="sprint-survey"
className={`sprint-survey flex h-auto transform flex-col rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all duration-500 ${modalWidth}`}
>
<Dialog.Title
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/login.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe("Login", () => {
cy.get("label").contains("Email").click().type("[email protected]");
cy.get("label").contains("Password").click().type("cypress");
cy.get("button").contains("Log in").click();
cy.wait(4000);
cy.wait(12000);
cy.url().should("include", "/dashboard");
});
it("Visits page not being signed in, and gets redirected to login", () => {
Expand Down
12 changes: 12 additions & 0 deletions cypress/e2e/pcp.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
describe("PCP", () => {
beforeEach(() => {
cy.visit("/");
cy.get("label").contains("Email").click().type("[email protected]");
cy.get("label").contains("Password").click().type("cypress");
cy.get("button").contains("Log in").click();
cy.wait(12000);
cy.url().should("include", "/dashboard");
cy.visit("/pcp");
cy.wait(8000);
});
});
8 changes: 3 additions & 5 deletions cypress/e2e/rulerSurvey.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const randomEmotion = {
describe("Testing different surveys", () => {
beforeEach(() => {
cy.visit("/");
cy.get("label").contains("Email").click().type("cypress@gmail.com");
cy.get("label").contains("Email").click().type("cypress@outlook.com");
cy.get("label").contains("Password").click().type("cypress");
cy.get("button").contains("Log in").click();
cy.wait(3000);
cy.wait(8000);
cy.url().should("include", "/dashboard");
cy.get('[data-testid="notification-button"]').click();
cy.get('[data-testid="Daily Ruler Survey"]').click();
Expand Down Expand Up @@ -57,8 +57,6 @@ describe("Testing different surveys", () => {
).click();
cy.get('[data-testid="ruler-step-two"]').should("exist");
cy.get("textarea").type("This is a test comment");
cy.get("button").contains("Submit").click();
cy.get('[data-testid="ruler-survey"]').should("not.exist");
cy.get("div").contains("Encuesta enviada exitosamente!").should("exist");
cy.get("textarea").invoke("val").should("eq", "This is a test comment");
});
});
9 changes: 5 additions & 4 deletions cypress/e2e/signin.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ describe("Register", () => {
});

it("Visits Register page, and signs up", () => {
cy.task("deleteDummyUser", { email: "cypress@gmail.com" });
cy.get("label").contains("Name").click().type("Cypress prueba");
cy.get("label").contains("Email").click().type("cypress@gmail.com");
cy.task("deleteDummyUser", { email: "cypress2@gmail.com" });
cy.get("label").contains("Name").click().type("prueba");
cy.get("label").contains("Email").click().type("cypress2@gmail.com");
cy.get("label").contains("Password").click().type("cypress");
cy.get("label").contains("Job Title").click().type("Cypress");
cy.get("label").contains("Department").click().type("QA");
cy.get("button").contains("Register").click();
cy.get("div").contains("Account created successfully.").should("exist");
cy.wait(3000);
cy.wait(8000);
cy.url().should("include", "/dashboard");
cy.visit("/profile");
cy.wait(8000);
cy.get("h2").contains("Cypress prueba");
});

Expand Down
13 changes: 13 additions & 0 deletions cypress/e2e/sprintSurvey.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe("Sprint Survey", () => {
beforeEach(() => {
cy.visit("/");
cy.get("label").contains("Email").click().type("[email protected]");
cy.get("label").contains("Password").click().type("cypress");
cy.get("button").contains("Log in").click();
cy.wait(12000);
cy.url().should("include", "/dashboard");
cy.get('[data-testid="notification-button"]').click();
cy.get('[data-testid="Sprint Survey"]').click();
cy.get('[data-testid="sprint-survey"]').should("exist");
});
});
4 changes: 1 addition & 3 deletions services/tasks-and-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ export async function getUserTasksForCurrentSprintByProjectId(
// check if the sprint is not processed to throw an error
// check if there's no sprint survey results throw an error
// check if all the surveys were answered, so the only one left is the project one

if (!currentSprintSurvey.processed) {
return "Curreny sprint survey was found, but it is not processed yet";
return "Current sprint survey was found, but it is not processed yet";
}

const tasks = await db
Expand All @@ -63,7 +62,6 @@ export async function getUserTasksForCurrentSprintByProjectId(
),
)
.orderBy(asc(pipTask.title));

if (tasks.length === 0) {
return "No tasks available. Ask your manager for an update.";
}
Expand Down
16 changes: 14 additions & 2 deletions services/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,21 @@ export async function getUserSkillsById(id: string) {
and(eq(userSkill.userId, id), eq(userSkill.kind, "AREA_OF_OPPORTUNITY")),
);

const strengthsSet = strengths.filter((s) => {
const set = new Set();
if (set.has(s.name)) return false;
set.add(s.name);
return true;
});
const areasOppSet = areasOfOportunity.filter((s) => {
const set = new Set();
if (set.has(s.name)) return false;
set.add(s.name);
return true;
});
const traits = {
strengths: strengths,
areasOfOportunity: areasOfOportunity,
strengths: strengthsSet,
areasOfOportunity: areasOppSet,
};
return traits;
}
Expand Down

0 comments on commit 0680557

Please sign in to comment.