comment and footer
This commit is contained in:
parent
c0bbd74a34
commit
3caca2c7d5
20 changed files with 1585 additions and 6633 deletions
|
@ -10,9 +10,13 @@
|
|||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.0.17",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
"react-dom": "^18.3.1",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss": "^4.0.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.17.0",
|
||||
|
|
301
pnpm-lock.yaml
generated
301
pnpm-lock.yaml
generated
|
@ -8,6 +8,12 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.0.17
|
||||
version: 4.0.17(vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.2))
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
date-fns:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
|
@ -17,6 +23,12 @@ importers:
|
|||
react-dom:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1(react@18.3.1)
|
||||
tailwind-merge:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
tailwindcss:
|
||||
specifier: ^4.0.17
|
||||
version: 4.0.17
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: ^9.17.0
|
||||
|
@ -29,7 +41,7 @@ importers:
|
|||
version: 18.3.5(@types/react@18.3.18)
|
||||
'@vitejs/plugin-react-swc':
|
||||
specifier: ^3.5.0
|
||||
version: 3.7.2(vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.1))
|
||||
version: 3.7.2(vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.2))
|
||||
eslint:
|
||||
specifier: ^9.17.0
|
||||
version: 9.18.0(jiti@2.4.2)
|
||||
|
@ -50,7 +62,7 @@ importers:
|
|||
version: 8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3)
|
||||
vite:
|
||||
specifier: ^6.0.5
|
||||
version: 6.0.9(jiti@2.4.2)(lightningcss@1.29.1)
|
||||
version: 6.0.9(jiti@2.4.2)(lightningcss@1.29.2)
|
||||
|
||||
packages:
|
||||
|
||||
|
@ -440,6 +452,84 @@ packages:
|
|||
'@swc/types@0.1.17':
|
||||
resolution: {integrity: sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==}
|
||||
|
||||
'@tailwindcss/node@4.0.17':
|
||||
resolution: {integrity: sha512-LIdNwcqyY7578VpofXyqjH6f+3fP4nrz7FBLki5HpzqjYfXdF2m/eW18ZfoKePtDGg90Bvvfpov9d2gy5XVCbg==}
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.0.17':
|
||||
resolution: {integrity: sha512-3RfO0ZK64WAhop+EbHeyxGThyDr/fYhxPzDbEQjD2+v7ZhKTb2svTWy+KK+J1PHATus2/CQGAGp7pHY/8M8ugg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.0.17':
|
||||
resolution: {integrity: sha512-e1uayxFQCCDuzTk9s8q7MC5jFN42IY7nzcr5n0Mw/AcUHwD6JaBkXnATkD924ZsHyPDvddnusIEvkgLd2CiREg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.0.17':
|
||||
resolution: {integrity: sha512-d6z7HSdOKfXQ0HPlVx1jduUf/YtBuCCtEDIEFeBCzgRRtDsUuRtofPqxIVaSCUTOk5+OfRLonje6n9dF6AH8wQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.0.17':
|
||||
resolution: {integrity: sha512-EjrVa6lx3wzXz3l5MsdOGtYIsRjgs5Mru6lDv4RuiXpguWeOb3UzGJ7vw7PEzcFadKNvNslEQqoAABeMezprxQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17':
|
||||
resolution: {integrity: sha512-65zXfCOdi8wuaY0Ye6qMR5LAXokHYtrGvo9t/NmxvSZtCCitXV/gzJ/WP5ksXPhff1SV5rov0S+ZIZU+/4eyCQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.0.17':
|
||||
resolution: {integrity: sha512-+aaq6hJ8ioTdbJV5IA1WjWgLmun4T7eYLTvJIToiXLHy5JzUERRbIZjAcjgK9qXMwnvuu7rqpxzej+hGoEcG5g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.0.17':
|
||||
resolution: {integrity: sha512-/FhWgZCdUGAeYHYnZKekiOC0aXFiBIoNCA0bwzkICiMYS5Rtx2KxFfMUXQVnl4uZRblG5ypt5vpPhVaXgGk80w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.0.17':
|
||||
resolution: {integrity: sha512-gELJzOHK6GDoIpm/539Golvk+QWZjxQcbkKq9eB2kzNkOvrP0xc5UPgO9bIMNt1M48mO8ZeNenCMGt6tfkvVBg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.0.17':
|
||||
resolution: {integrity: sha512-68NwxcJrZn94IOW4TysMIbYv5AlM6So1luTlbYUDIGnKma1yTFGBRNEJ+SacJ3PZE2rgcTBNRHX1TB4EQ/XEHw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.0.17':
|
||||
resolution: {integrity: sha512-AkBO8efP2/7wkEXkNlXzRD4f/7WerqKHlc6PWb5v0jGbbm22DFBLbIM19IJQ3b+tNewQZa+WnPOaGm0SmwMNjw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.0.17':
|
||||
resolution: {integrity: sha512-7/DTEvXcoWlqX0dAlcN0zlmcEu9xSermuo7VNGX9tJ3nYMdo735SHvbrHDln1+LYfF6NhJ3hjbpbjkMOAGmkDg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide@4.0.17':
|
||||
resolution: {integrity: sha512-B4OaUIRD2uVrULpAD1Yksx2+wNarQr2rQh65nXqaqbLY1jCd8fO+3KLh/+TH4Hzh2NTHQvgxVbPdUDOtLk7vAw==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@tailwindcss/vite@4.0.17':
|
||||
resolution: {integrity: sha512-HJbBYDlDVg5cvYZzECb6xwc1IDCEM3uJi3hEZp3BjZGCNGJcTsnCpan+z+VMW0zo6gR0U6O6ElqU1OoZ74Dhww==}
|
||||
peerDependencies:
|
||||
vite: ^5.2.0 || ^6
|
||||
|
||||
'@types/estree@1.0.6':
|
||||
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
|
||||
|
||||
|
@ -550,6 +640,10 @@ packages:
|
|||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
clsx@2.1.1:
|
||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
|
@ -582,10 +676,13 @@ packages:
|
|||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
detect-libc@2.0.3:
|
||||
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
enhanced-resolve@5.18.1:
|
||||
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
esbuild@0.24.2:
|
||||
resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==}
|
||||
|
@ -705,6 +802,9 @@ packages:
|
|||
resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
graphemer@1.4.0:
|
||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||
|
||||
|
@ -766,68 +866,68 @@ packages:
|
|||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
lightningcss-darwin-arm64@1.29.1:
|
||||
resolution: {integrity: sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==}
|
||||
lightningcss-darwin-arm64@1.29.2:
|
||||
resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
lightningcss-darwin-x64@1.29.1:
|
||||
resolution: {integrity: sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==}
|
||||
lightningcss-darwin-x64@1.29.2:
|
||||
resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
lightningcss-freebsd-x64@1.29.1:
|
||||
resolution: {integrity: sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==}
|
||||
lightningcss-freebsd-x64@1.29.2:
|
||||
resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.29.1:
|
||||
resolution: {integrity: sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==}
|
||||
lightningcss-linux-arm-gnueabihf@1.29.2:
|
||||
resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.29.1:
|
||||
resolution: {integrity: sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==}
|
||||
lightningcss-linux-arm64-gnu@1.29.2:
|
||||
resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.29.1:
|
||||
resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==}
|
||||
lightningcss-linux-arm64-musl@1.29.2:
|
||||
resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.29.1:
|
||||
resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==}
|
||||
lightningcss-linux-x64-gnu@1.29.2:
|
||||
resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-linux-x64-musl@1.29.1:
|
||||
resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==}
|
||||
lightningcss-linux-x64-musl@1.29.2:
|
||||
resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.29.1:
|
||||
resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==}
|
||||
lightningcss-win32-arm64-msvc@1.29.2:
|
||||
resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
lightningcss-win32-x64-msvc@1.29.1:
|
||||
resolution: {integrity: sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==}
|
||||
lightningcss-win32-x64-msvc@1.29.2:
|
||||
resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
lightningcss@1.29.1:
|
||||
resolution: {integrity: sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==}
|
||||
lightningcss@1.29.2:
|
||||
resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
locate-path@6.0.0:
|
||||
|
@ -966,6 +1066,16 @@ packages:
|
|||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
tailwind-merge@3.0.2:
|
||||
resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==}
|
||||
|
||||
tailwindcss@4.0.17:
|
||||
resolution: {integrity: sha512-OErSiGzRa6rLiOvaipsDZvLMSpsBZ4ysB4f0VKGXUrjw2jfkJRd6kjRKV2+ZmTCNvwtvgdDam5D7w6WXsdLJZw==}
|
||||
|
||||
tapable@2.2.1:
|
||||
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
@ -1301,6 +1411,67 @@ snapshots:
|
|||
dependencies:
|
||||
'@swc/counter': 0.1.3
|
||||
|
||||
'@tailwindcss/node@4.0.17':
|
||||
dependencies:
|
||||
enhanced-resolve: 5.18.1
|
||||
jiti: 2.4.2
|
||||
tailwindcss: 4.0.17
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.0.17':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide@4.0.17':
|
||||
optionalDependencies:
|
||||
'@tailwindcss/oxide-android-arm64': 4.0.17
|
||||
'@tailwindcss/oxide-darwin-arm64': 4.0.17
|
||||
'@tailwindcss/oxide-darwin-x64': 4.0.17
|
||||
'@tailwindcss/oxide-freebsd-x64': 4.0.17
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.17
|
||||
'@tailwindcss/oxide-linux-arm64-gnu': 4.0.17
|
||||
'@tailwindcss/oxide-linux-arm64-musl': 4.0.17
|
||||
'@tailwindcss/oxide-linux-x64-gnu': 4.0.17
|
||||
'@tailwindcss/oxide-linux-x64-musl': 4.0.17
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.17
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.0.17
|
||||
|
||||
'@tailwindcss/vite@4.0.17(vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.2))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.0.17
|
||||
'@tailwindcss/oxide': 4.0.17
|
||||
lightningcss: 1.29.2
|
||||
tailwindcss: 4.0.17
|
||||
vite: 6.0.9(jiti@2.4.2)(lightningcss@1.29.2)
|
||||
|
||||
'@types/estree@1.0.6': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
@ -1393,10 +1564,10 @@ snapshots:
|
|||
'@typescript-eslint/types': 8.20.0
|
||||
eslint-visitor-keys: 4.2.0
|
||||
|
||||
'@vitejs/plugin-react-swc@3.7.2(vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.1))':
|
||||
'@vitejs/plugin-react-swc@3.7.2(vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.2))':
|
||||
dependencies:
|
||||
'@swc/core': 1.10.8
|
||||
vite: 6.0.9(jiti@2.4.2)(lightningcss@1.29.1)
|
||||
vite: 6.0.9(jiti@2.4.2)(lightningcss@1.29.2)
|
||||
transitivePeerDependencies:
|
||||
- '@swc/helpers'
|
||||
|
||||
|
@ -1441,6 +1612,8 @@ snapshots:
|
|||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
|
||||
clsx@2.1.1: {}
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
@ -1465,8 +1638,12 @@ snapshots:
|
|||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
optional: true
|
||||
detect-libc@2.0.3: {}
|
||||
|
||||
enhanced-resolve@5.18.1:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
tapable: 2.2.1
|
||||
|
||||
esbuild@0.24.2:
|
||||
optionalDependencies:
|
||||
|
@ -1627,6 +1804,8 @@ snapshots:
|
|||
|
||||
globals@15.14.0: {}
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
graphemer@1.4.0: {}
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
@ -1650,8 +1829,7 @@ snapshots:
|
|||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
jiti@2.4.2:
|
||||
optional: true
|
||||
jiti@2.4.2: {}
|
||||
|
||||
js-tokens@4.0.0: {}
|
||||
|
||||
|
@ -1674,51 +1852,50 @@ snapshots:
|
|||
prelude-ls: 1.2.1
|
||||
type-check: 0.4.0
|
||||
|
||||
lightningcss-darwin-arm64@1.29.1:
|
||||
lightningcss-darwin-arm64@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-darwin-x64@1.29.1:
|
||||
lightningcss-darwin-x64@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-freebsd-x64@1.29.1:
|
||||
lightningcss-freebsd-x64@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.29.1:
|
||||
lightningcss-linux-arm-gnueabihf@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.29.1:
|
||||
lightningcss-linux-arm64-gnu@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm64-musl@1.29.1:
|
||||
lightningcss-linux-arm64-musl@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-x64-gnu@1.29.1:
|
||||
lightningcss-linux-x64-gnu@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-x64-musl@1.29.1:
|
||||
lightningcss-linux-x64-musl@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.29.1:
|
||||
lightningcss-win32-arm64-msvc@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-win32-x64-msvc@1.29.1:
|
||||
lightningcss-win32-x64-msvc@1.29.2:
|
||||
optional: true
|
||||
|
||||
lightningcss@1.29.1:
|
||||
lightningcss@1.29.2:
|
||||
dependencies:
|
||||
detect-libc: 1.0.3
|
||||
detect-libc: 2.0.3
|
||||
optionalDependencies:
|
||||
lightningcss-darwin-arm64: 1.29.1
|
||||
lightningcss-darwin-x64: 1.29.1
|
||||
lightningcss-freebsd-x64: 1.29.1
|
||||
lightningcss-linux-arm-gnueabihf: 1.29.1
|
||||
lightningcss-linux-arm64-gnu: 1.29.1
|
||||
lightningcss-linux-arm64-musl: 1.29.1
|
||||
lightningcss-linux-x64-gnu: 1.29.1
|
||||
lightningcss-linux-x64-musl: 1.29.1
|
||||
lightningcss-win32-arm64-msvc: 1.29.1
|
||||
lightningcss-win32-x64-msvc: 1.29.1
|
||||
optional: true
|
||||
lightningcss-darwin-arm64: 1.29.2
|
||||
lightningcss-darwin-x64: 1.29.2
|
||||
lightningcss-freebsd-x64: 1.29.2
|
||||
lightningcss-linux-arm-gnueabihf: 1.29.2
|
||||
lightningcss-linux-arm64-gnu: 1.29.2
|
||||
lightningcss-linux-arm64-musl: 1.29.2
|
||||
lightningcss-linux-x64-gnu: 1.29.2
|
||||
lightningcss-linux-x64-musl: 1.29.2
|
||||
lightningcss-win32-arm64-msvc: 1.29.2
|
||||
lightningcss-win32-x64-msvc: 1.29.2
|
||||
|
||||
locate-path@6.0.0:
|
||||
dependencies:
|
||||
|
@ -1855,6 +2032,12 @@ snapshots:
|
|||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
tailwind-merge@3.0.2: {}
|
||||
|
||||
tailwindcss@4.0.17: {}
|
||||
|
||||
tapable@2.2.1: {}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
|
@ -1883,7 +2066,7 @@ snapshots:
|
|||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.1):
|
||||
vite@6.0.9(jiti@2.4.2)(lightningcss@1.29.2):
|
||||
dependencies:
|
||||
esbuild: 0.24.2
|
||||
postcss: 8.5.1
|
||||
|
@ -1891,7 +2074,7 @@ snapshots:
|
|||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.4.2
|
||||
lightningcss: 1.29.1
|
||||
lightningcss: 1.29.2
|
||||
|
||||
which@2.0.2:
|
||||
dependencies:
|
||||
|
|
438
src/App.tsx
438
src/App.tsx
|
@ -1,263 +1,211 @@
|
|||
import './common.css'
|
||||
import './minor.css'
|
||||
import './content.css'
|
||||
import './App.css'
|
||||
import { format } from 'date-fns';
|
||||
import { CommentItem, CommentListContainer, SubCommentData } from './Comment';
|
||||
import CommentHeader from './CommentHeader';
|
||||
import { Footer } from './Footer';
|
||||
import { GalleryContent } from './Gallery';
|
||||
import { GalleryTitleHeader } from './GalleryTitleHeader';
|
||||
import { GalleryTable, TableRowData } from './table';
|
||||
|
||||
|
||||
function getTimeFromNow(date: Date) {
|
||||
const now = new Date()
|
||||
if (now.getFullYear() !== date.getFullYear()) {
|
||||
return format(date, "yyyy.MM.dd")
|
||||
}
|
||||
return format(date, "HH:mm")
|
||||
}
|
||||
const tableData: TableRowData[] = [
|
||||
{ // Survey Example
|
||||
id: 2995,
|
||||
category: "설문",
|
||||
titleText: "어떤 상황이 와도 가족 안 굶길 것 같은 생활력 강해 보이는 스타는?",
|
||||
variant: "icon_survey",
|
||||
author: {
|
||||
type: "operator",
|
||||
},
|
||||
date: "25.03.24",
|
||||
views: "-",
|
||||
recommendations: "-",
|
||||
isAdOrSurvey: true,
|
||||
},
|
||||
{ // AD Example
|
||||
id: 2996,
|
||||
category: "AD",
|
||||
titleText: "트릭컬 지금 접속 시 죠안 확정권 지급",
|
||||
variant: "icon_ad",
|
||||
author: {
|
||||
type: "operator",
|
||||
},
|
||||
date: "25.03.28",
|
||||
views: "-",
|
||||
recommendations: "-",
|
||||
isAdOrSurvey: true,
|
||||
},
|
||||
{ // Notice Example 1
|
||||
id: 1012381,
|
||||
category: "공지",
|
||||
titleText: "3월 5주차 주던",
|
||||
commentCount: 7,
|
||||
variant: "icon_notice",
|
||||
author: {
|
||||
type: "nickname",
|
||||
nickname: "보배단",
|
||||
userType: "manager", // Optional, if applicable
|
||||
},
|
||||
date: "25.03.27",
|
||||
views: 3178,
|
||||
recommendations: 12,
|
||||
isNotice: true,
|
||||
},
|
||||
{ // Notice Example 2
|
||||
id: 784571,
|
||||
category: "공지",
|
||||
titleText: "인방 떡밥은 별도의 갤러리를 이용해주세요",
|
||||
commentCount: 3,
|
||||
variant: "icon_notice",
|
||||
author: {
|
||||
type: "nickname",
|
||||
nickname: "ㅇㅇ",
|
||||
userType: "submanager", // Optional, if applicable
|
||||
},
|
||||
date: "25.03.08",
|
||||
views: 7018,
|
||||
recommendations: 6,
|
||||
isNotice: true,
|
||||
},
|
||||
{ // Normal Row Example 1
|
||||
id: 1040045,
|
||||
category: "일반",
|
||||
titleText: "버서커 헬 졸업해도되는데 태초한번도 안떠서 계속 돌림",
|
||||
variant: "icon_pic",
|
||||
commentCount: 2,
|
||||
author: {
|
||||
type: "nickname",
|
||||
nickname: "븜구리",
|
||||
userType: "manager", // Optional, if applicable
|
||||
},
|
||||
date: "21:58",
|
||||
views: 4,
|
||||
recommendations: 0,
|
||||
},
|
||||
{ // Normal Row Example 2 (IP Author)
|
||||
id: 1040043,
|
||||
category: "일반",
|
||||
titleText: "혹시 엘마가 진각무기압타 빗자루 쓸 수 있음?",
|
||||
variant: "icon_txt",
|
||||
author: {
|
||||
type: "IP",
|
||||
ip: "1.248",
|
||||
},
|
||||
date: "21:58",
|
||||
views: 1,
|
||||
recommendations: 0,
|
||||
},
|
||||
// ... Add all other rows from the original HTML here
|
||||
{ // News Row Example
|
||||
id: '', // No ID
|
||||
category: "뉴스",
|
||||
titleText: "'2025 조치원 봄꽃축제' 개최 소식 밝혀",
|
||||
variant: "icon_dctrend",
|
||||
date: "18:00",
|
||||
views: "",
|
||||
recommendations: "",
|
||||
isNews: true,
|
||||
titleLinkUrl: '#', // Add actual URL
|
||||
},
|
||||
];
|
||||
|
||||
type Writer = {
|
||||
type: "유동닉",
|
||||
/**
|
||||
* IP address without the last two octet
|
||||
* e.g. "192.168"
|
||||
*/
|
||||
ip: string
|
||||
} | {
|
||||
type: "반유동"
|
||||
} | {
|
||||
type: "고닉",
|
||||
nickname: string,
|
||||
완장?: "주딱" | "파딱"
|
||||
} | {
|
||||
type: "운영자"
|
||||
};
|
||||
|
||||
interface GalleryTableRowProps {
|
||||
id: number
|
||||
subject: string
|
||||
title: string
|
||||
replyCount: number
|
||||
writer: Writer
|
||||
type: "icon_notice" | "icon_pic" | "icon_txt" | "icon_survey"
|
||||
date: Date
|
||||
viewCount: number
|
||||
recommendCount: number
|
||||
fixed?: boolean
|
||||
}
|
||||
// Sample data - replace with your actual data source/props
|
||||
const comments: SubCommentData[] = [
|
||||
{
|
||||
id: 1,
|
||||
author: { type: 'IP', ip: '222.116' }, // Assuming author is an object with type and name
|
||||
text: '너 지금 상현이햄을 ■■라고',
|
||||
timestamp: '03.31 17:44:25',
|
||||
showDelete: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
||||
const NicknameImagePath = {
|
||||
"주딱": "/fix_managernik.gif",
|
||||
"파딱": "/fix_sub_managernik.gif",
|
||||
"반유동": "/nik.gif",
|
||||
"default": "/fix_nik.gif"
|
||||
}
|
||||
function RenderWriter({ writer }: { writer: Writer }) {
|
||||
const type = writer.type;
|
||||
if (type === "운영자") {
|
||||
return <span className="nickname in" title="운영자"><em>운영자</em></span>
|
||||
}
|
||||
const nickname = writer.type === "고닉" ? writer.nickname : "ㅇㅇ";
|
||||
return <>
|
||||
<span className="nickname in" title={nickname}><em>{nickname}</em></span>
|
||||
{writer.type === "유동닉" && <span className="ip">({writer.ip})</span>}
|
||||
<span className="writer_nikcon">
|
||||
{writer.type === "고닉" && <img src={NicknameImagePath[writer.완장 ?? "default"]} title={`${nickname} : 완장`}
|
||||
width="12" height="11" style={{ "cursor": "pointer", marginLeft: "2px" }}
|
||||
alt="갤로그로 이동합니다." />}
|
||||
{writer.type === "반유동" && <img src={NicknameImagePath["반유동"]} title={`${nickname} : 닉네임`}
|
||||
width="12" height="11" style={{ "cursor": "pointer", marginLeft: "2px" }}
|
||||
alt="갤로그로 이동합니다." />}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
author: { type: "IP", ip: "218.144" },
|
||||
text: '미국인들도 저사람 얘기할때마다 동양인이 어쩌고랑 엮는데 왤케화남ㅋㅋ',
|
||||
timestamp: '03.31 18:16:45',
|
||||
showDelete: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
|
||||
function GalleryTableRow(
|
||||
{
|
||||
id,
|
||||
subject,
|
||||
title,
|
||||
replyCount,
|
||||
writer,
|
||||
type,
|
||||
date,
|
||||
viewCount,
|
||||
recommendCount,
|
||||
fixed = false,
|
||||
}: GalleryTableRowProps
|
||||
) {
|
||||
const wrap = (node: React.ReactNode) => fixed ? <b>{node}</b> : node;
|
||||
author: { type: "IP", ip: "183.96" },
|
||||
|
||||
return <tr className="ub-content us-post" data-no={id.toString()} data-type={type}>
|
||||
<td className="gall_num">{id}</td>
|
||||
<td className="gall_subject"><b>{subject}</b></td>
|
||||
<td className="gall_tit ub-word">
|
||||
<a href="/mgallery/board/view/?id=genrenovel&no=9101266&page=1" view-msg="">
|
||||
<em className={`icon_img ${type}`}></em>
|
||||
{wrap(title)}
|
||||
</a>
|
||||
<a className="reply_numbox">
|
||||
<span className="reply_num">[{replyCount}]</span>
|
||||
</a>
|
||||
</td>
|
||||
<td className="gall_writer ub-writer" data-nick={writer} data-ip="" data-loc="list">
|
||||
{wrap(
|
||||
<RenderWriter writer={writer} />
|
||||
)}
|
||||
</td>
|
||||
<td className="gall_date" title={format(date, "yyyy-MM-dd hh:mm:ss")}>
|
||||
{getTimeFromNow(date)}
|
||||
</td>
|
||||
<td className="gall_count">{viewCount}</td>
|
||||
<td className="gall_recommend">{recommendCount}</td>
|
||||
</tr>
|
||||
}
|
||||
text: '다른 나라랑 다르게 미국에선 ~계 미국인이라는 정체성이 확고하고 사회적인 인식도 그럼',
|
||||
timestamp: '03.31 18:18:40',
|
||||
showDelete: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
author: { type: "semi-nickname", nickname: "ㅇㅇ" },
|
||||
text: '이새낀 미국을 모르노 ㅋㅋㅋㅋ',
|
||||
timestamp: '03.31 20:34:54',
|
||||
showDelete: false, // No delete button in this example
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
author: { type: "semi-nickname", nickname: "ㅇㅇ" },
|
||||
text: '어어 내려놔라',
|
||||
timestamp: '03.31 21:16:46',
|
||||
showDelete: false,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
author: { type: "nickname", nickname: '티르칸쟈카' },
|
||||
text: '원종원종아...',
|
||||
timestamp: '03.31 21:23:59',
|
||||
showDelete: false,
|
||||
},
|
||||
// Add more comment objects as needed
|
||||
];
|
||||
|
||||
function GalleryTable() {
|
||||
return <div className='gall_listwrap list'>
|
||||
<table className="gall_list">
|
||||
<caption>갤러리 리스트</caption>
|
||||
<colgroup>
|
||||
<col style={{ "width": "7%" }} />
|
||||
<col style={{ "width": "51px" }} />
|
||||
<col />
|
||||
<col style={{ "width": "18%" }} />
|
||||
<col style={{ "width": "6%" }} />
|
||||
<col style={{ "width": "6%" }} />
|
||||
<col style={{ "width": "6%" }} />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">번호</th>
|
||||
<th scope="col">말머리</th>
|
||||
<th scope="col">제목</th>
|
||||
<th scope="col">글쓴이</th>
|
||||
<th scope="col">작성일</th>
|
||||
<th scope="col">조회</th>
|
||||
<th scope="col">추천</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="listwrap2 ">
|
||||
|
||||
<GalleryTableRow
|
||||
id={2973}
|
||||
subject="설문"
|
||||
title="입금 전,후 관리에 따라 외모 갭이 큰 스타는?"
|
||||
writer={{ type: "운영자" }}
|
||||
type="icon_survey"
|
||||
date={new Date("2025-01-20 22:52:52")}
|
||||
viewCount={0}
|
||||
recommendCount={0}
|
||||
replyCount={0}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9101266}
|
||||
subject="공지"
|
||||
title="장르소설 마이너 갤러리 공지 모음"
|
||||
writer={{ type: "고닉", nickname: "apocalypse", 완장: "파딱" }}
|
||||
type="icon_notice"
|
||||
date={new Date("2024-08-08 23:55:43")}
|
||||
viewCount={35080}
|
||||
recommendCount={21}
|
||||
replyCount={18}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9073478}
|
||||
subject="공지"
|
||||
title="주딱 문의글"
|
||||
writer={{ type: "유동닉", ip: "223.39" }}
|
||||
type="icon_notice"
|
||||
date={new Date("2024-08-04 07:24:58")}
|
||||
viewCount={45439}
|
||||
recommendCount={24}
|
||||
replyCount={28}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9056755}
|
||||
subject="공지"
|
||||
title="신문고"
|
||||
writer={{ type: "유동닉", ip: "118.235" }}
|
||||
type="icon_notice"
|
||||
date={new Date("2024-08-01 06:47:52")}
|
||||
viewCount={141598}
|
||||
recommendCount={45}
|
||||
replyCount={11}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9861519}
|
||||
subject="리뷰"
|
||||
title="[리뷰대회]이민갔는데 딸이 생겼다"
|
||||
writer={{ type: "고닉", nickname: "나이브르" }}
|
||||
type="icon_pic"
|
||||
date={new Date("2025-01-20 22:52:52")}
|
||||
viewCount={10}
|
||||
recommendCount={1}
|
||||
replyCount={2}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9861518}
|
||||
subject="일반"
|
||||
title="사펑불퇴 비처녀 음해는 그냥 글을 안읽은거 아니냐?"
|
||||
writer={{ type: "유동닉", ip: "118.45" }}
|
||||
type="icon_txt"
|
||||
date={new Date("2025-01-20 22:52:51")}
|
||||
viewCount={9}
|
||||
recommendCount={0}
|
||||
replyCount={0}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9861517}
|
||||
subject="일반"
|
||||
title="역변영애 칼릭스를 진 남주로 할거였으면"
|
||||
writer={{ type: "유동닉", ip: "220.89" }}
|
||||
type="icon_txt"
|
||||
date={new Date("2025-01-20 22:52:42")}
|
||||
viewCount={5}
|
||||
recommendCount={0}
|
||||
replyCount={0}
|
||||
/>
|
||||
|
||||
<GalleryTableRow
|
||||
id={9861516}
|
||||
subject="일반"
|
||||
title="미3술가 좀 식네"
|
||||
writer={{ type: "고닉", nickname: "오이탕후루" }}
|
||||
type="icon_pic"
|
||||
date={new Date("2025-01-20 22:52:31")}
|
||||
viewCount={7}
|
||||
recommendCount={0}
|
||||
replyCount={1}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
width: "1160px",
|
||||
margin: "20px auto 0",
|
||||
}}
|
||||
<div>
|
||||
<main
|
||||
className='w-[1160px] m-[20px_auto_0]'
|
||||
>
|
||||
<GalleryTitleHeader />
|
||||
<div
|
||||
style={{
|
||||
borderTop: "2px solid #29367c",
|
||||
width: "1158px"
|
||||
}}
|
||||
/>
|
||||
<GalleryContent />
|
||||
</div>
|
||||
<GalleryTable />
|
||||
</>
|
||||
<section className='' >
|
||||
<GalleryTitleHeader />
|
||||
<div
|
||||
className='border-custom-blue-dark border-2 w-[1158px]'
|
||||
/>
|
||||
<GalleryContent />
|
||||
<CommentHeader />
|
||||
<CommentListContainer>
|
||||
<CommentItem comment={{
|
||||
id: 1,
|
||||
author: { type: "nickname", nickname: "동아리망했다" },
|
||||
text: '너 지금 상현이햄을 ■■라고',
|
||||
timestamp: '03.31 17:44:25',
|
||||
showDelete: true,
|
||||
}} />
|
||||
<CommentItem comment={{
|
||||
id: 2,
|
||||
author: { type: "IP", ip: "218.144" },
|
||||
text: '그냥 미국인인데 조센징들은 왜 조선계라고 못 넣어서 안달일까',
|
||||
timestamp: '03.31 18:16:45',
|
||||
showDelete: true,
|
||||
subComments: comments,
|
||||
}} />
|
||||
<CommentItem comment={{
|
||||
id: 3,
|
||||
author: { type: "IP", ip: "123.245" },
|
||||
text: 'aaa',
|
||||
timestamp: '03.31 18:16:45',
|
||||
showDelete: true,
|
||||
}} />
|
||||
</CommentListContainer>
|
||||
<div style={{
|
||||
width: "840px",
|
||||
}}>
|
||||
<GalleryTable data={tableData} />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
32
src/Button.tsx
Normal file
32
src/Button.tsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { cn } from "./util/cn";
|
||||
|
||||
|
||||
export function Button({ children, className, onClick }: {
|
||||
children: React.ReactNode; className?: string; onClick?: () => void
|
||||
}) {
|
||||
return <button
|
||||
onClick={onClick}
|
||||
className={cn(`
|
||||
bg-[#3b4890]
|
||||
text-white
|
||||
text-shadow-[#1d2761_0px_-1px]
|
||||
cursor-pointer
|
||||
align-middle
|
||||
text-sm
|
||||
font-apple
|
||||
font-bold
|
||||
w-[82px]
|
||||
h-[35px]
|
||||
pr-0.5
|
||||
leading-[31px]
|
||||
ml-[3px]
|
||||
border
|
||||
border-solid
|
||||
border-custom-blue-dark
|
||||
border-b-[3px]
|
||||
rounded-xs
|
||||
`, className)}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
}
|
185
src/Comment.tsx
Normal file
185
src/Comment.tsx
Normal file
|
@ -0,0 +1,185 @@
|
|||
import { AuthorData } from "./table";
|
||||
|
||||
interface CommentDataBase {
|
||||
id: number;
|
||||
author: AuthorData;
|
||||
text: string;
|
||||
timestamp: string;
|
||||
showDelete?: boolean;
|
||||
}
|
||||
export interface SubCommentData extends CommentDataBase {
|
||||
parentId?: number;
|
||||
}
|
||||
export interface CommentData extends CommentDataBase {
|
||||
subComments?: SubCommentData[]; // Optional sub-comments
|
||||
}
|
||||
|
||||
export function CommentListContainer({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return <ul className="list-none pl-0 m-0 text-[13px]">{children}</ul>
|
||||
}
|
||||
export function CommentItem({ comment }: { comment: CommentData }) {
|
||||
const renderSubComments = () => {
|
||||
if (comment.subComments && comment.subComments.length > 0) {
|
||||
return (
|
||||
<CommentReplySection comments={comment.subComments} />
|
||||
);
|
||||
}
|
||||
return null; // No sub-comments to render
|
||||
}
|
||||
return <>
|
||||
<li className="bg-transparent text-[13px]">
|
||||
<div className="border-t relative border-custom-gray-light px-[3px] pt-[9px] pb-[7px] flex"
|
||||
>
|
||||
<div style={{
|
||||
width: '132px', marginRight: '33px', marginTop: '3px',
|
||||
lineHeight: '13px'
|
||||
}}>
|
||||
<span className="relative text-[13px] cursor-pointer inline">
|
||||
<span style={{
|
||||
fontSize: '12px',
|
||||
color: 'rgb(119, 119, 119)',
|
||||
verticalAlign: 'top'
|
||||
}}
|
||||
className="font-normal"
|
||||
>
|
||||
<em
|
||||
className="overflow-hidden text-ellipsis not-italic
|
||||
align-tops pr-px inline-block text-nowrap max-w-[110px]"
|
||||
> {comment.author.type === 'nickname' ? comment.author.nickname : 'ㅇㅇ'} </em>
|
||||
</span>
|
||||
{comment.author.type === 'nickname' && (
|
||||
<a className="text-custom-gray-dark inline">
|
||||
<img
|
||||
className="inline-block align-middle cursor-pointer"
|
||||
src="/fix_nik.gif" alt="icon"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{
|
||||
width: '820px', cursor: 'pointer'
|
||||
}}
|
||||
className="flex-1"
|
||||
>
|
||||
<p style={{
|
||||
lineHeight: '20px', cursor: 'pointer',
|
||||
wordBreak: 'break-all',
|
||||
overflowX: 'hidden', overflowY: 'hidden', width: '820px'
|
||||
}}
|
||||
className="overflow-hidden break-all cursor-pointer"
|
||||
> {comment.text} </p>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-custom-gray-medium align-middle mt-px text-[12px] float-left">
|
||||
{comment.timestamp}
|
||||
</span>
|
||||
{comment.showDelete && (
|
||||
<div className="flex items-center justify-end ml-[6px] relative">
|
||||
<button className="
|
||||
bg-sp-img bg-[-268px_-200px] w-[13px] h-[13px]
|
||||
align-top font-apple-dotum
|
||||
" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{renderSubComments()}
|
||||
</>
|
||||
}
|
||||
|
||||
function CommentReplyItem({ comment }: { comment: SubCommentData }) {
|
||||
// Function to handle potential HTML in author name
|
||||
const renderAuthor = () => {
|
||||
const authorMaxWidth = comment.author.type === 'IP' ? '84px' : '107px'; // Default to 107px if not specified
|
||||
return (
|
||||
<em
|
||||
className="inline-block text-ellipsis overflow-hidden whitespace-nowrap align-top not-italic text-custom-gray-dark"
|
||||
style={{ maxWidth: authorMaxWidth }} // Apply dynamic max-width
|
||||
>
|
||||
{comment.author.type === 'nickname' ? comment.author.nickname : 'ㅇㅇ'}
|
||||
</em>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<li className="bg-transparent pt-[9px] pr-3 pb-[7px] pl-3 border-t border-solid border-gray-300 first:border-t-0">
|
||||
<div className="bg-transparent relative flow-root"> {/* Use flow-root to contain floats */}
|
||||
{/* Author Info */}
|
||||
<div className="bg-transparent float-left w-[133px] mr-[23px] mt-[3px] leading-[13px]">
|
||||
<span className="bg-transparent relative text-[13px] cursor-pointer">
|
||||
<span className="bg-transparent text-xs text-gray-700 align-top">
|
||||
{renderAuthor()}
|
||||
{comment.author.type === "IP" && ( // Conditionally render IP if it exists
|
||||
<span className="bg-transparent font-tahoma text-[11px] text-custom-gray-medium inline-block align-[1px] ml-1">
|
||||
({comment.author.ip})
|
||||
</span>
|
||||
)}
|
||||
{comment.author.type === "nickname" && (
|
||||
<a
|
||||
className="text-custom-gray-dark inline ml-1"
|
||||
> <img
|
||||
className="inline-block align-middle cursor-pointer"
|
||||
src={
|
||||
comment.author.userType === "manager" ? "/fix_managernik.gif" :
|
||||
comment.author.userType === "submanager" ? "/fix_sub_managernik.gif" :
|
||||
"/fix_nik.gif"} alt="icon"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Timestamp and Actions (float right first in source order for correct float behavior) */}
|
||||
<div className="bg-transparent float-right">
|
||||
<span className="bg-transparent float-left text-xs text-custom-gray-medium align-top mt-[1px] mr-2">
|
||||
{comment.timestamp}
|
||||
</span>
|
||||
{comment.showDelete && ( // Conditionally render delete button
|
||||
<div className="bg-transparent float-right relative top-[3px] right-0">
|
||||
{/* Using top-[3px] might need adjustment based on exact alignment needs */}
|
||||
<button
|
||||
title="삭제" // Add title for accessibility
|
||||
className="bg-transparent cursor-pointer align-top text-[0px] font-apple-dotum text-custom-gray-medium bg-sp-img bg-[-268px_-200px] leading-none w-[13px] h-[13px]"
|
||||
>
|
||||
삭제 {/* Text hidden by text-[0px] but good for screen readers */}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Comment Text */}
|
||||
{/* Note: Original has width 820px container and 774px text. Simulating this might require careful flex/grid or removing float here */}
|
||||
{/* Simplified approach: Let text flow, adjust margins if needed */}
|
||||
<div className="bg-transparent overflow-hidden cursor-default"> {/* Use overflow-hidden to contain the text after floats */}
|
||||
<p className="leading-5 cursor-default break-words pl-0">
|
||||
{/* Removed float, width, relative, padding-left: 16px from original P. Adjust if layout breaks */}
|
||||
{/* Original P had pl-16px (pl-4). Let's add it back relative to the start of this div */}
|
||||
<span className="inline-block pl-4">{comment.text}</span> {/* Wrapped text in span to apply padding */}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export function CommentReplySection({ comments }: { comments: SubCommentData[] }) {
|
||||
return (
|
||||
<div className="bg-transparent overflow-hidden h-full text-[13px]"> {/* Assuming full height needed */}
|
||||
<div className="bg-gray-50 mb-3 ml-[30px] border border-solid border-gray-300">
|
||||
<ul className="bg-transparent list-none">
|
||||
{comments.map((comment) => (
|
||||
<CommentReplyItem key={comment.id} comment={comment} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
136
src/CommentHeader.tsx
Normal file
136
src/CommentHeader.tsx
Normal file
|
@ -0,0 +1,136 @@
|
|||
import { useState } from 'react';
|
||||
import { Separator } from './Separator';
|
||||
|
||||
function CommentHeader({
|
||||
onCloseComment,
|
||||
commentCount = 0,
|
||||
commnetClosed = false,
|
||||
}: {
|
||||
onCloseComment?: (c: boolean) => void;
|
||||
commentCount?: number;
|
||||
commnetClosed?: boolean;
|
||||
}) {
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
const [selectedSort, setSelectedSort] = useState('등록순'); // Default sort option
|
||||
|
||||
const sortOptions = ['등록순', '최신순', '답글순']; // Changed '답글수' to '답글순' to match list item
|
||||
|
||||
const handleSortSelection = (option: string) => {
|
||||
setSelectedSort(option);
|
||||
setIsDropdownOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-[38px] leading-[38px] font-bold flex items-center justify-between bg-transparent text-[12px]">
|
||||
{/* Left Section */}
|
||||
<div className="flex items-center space-x-1">
|
||||
<span>전체 댓글</span>
|
||||
<em className="text-custom-red-text not-italic font-normal bg-transparent">
|
||||
<span className="bg-transparent">{commentCount}</span>
|
||||
</em>
|
||||
<span>개</span>
|
||||
|
||||
{/* Custom Dropdown */}
|
||||
<div className="relative inline-block ml-1 box-border leading-0"> {/* Adjusted margin from original margin-left: 4px */}
|
||||
<div
|
||||
className="relative inline-block bg-white w-[55px] h-[19px] pl-[5px] border border-custom-border-gray text-[11px]
|
||||
text-custom-gray-dark leading-[18px] align-[1px] cursor-pointer font-normal font-apple-dotum"
|
||||
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
|
||||
>
|
||||
<span className="bg-transparent">{selectedSort}</span>
|
||||
<span className="sr-only">정렬 기준선택</span> {/* Screen reader only text */}
|
||||
<em className="inline-block absolute right-[5px] top-[7px] w-[9px] h-[5px] bg-sp-img bg-[-126px_-43px]"></em>
|
||||
</div>
|
||||
|
||||
{/* Dropdown List */}
|
||||
{isDropdownOpen && (
|
||||
<ul className="absolute box-border left-[-1px] top-[19px] z-20 w-[62px] list-none bg-custom-dropdown-bg border border-custom-border-gray pt-[6px] px-[5px] pb-[4px]">
|
||||
{sortOptions.map((option) => (
|
||||
// Original had strange inline-block and font-size: 0px. Using block and sensible text size.
|
||||
<li
|
||||
key={option}
|
||||
className="block leading-[16px] text-xs text-custom-dropdown-text font-normal font-apple-dotum cursor-pointer hover:bg-gray-200" // Added hover state
|
||||
onClick={() => handleSortSelection(option)}
|
||||
>
|
||||
{option}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{/* Hidden Select (kept for structure reference, usually not needed with custom dropdown) */}
|
||||
<select className="hidden absolute top-0 left-0 w-full h-full opacity-0 cursor-pointer font-apple-dotum text-xs align-middle">
|
||||
<option>등록순</option>
|
||||
<option>최신순</option>
|
||||
<option>답글순</option> {/* Changed from 답글수 */}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Hidden Reply Expand Button */}
|
||||
<button className="hidden cursor-pointer align-middle font-apple-dotum text-xs h-[21px] ml-[71px] mt-[-1px]">
|
||||
<span className="sr-only">답글 펼침 설정</span>
|
||||
<em className="inline-block w-[21px] h-[21px] bg-sp-img bg-[-84px_-52px]"></em>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Right Section */}
|
||||
<div className="flex items-center"> {/* Use space-x for spacing */}
|
||||
<a href="#" className="text-custom-gray-dark align-middle leading-[15px] font-apple text-[13px] font-bold no-underline hover:underline">
|
||||
본문 보기
|
||||
</a>
|
||||
<Separator className='mx-2.5' />
|
||||
<button className="cursor-pointer align-middle font-apple text-[13px] text-custom-gray-dark font-bold flex items-center"
|
||||
onClick={() => onCloseComment?.(!commnetClosed)}
|
||||
>
|
||||
{commnetClosed ? (<>
|
||||
<span className="font-apple text-[13px] text-custom-gray-dark font-bold">댓글열기</span>
|
||||
<em className="inline-block w-[9px] h-[5px] bg-sp-img bg-[-115px_-43px] ml-1 align-[2px]"></em>
|
||||
</>) : (
|
||||
<>
|
||||
<span className="font-apple text-[13px] text-custom-gray-dark font-bold">댓글닫기</span>
|
||||
<em className="inline-block w-[9px] h-[5px] bg-sp-img bg-[-84px_-52px] ml-1 align-[2px]"></em>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<Separator className='mx-2.5' />
|
||||
<button className="cursor-pointer align-middle font-apple text-[13px] text-custom-gray-dark font-bold">
|
||||
새로고침
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function CommentMenuList({
|
||||
onCloseComment,
|
||||
commnetClosed = false,
|
||||
}: {
|
||||
onCloseComment?: (c: boolean) => void;
|
||||
commnetClosed?: boolean;
|
||||
}) {
|
||||
return <div className="flex items-center"> {/* Use space-x for spacing */}
|
||||
<a href="#" className="text-custom-gray-dark align-middle leading-[15px] font-apple text-[13px] font-bold no-underline hover:underline">
|
||||
본문 보기
|
||||
</a>
|
||||
<Separator className='mx-2.5' />
|
||||
<button className="cursor-pointer align-middle font-apple text-[13px] text-custom-gray-dark font-bold flex items-center"
|
||||
onClick={() => onCloseComment?.(!commnetClosed)}
|
||||
>
|
||||
{commnetClosed ? (<>
|
||||
<span className="font-apple text-[13px] text-custom-gray-dark font-bold">댓글열기</span>
|
||||
<em className="inline-block w-[9px] h-[5px] bg-sp-img bg-[-115px_-43px] ml-1 align-[2px]"></em>
|
||||
</>) : (
|
||||
<>
|
||||
<span className="font-apple text-[13px] text-custom-gray-dark font-bold">댓글닫기</span>
|
||||
<em className="inline-block w-[9px] h-[5px] bg-sp-img bg-[-84px_-52px] ml-1 align-[2px]"></em>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<Separator className='mx-2.5' />
|
||||
<button className="cursor-pointer align-middle font-apple text-[13px] text-custom-gray-dark font-bold">
|
||||
새로고침
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
export default CommentHeader;
|
203
src/Footer.tsx
Normal file
203
src/Footer.tsx
Normal file
|
@ -0,0 +1,203 @@
|
|||
export function Footer() {
|
||||
return <footer
|
||||
className="bg-white pb-[50px]"
|
||||
>
|
||||
<div
|
||||
className="w-[1158px] mt-[20px] mx-auto border-x border-t-2 border-b
|
||||
border-x-[#cccccc] border-y-custom-blue-dark"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className="overflow-hidden flex items-center pt-[21px] pb-[30px] border-b border-b-[#cccccc]
|
||||
min-h-[108px]"
|
||||
>
|
||||
{[{
|
||||
title: "게임",
|
||||
items: [
|
||||
"던전앤파이터",
|
||||
"메이플스토리",
|
||||
"아이돌마스터",
|
||||
"리그 오브 레전드",
|
||||
"마비노기",
|
||||
"로스트아크",
|
||||
"FC 온라인",
|
||||
"승리의 여신 니케",
|
||||
"사운드 볼텍스",
|
||||
"포켓몬스터"
|
||||
]
|
||||
}, {
|
||||
title: "연예/방송",
|
||||
items: [
|
||||
"남자 연예인",
|
||||
"여자 연예인",
|
||||
"방탄소년단",
|
||||
"아이유",
|
||||
"태연",
|
||||
"기타 국내 드라마",
|
||||
"걸스플래닛999",
|
||||
"백종원의 골목식당",
|
||||
"미스터 트롯",
|
||||
"기타 미국드라마"
|
||||
]
|
||||
}, {
|
||||
title: "스포츠",
|
||||
items: [
|
||||
"한화 이글스",
|
||||
"롯데 자이언츠",
|
||||
"해외야구",
|
||||
"삼성 라이온즈",
|
||||
"국내야구",
|
||||
"해외축구",
|
||||
"KIA 타이거즈",
|
||||
"LG 트윈스",
|
||||
"키움 히어로즈",
|
||||
"SSG 랜더스"
|
||||
]
|
||||
}, {
|
||||
title: "교육/금융/IT",
|
||||
items: [
|
||||
"비트코인",
|
||||
"부동산",
|
||||
"정치, 사회",
|
||||
"컴퓨터 본체",
|
||||
"테블릿PC",
|
||||
"자격증",
|
||||
"학점은행제",
|
||||
"토익",
|
||||
"주식",
|
||||
"일어"
|
||||
]
|
||||
}, {
|
||||
title: "여행/음식/생물",
|
||||
items: [
|
||||
"도시",
|
||||
"여행-일본",
|
||||
"편의점",
|
||||
"치킨",
|
||||
"기타음식",
|
||||
"주류",
|
||||
"식물",
|
||||
"멍멍이",
|
||||
"파충류, 양서류",
|
||||
"야옹이",
|
||||
]
|
||||
}, {
|
||||
title: "취미/생활",
|
||||
items: [
|
||||
"인터넷방송",
|
||||
"판타지",
|
||||
"토이",
|
||||
"대출",
|
||||
"역학",
|
||||
"미스터리",
|
||||
"카툰-연재",
|
||||
"만화",
|
||||
"향수, 화장품",
|
||||
"안경",
|
||||
]
|
||||
}].map((section, index) => (
|
||||
<dl
|
||||
key={index}
|
||||
className="border-l border-[#f1f1f1] pl-[20px] min-h-[108px] w-[170px] box-content"
|
||||
>
|
||||
|
||||
<dt
|
||||
style={{
|
||||
marginBottom: "4px",
|
||||
fontWeight: "bold",
|
||||
textDecorationLine: "underline",
|
||||
fontSize: "12px",
|
||||
color: "#333333",
|
||||
letterSpacing: "0.025em"
|
||||
}}
|
||||
className="text-[12px] text-custom-gray-dark"
|
||||
>
|
||||
|
||||
{section.title}
|
||||
</dt>
|
||||
{section.items.map((item, idx) => (
|
||||
<dd
|
||||
key={idx}
|
||||
style={{
|
||||
paddingTop: "5px",
|
||||
fontSize: "12px",
|
||||
lineHeight: "100%"
|
||||
}}
|
||||
>
|
||||
<a href="javascript:void(0);"
|
||||
className="text-custom-gray-dark text-[11px]"
|
||||
>{item}</a>
|
||||
</dd>
|
||||
))}
|
||||
</dl>
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
lineHeight: "40px",
|
||||
height: "38px",
|
||||
paddingRight: "19px",
|
||||
paddingLeft: "16px",
|
||||
}}
|
||||
className="text-custom-gray-dark overflow-hidden grid"
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontSize: "11px",
|
||||
}}
|
||||
className="text-custom-gray-dark text-[11px] justify-self-end"
|
||||
>
|
||||
<a className="text-custom-gray-dark ml-[9px]">
|
||||
|
||||
<em className="inline-block mr-[4px] bg-sp-img bg-[-285px_-818px] w-2 h-2"
|
||||
/>
|
||||
야간모드
|
||||
</a>
|
||||
<a
|
||||
className="text-custom-gray-dark ml-[9px]"
|
||||
href="javascript:void(0);"
|
||||
onClick={() => {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}}
|
||||
>
|
||||
<em
|
||||
className="inline-block mr-[6px] bg-sp-img bg-[-52px_-50px] w-2 h-2"
|
||||
/>
|
||||
맨위로
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="text-[12px] text-custom-gray-dark divide-x divide-[ d7d7d7] mx-auto text-center pt-7 w-[1160px]"
|
||||
>
|
||||
<a className="px-2">
|
||||
회사소개
|
||||
</a>
|
||||
<a className="px-2">
|
||||
제휴안내
|
||||
</a>
|
||||
<a className="px-2">
|
||||
광고안내
|
||||
</a>
|
||||
<a className="px-2">
|
||||
이용약관
|
||||
</a>
|
||||
<a className="px-2">
|
||||
<b> 개인정보처리방침 </b>
|
||||
</a>
|
||||
<a className="px-2">
|
||||
청소년보호정책
|
||||
</a>
|
||||
<a className="px-2">
|
||||
마이너 갤러리 운영원칙
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className="text-[12px] text-custom-gray-dark font-tahoma mt-[10px] mx-auto w-[1160px] text-center tracking-[0]"
|
||||
>
|
||||
Copyright ⓒ 1999 - 2025 dcinside. All rights reserved.
|
||||
</div>
|
||||
</footer>
|
||||
}
|
729
src/Gallery.tsx
729
src/Gallery.tsx
|
@ -1,473 +1,284 @@
|
|||
import { Separator } from "./Separator"
|
||||
|
||||
function GalleryContentHeader() {
|
||||
return <header>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "16px",
|
||||
marginBottom: "29px",
|
||||
paddingBottom: "11px",
|
||||
borderBottomWidth: "1px",
|
||||
borderBottomStyle: "solid",
|
||||
borderBottomColor: "rgb(238, 238, 238)"
|
||||
}}
|
||||
>
|
||||
|
||||
<h3
|
||||
style={{
|
||||
paddingRight: "2px",
|
||||
paddingLeft: "2px",
|
||||
marginBottom: "7px",
|
||||
fontSize: "14px",
|
||||
}}
|
||||
>
|
||||
|
||||
<span> [일반] </span>
|
||||
<span>
|
||||
아 e글 유파들이 고도 왜 안올리는지 알았다
|
||||
</span>
|
||||
<span> </span>
|
||||
</h3>
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
fontSize: "13px",
|
||||
cursor: "pointer",
|
||||
paddingRight: "2px",
|
||||
paddingLeft: "2px",
|
||||
}}
|
||||
>
|
||||
<div style={{ float: "left" }}>
|
||||
return (
|
||||
<header>
|
||||
{/* Outer container with margin, padding, and bottom border */}
|
||||
<div className="mt-4 mb-[29px] pb-[11px] border-b border-solid border-gray-200">
|
||||
{/* Post Title */}
|
||||
<h3 className="px-0.5 mb-[7px] text-sm font-bold">
|
||||
<span> [일반] </span>
|
||||
<span>
|
||||
<em> 썬갤러 </em>
|
||||
아 e글 유파들이 고도 왜 안올리는지 알았다
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
fontFamily: "tahoma, sans-serif",
|
||||
fontSize: "11px",
|
||||
color: "rgb(153, 153, 153)"
|
||||
}}
|
||||
>
|
||||
(110.15)
|
||||
</span>
|
||||
<span style={{ backgroundColor: "transparent", cursor: "default" }}>
|
||||
<Separator />
|
||||
2025.02.04 21:32:47
|
||||
</span>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
{/* Metadata container */}
|
||||
<div
|
||||
style={{
|
||||
float: "right",
|
||||
paddingRight: "7px",
|
||||
}}
|
||||
className="relative text-[13px] cursor-pointer px-0.5 flex justify-between items-center"
|
||||
>
|
||||
|
||||
<span style={{ cursor: "default" }}>
|
||||
조회 65
|
||||
</span>
|
||||
<span style={{ cursor: "default" }}>
|
||||
<Separator />
|
||||
추천 0
|
||||
</span>
|
||||
<span style={{ cursor: "default" }}>
|
||||
<Separator />
|
||||
<a
|
||||
style={{
|
||||
backgroundColor: "rgb(238, 238, 238)",
|
||||
color: "rgb(51, 51, 51)",
|
||||
display: "inline-block",
|
||||
height: "20px",
|
||||
lineHeight: "20px",
|
||||
padding: "0px 10px",
|
||||
border: "1px solid rgb(204, 204, 204)",
|
||||
borderRadius: "50px",
|
||||
}}
|
||||
>
|
||||
댓글 13
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ clear: "both" }}></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
|
||||
function GalleryRecommendation() {
|
||||
return <div
|
||||
style={{
|
||||
backgroundColor: "rgb(255, 255, 255)",
|
||||
width: "auto",
|
||||
height: "auto",
|
||||
marginRight: "auto",
|
||||
marginBottom: "36px",
|
||||
marginLeft: "auto",
|
||||
paddingTop: "19px",
|
||||
border: "1px solid rgb(196, 196, 196)",
|
||||
borderRadius: "2px",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif',
|
||||
clear: "both",
|
||||
minWidth: "288px",
|
||||
display: "table"
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
textAlign: "center",
|
||||
fontSize: "0px",
|
||||
}}
|
||||
>
|
||||
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
overflow: "hidden",
|
||||
width: "139px",
|
||||
marginBottom: "2px",
|
||||
display: "inline-block"
|
||||
}}
|
||||
>
|
||||
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
float: "left",
|
||||
width: "67px",
|
||||
paddingTop: "10px",
|
||||
paddingLeft: "11px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
color: "rgb(85, 85, 85)"
|
||||
}}
|
||||
>
|
||||
<p
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
color: "rgb(211, 25, 0)",
|
||||
fontSize: "12px",
|
||||
}}
|
||||
>0</p>
|
||||
<p style={{ backgroundColor: "transparent", lineHeight: "12px" }}>
|
||||
{/* Left section: Author, IP, Timestamp */}
|
||||
<div>
|
||||
<span>
|
||||
<img
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
verticalAlign: "middle"
|
||||
}}
|
||||
/>
|
||||
{/* author name */}
|
||||
<em className="not-italic"> 썬갤러 </em> {/* Adjusted em styling for clarity */}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
color: "rgb(41, 54, 124)",
|
||||
fontSize: "11px",
|
||||
fontWeight: "normal"
|
||||
}}
|
||||
>
|
||||
|
||||
0
|
||||
<span className="font-tahoma text-[11px] text-gray-500 ml-1">
|
||||
(110.15)
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif',
|
||||
float: "right",
|
||||
width: "56px",
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPositionX: "0px",
|
||||
backgroundPositionY: "-315px",
|
||||
display: "inline-block",
|
||||
width: "56px",
|
||||
height: "56px",
|
||||
}}
|
||||
></em>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
width: "139px",
|
||||
marginBottom: "2px",
|
||||
display: "inline-block",
|
||||
marginLeft: "10px",
|
||||
}}
|
||||
>
|
||||
<span className="cursor-default">
|
||||
<Separator />
|
||||
2025.02.04 21:32:47
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif',
|
||||
float: "left",
|
||||
width: "56px",
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("https://nstatic.dcinside.com/dc/w/images/sp/sp_img.png?1112")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPositionX: "0px",
|
||||
backgroundPositionY: "-377px",
|
||||
display: "inline-block",
|
||||
width: "56px",
|
||||
height: "56px",
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
float: "right",
|
||||
width: "64px",
|
||||
paddingTop: "17px",
|
||||
paddingRight: "12px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
color: "rgb(85, 85, 85)",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
>
|
||||
<p style={{ backgroundColor: "transparent" }}> 0 </p>
|
||||
{/* Right section: Views, Recommends, Comments */}
|
||||
<div
|
||||
className="pr-[7px]"
|
||||
>
|
||||
<span className="cursor-default">
|
||||
조회 65
|
||||
</span>
|
||||
<Separator />
|
||||
<span className="cursor-default">
|
||||
추천 0
|
||||
</span>
|
||||
<Separator />
|
||||
<span className="cursor-default">
|
||||
{/* Comments link styled as a pill button */}
|
||||
<a href="#" // Add appropriate link target
|
||||
className="inline-block h-5 leading-5 px-2.5 bg-gray-200
|
||||
text-gray-700 border border-gray-300 rounded-full
|
||||
hover:bg-gray-300 hover:border-gray-400 text-xs">
|
||||
댓글 13
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
clear: "both",
|
||||
position: "relative",
|
||||
height: "36px",
|
||||
borderTopWidth: "1px",
|
||||
borderTopStyle: "solid",
|
||||
borderTopColor: "rgb(196, 196, 196)"
|
||||
}}
|
||||
>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "rgb(249, 249, 249)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
float: "left",
|
||||
width: "95px",
|
||||
height: "36px",
|
||||
marginLeft: "1px",
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: "rgb(196, 196, 196)",
|
||||
color: "rgb(85, 85, 85)",
|
||||
textShadow: "rgb(255, 255, 255) 0px 1px",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
width: "23px",
|
||||
height: "23px",
|
||||
backgroundPositionX: "-270px",
|
||||
backgroundPositionY: "-983px",
|
||||
marginRight: "3px",
|
||||
marginTop: "2px",
|
||||
verticalAlign: "-8px",
|
||||
display: "inline-block"
|
||||
}}
|
||||
>
|
||||
|
||||
</em>
|
||||
실베추
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "rgb(249, 249, 249)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
width: "96px",
|
||||
float: "left",
|
||||
height: "36px",
|
||||
marginLeft: "1px",
|
||||
borderRightWidth: "1px",
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: "rgb(196, 196, 196)",
|
||||
color: "rgb(85, 85, 85)",
|
||||
textShadow: "rgb(255, 255, 255) 0px 1px",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
width: "17px",
|
||||
height: "20px",
|
||||
backgroundPositionX: "-74px",
|
||||
backgroundPositionY: "-262px",
|
||||
marginRight: "6px",
|
||||
verticalAlign: "-4px",
|
||||
display: "inline-block"
|
||||
}}
|
||||
>
|
||||
|
||||
</em>
|
||||
공유
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "rgb(249, 249, 249)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
float: "left",
|
||||
width: "95px",
|
||||
height: "36px",
|
||||
marginLeft: "1px",
|
||||
color: "rgb(85, 85, 85)",
|
||||
textShadow: "rgb(255, 255, 255) 0px 1px",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
width: "18px",
|
||||
height: "20px",
|
||||
backgroundPositionX: "-74px",
|
||||
backgroundPositionY: "-241px",
|
||||
marginRight: "6px",
|
||||
verticalAlign: "-4px",
|
||||
display: "inline-block"
|
||||
}}
|
||||
>
|
||||
</em>
|
||||
신고
|
||||
</button>
|
||||
<div
|
||||
style={{ clear: "both" }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
function GalleryNFTPublishButton() {
|
||||
return <div
|
||||
interface GalleryRecommendationProps {
|
||||
recommendCount?: number;
|
||||
fixedNickCount?: number;
|
||||
downvoteCount?: number;
|
||||
}
|
||||
|
||||
function GalleryRecommendation({
|
||||
recommendCount = 0,
|
||||
fixedNickCount = 0,
|
||||
downvoteCount = 0
|
||||
}: GalleryRecommendationProps) {
|
||||
return <div
|
||||
className="bg-white mx-auto mb-9 font-apple border border-[#c4c4c4] rounded-xs
|
||||
pt-[19px] w-fit box-content">
|
||||
<div className="flex items-center justify-center overflow-hidden pb-2">
|
||||
<div className="flex justify-end overflow-hidden w-[139px] mb-0.5">
|
||||
<div
|
||||
style={{
|
||||
width: "67px",
|
||||
paddingTop: "10px",
|
||||
paddingLeft: "11px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
color: "rgb(85, 85, 85)"
|
||||
}}
|
||||
>
|
||||
<p className="text-base leading-[22px] text-[#d31900] font-bold"
|
||||
>{recommendCount}</p>
|
||||
<p
|
||||
className="leading-3 flex items-end justify-center"
|
||||
>
|
||||
<span className="text-[16px]">
|
||||
<img
|
||||
className="align-middle inline-block"
|
||||
src="/fix_nik.gif" alt="고정닉"
|
||||
/>
|
||||
|
||||
</span>
|
||||
<span className="text-custom-blue-dark text-[11px] font-normal">
|
||||
{fixedNickCount}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
className="font-apple text-[12px] cursor-pointer align-middle w-14"
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPositionX: "0px",
|
||||
backgroundPositionY: "-315px",
|
||||
display: "inline-block",
|
||||
width: "56px",
|
||||
height: "56px",
|
||||
}}
|
||||
></em>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: "139px",
|
||||
marginBottom: "2px",
|
||||
display: "inline-block",
|
||||
marginLeft: "10px",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
float: "left",
|
||||
width: "56px",
|
||||
}}
|
||||
className="font-apple"
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPositionX: "0px",
|
||||
backgroundPositionY: "-377px",
|
||||
display: "inline-block",
|
||||
width: "56px",
|
||||
height: "56px",
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
<div
|
||||
style={{
|
||||
float: "right",
|
||||
width: "64px",
|
||||
paddingTop: "17px",
|
||||
paddingRight: "12px",
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
color: "rgb(85, 85, 85)",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
>
|
||||
<p> {downvoteCount} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center justify-center overflow-hidden h-9 relative
|
||||
border-t border-[rgb(196,196,196)] divide-[rgb(196,196,196)] divide-x"
|
||||
>
|
||||
<SilbechuButton />
|
||||
<ShareButton />
|
||||
<ReportButton />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
function ReportButton() {
|
||||
return <button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
position: "absolute",
|
||||
left: "0px",
|
||||
top: "0px",
|
||||
fontSize: "0px",
|
||||
backgroundColor: "rgb(249, 249, 249)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
width: "95px",
|
||||
height: "36px",
|
||||
marginLeft: "1px",
|
||||
color: "rgb(85, 85, 85)",
|
||||
textShadow: "rgb(255, 255, 255) 0px 1px",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
|
||||
<button
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "rgb(59, 72, 144)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif',
|
||||
textShadow: "rgb(29, 39, 97) 0px -1px",
|
||||
color: "rgb(255, 255, 255)",
|
||||
overflow: "hidden",
|
||||
width: "auto",
|
||||
paddingRight: "12px",
|
||||
paddingLeft: "11px",
|
||||
height: "31px",
|
||||
lineHeight: "29px",
|
||||
marginLeft: "3px",
|
||||
border: "1px solid rgb(41, 54, 124)",
|
||||
borderRadius: "2px",
|
||||
fontWeight: "bold"
|
||||
}}
|
||||
>
|
||||
NFT 발행하기
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
fontSize: "12px",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif',
|
||||
backgroundImage:
|
||||
'url("https://nstatic.dcinside.com/dc/w/images/sp/sp_image.png")',
|
||||
backgroundImage: 'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
display: "inline-block",
|
||||
width: "17px",
|
||||
height: "17px",
|
||||
backgroundPositionX: "-1px",
|
||||
backgroundPositionY: "-1px",
|
||||
lineHeight: "0px",
|
||||
marginLeft: "5px",
|
||||
width: "18px",
|
||||
height: "20px",
|
||||
backgroundPosition: "-74px -241px",
|
||||
marginRight: "6px",
|
||||
verticalAlign: "-4px",
|
||||
display: "inline-block"
|
||||
}}
|
||||
className="inline-block"
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
position: "absolute",
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
visibility: "hidden",
|
||||
marginTop: "-1px",
|
||||
marginRight: "-1px",
|
||||
marginBottom: "-1px",
|
||||
marginLeft: "-1px",
|
||||
width: "0px",
|
||||
top: "-9999px",
|
||||
fontSize: "0px",
|
||||
}}
|
||||
>
|
||||
엔에프티 안내
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</em>
|
||||
신고
|
||||
</button>;
|
||||
}
|
||||
|
||||
function ShareButton() {
|
||||
return <button
|
||||
style={{
|
||||
backgroundColor: "rgb(249, 249, 249)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
width: "96px",
|
||||
height: "36px",
|
||||
marginLeft: "1px",
|
||||
textShadow: "rgb(255, 255, 255) 0px 1px",
|
||||
}}
|
||||
className="align-middle relative cursor-pointer"
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundPosition: "-74px -262px",
|
||||
width: "17px",
|
||||
height: "20px",
|
||||
marginRight: "6px",
|
||||
verticalAlign: "-4px",
|
||||
}}
|
||||
className="inline-block bg-sp-img"
|
||||
>
|
||||
</em>
|
||||
공유
|
||||
</button>;
|
||||
}
|
||||
|
||||
function SilbechuButton() {
|
||||
return <button
|
||||
style={{
|
||||
backgroundColor: "rgb(249, 249, 249)",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "middle",
|
||||
width: "95px",
|
||||
height: "36px",
|
||||
marginLeft: "1px",
|
||||
color: "rgb(85, 85, 85)",
|
||||
textShadow: "rgb(255, 255, 255) 0px 1px",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
width: "23px",
|
||||
height: "23px",
|
||||
backgroundPositionX: "-270px",
|
||||
backgroundPositionY: "-983px",
|
||||
marginRight: "3px",
|
||||
marginTop: "2px",
|
||||
verticalAlign: "-8px",
|
||||
display: "inline-block"
|
||||
}}
|
||||
className="bg-sp-img"
|
||||
>
|
||||
</em>
|
||||
실베추
|
||||
</button>;
|
||||
}
|
||||
|
||||
export function GalleryContent() {
|
||||
return <div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, 굴림, Gulim, sans-serif',
|
||||
fontSize: "13px",
|
||||
color: "rgb(51, 51, 51)"
|
||||
}}
|
||||
return <article
|
||||
className="text-custom-gray-dark text-[13px] font-apple"
|
||||
>
|
||||
<GalleryContentHeader />
|
||||
<div style={{ lineHeight: "22px" }}>
|
||||
<div style={{ backgroundColor: "transparent", marginBottom: "50px" }}>
|
||||
<div style={{ marginBottom: "50px" }}>
|
||||
<div
|
||||
style={{
|
||||
overflow: "hidden",
|
||||
|
@ -475,10 +286,9 @@ export function GalleryContent() {
|
|||
}}
|
||||
>
|
||||
<div>
|
||||
<span style={{ backgroundColor: "transparent", marginLeft: "10px" }}>
|
||||
<span style={{ marginLeft: "10px" }}>
|
||||
<img
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
maxWidth: "100%",
|
||||
width: "550px",
|
||||
height: "350px",
|
||||
|
@ -489,8 +299,6 @@ export function GalleryContent() {
|
|||
<pre />
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
overflow: "hidden",
|
||||
width: "900px",
|
||||
}}
|
||||
>
|
||||
|
@ -505,29 +313,18 @@ export function GalleryContent() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ backgroundColor: "transparent", position: "relative" }}>
|
||||
<GalleryNFTPublishButton />
|
||||
<GalleryRecommendation />
|
||||
<div className="relative">
|
||||
<GalleryRecommendation
|
||||
recommendCount={2}
|
||||
fixedNickCount={1}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
textAlign: "center",
|
||||
marginTop: "10px",
|
||||
}}
|
||||
className="w-full overflow-hidden text-center mt-2"
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
width: "728px",
|
||||
marginTop: "20px",
|
||||
marginRight: "auto",
|
||||
marginLeft: "auto"
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
className="w-[728px] mt-[20px] mx-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
}
|
|
@ -1,183 +1,50 @@
|
|||
import { Separator } from "./Separator";
|
||||
import { Separator } from "./Separator"
|
||||
|
||||
export function GalleryTitleHeader() {
|
||||
return <header>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
height: "37px",
|
||||
marginBottom: "3px",
|
||||
paddingTop: "4px",
|
||||
}}
|
||||
>
|
||||
<div style={{ float: "left" }}>
|
||||
<h2
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
marginTop: "-2px",
|
||||
marginRight: "6px",
|
||||
marginLeft: "2px",
|
||||
float: "left",
|
||||
fontSize: "24px",
|
||||
maxWidth: "420px",
|
||||
fontFamily: "'Nanum Gothic', sans-serif",
|
||||
letterSpacing: "-1px",
|
||||
margin: "2px 8px 0 3px",
|
||||
"textOverflow": "ellipsis",
|
||||
overflow: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
color: "#29367c",
|
||||
}}
|
||||
>
|
||||
<a style={{ color: "rgb(41, 54, 124)" }}>
|
||||
워썬더 갤러리
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
display: "inline-block",
|
||||
verticalAlign: "top",
|
||||
marginLeft: "4px",
|
||||
width: "22px",
|
||||
height: "22px",
|
||||
backgroundPositionX: "-195px",
|
||||
backgroundPositionY: "-844px",
|
||||
marginTop: "3px",
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
</a>
|
||||
</h2>
|
||||
<div style={{ clear: "both" }}></div>
|
||||
</div>
|
||||
<div style={{ backgroundColor: "transparent", float: "right", paddingTop: "12px" }}>
|
||||
<div style={{
|
||||
backgroundColor: "transparent",
|
||||
position: "relative",
|
||||
display: "inline-block"
|
||||
}}>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "top",
|
||||
fontSize: "12px",
|
||||
color: "rgb(51, 51, 51)",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
설정
|
||||
</button>
|
||||
<span style={{ backgroundColor: "transparent", marginRight: "2px" }}>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
display: "inline-block",
|
||||
width: "6px",
|
||||
height: "6px",
|
||||
marginLeft: "4px",
|
||||
verticalAlign: "4px",
|
||||
lineHeight: "30px",
|
||||
backgroundPositionX: "-70px",
|
||||
backgroundPositionY: "-59px"
|
||||
}}
|
||||
>
|
||||
</em>
|
||||
</span>
|
||||
return (
|
||||
<header className="bg-transparent h-[37px] mb-[3px] pt-[4px] text-gray-500">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center">
|
||||
<h2 className="mt-[-2px] mr-[6px] ml-[2px] text-[24px] max-w-[420px] font-[nanumGothic] tracking-[-1px] m-[2px_8px_0_3px] overflow-hidden whitespace-nowrap text-ellipsis text-custom-blue-dark">
|
||||
<a className="text-custom-blue-dark font-bold">
|
||||
워썬더 갤러리
|
||||
<div className="bg-sp-img bg-no-repeat inline-block align-top ml-[4px] w-[22px] h-[22px] bg-[-195px_-844px] mt-[3px]">
|
||||
</div>
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
<div className="flex items-center text-[12px]">
|
||||
<div className="relative inline-block">
|
||||
<button className="cursor-pointer align-top relative">
|
||||
설정
|
||||
</button>
|
||||
<span className="mr-[2px] leading-10px">
|
||||
<em className="sr-only">New</em>
|
||||
<em className="bg-sp-img bg-no-repeat inline-block w-[6px] h-[6px] ml-[4px] align-[4px] leading-[30px] bg-[-70px_-59px]">
|
||||
</em>
|
||||
</span>
|
||||
</div>
|
||||
<Separator />
|
||||
<button className="cursor-pointer align-top font-sans">
|
||||
연관 갤러리(2/8)
|
||||
<span className="mr-[2px] ml-[2px] hidden">
|
||||
</span>
|
||||
<em className="bg-sp-img bg-no-repeat inline-block w-[9px] h-[5px] bg-[-115px_-43px] align-[1px] ml-[2px]">
|
||||
</em>
|
||||
</button>
|
||||
<Separator />
|
||||
<button className="cursor-pointer align-top">
|
||||
갤주소 복사
|
||||
</button>
|
||||
<Separator />
|
||||
<button className="cursor-pointer align-top">이용안내</button>
|
||||
<Separator />
|
||||
<button className="cursor-pointer align-top">
|
||||
<em className="bg-sp-img bg-no-repeat inline-block w-[15px] h-[15px] bg-[-56px_-168px] mt-[1px]">
|
||||
</em>
|
||||
</button>
|
||||
</div>
|
||||
<Separator />
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "top",
|
||||
fontSize: "12px",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif',
|
||||
color: "rgb(51, 51, 51)"
|
||||
}}
|
||||
>
|
||||
연관 갤러리(2/8)
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
marginRight: "2px",
|
||||
marginLeft: "2px",
|
||||
display: "none"
|
||||
}}
|
||||
>
|
||||
</span>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
display: "inline-block",
|
||||
width: "9px",
|
||||
height: "5px",
|
||||
backgroundPositionX: "-115px",
|
||||
backgroundPositionY: "-43px",
|
||||
verticalAlign: "1px",
|
||||
marginLeft: "2px",
|
||||
}}
|
||||
>
|
||||
</em>
|
||||
</button>
|
||||
<Separator />
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "top",
|
||||
fontSize: "12px",
|
||||
color: "rgb(51, 51, 51)"
|
||||
}}
|
||||
>
|
||||
갤주소 복사
|
||||
</button>
|
||||
<Separator />
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "top",
|
||||
fontSize: "12px",
|
||||
color: "rgb(51, 51, 51)"
|
||||
}}
|
||||
>이용안내</button>
|
||||
<Separator />
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
cursor: "pointer",
|
||||
verticalAlign: "top",
|
||||
fontSize: "12px",
|
||||
color: "rgb(51, 51, 51)"
|
||||
}}
|
||||
>
|
||||
<em
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
backgroundImage:
|
||||
'url("/sp_image.png")',
|
||||
backgroundRepeat: "no-repeat",
|
||||
display: "inline-block",
|
||||
width: "15px",
|
||||
height: "15px",
|
||||
backgroundPositionX: "-56px",
|
||||
backgroundPositionY: "-168px",
|
||||
marginTop: "1px",
|
||||
}}
|
||||
>
|
||||
</em>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header >
|
||||
}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
export function Separator() {
|
||||
return <div style={{
|
||||
content: "",
|
||||
display: "inline-block",
|
||||
width: "1px",
|
||||
height: "12px",
|
||||
background: "#ccc",
|
||||
margin: "0 10px 0 6px",
|
||||
verticalAlign: "-1px",
|
||||
}} />;
|
||||
import { cn } from "./util/cn";
|
||||
|
||||
export function Separator({ className } : { className?: string }) {
|
||||
return <div className={cn("inline-block h-3 w-[1px] bg-gray-400 mx-2 my-0 align-[-1px]",
|
||||
className)} />;
|
||||
}
|
||||
|
|
2150
src/common.css
2150
src/common.css
File diff suppressed because it is too large
Load diff
1953
src/content.css
1953
src/content.css
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,24 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
|
||||
/* --- Extend Tailwind Theme using @theme --- */
|
||||
@theme {
|
||||
--color-custom-blue-dark: rgb(41 54 124);
|
||||
--color-custom-gray-dark: rgb(51 51 51);
|
||||
--color-custom-gray-medium: rgb(153 153 153);
|
||||
--color-custom-gray-light: rgb(238 238 238);
|
||||
--color-custom-green: rgb(0 153 51);
|
||||
--color-custom-red-text: rgb(211 25 0);
|
||||
--color-custom-border-gray: rgb(204 204 204);
|
||||
--color-custom-dropdown-bg: rgb(243 243 243);
|
||||
--color-custom-dropdown-text: rgb(85 85 85);
|
||||
|
||||
--font-apple: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, 굴림, Gulim, sans-serif;
|
||||
--font-apple-dotum: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", arial, Dotum, 돋움, sans-serif;
|
||||
--font-tahoma: tahoma, sans-serif;
|
||||
}
|
||||
|
||||
@utility bg-sp-img{
|
||||
background-image: url('/sp_image.png');
|
||||
background-repeat: no-repeat;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import "./reset.css"
|
||||
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
|
||||
|
|
1568
src/minor.css
1568
src/minor.css
File diff suppressed because it is too large
Load diff
0
src/table.css
Normal file
0
src/table.css
Normal file
235
src/table.tsx
Normal file
235
src/table.tsx
Normal file
|
@ -0,0 +1,235 @@
|
|||
import { cn } from './util/cn';
|
||||
|
||||
export type AuthorData = {
|
||||
// 운영자
|
||||
type: "operator"
|
||||
} | {
|
||||
// 고닉
|
||||
// 중복 불가능 닉네임
|
||||
type: "nickname",
|
||||
nickname: string,
|
||||
// 파딱, 주딱 구분을 위한 userType
|
||||
userType?: "manager" | "submanager" // Optional, if applicable
|
||||
} | {
|
||||
// 유동닉
|
||||
type: "IP",
|
||||
// IP 주소
|
||||
ip: string,
|
||||
} | {
|
||||
// 반유동닉
|
||||
// 중복 가능 닉네임
|
||||
type: "semi-nickname",
|
||||
nickname: string,
|
||||
}
|
||||
|
||||
// --- Data Interface (Remains the same) ---
|
||||
export interface TableRowData {
|
||||
id: string | number;
|
||||
category: string;
|
||||
titleText: string;
|
||||
commentCount?: number;
|
||||
// e.g., "icon_notice", "icon_pic", "icon_txt", "icon_survey"
|
||||
variant?: "icon_notice" | "icon_recoming" | "icon_recomovie" | "icon_pic" | "icon_txt" | "icon_survey"
|
||||
| "icon_ad" | "icon_dctrend";
|
||||
|
||||
// e.g., "운영자", "고닉", "반유동", "유동닉"
|
||||
author?: {
|
||||
type: "operator"
|
||||
} | {
|
||||
type: "nickname",
|
||||
nickname: string,
|
||||
userType?: "manager" | "submanager" // Optional, if applicable
|
||||
} | {
|
||||
type: "IP",
|
||||
ip: string,
|
||||
} | {
|
||||
type: "semi-nickname",
|
||||
nickname: string,
|
||||
}
|
||||
|
||||
date: string;
|
||||
|
||||
views: "" | "-" | number;
|
||||
recommendations: "" | "-" | number;
|
||||
// Special flags for row types affecting style/structure
|
||||
isNotice?: boolean;
|
||||
isAdOrSurvey?: boolean;
|
||||
isNews?: boolean; // Handle the last row type specifically if needed
|
||||
titleLinkUrl?: string; // Optional URL for title
|
||||
authorLinkUrl?: string; // Optional URL for author
|
||||
}
|
||||
|
||||
// --- Child Component: TableRow ---
|
||||
interface TableRowProps {
|
||||
rowData: TableRowData;
|
||||
}
|
||||
|
||||
const NicknameImagePath = {
|
||||
"주딱": "/fix_managernik.gif",
|
||||
"파딱": "/fix_sub_managernik.gif",
|
||||
"반유동": "/nik.gif",
|
||||
"default": "/fix_nik.gif"
|
||||
}
|
||||
|
||||
export function TableRow({ rowData }: TableRowProps) {
|
||||
const {
|
||||
id,
|
||||
category,
|
||||
titleText,
|
||||
commentCount,
|
||||
variant,
|
||||
date,
|
||||
views,
|
||||
recommendations,
|
||||
isNotice,
|
||||
isAdOrSurvey,
|
||||
isNews,
|
||||
titleLinkUrl = "#",
|
||||
authorLinkUrl = "#",
|
||||
author,
|
||||
} = rowData;
|
||||
|
||||
const iconTable = {
|
||||
icon_notice: "0px 0px",
|
||||
icon_recoming: "0px -193px",
|
||||
icon_recomovie: "0px -193px",
|
||||
icon_pic: "0px -100px",
|
||||
icon_txt: "0px -123px",
|
||||
icon_survey: "0px -170px",
|
||||
icon_ad: "0px -193px",
|
||||
icon_dctrend: "-3px -877px", // Example for news
|
||||
}
|
||||
const iconPosition = iconTable[variant ?? "icon_txt"]; // Default to undefined if not found
|
||||
|
||||
// --- Base Cell Styles ---
|
||||
// Note: some styles like height/padding might be slightly different due to Tailwind defaults vs specific px
|
||||
const tdBaseClasses = 'border-t border-custom-gray-light align-middle text-custom-gray-dark h-[25px] relative px-1 py-[2px]'; // Approximates tdBaseStyle
|
||||
const tdCenterClasses = cn(tdBaseClasses, "text-center font-tahoma text-[11px] pt-[1px] pb-[2px]"); // Approximates tdCenterStyle
|
||||
// --- Standard Row Rendering ---
|
||||
return (
|
||||
<tr className="bg-transparent hover:bg-custom-gray-light">
|
||||
<td className={tdCenterClasses}>{isNews ? "" : id}</td>
|
||||
<td className={cn(
|
||||
tdCenterClasses,
|
||||
'text-xs', // Base font size for category is 12px
|
||||
(isAdOrSurvey || isNotice) && 'font-bold', // Conditional bold
|
||||
)}>{category}</td>
|
||||
<td className={cn(tdBaseClasses, "text-left text-[13px] h-[29px]")}>
|
||||
<a href={titleLinkUrl} className={cn(
|
||||
'text-custom-gray-dark inline-block max-w-[82%] align-middle text-ellipsis whitespace-nowrap overflow-hidden pt-[1px] leading-tight', // Approximates titleLinkStyle
|
||||
"hover:underline",
|
||||
isNews && '!text-custom-green', // News specific color override
|
||||
(isNotice || isAdOrSurvey) && 'font-bold', // Title bold for Notice/Ad/Survey
|
||||
)}>
|
||||
{iconPosition && (
|
||||
<em className="inline-block w-[15px] h-[15px] align-[-3px] mr-[7px] bg-no-repeat" style={{
|
||||
background: `url("/icon_img.png?1012")`,
|
||||
backgroundPosition: iconPosition,
|
||||
}}></em>
|
||||
)}
|
||||
{/* Title text - boldness handled by titleLinkClasses */}
|
||||
{titleText}
|
||||
</a>
|
||||
{commentCount !== undefined && commentCount > 0 && (
|
||||
<span className="text-xs text-custom-gray-medium ml-1 align-middle tracking-[-0.05em]">
|
||||
[{commentCount}]
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className={cn(
|
||||
tdCenterClasses, // Base style for author cell
|
||||
'text-[13px]', // Author cell often uses 13px base font size
|
||||
authorLinkUrl !== '#' ? 'cursor-pointer' : 'cursor-default', // Conditional cursor
|
||||
)}>
|
||||
{author?.type === "operator" ? (
|
||||
<b className="font-bold">운영자</b>
|
||||
) : (
|
||||
<>
|
||||
{/* Author Name Span */}
|
||||
<span className="inline-block max-w-[81%] align-top text-ellipsis overflow-hidden whitespace-nowrap">
|
||||
{/* Inner em/span for potential finer control if needed */}
|
||||
<em className="not-italic leading-[13px]">
|
||||
{author?.type === "nickname" ? author?.nickname : "ㅇㅇ"}
|
||||
</em>
|
||||
</span>
|
||||
{/* Author IP */}
|
||||
{author?.type === "IP" && (
|
||||
<span className="font-tahoma text-[11px] text-custom-gray-medium tracking-[-0.05em] ml-[3px]">
|
||||
({author.ip})
|
||||
</span>
|
||||
)}
|
||||
{/* Author Icon Placeholder */}
|
||||
{author?.type !== "IP" && (
|
||||
<a href={authorLinkUrl} className="text-custom-gray-dark ml-0.5 inline-block">
|
||||
{/* Replace with actual icon component or img tag */}
|
||||
<img
|
||||
alt="icon"
|
||||
src={
|
||||
author?.type === "nickname" ? (
|
||||
author?.userType === "manager" ? NicknameImagePath["주딱"] :
|
||||
author?.userType === "submanager" ? NicknameImagePath["파딱"] :
|
||||
NicknameImagePath["default"]
|
||||
) : NicknameImagePath["반유동"]
|
||||
}
|
||||
className="align-middle cursor-pointer w-3 h-3" // Example size
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td className={tdCenterClasses}>{date}</td>
|
||||
<td className={tdCenterClasses}>{views}</td>
|
||||
<td className={tdCenterClasses}>{recommendations}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
// --- Main Component: Table ---
|
||||
export function GalleryTable(props: {
|
||||
data: TableRowData[];
|
||||
}) {
|
||||
const { data } = props; // Destructure props to get data
|
||||
|
||||
// --- Base TH Styles ---
|
||||
const thBaseClasses = 'bg-transparent h-[37px] border-t-2 border-b border-custom-blue-dark align-middle text-center text-custom-gray-dark font-appleDotum'; // Uses config colors
|
||||
|
||||
return (
|
||||
<table className="bg-transparent border-collapse table-fixed text-xs font-apple w-full border-b border-custom-blue-dark">
|
||||
{/* Screen Reader Only Caption */}
|
||||
<caption className="relative w-0 text-[0px] leading-[0] -z-10">
|
||||
갤러리 리스트
|
||||
</caption>
|
||||
{/* Column Widths */}
|
||||
<colgroup>
|
||||
<col style={{ width: "7%" }} />
|
||||
<col style={{ width: 51 }} />
|
||||
<col />
|
||||
<col style={{ width: "18%" }} />
|
||||
<col style={{ width: "6%" }} />
|
||||
<col style={{ width: "6%" }} />
|
||||
<col style={{ width: "6%" }} />
|
||||
</colgroup>
|
||||
{/* Table Header */}
|
||||
<thead className="bg-transparent">
|
||||
<tr className="bg-transparent">
|
||||
<th className={thBaseClasses}> 번호 </th>
|
||||
<th className={thBaseClasses}> 말머리 </th>
|
||||
<th className={thBaseClasses}> 제목 </th>
|
||||
<th className={thBaseClasses}> 글쓴이 </th>
|
||||
<th className={thBaseClasses}> 작성일 </th>
|
||||
<th className={thBaseClasses}> 조회 </th>
|
||||
<th className={thBaseClasses}> 추천 </th>
|
||||
{/* Note: Original CSS applied right border to all TH. Tailwind border utilities apply to all sides unless specified (e.g., border-l), so the above covers it. If you only wanted specific borders, you'd adjust.*/}
|
||||
</tr>
|
||||
</thead>
|
||||
{/* Table Body */}
|
||||
<tbody className="bg-transparent">
|
||||
{data.map((row, index) => (
|
||||
// Using id-index key for potential non-unique IDs between notices/regular posts
|
||||
<TableRow key={`${row.id}-${index}`} rowData={row} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
6
src/util/cn.ts
Normal file
6
src/util/cn.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: (string | undefined | false)[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
7
tailwind.config.js
Normal file
7
tailwind.config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
// tailwind.config.js
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}", // Adjust path as needed
|
||||
]
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
// import tailwindcss from '@tailwindcss/vite'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
tailwindcss(),
|
||||
],
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue