diff --git a/src/custom/FlipCard/FlipCard.tsx b/src/custom/FlipCard/FlipCard.tsx index 7ecceaa05..cb5380c03 100644 --- a/src/custom/FlipCard/FlipCard.tsx +++ b/src/custom/FlipCard/FlipCard.tsx @@ -7,8 +7,16 @@ export type FlipCardProps = { onClick?: () => void; onShow?: () => void; children: [React.ReactNode, React.ReactNode]; + disableFlip?: boolean; }; +/** + * Helper function to get the front or back child component from the children array + * @param children Array containing exactly two child components + * @param key Index to retrieve (0 for front, 1 for back) + * @throws Error if children is undefined or doesn't contain exactly two components + * @returns The selected child component + */ function GetChild(children: [React.ReactNode, React.ReactNode], key: number) { if (!children) throw Error('FlipCard requires exactly two child components'); if (children.length != 2) throw Error('FlipCard requires exactly two child components'); @@ -42,7 +50,31 @@ const BackContent = styled('div')({ wordBreak: 'break-word' }); -export function FlipCard({ duration = 500, onClick, onShow, children }: FlipCardProps) { +/** + * A card component that provides a flipping animation between two content faces + * + * @component + * @param props.duration - Animation duration in milliseconds (default: 500) + * @param props.onClick - Callback function triggered on card click + * @param props.onShow - Additional callback function triggered when card shows new face + * @param props.children - Array of exactly two child components (front and back) + * @param props.disableFlip - When true, prevents the card from flipping (default: false) + * + * @example + * ```tsx + * + *
Front Content
+ *
Back Content
+ *
+ * ``` + */ +export function FlipCard({ + duration = 500, + onClick, + onShow, + children, + disableFlip = false +}: FlipCardProps) { const [flipped, setFlipped] = React.useState(false); const [activeBack, setActiveBack] = React.useState(false); @@ -72,6 +104,7 @@ export function FlipCard({ duration = 500, onClick, onShow, children }: FlipCard return ( { + if (disableFlip) return; setFlipped((flipped) => !flipped); onClick && onClick(); onShow && onShow(); diff --git a/src/custom/Workspaces/WorkspaceTransferButton.tsx b/src/custom/Workspaces/WorkspaceTransferButton.tsx new file mode 100644 index 000000000..4eba00f17 --- /dev/null +++ b/src/custom/Workspaces/WorkspaceTransferButton.tsx @@ -0,0 +1,113 @@ +import { SyncAlt as SyncAltIcon } from '@mui/icons-material'; +import { Grid, Tooltip, Typography } from '../../base'; +import { useTheme } from '../../theme'; +import { formatShortDate, formatShortDateTime } from './helper'; +import { PopupButton, Record, TabCount, TabTitle } from './styles'; + +interface TransferButtonProps { + title: string; + count: number; + onAssign: () => void; + disabled: boolean; +} + +interface RedirectButtonProps { + title: string; + count: number; + disabled?: boolean; +} + +export const TransferButton: React.FC = ({ + title, + count, + onAssign, + disabled +}) => { + const theme = useTheme(); + return ( + + + {count} + {title} + + + + ); +}; + +export const RedirectButton: React.FC = ({ + title, + count, + disabled = true +}) => { + return ( + + + {count} + {title} + {/* */} + + + ); +}; + +interface RecordRowProps { + title: string; + name: string; + date?: string | Date; +} + +export const RecordRow: React.FC = ({ title, name, date }) => { + const theme = useTheme(); + + return ( + + + + {title} + + + {name} + + + + + + {date ? formatShortDate(date) : '-'} + + + + + ); +}; diff --git a/src/custom/Workspaces/helper.ts b/src/custom/Workspaces/helper.ts index 553442794..23e613b2f 100644 --- a/src/custom/Workspaces/helper.ts +++ b/src/custom/Workspaces/helper.ts @@ -17,3 +17,65 @@ export const parseDeletionTimestamp = (data: { return DEFAULT_DATE; } }; + +/** + * Formats a date into a short date-time string (e.g., "Jan 1, 2024, 09:30 AM") + * + * @param {Date | string} date - The date to format. Can be a Date object or date string + * @returns {string} Formatted date string in the format "MMM D, YYYY, HH:MM AM/PM" + * + * @example + * formatShortDateTime("2024-01-01T09:30:00") // Returns "Jan 1, 2024, 09:30 AM" + * formatShortDateTime(new Date()) // Returns current date-time in short format + * + * Generated by Copilot + */ +export const formatShortDateTime = (date: Date | string): string => { + return new Date(date).toLocaleDateString('en-US', { + day: 'numeric', + month: 'short', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); +}; + +/** + * Formats a date into a short date string (e.g., "Jan 1, 2024") + * + * @param {Date | string} date - The date to format. Can be a Date object or date string + * @returns {string} Formatted date string in the format "MMM D, YYYY" + * + * @example + * formatShortDate("2024-01-01") // Returns "Jan 1, 2024" + * formatShortDate(new Date()) // Returns current date in short format + * + * Generated by Copilot + */ +export const formatShortDate = (date: Date | string): string => { + return new Date(date).toLocaleDateString('en-US', { + day: 'numeric', + month: 'short', + year: 'numeric' + }); +}; + +/** + * Formats a date into a long date string (e.g., "January 1, 2024") + * + * @param {Date | string} date - The date to format. Can be a Date object or date string + * @returns {string} Formatted date string in the format "MMMM D, YYYY" + * + * @example + * formattoLongDate("2024-01-01") // Returns "January 1, 2024" + * formattoLongDate(new Date()) // Returns current date in long format + * + * Generated by Copilot + */ +export const formattoLongDate = (date: Date | string): string => { + return new Date(date).toLocaleDateString('en-US', { + day: 'numeric', + month: 'long', + year: 'numeric' + }); +}; diff --git a/src/custom/Workspaces/index.ts b/src/custom/Workspaces/index.ts index 82cd1eacd..7215852a7 100644 --- a/src/custom/Workspaces/index.ts +++ b/src/custom/Workspaces/index.ts @@ -1,17 +1,22 @@ import AssignmentModal from './AssignmentModal'; import DesignTable from './DesignTable'; import EnvironmentTable from './EnvironmentTable'; +import WorkspaceCard from './WorkspaceCard'; import WorkspaceTeamsTable from './WorkspaceTeamsTable'; import WorkspaceViewsTable from './WorkspaceViewsTable'; import useDesignAssignment from './hooks/useDesignAssignment'; import useEnvironmentAssignment from './hooks/useEnvironmentAssignment'; import useTeamAssignment from './hooks/useTeamAssignment'; import useViewAssignment from './hooks/useViewsAssignment'; +import { L5DeleteIcon, L5EditIcon } from './styles'; export { AssignmentModal, DesignTable, EnvironmentTable, + L5DeleteIcon, + L5EditIcon, + WorkspaceCard, WorkspaceTeamsTable, WorkspaceViewsTable, useDesignAssignment, diff --git a/src/icons/Delete/DeleteIcon.tsx b/src/icons/Delete/DeleteIcon.tsx index 31d3a5500..0877592e3 100644 --- a/src/icons/Delete/DeleteIcon.tsx +++ b/src/icons/Delete/DeleteIcon.tsx @@ -8,14 +8,15 @@ export const DeleteIcon = ({ style, ...props }: IconProps): JSX.Element => { + const _finalFill = style?.fill || fill; + return (