Merge remote-tracking branch 'origin/iipbs/common/main' into iipbs/sn/dev

This commit is contained in:
yschoi
2025-03-27 17:01:33 +09:00
17 changed files with 268 additions and 36 deletions
+2
View File
@@ -14,6 +14,8 @@ dist
# misc
.DS_Store
apps/wr/.next/**/*
apps/fo/.next/**/*
# env
.env*
@@ -1,3 +1,7 @@
@import "@common/assets/styles/base.css";
@import "@common/assets/styles/diveicon.css";
@import "@common/assets/styles/components.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -70,4 +74,4 @@
body {
@apply bg-background text-foreground;
}
}
}
@@ -0,0 +1,53 @@
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@common/components";
import React from "react";
type ModalType = {
bodyClass: string;
butNm: string;
title: string;
body: React.ReactNode;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
export function UiModal({ bodyClass, butNm, title, body, open, onOpenChange }: ModalType) {
const dialogProps = open !== undefined && onOpenChange !== undefined
? { open, onOpenChange }
: {};
return (
<>
{!open && (
<Dialog>
<DialogTrigger asChild>
<Button className="mr-4 rounded-lg">{butNm}</Button>
</DialogTrigger>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
{open && (
<Dialog {...dialogProps}>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
</>
);
}
@@ -0,0 +1,52 @@
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@common/components";
type ModalType = {
bodyClass: string;
butNm: string;
title: string;
body: React.ReactNode;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
export function UiModal({ bodyClass, butNm, title, body, open, onOpenChange }: ModalType) {
const dialogProps = open !== undefined && onOpenChange !== undefined
? { open, onOpenChange }
: {};
return (
<>
{!open && (
<Dialog>
<DialogTrigger asChild>
<Button className="mr-4 rounded-lg">{butNm}</Button>
</DialogTrigger>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
{open && (
<Dialog {...dialogProps}>
<DialogContent className={bodyClass}>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
</DialogDescription>
</DialogHeader>
{body}
<DialogFooter className="sm:justify-start">
</DialogFooter>
</DialogContent>
</Dialog>
)}
</>
);
}
@@ -9,4 +9,11 @@ export * from "./search_input";
export * from "./search_input_select";
export * from "./select";
export * from "./table";
export * from "./main_content_div";
export * from "./title";
export * from "./search_form_left";
export * from "./search_form_right";
export * from "./table_div";
export * from "./list_div";
export * from "./tab";
export * from "./dialog_ui"
@@ -0,0 +1,11 @@
import React from 'react'
function ListDiv(props: {children: React.ReactNode}) {
return (
<div className="card card-border">
{props.children}
</div>
)
}
export default ListDiv
@@ -0,0 +1,11 @@
import React from 'react'
export default function MainDiv(props: {children: React.ReactNode}) {
return (
<div className="min-h-screen bg-container">
{props.children}
</div>
)
}
export { MainDiv };
@@ -1,9 +1,9 @@
function SearchDiv ({children}:{ children: React.ReactNode; }) {
return (
<div className="card card-border ">
{children}
</div>
);
<div className="flex card card-border !mt-6">
{children}
</div>
)
}
export { SearchDiv };
@@ -0,0 +1,11 @@
import React from 'react'
function SearchFormLeft(props: {children: React.ReactNode}) {
return (
<div className="grid grid-cols-12 gap-4 w-4/5 mx-4">
{props.children}
</div>
)
}
export { SearchFormLeft };
@@ -0,0 +1,11 @@
import React from 'react'
function SearchFormRight(props: {children: React.ReactNode}) {
return (
<div className="w-1/5 mx-5 flex items-center justify-end space-x-2">
{props.children}
</div>
)
}
export { SearchFormRight };
@@ -1,15 +1,16 @@
import { Input, Label } from "@common/components";
import React from "react";
const SearchInput = React.forwardRef<
HTMLDivElement& HTMLInputElement,
React.HTMLAttributes<HTMLDivElement> & {className:string, label:string}>
(({className, label}, ref) => {
const SearchInput = React.forwardRef<HTMLInputElement, {className:string, label:string, textValue:string, setText:(val:string)=>void}>(({className, label, textValue, setText}, ref) => {
const changeText=(e:React.ChangeEvent<HTMLInputElement>)=>{
if(e?.target?.value) setText(e.target.value)
}
return (
<div className={className+" flex"} >
{label && <Label className="m-4 text-2xl w-1/4">{label}</Label>}
<Input className="ml-8 w-3/4 text-lg" ref={ref}></Input>
<div className={className+" flex items-center"} >
{label && <Label className="w-20 text-base text-gray-600">{label}</Label>}
<Input className="flex-1 ml-8 w-3/4 h-10 border rounded" value={textValue} onChange={changeText}></Input>
</div>
)
});
export { SearchInput };
export { SearchInput };
@@ -11,19 +11,23 @@ export type SelectDataType = {
* @param label - string label
* @param selectData - SelectDataType[] 선택 데이터
* @param onSelectValue - (val:string)=>void 선택 값 콜백
* @param textValue - string 입력 값
* @param setText - (val:string)=>void 입력 값 설정 콜백
* @param selectValue - string select 선택 값
* @param refs - React.forwardRef<HTMLInputElement> | null 입력값 ref
* @returns React.FC
*/
const SearchInputSelect = React.forwardRef<HTMLInputElement, {className:string, label:string, selectData: SelectDataType[], onSelectValue:(val:string)=>void, textValue:string, setText:(val:string)=>void}>(({className, label, selectData, onSelectValue, textValue, setText}) => {
const SearchInputSelect = React.forwardRef<HTMLInputElement, {className:string, label:string, selectData: SelectDataType[], onSelectValue:(val:string)=>void, textValue:string, setText:(val:string)=>void, selectValue:string}>(({className, label, selectData, onSelectValue, textValue, setText, selectValue}, ref) => {
const changeText=(e:React.ChangeEvent<HTMLInputElement>)=>{
if(e?.target?.value) setText(e.target.value)
}
return (
<div className={className+" flex items-center"} >
{label && <Label className="m-4 text-2xl w-1/4">{label}</Label>}
{label && <Label className="w-20 text-base text-gray-600">{label}</Label>}
<div className="flex w-full items-center">
<Input className="w-2/3 text-lg" value={textValue} onChange={changeText} />
<Select onValueChange={onSelectValue}>
<Input className="w-2/3 text-lg h-10 p-2 border rounded" value={textValue} onChange={changeText} />
<Select onValueChange={onSelectValue} value={selectValue}>
<SelectTrigger className="ml-2 w-1/3 text-lg" >
<SelectValue placeholder={selectData?.[0]?.text ?? ""} />
</SelectTrigger>
@@ -38,4 +42,4 @@ const SearchInputSelect = React.forwardRef<HTMLInputElement, {className:string,
</div>
)
});
export { SearchInputSelect };
export { SearchInputSelect };
@@ -5,26 +5,32 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from ".
/** 차트 기본 스타일 */
interface SelectBox1 {
text:string,
val:string
val:string|number
}
const SelectBox = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & {label:string, selectClass:string|undefined, className:string, selectArray:SelectBox1[], onSelectValue:(val:string)=>void}
>(({ label, className, selectClass, selectArray, onSelectValue }, ref)=>{
React.HTMLAttributes<HTMLDivElement> & {
label:string,
selectClass:string|undefined,
className:string,
selectArray:SelectBox1[],
onSelectValue:(val:string|number)=>void,
value?: string|number
}
>(({ label, className, selectClass, selectArray, onSelectValue, value }, ref)=>{
const placeHolder = selectArray?.[0]?.text ?? "";
return (
<div className={className+" flex items-center"} ref={ref}>
{label && <Label className="m-4 text-2xl w-1/4">{label}</Label>}
<Select onValueChange={onSelectValue}>
<SelectTrigger className={selectClass?selectClass:"ml-8 w-3/4 text-2xl"}>
{label && <Label className="w-20 text-base text-gray-600">{label}</Label>}
<Select onValueChange={onSelectValue} value={value !== undefined ? String(value) : undefined}>
<SelectTrigger className={selectClass?selectClass:"flex-1 p-2 border rounded"}>
<SelectValue placeholder={placeHolder} />
</SelectTrigger>
<SelectContent>
{selectArray.map((selectArray) => (
<SelectItem key={selectArray.val} value={selectArray.val}>{selectArray.text}</SelectItem>
<SelectItem key={selectArray.val} value={String(selectArray.val)}>{selectArray.text}</SelectItem>
))}
</SelectContent>
</Select>
@@ -0,0 +1,36 @@
import { Tabs, TabsList, TabsTrigger } from '@common/components/ui';
import React from 'react';
interface TabItem {
value: string;
label: string;
}
interface UITabProps extends React.HTMLAttributes<HTMLDivElement> {
defaultValue?: string;
tabList: TabItem[];
children: React.ReactNode;
}
const UITab = React.forwardRef<
HTMLDivElement,
UITabProps
>(({defaultValue, tabList, children}, ref)=>{
return (
<Tabs defaultValue={defaultValue || tabList[0]?.value} className={"w-full space-x-1 border-b border-gray-200"}>
<TabsList className="flex space-x-1">
{tabList.map((tab) => (
<TabsTrigger
key={tab.value}
value={tab.value}
className="py-2 px-4 text-sm font-medium border-b-2 focus:outline-none data-[state=active]:border-blue-500 data-[state=active]:text-blue-600 data-[state=inactive]:border-transparent data-[state=inactive]:text-gray-500 hover:text-gray-700 hover:border-gray-300"
>
{tab.label}
</TabsTrigger>
))}
</TabsList>
{children}
</Tabs>
)
})
export { UITab };
@@ -8,7 +8,7 @@ type UiTableProps = {
pageSize: number;
total: number;
children: React.ReactNode | undefined;
cellClick : (index:number)=>void | undefined;
cellClick : ((index:number|undefined)=>void) | undefined;
}
type UiHeadProps = {
@@ -21,28 +21,29 @@ export function UiTable({ tableData, headlist, pageSize, total, children, headNa
return (
<>
{headName ? headName : <></>}
<div className="card !m-[1.2rem] h-[49rem] overflow-auto !p-0">
<Table>
<TableHeader>
{headName ? <div className="card-header">
<h3 className="text-2xl font-medium text-label">{headName}</h3>
</div> : <></>}
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
<Table>
<TableHeader>
{children ? <>{children}</> : <TableRow>
{headlist?.map((head) => (
<TableHead key={head.id}>{head.title}</TableHead>
))}
</TableRow>}
</TableHeader>
<TableBody className='text-center'>
{tableData?.map((el: { [key: string]: string | number | boolean }, index) => (
<TableRow key={index + "row"} >
{headlist.map((head) => (
<TableCell onClick={()=>cellClick(index)} key={head.id + index}>{el[head.id]}</TableCell>
<TableCell className="cursor-pointer" onClick={()=>cellClick && cellClick(index)} key={head.id + index}>{el[head.id]}</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
{total <= 0 ? <></> : <UiPageNations total={total} cur={cur} pageSize={pageSize} />}
</Table>
{total <= 0 ? <></> : <UiPageNations total={total} cur={cur} pageSize={pageSize} />}
</div>
</>
);
@@ -0,0 +1,11 @@
import React from 'react'
function ContentsDiv(props: {children: React.ReactNode}) {
return (
<div className="card card-border !mt-6">
{props.children}
</div>
)
}
export { ContentsDiv };
@@ -0,0 +1,11 @@
import React from 'react'
function Title(props: {title: string}) {
return (
<h2 className="px-[1.8rem] pt-[2rem] text-[2.4rem] font-semibold text-title">
{props.title}
</h2>
)
}
export { Title };