Skip to content

feat: implemented teacher profile button and popup#58

Merged
ChinemeremChigbo merged 4 commits intomainfrom
daniel/teacher-pop-up
Mar 3, 2025
Merged

feat: implemented teacher profile button and popup#58
ChinemeremChigbo merged 4 commits intomainfrom
daniel/teacher-pop-up

Conversation

@daniel-su1
Copy link
Contributor

@daniel-su1 daniel-su1 commented Feb 5, 2025

Notion ticket link

Teacher Profile Popup Frontend

Implementation description

-implemented teacher popup on the right side of CalendarHeader, created ProfileMenu component

Steps to test

  1. go to main calendar page and click on it, it should be there 💀

What should reviewers focus on?

Checklist

  • My PR name is descriptive and in imperative tense
  • My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits
  • I have run the appropriate linter(s)
  • I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR

@vercel
Copy link

vercel bot commented Feb 5, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
sistema ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 3, 2025 9:50am

@daniel-su1 daniel-su1 requested review from a team, 135ze and ChinemeremChigbo February 5, 2025 01:24
@ChinemeremChigbo ChinemeremChigbo requested review from a team and removed request for a team February 5, 2025 01:27
Copy link
Member

@ChinemeremChigbo ChinemeremChigbo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have listed some suggested changed. I also think you should remove the profile.tsx file. I have made a PR that implements the changes I would like here: . If you agree, please squash these changes into your branch and re-request a review

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The month text should be left aligned and I would remove unnecessary comments:

import React from 'react';
import {
  Menu,
  MenuButton,
  IconButton,
  MenuList,
  Text,
  Avatar,
  Button,
  useColorModeValue,
} from '@chakra-ui/react';
import { signOut } from 'next-auth/react';

// Helper to color-code the "X/Y Absences Taken"
function getAbsenceColor(usedAbsences: number) {
  if (usedAbsences <= 6) return 'green.500';
  if (usedAbsences <= 8) return 'yellow.500';
  return 'red.500';
}

// Same interface as used in CalendarHeader, or define your own
interface UserData {
  name: string;
  email: string;
  image?: string;
  usedAbsences: number;
  numOfAbsences: number;
}

interface ProfileMenuProps {
  userData?: UserData;
}

const ProfileMenu: React.FC<ProfileMenuProps> = ({ userData }) => {
  const absenceColor = userData
    ? getAbsenceColor(userData.usedAbsences)
    : 'gray.500';

  return (
    <Menu>
      <MenuButton
        as={IconButton}
        icon={
          <Avatar
            name={userData?.name ?? 'User'}
            src={userData?.image}
            size="sm"
          />
        }
        variant="ghost"
        aria-label="Open profile menu"
        _hover={{ bg: useColorModeValue('gray.100', 'gray.700') }}
      />
      <MenuList
        minW="280px" // Make the pop-up larger
        p="2rem" // Add some padding
        textAlign="center"
        boxShadow="lg"
        borderRadius="md"
      >
        {/* Title: "Hi, [Name]!" in 2xl */}
        <Text fontSize="2xl" fontWeight="semibold" mb={1}>
          Hi, {userData?.name}!
        </Text>
        {/* Email below the title */}
        <Text fontSize="sm" color="gray.500" mb={3}>
          {userData?.email}
        </Text>
        {/* Larger avatar below the email */}
        <Avatar
          name={userData?.name ?? 'User'}
          src={userData?.image}
          size="xl"
          mx="auto"
          mb={3}
        />
        {/* Absences Taken: e.g. "4/10" in color */}
        <Text fontSize="md" mb={4}>
          <Text as="span" fontWeight="bold" color={absenceColor}>
            {userData?.usedAbsences}/{userData?.numOfAbsences}
          </Text>{' '}
          Absences Taken
        </Text>
        {/* Log Out button: white background, gray border */}
        <Button
          onClick={() => signOut()}
          variant="outline"
          borderColor="gray.300"
          borderRadius="md"
          size="md"
          width="100%"
          _hover={{ bg: useColorModeValue('gray.100', 'gray.700') }}
        >
          Log Out
        </Button>
      </MenuList>
    </Menu>
  );
};

