Skip to content

Frontend TsDoc Convention

박상은 edited this page Mar 16, 2025 · 1 revision

πŸ“ νƒ€μž…

λͺ¨λ“  νƒ€μž…μ— ν•„μˆ˜

  • μž₯점

    1. types/에 μžˆλŠ” 파일 μžμ²΄κ°€ 더 μƒμ„Έν•œ API λ¬Έμ„œκ°€ 됨
    2. λ³€μˆ˜λͺ…λ§ŒμœΌλ‘œ μœ μΆ”ν•˜κΈ° μ–΄λ €μš΄ νƒ€μž…μ˜ 경우 쑰금 더 μƒμ„Έν•œ 정보λ₯Ό λ°”λ‘œ 확인할 수 있음
  • 단점

    1. μ½”λ“œκ°€ λŠ˜μ–΄λ‚˜μ„œ λΆˆνŽΈν•  수 있음
    2. λ°±μ—”λ“œμ™€ λ™κΈ°ν™”λ˜μ§€ μ•ŠλŠ” 경우 νŒŒμ•…μ΄ 맀우 μ–΄λ €μ›Œμ§
/**
 * + μœ μ € μ±„μš©κ΄€ 승인 μƒνƒœ
 *   1. `review`: 검토쀑
 *   1. `needSupplement`: κΆŒν•œ 보좩
 *   1. `approved`: ν—ˆμš©
 *   1. `noPermission`: κΆŒν•œ μ—†μŒ
 **/
export type UserRecruitmentAdminApprovedStatus =
  | 'review'
  | 'needSupplement'
  | 'approved'
  | 'noPermission';

/**
 * + μœ μ € μ±„μš©κ΄€ μƒνƒœ
 *   1. `none`:
 *   1. `member`: 멀버
 *   1. `manager`: λ§€λ‹ˆμ €
 *   1. `master`: λ§ˆμŠ€ν„°
 *   1. `resign`: ν‡΄μ‚¬μž
 */
export type UserRecruitmentAdminStatus = 'none' | 'member' | 'manager' | 'master' | 'resign';

/** μœ μ € μ±„μš©κ΄€ */
export interface UserRecruitmentAdmin {
  /** μœ μ € μ±„μš©κ΄€ μ‹λ³„μž */
  id: number;
  /** μœ μ € μ±„μš©κ΄€ μœ μ € μ‹λ³„μž */
  userId: number;
  /** μœ μ € μ±„μš©κ΄€ νšŒμ‚¬ μ‹λ³„μž */
  recruitmentCompanyId: number;
  /** μœ μ € μ±„μš©κ΄€ νœ΄λŒ€ν° 번호 */
  phone: string;
  /** μœ μ € μ±„μš©κ΄€ μ†Œμ† */
  department: string;
  /** μœ μ € μ±„μš©κ΄€ 직급 */
  position: string;
  /** μœ μ € μ±„μš©κ΄€ 승인 μƒνƒœ */
  approvedStatus: UserRecruitmentAdminApprovedStatus;
  /** μœ μ € μ±„μš©κ΄€ μƒνƒœ */
  status: UserRecruitmentAdminStatus;
  /** μœ μ € μ±„μš©κ΄€ λŒ€ν‘œ λ§ˆμŠ€ν„° μ—¬λΆ€ */
  isOriginMaster: false;
  /** μœ μ € μ±„μš©κ΄€ TODO: ? */
  isBannerClosed: false;
  /** μœ μ € μ±„μš©κ΄€ μ‚­μ œ μ—¬λΆ€ */
  isDeleted: false;
  /** μœ μ € μ±„μš©κ΄€ 생성 μ‹œκ°„ */
  createdAt: string;
  /** μœ μ € μ±„μš©κ΄€ μˆ˜μ • μ‹œκ°„ */
  updatedAt: string;
  /** μœ μ € μ±„μš©κ΄€ νšŒμ‚¬ 이름 */
  companyName: string;
  /** μœ μ € μ±„μš©κ΄€ νšŒμ‚¬κ°€ 승인됐고, μ„œλΉ„μŠ€κ°€ μžˆλŠ”μ§€ μ—¬λΆ€ */
  isCompanyCompleted: boolean;
  /** μœ μ € μ±„μš©κ΄€ μ±„μš©κ΄€ κ΄€λ¦¬μžκ°€ λ§ˆμ§€λ§‰μœΌλ‘œ λ³Έ μ±„μš© 곡고 μ‹λ³„μž */
  lastWatchedRecruitmentNoticeId: number;
}

/** 둜그인된 μœ μ € 정보 νƒ€μž… */
export interface UserInfoType {
  /** μœ μ € μ‹λ³„μž */
  id: number;
  /** μœ μ € 이메일 */
  email: string;
  /** μœ μ € μ†Œμ…œ 둜그인 κ³ μœ κ°’ */
  externalId: string | null;
  /** μœ μ € μ±„μš©κ΄€ 정보 */
  recruitmentAdmin: UserRecruitmentAdmin | null;
}

export const loadloggedInfoAPI = () => axios.get<UserInfoType>('/api/v2/me');
(async () => {
  const user = await loadloggedInfoAPI();

  // μœ μ € μ±„μš©κ΄€ 정보
  // μœ μ € μ±„μš©κ΄€ νšŒμ‚¬κ°€ 승인됐고, μ„œλΉ„μŠ€κ°€ μžˆλŠ”μ§€ μ—¬λΆ€
  user.recruitmentAdmin.isCompanyCompleted
})()

🧱 μ»΄ν¬λ„ŒνŠΈ

곡용으둜 μ‚¬μš©ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈμ—λŠ” ν•„μˆ˜, κ·Έ μ΄μ™ΈλŠ” 선택

  • μž₯점

    1. μ»΄ν¬λ„ŒνŠΈμ— 직접 λ“€μ–΄κ°€μ§€ μ•Šμ•„λ„ μ‚¬μš©ν•˜λŠ” λΆ€λΆ„μ—μ„œ λ°”λ‘œ props에 λŒ€ν•œ 정보λ₯Ό μ•Œ 수 있음
    2. ꡬ체적으둜 μ„€λͺ…을 μž‘μ„±ν•˜λ‹€λ³΄λ©΄ 더블 체크할 수 있음
    3. λ§Œμ•½ Stortbook을 μ‚¬μš©ν•œλ‹€λ©΄ μžλ™μ μœΌλ‘œ μ»΄ν¬λ„ŒνŠΈμ™€ props에 λŒ€ν•œ μ„€λͺ…이 κΈ°μž…λ¨
  • 단점

    1. μ»΄ν¬λ„ŒνŠΈκ°€ 였히렀 더 길어짐
interface Props {
  /**
   * 클래슀λͺ… ( `tailwindCss` )
   * @default ""
   */
  className?: string;
  /**
   * λ‘₯κΈ€κ²Œ μ²˜λ¦¬ν• μ§€ μ—¬λΆ€
   * @default false
   */
  rounded?: boolean;

  /**
   * μ•„λ°”νƒ€λ‘œ μ‚¬μš©ν•  ν…μŠ€νŠΈ
   * @default ""
   */
  text?: string;
  /**
   * μ•„λ°”νƒ€λ‘œ μ‚¬μš©ν•  ν…μŠ€νŠΈμ˜ 길이
   * @default ""
   */
  overflowTextLength?: number;
  /**
   * μ•„λ°”νƒ€λ‘œ μ‚¬μš©ν•  μ•„μ΄μ½˜
   * @default undefined
   */
  icon?: React.ReactNode;
  /**
   * μ•„λ°”νƒ€λ‘œ μ‚¬μš©ν•  이미지 URL
   * @default ""
   */
  imagePath?: `https://${string}`;
}

/**
 * `framer-motion`κ³Ό `tailwindcss`λ₯Ό μ‚¬μš©ν•˜λŠ” 곡용 아바타
 * ( μš°μ„ μˆœμœ„: `text` > `icon` > `imagePath` )
 *
 * @link [λ””μžμΈ 및 속성 μ°Έκ³  - Avatar(Antd)](https://ant.design/components/avatar)
 * @example
 * <Avatar text="κΉ€λ…μž" />
 * <Avatar className="bg-main-500" icon={<HomeIcon />} />
 * <Avatar imagePath="https://avatars.githubusercontent.com/u/63289318?v=4" />
 *
 * @todo <Image />와 <img /> λΆ„κΈ°μ²˜λ¦¬ν•˜κΈ°
 */
const Avatar: React.FC<Props> = ({
  className = "",
  rounded = false,
  text = "",
  overflowTextLength = 1,
  icon,
  imagePath = "",
}) => {
  return (
    <figure></figure>
  );
};

export default Avatar;

// μ‚¬μš©ν•˜λŠ” κ³³μ—μ„œ 마우슀λ₯Ό μ˜¬λ¦¬κ±°λ‚˜ μžλ™μ™„μ„±ν• λ•Œ TsDoc에 μž‘μ„±ν•œ μ„€λͺ…이 좜λ ₯됨
<Avatar imagePath="" />

πŸ–ŒοΈ μ»€μŠ€ν…€ ν›…

곡용으둜 μ‚¬μš©ν•˜λŠ” μ»€μŠ€ν…€ ν›…μ—λŠ” ν•„μˆ˜, κ·Έ μ΄μ™ΈλŠ” 선택

import { useState } from 'react'

import type { RefObject } from 'react'

import { useEventListener } from '../useEventListener'

/**
 * Custom hook that tracks whether a DOM element is being hovered over.
 * @template T - The type of the DOM element. Defaults to `HTMLElement`.
 * @param {RefObject<T>} elementRef - The ref object for the DOM element to track.
 * @returns {boolean} A boolean value indicating whether the element is being hovered over.
 * @public
 * @see [Documentation](https://usehooks-ts.com/react-hook/use-hover)
 * @example
 * ```tsx
 * const buttonRef = useRef<HTMLButtonElement>(null);
 * const isHovered = useHover(buttonRef);
 * // Access the isHovered variable to determine if the button is being hovered over.
 * ```
 */
export function useHover<T extends HTMLElement = HTMLElement>(
  elementRef: RefObject<T>,
): boolean {
  const [value, setValue] = useState<boolean>(false)

  const handleMouseEnter = () => {
    setValue(true)
  }
  const handleMouseLeave = () => {
    setValue(false)
  }

  useEventListener('mouseenter', handleMouseEnter, elementRef)
  useEventListener('mouseleave', handleMouseLeave, elementRef)

  return value
}

πŸŽ€ λ°μ½”λ ˆμ΄ν„° ν™œμš©

μ μ ˆν•œ λ°μ½”λ ˆμ΄ν„°κ°€ μžˆλ‹€λ©΄ μ‚¬μš©ν•˜λŠ”κ²Œ 쒋을 것 κ°™μŒ @deprecated, @exampleλŠ” μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμ„ 것 κ°™μŒ

/**
 * 숫자 λ‘κ°œλ₯Ό λ°›μ•„μ„œ λ”ν•˜λŠ” ν•¨μˆ˜
 * 
 * @example
 * addNumber(1, 1); // 2
 * 
 * @link [λ―Έλ‹ˆμΈν„΄](https://miniintern.com)
 * 
 * @see λ‹€λ₯Έ 참고할것듀
 * 
 * // μ•ˆμ“΄λ‹€κ³  μƒκ°λ˜λŠ” μ»΄ν¬λ„ŒνŠΈ/ν•¨μˆ˜/νƒ€μž… 등에 μž‘μ„±ν•΄λ‘κ³  ν…ŒμŠ€νŠΈν•˜κ³  μ‚­μ œν•˜λŠ”λ° μ‚¬μš©
 * @deprecated
 * 
 * // κΈ°λ³Έ 값이 μžˆλŠ” 경우 λͺ…μ‹œ
 * @defaultValue 10
 * 
 * // νƒ€μž…μŠ€ν¬λ¦½νŠΈλΌμ„œ ꡳ이 ν•„μš”μ—†μ§€ μ•Šμ„κΉŒ 생각함
 * // λ§€κ°œλ³€μˆ˜λ‚˜ 리턴값에 λŒ€ν•œ νƒ€μž…μ€ λ”°λ‘œ λ§Œλ“€μ–΄μ„œ ν•¨μˆ˜ 자체의 νƒ€μž…μœΌλ‘œ μ μš©ν•˜λŠ” 방식이 μ’‹μ§€ μ•Šμ„κΉŒ 생각함
 * @params
 * @returns
 **/
const addNumber = (a: number, b: number) => a + b;
Clone this wiki locally