Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

002 sep 20 vendor view design #20

Conversation

MuhammadKhalilzadeh
Copy link
Collaborator

@MuhammadKhalilzadeh MuhammadKhalilzadeh commented Sep 24, 2024

Tasks:

  • Show vendors list
  • Add a new vendor
  • Edit a vendor
  • Remove a vendor

Screenshot 2024-09-24 115643

Screenshot 2024-09-24 115630

Screenshot 2024-09-24 115621

Screenshot 2024-09-24 115612

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new components: IconButton, DatePicker, BasicModal, AddNewVendor, and TableWithPlaceholder.
    • Added vendor management interface in the Vendors component, including a modal for adding new vendors.
    • Integrated new date picker functionality and interactive buttons with contextual menus.
  • Improvements

    • Enhanced styling for components, including a new CSS file for the Date Picker and updated dashboard background color.
    • Added new dependencies for improved UI components and date management.
  • Bug Fixes

    • Updated type safety for paginated and reversed properties in the BasicTable component.

@MuhammadKhalilzadeh MuhammadKhalilzadeh added the frontend Frontend related tasks/issues label Sep 24, 2024
@MuhammadKhalilzadeh MuhammadKhalilzadeh self-assigned this Sep 24, 2024
Copy link

coderabbitai bot commented Sep 24, 2024

Walkthrough

The pull request introduces new components and updates existing ones to enhance vendor management functionality within the application. Key changes include the addition of modal components for adding and confirming the deletion of vendors, a date picker, and an icon button with a contextual menu. The package.json file has been updated to include new Material-UI libraries. Additionally, type safety has been improved in the BasicTable component, and a structured list of vendor data has been added for better data management.

Changes

File Path Change Summary
Clients/package.json Updated dependencies: @mui/material from ^6.1.0 to ^6.1.1, added @mui/lab (^6.0.0-beta.10), @mui/x-date-pickers (^7.18.0), and dayjs (^1.11.13).
Clients/src/presentation/components/IconButton/index.tsx Added new component IconButton with a menu for user actions.
Clients/src/presentation/components/Inputs/Datepicker/index.css Introduced CSS for the MUI Date Picker component, defining styles for height, padding, and font size.
Clients/src/presentation/components/Inputs/Datepicker/index.tsx Added new component DatePicker utilizing Material-UI's date picker functionality with customizable props.
Clients/src/presentation/components/Inputs/Field/index.tsx Updated FieldProps interface to include optional width property.
Clients/src/presentation/components/Modals/Basic/index.tsx Added new component BasicModal for vendor deletion confirmation.
Clients/src/presentation/components/Modals/NewVendor/index.tsx Added new component AddNewVendor for adding vendor information with tabbed interface.
Clients/src/presentation/components/Table/WithPlaceholder/index.tsx Introduced new component TableWithPlaceholder for displaying vendors with a placeholder image.
Clients/src/presentation/components/Table/index.tsx Updated paginated and reversed properties in BasicTable to enforce boolean type.
Clients/src/presentation/containers/Dashboard/index.tsx Modified Dashboard component to include a sx prop for styling.
Clients/src/presentation/mocks/vendors.data.ts Added new file containing structured vendor data.
Clients/src/presentation/pages/Vendors/index.tsx Expanded Vendors component to manage vendors with modals and tables, integrating new UI elements.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant VendorsPage
    participant AddNewVendorModal
    participant BasicModal

    User->>VendorsPage: Open Vendors Page
    VendorsPage->>User: Display Vendors List
    User->>VendorsPage: Click "Add New Vendor"
    VendorsPage->>AddNewVendorModal: Open Modal
    AddNewVendorModal->>User: Display Vendor Form
    User->>AddNewVendorModal: Fill Form and Click "Save"
    AddNewVendorModal->>VendorsPage: Close Modal
    VendorsPage->>User: Refresh Vendors List
    User->>VendorsPage: Click "Delete Vendor"
    VendorsPage->>BasicModal: Open Confirmation Modal
    BasicModal->>User: Confirm Deletion
Loading

Poem

🐰 In the garden where vendors bloom,
A modal opens, dispelling gloom.
With buttons and pickers, oh what a sight,
New features hop in, bringing delight!
So gather 'round, let’s celebrate,
With code so fresh, it’s truly great! 🌼


Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between ab0fca1 and 769d543.

Files selected for processing (1)
  • Clients/src/presentation/components/Table/index.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • Clients/src/presentation/components/Table/index.tsx

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    -- I pushed a fix in commit <commit_id>, please review it.
    -- Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 26

Outside diff range and nitpick comments (18)
Clients/src/presentation/components/Inputs/Datepicker/index.css (5)

1-3: Consider using relative units for better responsiveness.

