[260203] 인벤토리 프로젝트 초안
This commit is contained in:
198
.gitignore
vendored
Normal file
198
.gitignore
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### macOS Patch ###
|
||||
# iCloud generated files
|
||||
*.icloud
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
205
data.js
Normal file
205
data.js
Normal file
@@ -0,0 +1,205 @@
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: 10,
|
||||
title: "iPhone 10 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매중", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
title: "iPhone 9 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: 'Design',
|
||||
status: "판매예정", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: "iPhone 8 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Games",
|
||||
status: "판매완료",
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: "iPhone 7 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매예정", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: "iPhone 6 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매중", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "iPhone 5 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매중", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "iPhone 4 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매중", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "iPhone 3 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매중", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "iPhone 2 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매중", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "iPhone 13 Pro",
|
||||
price: 750000,
|
||||
currency: "₩",
|
||||
category: "Tech",
|
||||
status: "판매예정", // 판매중, Sold
|
||||
description: "Sierra Blue, 256GB, Pristine condition.",
|
||||
fullDescription: "Pristine condition, used for less than 2 months. Battery health 99%.",
|
||||
images: [
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc",
|
||||
"https://lh3.googleusercontent.com/aida-public/AB6AXuA7hmGyvHzZaWVIskqdD5YU8lZM79hZ0JQjlKk75lRwcbonNCkKqS1EmRqbRzgcdq4AF6nOitcS23NvUZJ4aq_kt_pC2tG875KcVuro1hpXzdRixXHg5p0Dj0WTAaHyfc7GRWqFwOG3Sj0WOyXxULWDvKCR92rySu5iZz7hM6j73uP9i5QRRrkukQIzJWyx_KKmBc_uHX6v0MRn05_uttHQCtBeMUiabXwujqea0pay9fk7jC2mWHS5DaweeVv7SYuXSvypdJRZggs"
|
||||
],
|
||||
specs: {
|
||||
purchaseDate: "2023-10",
|
||||
condition: "Mint (S-Grade)"
|
||||
}
|
||||
},
|
||||
// ... 추가 상품 데이터 (8~12개 이상)
|
||||
];
|
||||
export default products;
|
||||
306
index.html
Normal file
306
index.html
Normal file
@@ -0,0 +1,306 @@
|
||||
<!doctype html>
|
||||
|
||||
<html class="light" lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
<title>Minimalist Product Catalog</title>
|
||||
<!-- Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||
<!-- Google Fonts: Inter -->
|
||||
<link href="https://fonts.googleapis.com" rel="preconnect" />
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<!-- Material Symbols -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet" />
|
||||
<script id="tailwind-config">
|
||||
tailwind.config = {
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
"primary": "#137fec",
|
||||
"background-light": "#f6f7f8",
|
||||
"background-dark": "#101922",
|
||||
},
|
||||
fontFamily: {
|
||||
"display": ["Inter", "sans-serif"]
|
||||
},
|
||||
borderRadius: {
|
||||
"DEFAULT": "0.25rem",
|
||||
"lg": "0.5rem",
|
||||
"xl": "0.75rem",
|
||||
"full": "9999px"
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.material-symbols-outlined {
|
||||
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
|
||||
}
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
/* 스크롤바 완전히 숨기기 */
|
||||
.no-scrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
#modal-main-carousel-container {
|
||||
scroll-snap-type: none;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.filter-chip,
|
||||
.status-chip {
|
||||
@apply px-4 py-2 rounded-full text-sm font-medium transition
|
||||
border border-slate-200 dark:border-slate-700
|
||||
bg-slate-50 dark:bg-slate-800
|
||||
text-slate-700 dark:text-slate-300;
|
||||
}
|
||||
|
||||
.filter-chip.active,
|
||||
.status-chip.active {
|
||||
@apply bg-primary text-white border-primary;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-background-light dark:bg-background-dark transition-colors duration-200">
|
||||
<div class="relative flex h-auto min-h-screen w-full flex-col group/design-root overflow-x-hidden">
|
||||
<div class="layout-container flex h-full grow flex-col">
|
||||
<!-- Top Navigation Bar -->
|
||||
<header class="sticky top-0 z-50 flex items-center justify-between whitespace-nowrap border-b border-solid border-slate-200 dark:border-slate-800 bg-white/80 dark:bg-background-dark/80 backdrop-blur-md px-6 md:px-40 py-3">
|
||||
<div class="flex items-center gap-8">
|
||||
<div class="flex items-center gap-3 text-slate-900 dark:text-white">
|
||||
<div class="flex items-center justify-center size-8 bg-primary rounded-lg text-white">
|
||||
<span class="material-symbols-outlined text-xl">inventory_2</span>
|
||||
</div>
|
||||
<h2 class="text-lg font-bold leading-tight tracking-tight">Studio Archive</h2>
|
||||
</div>
|
||||
<!-- <nav class="hidden md:flex items-center gap-8">
|
||||
<a class="text-slate-900 dark:text-slate-100 text-sm font-medium hover:text-primary transition-colors" href="#">Collection</a>
|
||||
<a class="text-slate-500 dark:text-slate-400 text-sm font-medium hover:text-primary transition-colors" href="#">Tech</a>
|
||||
<a class="text-slate-500 dark:text-slate-400 text-sm font-medium hover:text-primary transition-colors" href="#">Archive</a>
|
||||
</nav> -->
|
||||
</div>
|
||||
<div class="flex flex-1 justify-end gap-4 items-center">
|
||||
<label class="hidden sm:flex flex-col min-w-40 !h-10 max-w-64">
|
||||
<div class="flex w-full flex-1 items-stretch rounded-lg h-full border border-slate-200 dark:border-slate-700">
|
||||
<div class="text-slate-400 flex items-center justify-center pl-3">
|
||||
<span class="material-symbols-outlined text-[20px]">search</span>
|
||||
</div>
|
||||
<input id="search-input" class="form-input flex w-full min-w-0 flex-1 border-none bg-transparent focus:outline-0 focus:ring-0 text-slate-900 dark:text-slate-100 placeholder:text-slate-400 px-3 text-sm font-normal" placeholder="Search items..." value="" />
|
||||
</div>
|
||||
</label>
|
||||
<!-- <div
|
||||
class="bg-center bg-no-repeat aspect-square bg-cover rounded-full size-9 border border-slate-200 dark:border-slate-700"
|
||||
data-alt="Portrait of a person profile picture"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuBU9SHb3BY7t3kVP81gp9gRzobkneoAoEWyLZTb8OkxnYI0bwWzk_iPiExHkPUCEq1AnlBnrCBOTB0rRx0qdDYF_KML3YtftYZP4bXiA1IY5Y5u0r16HQpYhzTYmQnnY-k52Z6u1DsCkepdeftke78K45WWvluFzOif6NcHRnfe9_LTOTDEwhD4mtsWJOYI5BenKhudyufV9u1SXblfulp5JXYm4MwqYMGLD4iLzXkjiVH5C-0Ry66mfrxkOhME00b-vfj9luQIVtE");'></div> -->
|
||||
</div>
|
||||
</header>
|
||||
<main class="flex-1">
|
||||
<!-- Headline Section -->
|
||||
<div class="px-6 md:px-40 py-12 flex flex-col items-center">
|
||||
<h1 class="text-slate-900 dark:text-white tracking-tight text-3xl md:text-5xl font-bold leading-tight text-center max-w-3xl">Curated quality items for your creative workspace.</h1>
|
||||
<p class="mt-4 text-slate-500 dark:text-slate-400 text-center text-lg max-w-xl">A personal collection of tech, furniture, and tools, looking for their next home.</p>
|
||||
</div>
|
||||
<!-- -->
|
||||
|
||||
<section class="mb-8 px-6 md:px-40">
|
||||
<div class="rounded-2xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 flex flex-col gap-4">
|
||||
|
||||
<!-- 카테고리 -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<h4 class="text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
Category
|
||||
</h4>
|
||||
<div id="filter-chips" class="flex flex-wrap gap-2"></div>
|
||||
</div>
|
||||
|
||||
<div class="h-px bg-slate-100 dark:bg-slate-700"></div>
|
||||
|
||||
<!-- 상태 -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<h4 class="text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
Status
|
||||
</h4>
|
||||
<div id="status-chips" class="flex flex-wrap gap-2"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- Filters/Chips Section -->
|
||||
|
||||
<div class="px-6 md:px-40 flex justify-center">
|
||||
<div class="flex gap-2 p-1 flex-wrap justify-center bg-slate-100 dark:bg-slate-800 rounded-xl">
|
||||
<!-- <div id="filter-chips" class="flex gap-2 flex-wrap"></div> -->
|
||||
<!-- <div id="status-chips" class="flex gap-2 flex-wrap mt-2"></div> -->
|
||||
<!-- <div class="flex h-9 px-5 shrink-0 items-center justify-center rounded-lg bg-white dark:bg-slate-700 shadow-sm cursor-pointer transition-all">
|
||||
<p class="text-slate-900 dark:text-white text-sm font-semibold">All Items</p>
|
||||
</div>
|
||||
<div class="flex h-9 px-5 shrink-0 items-center justify-center rounded-lg hover:bg-white/50 dark:hover:bg-slate-700/50 cursor-pointer transition-all">
|
||||
<p class="text-slate-500 dark:text-slate-300 text-sm font-medium">Available</p>
|
||||
</div>
|
||||
<div class="flex h-9 px-5 shrink-0 items-center justify-center rounded-lg hover:bg-white/50 dark:hover:bg-slate-700/50 cursor-pointer transition-all">
|
||||
<p class="text-slate-500 dark:text-slate-300 text-sm font-medium">Computing</p>
|
||||
</div>
|
||||
<div class="flex h-9 px-5 shrink-0 items-center justify-center rounded-lg hover:bg-white/50 dark:hover:bg-slate-700/50 cursor-pointer transition-all">
|
||||
<p class="text-slate-500 dark:text-slate-300 text-sm font-medium">Furniture</p>
|
||||
</div>
|
||||
<div class="flex h-9 px-5 shrink-0 items-center justify-center rounded-lg hover:bg-white/50 dark:hover:bg-slate-700/50 cursor-pointer transition-all">
|
||||
<p class="text-slate-500 dark:text-slate-300 text-sm font-medium">Sold</p>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- Product Grid -->
|
||||
<div class="px-6 md:px-40 py-10">
|
||||
<div id="product-grid" class="grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8">
|
||||
<!-- Product Item -->
|
||||
<div class="group flex flex-col gap-4">
|
||||
<div class="relative w-full aspect-[4/5] bg-slate-50 dark:bg-slate-800 rounded-xl overflow-hidden shadow-sm group-hover:shadow-md transition-shadow">
|
||||
<div
|
||||
class="w-full h-full bg-center bg-no-repeat bg-cover transform group-hover:scale-105 transition-transform duration-500"
|
||||
data-alt="Modern smartphone against minimalist background"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuCJW9hNp1uNfX6KZ1fyWZtxOEYdMb7hzRHsDrey6r63fcoisTxQTWWgL99dRcVZQJO1zZyI-HEU6cTgN-YEiXbqpbRZe0LqqC7bKp38y4i901ZuEnOdNXWyNVGNlfOGKG4z571bvFgX7qeVhH8VqsfP_ueAsCyLd9whzNZ-5KdsnR_nYvxO847cVKDMMFJpu347XFXo_QIaZK-Y4RLJAxa7Vv5E6OSrimV6zedPzkwp8yl7FvHbP-QLZ_lbQWZX-Lw6gTBAHiaoAkY");'></div>
|
||||
<div class="absolute top-3 left-3">
|
||||
<span class="px-2 py-1 text-[10px] uppercase tracking-wider font-bold rounded bg-primary/10 text-primary backdrop-blur-md border border-primary/20">Available</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex justify-between items-start">
|
||||
<h3 class="text-slate-900 dark:text-white text-base font-semibold leading-tight group-hover:text-primary transition-colors">iPhone 13 Pro</h3>
|
||||
<p class="text-slate-900 dark:text-white text-base font-bold">$750</p>
|
||||
</div>
|
||||
<p class="text-slate-500 dark:text-slate-400 text-sm font-normal">Sierra Blue, 256GB, Pristine</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Pagination -->
|
||||
<div class="px-6 md:px-40 py-12">
|
||||
<div id="pagination" class="flex items-center justify-center gap-2">
|
||||
<!-- <a class="flex size-10 items-center justify-center rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-500" href="#">
|
||||
<span class="material-symbols-outlined">chevron_left</span>
|
||||
</a>
|
||||
<a class="text-sm font-bold flex size-10 items-center justify-center text-white rounded-lg bg-primary" href="#">1</a>
|
||||
<a class="text-sm font-medium flex size-10 items-center justify-center text-slate-500 dark:text-slate-400 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800" href="#">2</a>
|
||||
<a class="text-sm font-medium flex size-10 items-center justify-center text-slate-500 dark:text-slate-400 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800" href="#">3</a>
|
||||
<a class="flex size-10 items-center justify-center rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-500" href="#">
|
||||
<span class="material-symbols-outlined">chevron_right</span>
|
||||
</a> -->
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<!-- Modal -->
|
||||
<!-- Backdrop Overlay -->
|
||||
<div id="product-modal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm p-4 md:p-10 hidden" onclick="if(event.target === this) closeModal()">
|
||||
<!-- Modal Container -->
|
||||
<div class="relative w-full max-w-6xl max-h-[90vh] bg-white dark:bg-background-dark rounded-xl shadow-2xl overflow-hidden flex flex-col md:flex-row border border-gray-200 dark:border-gray-800">
|
||||
<!-- Close Button -->
|
||||
<button onclick="closeModal()" class="absolute top-4 right-4 z-50 flex items-center justify-center w-10 h-10 rounded-full bg-white/80 dark:bg-gray-800/80 backdrop-blur hover:bg-white dark:hover:bg-gray-700 transition-colors shadow-sm">
|
||||
<span class="material-symbols-outlined text-gray-900 dark:text-white">close</span>
|
||||
</button>
|
||||
<!-- Left: Gallery Section -->
|
||||
<div class="w-full md:w-3/5 bg-gray-50 dark:bg-gray-900 flex flex-col relative overflow-hidden">
|
||||
<!-- Main Carousel -->
|
||||
<div id="modal-main-carousel-container" class="flex-1 overflow-x-auto no-scrollbar flex items-center ml-0 lg:ml-24">
|
||||
<div id="modal-main-carousel" class="flex h-full w-full">
|
||||
<!-- Image -->
|
||||
<div class="flex-shrink-0 w-full h-full snap-center flex items-center justify-center p-4">
|
||||
<div
|
||||
class="w-full h-full bg-center bg-no-repeat bg-contain rounded-lg"
|
||||
data-alt="Front view of Sony WH-1000XM5 headphones in black"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuCOlUeqiUla7LkapcfcrnlTRF-bvdnD2tGTS8zjFgnxr6MNEwmTehjldThx6SCikcIP4-uUK4fbm1EFxj7XKKckJnQr8AunGsdWdgOlH5Fex0ML3uFw5fCnp997fuXQa2ceXdqXfiGDM17AdqB7tx9kxLoxEUXDxROSiH7I2-KFOweIR1-dBljEbeih1fQ1y_HACne_STdXKwGfrkPsHOXz-Ls7-MBW8uD1i5Mz64d3I8z4sO036qIlTNd2Iz4pqPxp7ucNkhrtQoc");'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Carousel Navigation -->
|
||||
<div id="modal-dots" class="absolute bottom-6 left-1/2 -translate-x-1/2 flex items-center gap-2">
|
||||
<div class="w-2 h-2 rounded-full bg-primary"></div>
|
||||
<div class="w-2 h-2 rounded-full bg-gray-300 dark:bg-gray-700"></div>
|
||||
<div class="w-2 h-2 rounded-full bg-gray-300 dark:bg-gray-700"></div>
|
||||
</div>
|
||||
<!-- Side Thumbnails (Visible on Large Screens) -->
|
||||
<div id="modal-thumbnails" class="hidden lg:flex absolute left-4 top-1/2 -translate-y-1/2 flex-col gap-3 max-h-[70vh] overflow-y-auto no-scrollbar pr-1">
|
||||
<div
|
||||
class="size-16 rounded-lg border-2 border-primary bg-cover bg-center overflow-hidden cursor-pointer"
|
||||
data-alt="Thumbnail front view"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuBFrW2dPhArwFKxHL3LH03GD_jG31BBbMo0Dfkz7QOOhw7j5e-11atdSMyIhfiQiILtIulqm20x3fMcXr50IbtwKu3cZLMwpPbNqsnHyZiIB1jZL3a-Fvaq95WLPmyWZU82rrpFZozX2ICjWK4H1oO0Q1VuyIksmBoKaXce3-HxGY_pD8HuO1ua_PgT_ZGTTVagbUpcDDuUjbqEZ_Xd9XY74NyYBP-CwuG0ab_rvav-c9DFrkxQ1PKe-TLvJf-lXAA1iuEkhdKGVDQ");'></div>
|
||||
<div
|
||||
class="size-16 rounded-lg border border-transparent bg-cover bg-center overflow-hidden cursor-pointer opacity-70 hover:opacity-100"
|
||||
data-alt="Thumbnail side view"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuAq1q1Tdi4V77S-ZpUxbkru_BT1vkcqXqQELpgawTTZ-iNZEM2VRXChC2bpa38TSAGt8TCyZ1exgHFPCwaswHv4d4SS-8EfpDv3hYwyvYWbl6j9-gSpmTsaRQE2Sn86yRkrABWZSA68TMtZaI138Q440vVOS52qd_cINWShrdv-rM-DgW2q15sWcWToiqLtiDnpGiQMHOK8BU97VOLd-9WPP-WQSUqf8FCuho2PvmupnqrYvrBWjN83upohCeer5xMQWpMGoIbZztg");'></div>
|
||||
<div
|
||||
class="size-16 rounded-lg border border-transparent bg-cover bg-center overflow-hidden cursor-pointer opacity-70 hover:opacity-100"
|
||||
data-alt="Thumbnail case view"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuDvRgvsYOJNQ2ow1S9CIvQ20TEk6U75hkG-ZNfwYk_htB6pRZNw87XJvXZGtRIva58DthJxX_yPNsbUPwntguucSfqBdeFERyYx_sH0Ta-KqZhwKpnCpCLUdFli_JgSzg2L-s5UsYPadChOKdsiV2iieblFwRFkB_0_Qap99PY7W6mZ5KFzpyx3M4LhBJnq06MQlJF6_P5NSBUbMy2VxveNFQWb8wMuJVTK8GC_XeVvC9wdxuf9fZOLAMc6wB_vY_LgBBRsfCb-8Tw");'></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Right: Details Section -->
|
||||
<div class="w-full md:w-2/5 flex flex-col h-full bg-white dark:bg-background-dark p-6 md:p-10 overflow-y-auto">
|
||||
<!-- Category/Badge -->
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<span id="modal-category" class="px-2.5 py-1 rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 text-xs font-bold uppercase tracking-wider">Audio & Tech</span>
|
||||
<span id="modal-status" class="px-2.5 py-1 rounded-lg bg-green-100 text-green-700 text-xs font-bold uppercase tracking-wider">Available</span>
|
||||
</div>
|
||||
<!-- Title -->
|
||||
<h1 id="modal-title" class="text-[#111418] dark:text-white text-3xl font-black leading-tight tracking-tight mb-2">Sony WH-1000XM5 Noise Canceling Headphones</h1>
|
||||
<!-- Price -->
|
||||
<p id="modal-price" class="text-[#111418] dark:text-white text-4xl font-bold mb-8">₩320,000</p>
|
||||
<!-- Spec List -->
|
||||
<div class="space-y-0 mb-8">
|
||||
<div class="flex items-center justify-between py-4 border-t border-gray-100 dark:border-gray-800">
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm font-medium uppercase tracking-tight">Purchase Date</span>
|
||||
<span id="modal-date" class="text-[#111418] dark:text-white text-sm font-semibold">October 2023</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between py-4 border-t border-gray-100 dark:border-gray-800">
|
||||
<span class="text-gray-500 dark:text-gray-400 text-sm font-medium uppercase tracking-tight">Condition Status</span>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="material-symbols-outlined text-primary text-lg">verified</span>
|
||||
<span id="modal-condition" class="text-[#111418] dark:text-white text-sm font-semibold">Mint (S-Grade)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Description -->
|
||||
<div class="mb-10">
|
||||
<h3 class="text-[#111418] dark:text-white text-sm font-bold uppercase tracking-widest mb-3">Item Description</h3>
|
||||
<p id="modal-desc" class="text-gray-600 dark:text-gray-300 text-base leading-relaxed">
|
||||
Pristine condition, used for less than 2 months for office work only. No visible scratches or dents. Battery health is at 99%. Comes with original retail box, carrying case, USB-C charging cable, and 3.5mm jack. Selling as I switched to a different setup.
|
||||
</p>
|
||||
</div>
|
||||
<!-- Footer / CTA -->
|
||||
<div class="mt-auto pt-6 border-t border-gray-100 dark:border-gray-800">
|
||||
<button class="w-full flex items-center justify-center gap-2 bg-primary hover:bg-blue-600 text-white font-bold py-4 px-6 rounded-xl transition-all shadow-lg shadow-primary/25">
|
||||
<span class="material-symbols-outlined">chat_bubble</span>
|
||||
<span>오픈카톡으로 문의하기</span>
|
||||
</button>
|
||||
<p class="text-center text-xs text-gray-400 dark:text-gray-500 mt-4 font-medium">Secure transaction recommended. Ships within 24 hours.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer -->
|
||||
<footer class="px-6 md:px-40 py-12 border-t border-slate-200 dark:border-slate-800">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center gap-6">
|
||||
<div class="flex items-center gap-2 text-slate-400 dark:text-slate-500 text-sm font-medium">
|
||||
<span>© 2024 Studio Archive Catalog</span>
|
||||
<span class="px-1 text-slate-300">•</span>
|
||||
<span>Personal Sales Page</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-6">
|
||||
<a class="text-slate-500 hover:text-primary transition-colors" href="#"><span class="material-symbols-outlined">mail</span></a>
|
||||
<a class="text-slate-500 hover:text-primary transition-colors" href="#"><span class="material-symbols-outlined">share</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
991
package-lock.json
generated
Normal file
991
package-lock.json
generated
Normal file
@@ -0,0 +1,991 @@
|
||||
{
|
||||
"name": "zenn-inventory",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@tailwindcss/cli": "^4.1.18",
|
||||
"tailwindcss": "^4.1.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/remapping": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
|
||||
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.31",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
|
||||
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
|
||||
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3",
|
||||
"is-glob": "^4.0.3",
|
||||
"node-addon-api": "^7.0.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@parcel/watcher-android-arm64": "2.5.6",
|
||||
"@parcel/watcher-darwin-arm64": "2.5.6",
|
||||
"@parcel/watcher-darwin-x64": "2.5.6",
|
||||
"@parcel/watcher-freebsd-x64": "2.5.6",
|
||||
"@parcel/watcher-linux-arm-glibc": "2.5.6",
|
||||
"@parcel/watcher-linux-arm-musl": "2.5.6",
|
||||
"@parcel/watcher-linux-arm64-glibc": "2.5.6",
|
||||
"@parcel/watcher-linux-arm64-musl": "2.5.6",
|
||||
"@parcel/watcher-linux-x64-glibc": "2.5.6",
|
||||
"@parcel/watcher-linux-x64-musl": "2.5.6",
|
||||
"@parcel/watcher-win32-arm64": "2.5.6",
|
||||
"@parcel/watcher-win32-ia32": "2.5.6",
|
||||
"@parcel/watcher-win32-x64": "2.5.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-android-arm64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
|
||||
"integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
|
||||
"integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-x64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
|
||||
"integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
|
||||
"integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
|
||||
"integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
|
||||
"integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
|
||||
"integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
|
||||
"integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
|
||||
"integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
|
||||
"integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-arm64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
|
||||
"integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-ia32": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
|
||||
"integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-x64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
|
||||
"integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/cli": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.1.18.tgz",
|
||||
"integrity": "sha512-sMZ+lZbDyxwjD2E0L7oRUjJ01Ffjtme5OtjvvnC+cV4CEDcbqzbp25TCpxHj6kWLU9+DlqJOiNgSOgctC2aZmg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@parcel/watcher": "^2.5.1",
|
||||
"@tailwindcss/node": "4.1.18",
|
||||
"@tailwindcss/oxide": "4.1.18",
|
||||
"enhanced-resolve": "^5.18.3",
|
||||
"mri": "^1.2.0",
|
||||
"picocolors": "^1.1.1",
|
||||
"tailwindcss": "4.1.18"
|
||||
},
|
||||
"bin": {
|
||||
"tailwindcss": "dist/index.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
|
||||
"integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.4",
|
||||
"enhanced-resolve": "^5.18.3",
|
||||
"jiti": "^2.6.1",
|
||||
"lightningcss": "1.30.2",
|
||||
"magic-string": "^0.30.21",
|
||||
"source-map-js": "^1.2.1",
|
||||
"tailwindcss": "4.1.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
|
||||
"integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tailwindcss/oxide-android-arm64": "4.1.18",
|
||||
"@tailwindcss/oxide-darwin-arm64": "4.1.18",
|
||||
"@tailwindcss/oxide-darwin-x64": "4.1.18",
|
||||
"@tailwindcss/oxide-freebsd-x64": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
|
||||
"@tailwindcss/oxide-linux-x64-musl": "4.1.18",
|
||||
"@tailwindcss/oxide-wasm32-wasi": "4.1.18",
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
|
||||
"@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-android-arm64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
|
||||
"integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
|
||||
"integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
|
||||
"integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
|
||||
"integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
|
||||
"integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
|
||||
"integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
|
||||
"integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
|
||||
"integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
|
||||
"integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
|
||||
"integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
|
||||
"bundleDependencies": [
|
||||
"@napi-rs/wasm-runtime",
|
||||
"@emnapi/core",
|
||||
"@emnapi/runtime",
|
||||
"@tybys/wasm-util",
|
||||
"@emnapi/wasi-threads",
|
||||
"tslib"
|
||||
],
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.7.1",
|
||||
"@emnapi/runtime": "^1.7.1",
|
||||
"@emnapi/wasi-threads": "^1.1.0",
|
||||
"@napi-rs/wasm-runtime": "^1.1.0",
|
||||
"@tybys/wasm-util": "^0.10.1",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
|
||||
"integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
|
||||
"integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.18.4",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
|
||||
"integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
|
||||
"integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"lightningcss-android-arm64": "1.30.2",
|
||||
"lightningcss-darwin-arm64": "1.30.2",
|
||||
"lightningcss-darwin-x64": "1.30.2",
|
||||
"lightningcss-freebsd-x64": "1.30.2",
|
||||
"lightningcss-linux-arm-gnueabihf": "1.30.2",
|
||||
"lightningcss-linux-arm64-gnu": "1.30.2",
|
||||
"lightningcss-linux-arm64-musl": "1.30.2",
|
||||
"lightningcss-linux-x64-gnu": "1.30.2",
|
||||
"lightningcss-linux-x64-musl": "1.30.2",
|
||||
"lightningcss-win32-arm64-msvc": "1.30.2",
|
||||
"lightningcss-win32-x64-msvc": "1.30.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-android-arm64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
|
||||
"integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-arm64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
|
||||
"integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
|
||||
"integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-freebsd-x64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
|
||||
"integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm-gnueabihf": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
|
||||
"integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-gnu": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
|
||||
"integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-musl": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
|
||||
"integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-gnu": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
|
||||
"integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-musl": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
|
||||
"integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-arm64-msvc": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
|
||||
"integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-x64-msvc": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
|
||||
"integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/mri": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "4.1.18",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
||||
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
||||
"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
package.json
Normal file
6
package.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@tailwindcss/cli": "^4.1.18",
|
||||
"tailwindcss": "^4.1.18"
|
||||
}
|
||||
}
|
||||
543
scripts/app.js
Normal file
543
scripts/app.js
Normal file
@@ -0,0 +1,543 @@
|
||||
import products from '/data.js';
|
||||
|
||||
const ITEMS_PER_PAGE = 8;
|
||||
let currentPage = 1;
|
||||
let activeCategories = new Set(['All']);
|
||||
let visibleProducts = products;
|
||||
let searchKeyword = '';
|
||||
|
||||
const VISIBILITY_CONFIG = {
|
||||
showUnlisted: false, // 🔥 미판매 노출 여부
|
||||
showSold: true,
|
||||
};
|
||||
|
||||
const STATUS_META = {
|
||||
미판매: {
|
||||
selectable: false, // 기본 필터에 안 뜸
|
||||
defaultVisible: false,
|
||||
soldOut: false,
|
||||
},
|
||||
판매예정: {
|
||||
selectable: true,
|
||||
defaultVisible: true,
|
||||
soldOut: false,
|
||||
},
|
||||
판매중: {
|
||||
selectable: true,
|
||||
defaultVisible: true,
|
||||
soldOut: false,
|
||||
},
|
||||
판매완료: {
|
||||
selectable: true,
|
||||
defaultVisible: false,
|
||||
soldOut: true,
|
||||
},
|
||||
};
|
||||
|
||||
const STATUS_FILTERS = [
|
||||
{
|
||||
key: '판매중',
|
||||
label: '판매중',
|
||||
defaultActive: true,
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
key: '판매예정',
|
||||
label: '판매 예정',
|
||||
defaultActive: true,
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
key: '미판매',
|
||||
label: '미판매',
|
||||
defaultActive: false,
|
||||
visible: VISIBILITY_CONFIG.showUnlisted,
|
||||
},
|
||||
{
|
||||
key: '판매완료',
|
||||
label: '판매완료',
|
||||
defaultActive: false,
|
||||
visible: VISIBILITY_CONFIG.showSold,
|
||||
},
|
||||
];
|
||||
|
||||
const STATUS_ORDER = {
|
||||
판매중: 0,
|
||||
판매예정: 1,
|
||||
미판매: 2,
|
||||
판매완료: 3, // 🔥 항상 맨 뒤
|
||||
};
|
||||
|
||||
const STATUS_COLOR = {
|
||||
판매중: 'bg-primary/10 text-primary border-primary/30',
|
||||
판매예정: 'bg-amber-400/10 text-amber-600 border-amber-400/30',
|
||||
판매완료: 'bg-slate-400/10 text-slate-500 border-slate-400/30',
|
||||
미판매: 'bg-slate-200/10 text-slate-400 border-slate-300/30',
|
||||
};
|
||||
|
||||
let activeStatuses = new Set(
|
||||
Object.entries(STATUS_META)
|
||||
.filter(([_, meta]) => meta.defaultVisible)
|
||||
.map(([status]) => status),
|
||||
);
|
||||
|
||||
function renderStatusChips() {
|
||||
const container = document.getElementById('status-chips');
|
||||
if (!container) return;
|
||||
|
||||
container.innerHTML = '';
|
||||
|
||||
STATUS_FILTERS.filter((f) => f.visible).forEach(({ key, label }) => {
|
||||
const isActive = activeStatuses.has(key);
|
||||
const baseColor = STATUS_COLOR[key] ?? '';
|
||||
|
||||
const chip = document.createElement('button');
|
||||
|
||||
chip.className = `
|
||||
status-chip px-4 py-2 rounded-full text-sm font-medium transition
|
||||
border
|
||||
${isActive ? baseColor : 'bg-slate-50 text-slate-600 border-slate-200'}
|
||||
`;
|
||||
|
||||
chip.textContent = label;
|
||||
|
||||
chip.onclick = () => {
|
||||
toggleStatusFilter(key);
|
||||
};
|
||||
|
||||
container.appendChild(chip);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleStatusFilter(status) {
|
||||
if (activeStatuses.has(status)) {
|
||||
activeStatuses.delete(status);
|
||||
} else {
|
||||
activeStatuses.add(status);
|
||||
}
|
||||
|
||||
// 최소 1개는 유지
|
||||
if (activeStatuses.size === 0) {
|
||||
STATUS_FILTERS.filter((f) => f.defaultActive).forEach((f) => activeStatuses.add(f.key));
|
||||
}
|
||||
|
||||
applyFilters();
|
||||
renderStatusChips();
|
||||
}
|
||||
|
||||
const searchInput = document.getElementById('search-input');
|
||||
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
searchKeyword = e.target.value.trim().toLowerCase();
|
||||
applyFilters();
|
||||
});
|
||||
}
|
||||
|
||||
function applyFilters() {
|
||||
currentPage = 1;
|
||||
|
||||
visibleProducts = products
|
||||
.filter((product) => {
|
||||
// 🔒 미판매 강제 차단
|
||||
if (product.status === '미판매' && !VISIBILITY_CONFIG.showUnlisted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 🔒 판매완료 기본 숨김
|
||||
if (product.status === '판매완료' && !VISIBILITY_CONFIG.showSold) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const statusMatch = activeStatuses.has(product.status);
|
||||
const categoryMatch = activeCategories.has('All') || activeCategories.has(product.category);
|
||||
const searchMatch = searchKeyword === '' || product.title.toLowerCase().includes(searchKeyword);
|
||||
|
||||
return statusMatch && categoryMatch && searchMatch;
|
||||
})
|
||||
// 🔥 여기서 정렬
|
||||
.sort((a, b) => {
|
||||
const aOrder = STATUS_ORDER[a.status] ?? 999;
|
||||
const bOrder = STATUS_ORDER[b.status] ?? 999;
|
||||
return aOrder - bOrder;
|
||||
});
|
||||
|
||||
renderProducts(currentPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 상품 목록 렌더링
|
||||
*/
|
||||
export function renderProducts(page) {
|
||||
const grid = document.getElementById('product-grid');
|
||||
if (!grid) return;
|
||||
grid.innerHTML = '';
|
||||
|
||||
const startIndex = (page - 1) * ITEMS_PER_PAGE;
|
||||
const pagedProducts = visibleProducts.slice(startIndex, startIndex + ITEMS_PER_PAGE);
|
||||
|
||||
pagedProducts.forEach((product) => {
|
||||
const isSold = STATUS_META[product.status]?.soldOut === true;
|
||||
const cardHtml = `
|
||||
<div class="group flex flex-col gap-4 cursor-pointer" onclick="openModal(${product.id})">
|
||||
<div class="relative w-full aspect-[4/5] bg-slate-50 dark:bg-slate-800 rounded-xl overflow-hidden shadow-sm group-hover:shadow-md transition-shadow">
|
||||
<div class="w-full h-full bg-center bg-no-repeat bg-cover transform ${isSold ? 'grayscale opacity-80' : 'group-hover:scale-105'} transition-transform duration-500"
|
||||
style="background-image: url('${product.images[0]}')"></div>
|
||||
<div class="absolute top-3 left-3">
|
||||
<span class="px-2 py-1 text-[10px] uppercase tracking-wider font-bold rounded ${isSold ? 'bg-slate-900/10 text-slate-500' : 'bg-primary/10 text-primary'} backdrop-blur-md border border-primary/20">
|
||||
${product.status}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex justify-between items-start">
|
||||
<h3 class="text-slate-900 dark:text-white text-base font-semibold ${isSold ? 'line-through text-slate-400' : ''}">${product.title}</h3>
|
||||
<p class="text-slate-900 dark:text-white text-base font-bold text-nowrap">${product.currency}${product.price.toLocaleString()}</p>
|
||||
</div>
|
||||
<p class="text-slate-500 dark:text-slate-400 text-sm font-normal">${product.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
grid.insertAdjacentHTML('beforeend', cardHtml);
|
||||
});
|
||||
|
||||
renderPagination();
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. 모달 열기 및 데이터 채우기
|
||||
*/
|
||||
window.openModal = (id) => {
|
||||
const product = products.find((p) => p.id === id);
|
||||
if (!product) return;
|
||||
|
||||
const modal = document.getElementById('product-modal');
|
||||
const images = product.images;
|
||||
|
||||
// 무한 루프를 위해 처음과 끝에 클론 추가 [마지막 이미지, ...원본 이미지..., 첫 이미지]
|
||||
const loopImages = [images[images.length - 1], ...images, images[0]];
|
||||
|
||||
const mainImagesHtml = loopImages
|
||||
.map(
|
||||
(img) => `
|
||||
<div class="flex-shrink-0 w-full h-full snap-center flex items-center justify-center p-4 select-none">
|
||||
<img src="${img}" draggable="false" class="max-w-full max-h-full object-contain pointer-events-none shadow-sm">
|
||||
</div>
|
||||
`,
|
||||
)
|
||||
.join('');
|
||||
|
||||
// 2. 사이드 썸네일 동적 생성
|
||||
const thumbnailsHtml = product.images
|
||||
.map(
|
||||
(img, idx) => `
|
||||
<div onclick="scrollToImage(${idx})"
|
||||
class="modal-thumb-item size-16 rounded-lg border-2 ${idx === 0 ? 'border-primary' : 'border-transparent'}
|
||||
bg-cover bg-center overflow-hidden cursor-pointer ${idx === 0 ? 'opacity-100' : 'opacity-70'}
|
||||
hover:opacity-100 transition-all flex-shrink-0"
|
||||
style="background-image: url('${img}');"></div>
|
||||
`,
|
||||
)
|
||||
.join('');
|
||||
|
||||
// 3. 페이지네이션 도트 동적 생성
|
||||
const dotsHtml = product.images
|
||||
.map(
|
||||
(_, idx) => `
|
||||
<div class="modal-dot-item ${idx === 0 ? 'w-4 bg-primary' : 'w-2 bg-gray-300 dark:bg-gray-700'} h-2 rounded-full transition-all"></div>
|
||||
`,
|
||||
)
|
||||
.join('');
|
||||
|
||||
// HTML 주입
|
||||
document.getElementById('modal-main-carousel').innerHTML = mainImagesHtml;
|
||||
document.getElementById('modal-thumbnails').innerHTML = thumbnailsHtml;
|
||||
document.getElementById('modal-dots').innerHTML = dotsHtml;
|
||||
|
||||
// 텍스트 정보 주입 (ID들 맞춰주세요)
|
||||
document.getElementById('modal-title').textContent = product.title;
|
||||
document.getElementById('modal-price').textContent = `${product.currency}${product.price.toLocaleString()}`;
|
||||
// ... 나머지 정보 주입
|
||||
|
||||
modal.classList.remove('hidden');
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
// 드래그 기능 다시 연결
|
||||
const container = document.getElementById('modal-main-carousel-container');
|
||||
const carousel = document.getElementById('modal-main-carousel');
|
||||
carousel.innerHTML = mainImagesHtml;
|
||||
|
||||
modal.classList.remove('hidden');
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
// 초기 위치 설정 (클론된 마지막 이미지 다음인 '진짜 첫 번째' 이미지로 이동)
|
||||
// const initialIndex = 1;
|
||||
container.style.scrollBehavior = 'auto';
|
||||
container.scrollLeft = container.clientWidth;
|
||||
|
||||
// 드래그 및 무한 루프 감시 시작
|
||||
initBetterCarousel(container, images.length);
|
||||
};
|
||||
|
||||
function initBetterCarousel(container, originalLength) {
|
||||
let isDragging = false;
|
||||
let startX = 0;
|
||||
let startScroll = 0;
|
||||
let startTime = 0;
|
||||
|
||||
const width = () => container.clientWidth;
|
||||
|
||||
container.addEventListener('mousedown', start);
|
||||
container.addEventListener('touchstart', start, { passive: true });
|
||||
|
||||
function start(e) {
|
||||
isDragging = true;
|
||||
startX = e.touches ? e.touches[0].pageX : e.pageX;
|
||||
startScroll = container.scrollLeft;
|
||||
startTime = Date.now();
|
||||
}
|
||||
|
||||
container.addEventListener('mousemove', move);
|
||||
container.addEventListener('touchmove', move, { passive: false });
|
||||
|
||||
function move(e) {
|
||||
if (!isDragging) return;
|
||||
const x = e.touches ? e.touches[0].pageX : e.pageX;
|
||||
container.scrollLeft = startScroll - (x - startX);
|
||||
}
|
||||
|
||||
container.addEventListener('mouseup', end);
|
||||
container.addEventListener('mouseleave', end);
|
||||
container.addEventListener('touchend', end);
|
||||
|
||||
function end(e) {
|
||||
if (!isDragging) return;
|
||||
isDragging = false;
|
||||
|
||||
const delta = container.scrollLeft - startScroll;
|
||||
const elapsed = Date.now() - startTime;
|
||||
|
||||
const direction = Math.abs(delta) > width() * 0.1 || elapsed < 200 ? (delta > 0 ? 1 : -1) : 0;
|
||||
|
||||
let index = Math.round(startScroll / width()) + direction;
|
||||
|
||||
container.style.scrollBehavior = 'smooth';
|
||||
container.scrollTo({ left: index * width() });
|
||||
|
||||
// 무한 루프 보정
|
||||
setTimeout(() => {
|
||||
container.style.scrollBehavior = 'auto';
|
||||
if (index === 0) {
|
||||
container.scrollLeft = width() * originalLength;
|
||||
}
|
||||
if (index === originalLength + 1) {
|
||||
container.scrollLeft = width();
|
||||
}
|
||||
syncModalUI(originalLength);
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지 슬라이드와 UI(Dots, Thumbs) 동기화
|
||||
*/
|
||||
function syncModalUI(originalLength) {
|
||||
const container = document.getElementById('modal-main-carousel-container');
|
||||
const index = getRealIndex(container, originalLength);
|
||||
|
||||
document.querySelectorAll('.modal-thumb-item').forEach((t, i) => {
|
||||
t.classList.toggle('border-primary', i === index);
|
||||
t.classList.toggle('opacity-100', i === index);
|
||||
t.classList.toggle('opacity-70', i !== index);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.modal-dot-item').forEach((d, i) => {
|
||||
d.classList.toggle('bg-primary', i === index);
|
||||
d.classList.toggle('w-4', i === index);
|
||||
d.classList.toggle('bg-gray-300', i !== index);
|
||||
d.classList.toggle('w-2', i !== index);
|
||||
});
|
||||
|
||||
ensureThumbnailVisible(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. 모달 내 이미지 스크롤 및 UI 동기화
|
||||
*/
|
||||
window.scrollToImage = (index) => {
|
||||
const container = document.getElementById('modal-main-carousel-container');
|
||||
if (!container) return;
|
||||
|
||||
container.scrollTo({
|
||||
left: container.clientWidth * (index + 1), // 🔥 중요
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 5. 기타 (페이지네이션, 모달 닫기)
|
||||
*/
|
||||
function renderPagination() {
|
||||
const container = document.getElementById('pagination');
|
||||
if (!container) return;
|
||||
const totalPages = Math.ceil(visibleProducts.length / ITEMS_PER_PAGE);
|
||||
|
||||
let html = `<button onclick="changePage(${currentPage - 1})" class="size-10 flex items-center justify-center ${currentPage === 1 ? 'invisible' : ''}"><span class="material-symbols-outlined">chevron_left</span></button>`;
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
html += `<button onclick="changePage(${i})" class="size-10 font-bold rounded-lg ${i === currentPage ? 'bg-primary text-white' : 'text-slate-500'}">${i}</button>`;
|
||||
}
|
||||
html += `<button onclick="changePage(${currentPage + 1})" class="size-10 flex items-center justify-center ${currentPage === totalPages ? 'invisible' : ''}"><span class="material-symbols-outlined">chevron_right</span></button>`;
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
window.changePage = (page) => {
|
||||
currentPage = page;
|
||||
renderProducts(currentPage);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
window.closeModal = () => {
|
||||
document.getElementById('product-modal').classList.add('hidden');
|
||||
document.body.style.overflow = 'auto';
|
||||
};
|
||||
|
||||
// 초기 실행
|
||||
document.addEventListener('DOMContentLoaded', () => renderProducts(currentPage));
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key !== 'Escape') return;
|
||||
|
||||
const modal = document.getElementById('product-modal');
|
||||
if (!modal || modal.classList.contains('hidden')) return;
|
||||
|
||||
closeModal();
|
||||
});
|
||||
|
||||
const thumbnailContainer = document.getElementById('modal-thumbnails');
|
||||
|
||||
function ensureThumbnailVisible(index) {
|
||||
const container = document.getElementById('modal-thumbnails');
|
||||
if (!container) return;
|
||||
|
||||
const thumbs = container.querySelectorAll('.modal-thumb-item');
|
||||
const active = thumbs[index];
|
||||
if (!active) return;
|
||||
|
||||
const cRect = container.getBoundingClientRect();
|
||||
const tRect = active.getBoundingClientRect();
|
||||
|
||||
const isVisible = tRect.top >= cRect.top && tRect.bottom <= cRect.bottom;
|
||||
|
||||
if (!isVisible) {
|
||||
active.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getRealIndex(container, originalLength) {
|
||||
let rawIndex = Math.round(container.scrollLeft / container.clientWidth);
|
||||
let index = rawIndex - 1; // 클론 보정
|
||||
|
||||
if (index < 0) index = originalLength - 1;
|
||||
if (index >= originalLength) index = 0;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
// 카테고리 필터
|
||||
function getCategories(products) {
|
||||
return ['All', ...new Set(products.map((p) => p.category))];
|
||||
}
|
||||
|
||||
function renderCategoryChips(products) {
|
||||
const container = document.getElementById('filter-chips');
|
||||
if (!container) return;
|
||||
|
||||
const categories = ['All', ...new Set(products.map((p) => p.category))];
|
||||
|
||||
container.innerHTML = '';
|
||||
|
||||
categories.forEach((cat) => {
|
||||
const isActive = activeCategories.has(cat);
|
||||
|
||||
const chip = document.createElement('button');
|
||||
chip.className = `
|
||||
filter-chip px-4 py-2 rounded-full text-sm font-medium transition
|
||||
border
|
||||
${isActive
|
||||
? 'bg-primary text-white border-primary'
|
||||
: 'bg-slate-50 text-slate-600 border-slate-200'}
|
||||
`;
|
||||
chip.textContent = cat;
|
||||
chip.dataset.category = cat;
|
||||
|
||||
chip.onclick = () => {
|
||||
toggleCategory(cat);
|
||||
};
|
||||
|
||||
container.appendChild(chip);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleCategory(category) {
|
||||
if (category === 'All') {
|
||||
activeCategories.clear();
|
||||
activeCategories.add('All');
|
||||
} else {
|
||||
activeCategories.delete('All');
|
||||
activeCategories.has(category)
|
||||
? activeCategories.delete(category)
|
||||
: activeCategories.add(category);
|
||||
|
||||
if (activeCategories.size === 0) {
|
||||
activeCategories.add('All');
|
||||
}
|
||||
}
|
||||
|
||||
renderCategoryChips(products);
|
||||
applyFilters();
|
||||
}
|
||||
|
||||
function bindCategoryFilter(products) {
|
||||
const chips = document.querySelectorAll('.filter-chip');
|
||||
|
||||
chips.forEach((chip) => {
|
||||
chip.addEventListener('click', () => {
|
||||
const category = chip.dataset.category;
|
||||
|
||||
if (category === 'All') {
|
||||
activeCategories.clear();
|
||||
activeCategories.add('All');
|
||||
} else {
|
||||
activeCategories.delete('All');
|
||||
|
||||
if (activeCategories.has(category)) {
|
||||
activeCategories.delete(category);
|
||||
} else {
|
||||
activeCategories.add(category);
|
||||
}
|
||||
|
||||
// 아무 것도 없으면 All로 복귀
|
||||
if (activeCategories.size === 0) {
|
||||
activeCategories.add('All');
|
||||
}
|
||||
}
|
||||
|
||||
applyFilters();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 카테고리 필터
|
||||
renderCategoryChips(products);
|
||||
bindCategoryFilter(products);
|
||||
// updateChipUI();
|
||||
|
||||
// 상태 필터 (정책 기반)
|
||||
renderStatusChips();
|
||||
|
||||
// 🔥 최초 필터 적용 (이게 첫 렌더)
|
||||
applyFilters();
|
||||
1
style/input.css
Normal file
1
style/input.css
Normal file
@@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
1752
style/tailwind.css
Normal file
1752
style/tailwind.css
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user