diff options
Diffstat (limited to 'components/ui/text-utils.tsx')
| -rw-r--r-- | components/ui/text-utils.tsx | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/components/ui/text-utils.tsx b/components/ui/text-utils.tsx new file mode 100644 index 00000000..a3507dd0 --- /dev/null +++ b/components/ui/text-utils.tsx @@ -0,0 +1,131 @@ +"use client" + +import { useState } from "react" +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible" +import { ChevronDown, ChevronUp } from "lucide-react" + +export function TruncatedText({ + text, + maxLength = 50, + showTooltip = true +}: { + text: string | null + maxLength?: number + showTooltip?: boolean +}) { + if (!text) return <span className="text-muted-foreground">-</span> + + if (text.length <= maxLength) { + return <span>{text}</span> + } + + const truncated = text.slice(0, maxLength) + "..." + + if (!showTooltip) { + return <span>{truncated}</span> + } + + return ( + <TooltipProvider> + <Tooltip> + <TooltipTrigger asChild> + <span className="cursor-help border-b border-dotted border-gray-400"> + {truncated} + </span> + </TooltipTrigger> + <TooltipContent className="max-w-xs"> + <p className="whitespace-pre-wrap">{text}</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + ) +} + +export function ExpandableText({ + text, + maxLength = 100, + className = "" +}: { + text: string | null + maxLength?: number + className?: string +}) { + const [isExpanded, setIsExpanded] = useState(false) + + if (!text) return <span className="text-muted-foreground">-</span> + + if (text.length <= maxLength) { + return <span className={className}>{text}</span> + } + + return ( + <Collapsible open={isExpanded} onOpenChange={setIsExpanded}> + <div className={className}> + <CollapsibleTrigger asChild> + <button className="text-left w-full group"> + <span className="whitespace-pre-wrap"> + {isExpanded ? text : text.slice(0, maxLength) + "..."} + </span> + <span className="inline-flex items-center ml-2 text-blue-600 hover:text-blue-800"> + {isExpanded ? ( + <> + <ChevronUp className="w-3 h-3" /> + <span className="text-xs ml-1">접기</span> + </> + ) : ( + <> + <ChevronDown className="w-3 h-3" /> + <span className="text-xs ml-1">더보기</span> + </> + )} + </span> + </button> + </CollapsibleTrigger> + </div> + </Collapsible> + ) +} + +export function AddressDisplay({ + address, + addressEng, + postalCode, + addressDetail +}: { + address: string | null + addressEng: string | null + postalCode: string | null + addressDetail: string | null +}) { + const hasAnyAddress = address || addressEng || postalCode || addressDetail + + if (!hasAnyAddress) { + return <span className="text-muted-foreground">-</span> + } + + return ( + <div className="space-y-1"> + {postalCode && ( + <div className="text-xs text-muted-foreground"> + 우편번호: {postalCode} + </div> + )} + {address && ( + <div className="font-medium break-words"> + {address} + </div> + )} + {addressDetail && ( + <div className="text-sm text-muted-foreground break-words"> + {addressDetail} + </div> + )} + {addressEng && ( + <div className="text-sm text-muted-foreground break-words italic"> + {addressEng} + </div> + )} + </div> + ) +}
\ No newline at end of file |