The fixed height of 34px ensures consistency, which is good. However, using relative units like em or rem instead of pixels could improve responsiveness across different screen sizes and font settings.

Consider updating the height to use relative units:

.mui-date-picker {
-  height: 34px;
+  height: 2.125rem; /* Equivalent to 34px at default font size */
}

5-7: Maintain consistency with the parent element's units.

The fixed height matches the parent element, which is good for consistency. However, to improve maintainability and ensure the input base always matches the parent, consider using inherited values or relative units.

Consider updating the height to use inherited or relative units:

.mui-date-picker .MuiInputBase-root {
-  height: 34px;
+  height: inherit; /* Or use 100% */
}

9-12: Use relative units for better accessibility and responsiveness.

The padding and font size improve the input's usability and readability. However, using relative units instead of pixels would enhance accessibility and responsiveness.

Consider updating the CSS to use relative units:

.mui-date-picker .MuiInputBase-root input {
-  padding: 5px;
-  font-size: 13px;
+  padding: 0.3125rem; /* Equivalent to 5px at default font size */
+  font-size: 0.8125rem; /* Equivalent to 13px at default font size */
}

14-16: Use relative units for font size to improve accessibility.

The consistent font size between the label and input is good for visual harmony. However, using relative units instead of pixels for font size would enhance accessibility and responsiveness.

Consider updating the font size to use relative units:

.mui-date-picker > .MuiFormLabel-root {
-  font-size: 13px;
+  font-size: 0.8125rem; /* Equivalent to 13px at default font size */
}

1-16: Overall, good styling for the date picker component with room for improvement.

The CSS file provides a clear and consistent styling for the MUI Date Picker component. The styles define appropriate heights, paddings, and font sizes for various elements of the date picker, which should result in a visually appealing and functional component.

However, the main area for improvement is the use of fixed pixel values throughout the stylesheet. To enhance the component's responsiveness and accessibility:

  1. Consider using relative units (like rem or em) instead of pixels for all measurements.
  2. For heights, you might want to use inherit or percentage values to maintain consistency with parent elements.

These changes would make the date picker more flexible and adaptable to different screen sizes, font settings, and user preferences, aligning better with responsive design principles and accessibility guidelines.

Clients/src/presentation/containers/Dashboard/index.tsx (1)

8-13: LGTM! Consider extracting the style object for improved readability.

The addition of the sx prop to set the background color is a good enhancement to the Stack component's styling. This change aligns well with the PR objectives of improving the vendor management interface.

For improved readability and maintainability, consider extracting the style object into a separate constant. This approach can make the component more readable, especially if more styles are added in the future. Here's a suggested refactor:

 import { Stack } from "@mui/material";
 import "./index.css";
 import Sidebar from "../../components/Sidebar";
 import { Outlet } from "react-router";
 
+const dashboardStyles = {
+  backgroundColor: "#FCFCFD"
+};
+
 const Dashboard = () => {
   return (
     <Stack
       className="home-layout"
       flexDirection="row"
       gap={14}
-      sx={{ backgroundColor: "#FCFCFD" }}
+      sx={dashboardStyles}
     >
       <Sidebar />
       <Outlet />
     </Stack>
   );
 };

This change is optional and up to your team's coding standards and preferences.

Clients/src/presentation/mocks/vendors.data.ts (1)

60-60: Consider using named exports for better module usage.

The current default export is correct, but named exports are often preferred in TypeScript/JavaScript projects. They provide better refactoring support and make it clearer what's being imported.

Consider changing the export to:

export { listOfVendors };

This allows for more flexible importing and potentially easier refactoring in the future.

Overall, the structure of this mock data file is good and serves its purpose well for the vendor management interface. With the suggested improvements, it will be even more robust and maintainable.

Clients/package.json (1)

17-23: Summary of dependency changes

The updates to the package.json file indicate a focus on enhancing the UI components and introducing date/time functionality, which aligns well with the PR objectives for improving the vendor management interface. Here's a summary of the changes:

  1. Added @mui/lab (beta version) for experimental components
  2. Updated @mui/material to the latest minor version
  3. Added @mui/x-date-pickers for date/time selection functionality
  4. Added dayjs for efficient date manipulation

These changes should provide the necessary tools to implement the desired UI enhancements. However, please ensure that the use of the beta version of @mui/lab is necessary and that the team is aware of potential risks associated with using experimental components.

Consider documenting the decision to use these specific libraries and versions in the project documentation or README file. This will help future developers understand the rationale behind these choices and be aware of any potential limitations or considerations.

Clients/src/presentation/components/Inputs/Datepicker/index.tsx (1)

1-81: Overall assessment: Good foundation with room for improvement.