export default ProfileMenu;

import { signOut } from 'next-auth/react';

// Helper to color-code the "X/Y Absences Taken"
function getAbsenceColor(usedAbsences: number) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use const instead of function

icon={
<Avatar
name={userData?.name ?? 'User'}
src={userData?.image}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, not sure why but sometimes I need to navigate to the /profile page, and then navigate back to the calendar to get the image to show up. I assume it works on the profile page since it uses a use effect to make sure the data is available whereas this does not? Not quite sure, but would be nice if the image / other data was useeffected for this component.
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be:
image

`/api/users/email/${session.user.email}?shouldIncludeAbsences=true`
);
const data = await res.json();
// data.numOfAbsences plus data.absences?.length is the usage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove comments for things that feel obvious and make some changes to the spacing. Here are some of my suggestions:

import React from 'react';
import {
  Menu,
  MenuButton,
  IconButton,
  MenuList,
  Text,
  Avatar,
  Button,
  useColorModeValue,
} from '@chakra-ui/react';
import { signOut } from 'next-auth/react';

const getAbsenceColor = (usedAbsences: number) => {
  if (usedAbsences <= 6) return 'green.500';
  if (usedAbsences <= 8) return 'yellow.500';
  return 'red.500';
};

interface UserData {
  name: string;
  email: string;
  image?: string;
  usedAbsences: number;
  numOfAbsences: number;
}

interface ProfileMenuProps {
  userData?: UserData;
}

const ProfileMenu: React.FC<ProfileMenuProps> = ({ userData }) => {
  const absenceColor = userData
    ? getAbsenceColor(userData.usedAbsences)
    : 'gray.500';

  return (
    <Menu>
      <MenuButton
        as={IconButton}
        icon={
          <Avatar
            name={userData?.name ?? 'User'}
            src={userData?.image}
            size="sm"
          />
        }
        variant="ghost"
        aria-label="Open profile menu"
        _hover={{ bg: useColorModeValue('gray.100', 'gray.700') }}
      />
      <MenuList
        minW="280px"
        maxW="320px"
        p="3rem"
        textAlign="center"
        boxShadow="lg"
        borderRadius="md"
      >
        <Text
          fontSize="2xl"
          fontWeight="semibold"
          mb={2}
          whiteSpace="normal"
          wordBreak="break-word"
        >
          Hi, {userData?.name}!
        </Text>
        <Text fontSize="sm" color="gray.500" mb={4}>
          {userData?.email}
        </Text>
        <Avatar
          name={userData?.name ?? 'User'}
          src={userData?.image}
          size="xl"
          mx="auto"
          mb={4}
        />
        <Text fontSize="md" mb={5}>
          <Text as="span" fontWeight="bold" color={absenceColor}>
            {userData?.usedAbsences}/{userData?.numOfAbsences}
          </Text>{' '}
          Absences Taken
        </Text>
        <Button
          onClick={() => signOut()}
          variant="outline"
          borderColor="gray.300"
          borderRadius="md"
          size="md"
          width="100%"
          _hover={{ bg: useColorModeValue('gray.100', 'gray.700') }}
        >
          Log Out
        </Button>
      </MenuList>
    </Menu>
  );
};

export default ProfileMenu;

} from '@chakra-ui/icons';
import ProfileMenu from './ProfileMenu';

// Example interface for userData; adjust fields as needed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: interfaces may be moved to a types.ts file to be shared globally. mentioning just in case my PR gets merged before yours

https://github.com/uwblueprint/sistema/pull/49/files#diff-11e9171ff36dfa6e6b396909ac6b924cf79337d5f05a7eaa15f78a9b2e2eded6

@135ze 135ze mentioned this pull request Feb 15, 2025
4 tasks
} from '@chakra-ui/icons';
import ProfileMenu from './ProfileMenu';

interface UserData {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry lol looks like I was merged in first, please import from latest in main: d3663c8 for this file and ProfileMenu.tsx

@ChinemeremChigbo ChinemeremChigbo merged commit 0009708 into main Mar 3, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants