Skip to content

Commit

Permalink
Merge pull request #13 from wafflestudio/feat/org
Browse files Browse the repository at this point in the history
Feat: 조직도 기본페이지 UI
  • Loading branch information
Joeyoojin authored Feb 26, 2025
2 parents a43a953 + 23345f0 commit 1fd7fcb
Show file tree
Hide file tree
Showing 34 changed files with 705 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@tanstack/react-query": "^5.62.10",
"autoprefixer": "^10.4.20",
"class-variance-authority": "^0.7.1",
"postcss": "^8.4.49",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
9 changes: 9 additions & 0 deletions src/assets/icons/org/card_travel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/org/corporate_close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/org/corporate_open.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/org/dot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/assets/icons/org/file_export.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/assets/icons/org/history.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/org/line-list-space.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/icons/org/line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/assets/icons/org/organizationPageTitle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
3 changes: 3 additions & 0 deletions src/assets/icons/org/triangleButtonClose.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/org/triangleButtonOpen.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/components/organization/CorporationSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import GroupSelectBtn from './GroupSelectBtn';

const CorporationSelect = () => {
return (
<div className="flex items-center gap-2.5 text-sm font-medium">
<div>법인선택</div>
<GroupSelectBtn team="인프라보안팀" />
</div>
);
};

export default CorporationSelect;
14 changes: 14 additions & 0 deletions src/components/organization/EditBtn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type EditBtnProps = {
onClick: () => void;
text: string;
};
const EditBtn = ({ onClick, text }: EditBtnProps) => (
<button
onClick={onClick}
className="rounded-[30px] bg-lightGreen px-1.5 py-1 text-xs text-backgroundGreen"
>
{text}
</button>
);

export default EditBtn;
30 changes: 30 additions & 0 deletions src/components/organization/GroupMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import MenuButton from '@/components/organization/MenuBtn';
import { Icons } from '@/constants/icons';

const GroupMenu = () => {
return (
<div className="flex items-center justify-between rounded-md bg-backgroundGray p-1.5 pl-4">
<p className="text-sm text-textGray1">
조직을 구성하고 조직도를 내보낼 수 있습니다.
</p>

<div className="flex gap-2">
<MenuButton
icon={Icons.MenuHistory}
label="히스토리"
/>
<MenuButton
icon={Icons.MenuFileExport}
label="내보내기"
/>
<MenuButton
icon={Icons.MenuCardTravel}
label="조직도 편집"
type="edit"
/>
</div>
</div>
);
};

export default GroupMenu;
102 changes: 102 additions & 0 deletions src/components/organization/GroupRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { cva, VariantProps } from 'class-variance-authority';
import { useState } from 'react';

import EditBtn from './EditBtn';

import { Icons } from '@/constants/icons';
import { cn } from '@/utils/cn';

const groupRowVariants = cva(
'whitespace-nowrap w-full flex h-9 items-center py-2.5 pr-2 gap-1 border-b border-solid border-borderGray text-sm font-medium text-black',
{
variants: {
state: {
default: 'bg-white ',
hover: 'bg-backgroundGray',
hold: 'bg-[rgba(25,240,120,0.2)]',
unselected: 'bg-backgroundUnselected',
selected: 'text-backgroundGreen',
},
unclassified: {
true: 'text-textGray2',
false: '',
},
},

defaultVariants: {
state: 'default',
unclassified: false,
},
}
);

interface GroupRowProps extends VariantProps<typeof groupRowVariants> {
name: string;
level?: number;
state?: 'default' | 'hover' | 'hold' | 'unselected' | 'selected';
isEdit?: boolean;
unclassified?: boolean;
children?: GroupRowProps[];
}

const GroupRow = ({
name,
level = 1,
state = 'default',
isEdit = false,
unclassified = false,
children = [],
}: GroupRowProps) => {
const [isExpanded, setIsExpanded] = useState(false);
const hasUpperOrg = level > 1;
const hasChildren = children.length > 0;
const basePadding = 14;
const paddingIncrement = 24;
const paddingValue =
!hasChildren && !hasUpperOrg ? basePadding : (level - 1) * paddingIncrement;

return (
<>
<div
className={cn(
groupRowVariants({
state,
unclassified,
})
)}
style={{ paddingLeft: `${paddingValue}px` }}
>
{hasUpperOrg && <div className="pr-1">{Icons.Line}</div>}

{hasChildren && (
<button
onClick={() => setIsExpanded(!isExpanded)}
className={cn('px-1 transition-transform', {
'rotate-180': isExpanded,
})}
>
{isExpanded ? Icons.TriangleButtonOpen : Icons.TriangleButtonClose}
</button>
)}
<span className="flex-1">{name}</span>
{isEdit && (
<EditBtn
onClick={() => {}}
text="수정됨"
/>
)}
</div>
{isExpanded &&
children.map((child, index) => (
<GroupRow
key={index}
{...child}
level={level + 1}
isEdit={isEdit}
/>
))}
</>
);
};

export default GroupRow;
25 changes: 25 additions & 0 deletions src/components/organization/GroupSelectBtn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState } from 'react';

import { Icons } from '@/constants/icons';
import { cn } from '@/utils/cn';

type GroupSelectBtnProps = {
team: string;
};
const GroupSelectBtn = ({ team }: GroupSelectBtnProps) => {
const [isOpen, setIsOpen] = useState(false);

return (
<button
onClick={() => setIsOpen((prev) => !prev)}
className={cn(
'flex items-center gap-1 rounded-md bg-pointColor px-3 py-[5px] text-black hover:bg-backgroundGreen'
)}
>
<span className="text-sm font-medium">{team}</span>
<span>{isOpen ? Icons.CorporateOpen : Icons.CorporateClose}</span>
</button>
);
};

export default GroupSelectBtn;
76 changes: 76 additions & 0 deletions src/components/organization/LIstSpace.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { cva, VariantProps } from 'class-variance-authority';

import { Icons } from '@/constants/icons.tsx';
import { cn } from '@/utils/cn';

const listSpaceVariants = cva(
'w-full grid grid-cols-2 px-6 py-[14.5px] h-[66px] rounded-sm border-[0.5px] border-solid border-borderGray bg-white transition-all',
{
variants: {
state: {
default: '',
select: 'border-[1.5px] border-pointColor',
},
isHovered: {
true: 'bg-backgroundGray',
},
},
compoundVariants: [
{
state: 'default',
isHovered: true,
class: 'bg-backgroundGray',
},
{
state: 'select',
isHovered: true,
className: 'border-[1.5px] border-pointColor bg-backgroundGray',
},
],
defaultVariants: {
state: 'default',
isHovered: false,
},
}
);

interface ListSpaceProps extends VariantProps<typeof listSpaceVariants> {
name: string;
company: string;
department: string;
position: string;
onClick?: () => void;
isHovered?: boolean;
}

const ListSpace = ({
name,
company,
department,
position,
state = 'default',
isHovered = false,
onClick,
}: ListSpaceProps) => {
return (
<div
className={cn(listSpaceVariants({ state, isHovered }))}
onClick={onClick}
>
<div className="flex items-center justify-start gap-4">
<div>{Icons.LineListSpace}</div>
<span className="text-base font-semibold">{name}</span>
</div>

<div className="text-left text-sm font-medium">
<p className="text-textGray1">{company}</p>
<div className="flex items-center gap-1.5 text-textGray2">
{department}
<span>{Icons.Dot}</span> {position}
</div>
</div>
</div>
);
};

export default ListSpace;
44 changes: 44 additions & 0 deletions src/components/organization/ListHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { cva, VariantProps } from 'class-variance-authority';

import { cn } from '@/utils/cn';

const listHeaderVariants = cva(
'w-full flex items-center bg-backgroundGray text-titleBlack font-bold text-lg p-4',
{
variants: {
type: {
default: 'h-[53px]',
unclassified: 'h-[79px]',
},
},
defaultVariants: {
type: 'default',
},
}
);

interface ListHeaderProps extends VariantProps<typeof listHeaderVariants> {
title: string;
count: number;
description?: string;
}
const ListHeader = ({
title,
count,
type = 'default',
description,
}: ListHeaderProps) => {
return (
<div className={cn(listHeaderVariants({ type }))}>
<div className="flex items-baseline gap-2">
<span>{title}</span>
<span className="text-sm font-semibold text-textGray2">{count}</span>
</div>
{type === 'unclassified' && description && (
<p className="mt-2.5 text-[13px] text-textGray1">{description}</p>
)}
</div>
);
};

export default ListHeader;
Loading

0 comments on commit 1fd7fcb

Please sign in to comment.