The DatePicker component provides a solid foundation for date input in the vendor management interface, aligning well with the PR objectives. It leverages MUI components and theming effectively. However, there are opportunities for improvement:

  1. Simplify and extract complex styling logic.
  2. Refactor label rendering for better readability.
  3. Fully utilize component props in the MuiDatePicker.
  4. Verify the necessity of the external CSS file.

Addressing these points will enhance the component's maintainability and functionality.

Clients/src/presentation/components/Modals/Basic/index.tsx (2)

22-24: LGTM: Component definition is well-structured. Consider adding prop validation.

The component definition follows React best practices, and the use of useTheme ensures consistent styling.

Consider adding prop-types for runtime type checking:

import PropTypes from 'prop-types';

// ... (after the component definition)

BasicModal.propTypes = {
  isOpen: PropTypes.bool.isRequired,
  setIsOpen: PropTypes.func.isRequired,
};

25-56: LGTM: Modal content and styling are well-implemented. Consider improving accessibility.

The layout and styling are consistent with Material-UI guidelines, and the warning message clearly communicates the consequences of the action. The use of theme spacing and colors ensures consistency with the app's design.

Consider improving accessibility by adding an aria-labelledby attribute to the Modal:

- <Modal open={isOpen} onClose={setIsOpen}>
+ <Modal open={isOpen} onClose={setIsOpen} aria-labelledby="modal-delete-vendor">

This change will associate the modal with its title for screen readers.

Clients/src/presentation/components/Table/WithPlaceholder/index.tsx (2)

17-30: Approve state management with a suggestion for type safety.

The state management and handler functions are well-implemented. The use of useState for managing the modal state and tab value is appropriate.

For improved type safety, consider adding a type annotation for the data prop:

interface Vendor {
  // Define the structure of a vendor object
}

function TableWithPlaceholder({ data = listOfVendors }: { data?: Vendor[] }) {
  // Rest of the component
}

This will ensure that the data prop is correctly typed throughout the component.


112-122: Approve AddNewVendor implementation with a suggestion for prop types.

The implementation of the AddNewVendor modal and the component export are correct and follow best practices.

For improved type safety and code clarity, consider defining prop types for the AddNewVendor component:

interface AddNewVendorProps {
  isOpen: boolean;
  handleChange: (event: React.SyntheticEvent, newValue: string) => void;
  setIsOpen: (isOpen: boolean) => void;
  value: string;
}

<AddNewVendor
  isOpen={isOpen}
  handleChange={handleChange}
  setIsOpen={() => setIsOpen(false)}
  value={value}
/>

This will make the component's API more explicit and help catch potential type-related errors earlier in the development process.

Clients/src/presentation/pages/Vendors/index.tsx (1)

1-152: Consider overall component structure and performance optimizations.

The component structure is generally good, but there are a few areas for improvement:

  1. Functionality: Several key functions (back navigation, project selection, saving) are not fully implemented. Ensure all features are completed before merging.

  2. Performance: Consider moving inline function definitions out of the render method to prevent unnecessary re-renders. For example:

const handleBackClick = useCallback(() => {
  // Back navigation logic
}, []);

const handleProjectChange = useCallback((event) => {
  setValue(event.target.value);
  // Additional logic
}, []);

const handleSave = useCallback(() => {
  // Save logic
}, [/* dependencies */]);

// Use these in your JSX
onClick={handleBackClick}
onChange={handleProjectChange}
onClick={handleSave}
  1. Error Handling: Implement proper error handling for asynchronous operations (e.g., fetching vendors, saving changes).

  2. Loading States: Consider adding loading states for asynchronous operations to improve user experience.

  3. Accessibility: Ensure all interactive elements have proper aria labels and that the component follows accessibility best practices.

Addressing these points will significantly improve the component's functionality, performance, and user experience.

Clients/src/presentation/components/Table/index.tsx (2)

Line range hint 18-26: Consider improving type safety for TableData interface

The TableData interface uses any[] for both cols and rows. Consider defining more specific types for these arrays to improve type safety and code readability. For example:

interface TableColumn {
  id: number;
  name: string;
}

interface TableCell {
  id: number;
  data: JSX.Element;
}

interface TableRow {
  id: number;
  data: TableCell[];
  handleClick?: () => void;
}

interface TableData {
  cols: TableColumn[];
  rows: TableRow[];
}

This change would provide better type checking and autocompletion throughout the component.


Line range hint 86-90: Consider memoizing displayData calculation for performance

The displayData calculation is performed on every render. For large datasets, this could impact performance. Consider memoizing this calculation using useMemo to optimize performance:

const displayData = useMemo(() => {
  if (data && data.rows) {
    let rows = reversed ? [...data.rows].reverse() : data.rows;
    return paginated
      ? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
      : rows;
  }
  return [];
}, [data, reversed, paginated, page, rowsPerPage]);

This change ensures that the calculation is only performed when its dependencies change.

Clients/src/presentation/components/Inputs/Field/index.tsx (2)

55-55: LGTM! Consider adding JSDoc for the new width prop.

The addition of the width prop enhances the component's flexibility. It's a good practice to allow both number and string types for width.

Consider adding JSDoc for the new width prop to maintain consistency with other props and improve documentation:

/**
 * The width of the input field. Can be a number (interpreted as pixels) or a string (e.g., '100%', '200px').
 */
width?: number | string;

75-75: LGTM! Consider adding a default width for consistency.

The implementation of the width prop is correct and well-placed within the component.

To ensure consistent default styling and improve the component's usability, consider adding a default width. This can be done by modifying the destructuring statement:

width = "100%",

This change would make the component full-width by default while still allowing custom widths when specified.

Also applies to: 99-99

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 74da450 and ab0fca1.

Files ignored due to path filters (4)
  • Clients/package-lock.json is excluded by !**/package-lock.json
  • Clients/src/presentation/assets/icons/close.svg is excluded by !**/*.svg
  • Clients/src/presentation/assets/icons/left-arrow-long.svg is excluded by !**/*.svg
  • Clients/src/presentation/assets/imgs/table placeholder 1.png is excluded by !**/*.png
Files selected for processing (12)
  • Clients/package.json (1 hunks)
  • Clients/src/presentation/components/IconButton/index.tsx (1 hunks)
  • Clients/src/presentation/components/Inputs/Datepicker/index.css (1 hunks)
  • Clients/src/presentation/components/Inputs/Datepicker/index.tsx (1 hunks)
  • Clients/src/presentation/components/Inputs/Field/index.tsx (3 hunks)
  • Clients/src/presentation/components/Modals/Basic/index.tsx (1 hunks)
  • Clients/src/presentation/components/Modals/NewVendor/index.tsx (1 hunks)
  • Clients/src/presentation/components/Table/WithPlaceholder/index.tsx (1 hunks)
  • Clients/src/presentation/components/Table/index.tsx (1 hunks)
  • Clients/src/presentation/containers/Dashboard/index.tsx (1 hunks)
  • Clients/src/presentation/mocks/vendors.data.ts (1 hunks)
  • Clients/src/presentation/pages/Vendors/index.tsx (1 hunks)
Additional context used
Biome
Clients/src/presentation/components/Table/WithPlaceholder/index.tsx

[error] 70-93: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Additional comments not posted (13)
Clients/package.json (4)

18-18: Approved: Minor version update for @mui/material

The update of @mui/material from version ^6.1.0 to ^6.1.1 is a minor version increment. This type of update typically includes bug fixes and small improvements while maintaining backwards compatibility. Keeping dependencies up-to-date is a good practice for security and performance reasons.


20-20: Approved: Addition of @mui/x-date-pickers

The addition of @mui/x-date-pickers at version ^7.18.0 suggests the implementation of date/time selection functionality in the vendor management interface. This aligns well with the PR objectives of enhancing the user interface.

To ensure this dependency is being utilized effectively, please run the following script to check for its usage in the codebase:

#!/bin/bash
# Check for imports from @mui/x-date-pickers
rg --type typescript --type javascript 'from\s+[\'"]@mui/x-date-pickers[\'"]'

23-23: Approved: Addition of dayjs

The addition of dayjs at version ^1.11.13 is likely related to the introduction of @mui/x-date-pickers. dayjs is a lightweight and efficient library for date and time manipulation, often used in conjunction with MUI date pickers.

To ensure this dependency is being used effectively with @mui/x-date-pickers, please run the following script to check for its usage in the codebase:

#!/bin/bash
# Check for imports of dayjs and its usage with @mui/x-date-pickers
rg --type typescript --type javascript -e 'from\s+[\'"]dayjs[\'"]' -e 'from\s+[\'"]@mui/x-date-pickers[\'"].*dayjs'

17-17: Consider using a stable version of @mui/lab if available.

The addition of @mui/lab at version ^6.0.0-beta.10 suggests the use of experimental MUI components. While this aligns with the PR objectives of enhancing the vendor management interface, using a beta version in production could lead to instability or breaking changes in future updates.

Please verify if there are any stable alternatives for the specific components you're planning to use from @mui/lab. If not, ensure that the team is aware of the potential risks associated with using a beta version.

Clients/src/presentation/components/IconButton/index.tsx (1)

1-89: Overall assessment: Good implementation with room for improvement.

The IconButton component successfully implements the required functionality for managing vendor actions, aligning with the PR objectives. It provides a button with a dropdown menu for editing and removing vendors, including a confirmation modal for removal.

Key strengths:

  • Utilizes Material-UI components for consistent styling
  • Implements required functionality for vendor management

Areas for improvement:

  1. Enhance type safety by using more specific types and interfaces
  2. Improve code organization by extracting styles and subcomponents
  3. Enhance accessibility with proper aria labels and keyboard navigation
  4. Remove or comment out console.log statements for production
  5. Optimize event handling to reduce redundancy

Implementing these suggestions will result in a more robust, maintainable, and accessible component. Great work on the initial implementation!

Clients/src/presentation/components/Inputs/Datepicker/index.tsx (1)

7-13: LGTM: Well-defined interface for DatePicker props.

The DatePickerProps interface is well-structured and provides good flexibility for component customization. The use of optional props allows for various use cases.

Clients/src/presentation/components/Modals/Basic/index.tsx (2)

1-20: LGTM: Imports and interface definition are well-structured.

The imports are appropriate for the component's requirements, and the BasicModalProps interface is well-defined, following TypeScript best practices.


1-112: Overall, well-implemented component with minor improvements needed.

The BasicModal component is well-structured and aligns with the PR objectives of enhancing the vendor management interface. It provides a user-friendly confirmation dialog for vendor deletion, following React and Material-UI best practices.

Summary of suggestions:

  1. Add prop-types for runtime type checking.
  2. Improve accessibility by adding an aria-labelledby attribute to the Modal.
  3. Implement the deletion logic for the "Delete vendor" button.

These improvements will enhance the component's robustness and functionality.

Clients/src/presentation/pages/Vendors/index.tsx (1)

1-9: LGTM: Imports and component setup look good.

The imports cover all necessary dependencies for the component, including Material-UI components, custom components, and React hooks. The component is correctly declared as a functional component with appropriate state management setup.

Also applies to: 11-22

Clients/src/presentation/components/Table/index.tsx (2)

58-59: Improved type safety for paginated and reversed props

The change from any to boolean for the paginated and reversed props is a good improvement. This enhances type safety and prevents potential runtime errors by ensuring that only boolean values can be passed for these props.


Line range hint 1-224: Overall implementation looks good

The BasicTable component is well-structured and handles its responsibilities effectively. It provides a flexible and feature-rich table implementation with pagination and sorting capabilities. The use of Material-UI components ensures a consistent and modern look.

While there are some areas for potential improvement (as noted in previous comments), the overall implementation is solid and achieves its intended functionality.

Clients/src/presentation/components/Inputs/Field/index.tsx (1)

Line range hint 1-238: Overall, the changes enhance the Field component's flexibility, aligning with the PR objectives.

The addition of the width prop to the Field component is a valuable enhancement that aligns well with the PR objectives of improving the vendor management interface. This change allows for more flexible layouts when displaying vendor information, which can contribute to a better user experience in the vendor view, list, and forms for adding or editing vendors.

The implementation is clean, minimal, and doesn't introduce any breaking changes. It maintains the component's existing functionality while adding new capabilities.

Clients/src/presentation/components/Modals/NewVendor/index.tsx (1)

1-30: LGTM: Well-documented component with appropriate imports.

The component is well-documented using JSDoc comments, which clearly describe the purpose and props of the AddNewVendor component. The imports are appropriate for the functionality of the component, utilizing Material-UI components and custom inputs.

Comment on lines +1 to +24
/**
* TYPE:
Contractor
Partner
Supplier
Data source
AI model provider
*/

/**
* STATUS:
Active
Under review
Not active
*/

/**
* RISKS
Very high risk
High risk
Medium risk
Low risk
Very low risk
*/
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using TypeScript types instead of comments for better type safety and code organization.

The current implementation uses comments to define types, statuses, and risks. This approach doesn't leverage TypeScript's type system and may lead to inconsistencies or errors. Consider the following improvements:

  1. Use TypeScript enums or union types instead of comments.
  2. Improve the organization and separation of the comment blocks for better readability.

Here's an example of how you could refactor this:

enum VendorType {
  Contractor = 'Contractor',
  Partner = 'Partner',
  Supplier = 'Supplier',
  DataSource = 'Data source',
  AIModelProvider = 'AI model provider'
}

enum VendorStatus {
  Active = 'Active',
  UnderReview = 'Under review',
  NotActive = 'Not active'
}

enum RiskLevel {
  VeryHigh = 'Very high risk',
  High = 'High risk',
  Medium = 'Medium risk',
  Low = 'Low risk',
  VeryLow = 'Very low risk'
}

interface Vendor {
  name: string;
  type: VendorType;
  assignee: string;
  status: VendorStatus;
  risk: RiskLevel;
  review_date: string;
}

This approach provides better type safety, autocompletion, and makes the code more maintainable.

Comment on lines +25 to +58
const listOfVendors = [
{
name: "Apex",
type: "Contractor",
assignee: "John McAllen",
status: "Active",
risk: "High risk",
review_date: "12 January 2024",
},
{
name: "BuildCorp",
type: "Supplier",
assignee: "Jane Doe",
status: "Not active",
risk: "Medium risk",
review_date: "23 March 2023",
},
{
name: "ConstructCo",
type: "Contractor",
assignee: "Alice Johnson",
status: "Active",
risk: "Low risk",
review_date: "15 July 2023",
},
{
name: "DevPartners",
type: "Data source",
assignee: "Bob Smith",
status: "Active",
risk: "High risk",
review_date: "30 September 2023",
},
];
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add type annotations and consider using a standard date format.

The mock data structure looks good, but there are a couple of improvements we can make:

  1. Add type annotations to listOfVendors for better type safety.
  2. Consider using a standard date format (e.g., ISO 8601) for the review_date field to make it easier to perform date operations.

Here's an example of how you could refactor this:

const listOfVendors: Vendor[] = [
  {
    name: "Apex",
    type: VendorType.Contractor,
    assignee: "John McAllen",
    status: VendorStatus.Active,
    risk: RiskLevel.High,
    review_date: "2024-01-12",
  },
  // ... other vendor objects ...
];

This approach provides better type safety and uses a standard date format that's easier to work with in JavaScript/TypeScript.

Comment on lines +1 to +9
import {
Menu,
MenuItem,
IconButton as MuiIconButton,
useTheme,
} from "@mui/material";
import { ReactComponent as Setting } from "../../assets/icons/setting.svg";
import { useState } from "react";
import BasicModal from "../Modals/Basic";
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using absolute imports for better maintainability.

The import for the SVG icon uses a relative path:

import { ReactComponent as Setting } from "../../assets/icons/setting.svg";

Consider using absolute imports to make the code more resilient to file structure changes and easier to maintain. This can be achieved by configuring path aliases in your TypeScript configuration.

Comment on lines +11 to +15
const IconButton = () => {
const theme = useTheme();
const [anchorEl, setAnchorEl] = useState(null);
const [actions, setActions] = useState({});
const [isOpen, setIsOpen] = useState(false);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance type safety with TypeScript interfaces.

Consider defining an interface for the actions state to improve type safety and code readability:

interface Actions {
  id: string;
  url: string;
}

const [actions, setActions] = useState<Actions>({} as Actions);

This will provide better type checking and autocompletion when working with the actions state.

Comment on lines +17 to +24
const openMenu = (event: any, id: any, url: any) => {
console.log("open menu");
event.preventDefault();
event.stopPropagation();
setAnchorEl(event.currentTarget);
setActions({ id: id, url: url });
console.log(actions);
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve type safety and remove console.log statements.

  1. Replace any types with more specific types:
const openMenu = (event: React.MouseEvent, id: string, url: string) => {
  // ...
}
  1. Remove or comment out console.log statements before pushing to production:
// console.log("open menu");
// console.log(actions);

These changes will enhance type safety and prepare the code for production deployment.

Comment on lines +31 to +36
interface AddNewVendorProps {
isOpen: boolean;
setIsOpen: () => void;
value: string;
handleChange: (event: React.SyntheticEvent, newValue: string) => void;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider improving type safety for the value prop.

The value prop is currently typed as string, but it seems to be used for tab selection. To improve type safety and prevent potential errors, consider using a union type that explicitly defines the possible values.

Here's a suggested improvement:

interface AddNewVendorProps {
  isOpen: boolean;
  setIsOpen: () => void;
  value: "1" | "2"; // Explicitly define possible tab values
  handleChange: (event: React.SyntheticEvent, newValue: "1" | "2") => void;
}

This change will ensure that only valid tab values can be passed to the component and handled by the handleChange function.

Comment on lines +46 to +143
const vendorDetailsPanel = (
<TabPanel value="1" sx={{ paddingTop: theme.spacing(15), paddingX: 0 }}>
<Stack
direction={"row"}
justifyContent={"space-between"}
marginBottom={theme.spacing(10)}
>
<Field label="Vendor name" width={350} />
<Field label="Project the vendor is connected to" width={350} />
</Stack>
<Stack marginBottom={theme.spacing(10)}>
<Field
label="What does the vendor provide?"
width={"100%"}
type="description"
/>
</Stack>
<Stack
direction={"row"}
justifyContent={"space-between"}
marginBottom={theme.spacing(10)}
>
<Field label="Website" width={350} />
<Field label="Vendor contact person" width={350} />
</Stack>
<Stack
display={"flex"}
justifyContent={"space-between"}
marginBottom={theme.spacing(10)}
flexDirection={"row"}
>
<Field label="Review result" width={350} type="description" />
<Box
justifyContent={"space-between"}
display={"grid"}
gap={theme.spacing(10)}
>
<Select
items={[
{ _id: 1, name: "Select review status" },
{ _id: 2, name: "Select review status" },
]}
label="Review status"
placeholder="Select review status"
isHidden={false}
id=""
onChange={() => {}}
value={"Select review status"}
sx={{
width: 350,
}}
/>
<Select
items={[
{ _id: 1, name: "Select reviewer" },
{ _id: 2, name: "Select reviewer" },
]}
label="Reviewer"
placeholder="Select reviewer"
isHidden={false}
id=""
onChange={() => {}}
value={"Select reviewer"}
sx={{
width: 350,
}}
/>
</Box>
</Stack>
<Stack
display={"flex"}
justifyContent={"space-between"}
marginBottom={theme.spacing(10)}
flexDirection={"row"}
>
<Select
items={[
{ _id: 1, name: "Select risk status" },
{ _id: 2, name: "Select risk status" },
]}
label="Risk status"
placeholder="Select risk status"
isHidden={false}
id=""
onChange={() => {}}
value={"Select risk status"}
sx={{
width: 350,
}}
/>
<DatePicker
label="Review date"
sx={{
width: 350,
}}
/>
</Stack>
</TabPanel>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider extracting hardcoded options and using dynamic data.

The Select components in the vendorDetailsPanel have hardcoded options, which may lead to maintenance issues in the future.

Consider extracting these options into constants or fetching them from an API. For example:

const REVIEW_STATUS_OPTIONS = [
  { _id: 1, name: "Pending" },
  { _id: 2, name: "Approved" },
  { _id: 3, name: "Rejected" },
];

// Then in the component:
<Select
  items={REVIEW_STATUS_OPTIONS}
  label="Review status"
  // ... other props
/>

This approach will make it easier to update options in the future and potentially allow for dynamic option loading.

Comment on lines +46 to +291
<Stack
display={"flex"}
justifyContent={"space-between"}
marginBottom={theme.spacing(10)}
flexDirection={"row"}
>
<Box justifyContent={"space-between"} display={"grid"}>
<Select
items={[
{ _id: 1, name: "Select impact" },
{ _id: 2, name: "Select impact" },
]}
label="Impact"
placeholder="Select impact"
isHidden={false}
id=""
onChange={() => {}}
value={"Select impact"}
sx={{
width: 350,
}}
/>
<Select
items={[
{ _id: 1, name: "Select owner" },
{ _id: 2, name: "Select owner" },
]}
label="Action owner"
placeholder="Select owner"
isHidden={false}
id=""
onChange={() => {}}
value={"Select owner"}
sx={{
width: 350,
}}
/>
</Box>
<Field label="Review result" width={350} type="description" />
</Stack>

<Stack
direction={"row"}
justifyContent={"space-between"}
marginBottom={theme.spacing(10)}
>
<Select
items={[
{ _id: 1, name: "Select risk severity" },
{ _id: 2, name: "Select risk severity" },
]}
label="Risk severity"
placeholder="Select risk severity"
isHidden={false}
id=""
onChange={() => {}}
value={"Select risk severity"}
sx={{
width: 350,
}}
/>
<Select
items={[
{ _id: 1, name: "Select risk severity" },
{ _id: 2, name: "Select risk severity" },
]}
label="Likelihood"
placeholder="Select risk severity"
isHidden={false}
id=""
onChange={() => {}}
value={"Select risk severity"}
sx={{
width: 350,
}}
/>
</Stack>
<Stack
direction={"row"}
justifyContent={"flex-start"}
marginBottom={theme.spacing(10)}
>
<Select
items={[
{ _id: 1, name: "Select risk level" },
{ _id: 2, name: "Select risk level" },
]}
label="Risk level"
placeholder="Select risk level"
isHidden={false}
id=""
onChange={() => {}}
value={"Select risk level"}
sx={{
width: 350,
}}
/>
</Stack>
</TabPanel>
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider unifying repeated fields across panels.

The "Review result" field appears in both the vendorDetailsPanel and risksPanel. This repetition might lead to inconsistencies and maintenance issues.

Consider unifying these repeated fields or clarifying their purpose if they are intentionally different. If they represent the same data, you might want to move them to a common section or ensure they are synchronized.

Comment on lines +292 to +388
return (
<Modal
open={isOpen}
onClose={() => setIsOpen()}
sx={{ overflowY: "scroll" }}
>
<Stack
gap={theme.spacing(2)}
color={theme.palette.text.secondary}
sx={{
backgroundColor: "#D9D9D9",
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 800,
bgcolor: theme.palette.background.main,
border: 1,
borderColor: theme.palette.border,
borderRadius: theme.shape.borderRadius,
boxShadow: 24,
p: theme.spacing(15),
"&:focus": {
outline: "none",
},
}}
>
<Stack
display={"flex"}
flexDirection={"row"}
justifyContent={"space-between"}
alignItems={"center"}
>
<Typography
fontSize={16}
fontWeight={600}
marginBottom={theme.spacing(5)}
>
Add new vendor
</Typography>
<Close style={{ cursor: "pointer" }} onClick={setIsOpen} />
</Stack>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<TabList onChange={handleChange}>
<Tab
sx={{
width: 120,
paddingX: 0,
textTransform: "inherit",
fontSize: 13,
}}
label="Vendor details"
value="1"
/>
<Tab
sx={{
width: 60,
paddingX: 0,
textTransform: "capitalize",
fontSize: 13,
}}
label="Risks"
value="2"
/>
</TabList>
</Box>
{vendorDetailsPanel}
{risksPanel}
<Stack
sx={{
alignItems: "flex-end",
}}
>
<Button
variant="contained"
sx={{
width: 70,
height: 34,
fontSize: 13,
textTransform: "capitalize",
backgroundColor: "#4C7DE7",
boxShadow: "none",
borderRadius: "4px",
border: "1px solid #175CD3",
"&:hover": {
boxShadow: "none",
},
}}
onClick={() => console.log("Save button")}
>
Save
</Button>
</Stack>
</TabContext>
</Stack>
</Modal>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider extracting inline styles for better maintainability.

The modal component has a significant amount of inline styling using the sx prop. While this works, it can make the component harder to read and maintain as it grows.

Consider extracting these styles into a separate constant or even a styled component. For example:

const modalStyles = {
  modal: {
    overflowY: "scroll",
  },
  container: {
    backgroundColor: "#D9D9D9",
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    width: 800,
    bgcolor: theme.palette.background.main,
    border: 1,
    borderColor: theme.palette.border,
    borderRadius: theme.shape.borderRadius,
    boxShadow: 24,
    p: theme.spacing(15),
    "&:focus": {
      outline: "none",
    },
  },
  // ... other styles
};

// Then in the component:
<Modal
  open={isOpen}
  onClose={() => setIsOpen()}
  sx={modalStyles.modal}
>
  <Stack sx={modalStyles.container}>
    {/* ... */}
  </Stack>
</Modal>

This approach will make the component more readable and easier to maintain.

Comment on lines +366 to +384
<Button
variant="contained"
sx={{
width: 70,
height: 34,
fontSize: 13,
textTransform: "capitalize",
backgroundColor: "#4C7DE7",
boxShadow: "none",
borderRadius: "4px",
border: "1px solid #175CD3",
"&:hover": {
boxShadow: "none",
},
}}
onClick={() => console.log("Save button")}
>
Save
</Button>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement save functionality for the "Save" button.

The "Save" button currently only logs a message to the console. This doesn't fulfill the component's purpose of adding a new vendor.

Implement the actual save functionality for the "Save" button. This should include:

  1. Collecting all the input data from both panels.
  2. Validating the input data.
  3. Making an API call to save the new vendor information.
  4. Handling success and error cases.
  5. Closing the modal on successful save.

Here's a basic example of what this might look like:

const handleSave = async () => {
  try {
    // Collect and validate data
    const vendorData = collectAndValidateData();
    
    // Make API call
    await saveVendor(vendorData);
    
    // Close modal on success
    setIsOpen(false);
    
    // Optionally, show a success message or update the vendor list
  } catch (error) {
    // Handle and display any errors
    console.error('Failed to save vendor:', error);
    // Show error message to user
  }
};

// Then update the button:
<Button
  // ... other props
  onClick={handleSave}
>
  Save
</Button>

Remember to implement proper error handling and user feedback for a smooth user experience.

Copy link
Contributor

@MatthewSharpOTU MatthewSharpOTU left a comment

Choose a reason for hiding this comment

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

Everything looks good, I have a few questions about what to look for in particular for this project when doing a PR review for our next meeting.

@MuhammadKhalilzadeh
Copy link
Collaborator Author

@MatthewSharpOTU I'll write it in our channel

@gorkem-bwl
Copy link
Contributor

@MatthewSharpOTU I'll write it in our channel

There is also CodeRabbit, coming up with a lot of suggestions. To what extend will those be taken into consideration when doing a PR review? (another subject to discuss) ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
frontend Frontend related tasks/issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants