diff --git a/.gitignore b/.gitignore index b60eba4..174e867 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # dependencies /node_modules +**/node_modules /.pnp .pnp.* .yarn/* @@ -15,7 +16,9 @@ # next.js /.next/ +**/.next/ /out/ +**/out/ # production /build @@ -23,6 +26,8 @@ # misc .DS_Store *.pem +*.tar.gz +*.log # debug npm-debug.log* diff --git a/almeira-store-app/.gitignore b/almeira-store-app/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/almeira-store-app/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/almeira-store-app/AGENTS.md b/almeira-store-app/AGENTS.md new file mode 100644 index 0000000..643577d --- /dev/null +++ b/almeira-store-app/AGENTS.md @@ -0,0 +1,9 @@ + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/almeira-store-app/CLAUDE.md b/almeira-store-app/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/almeira-store-app/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/almeira-store-app/Dockerfile b/almeira-store-app/Dockerfile new file mode 100644 index 0000000..80966a7 --- /dev/null +++ b/almeira-store-app/Dockerfile @@ -0,0 +1,54 @@ +FROM node:20-alpine AS base + +# 1. Install dependencies +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +COPY package.json package-lock.json* ./ +RUN npm ci + +# 2. Build the app +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +# Appwrite and Public Envs for Build Phase +ARG NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 +ARG NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c +ARG NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db +ARG NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + +ENV NEXT_PUBLIC_APPWRITE_ENDPOINT=$NEXT_PUBLIC_APPWRITE_ENDPOINT +ENV NEXT_PUBLIC_APPWRITE_PROJECT_ID=$NEXT_PUBLIC_APPWRITE_PROJECT_ID +ENV NEXT_PUBLIC_APPWRITE_DATABASE_ID=$NEXT_PUBLIC_APPWRITE_DATABASE_ID +ENV NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=$NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID + +RUN npm run build + +# 3. Production Runner +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy standalone output & public static files +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/almeira-store-app/README.md b/almeira-store-app/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/almeira-store-app/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/almeira-store-app/android/.gitignore b/almeira-store-app/android/.gitignore new file mode 100644 index 0000000..48354a3 --- /dev/null +++ b/almeira-store-app/android/.gitignore @@ -0,0 +1,101 @@ +# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore + +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +# Cordova plugins for Capacitor +capacitor-cordova-android-plugins + +# Copied web assets +app/src/main/assets/public + +# Generated Config files +app/src/main/assets/capacitor.config.json +app/src/main/assets/capacitor.plugins.json +app/src/main/res/xml/config.xml diff --git a/almeira-store-app/android/app/.gitignore b/almeira-store-app/android/app/.gitignore new file mode 100644 index 0000000..043df80 --- /dev/null +++ b/almeira-store-app/android/app/.gitignore @@ -0,0 +1,2 @@ +/build/* +!/build/.npmkeep diff --git a/almeira-store-app/android/app/build.gradle b/almeira-store-app/android/app/build.gradle new file mode 100644 index 0000000..43ab6cd --- /dev/null +++ b/almeira-store-app/android/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + namespace = "co.almeira.store" + compileSdk = rootProject.ext.compileSdkVersion + defaultConfig { + applicationId "co.almeira.store" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + aaptOptions { + // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. + // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 + ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +repositories { + flatDir{ + dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" + implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" + implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" + implementation project(':capacitor-android') + testImplementation "junit:junit:$junitVersion" + androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" + implementation project(':capacitor-cordova-android-plugins') +} + +apply from: 'capacitor.build.gradle' + +try { + def servicesJSON = file('google-services.json') + if (servicesJSON.text) { + apply plugin: 'com.google.gms.google-services' + } +} catch(Exception e) { + logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") +} diff --git a/almeira-store-app/android/app/capacitor.build.gradle b/almeira-store-app/android/app/capacitor.build.gradle new file mode 100644 index 0000000..bbfb44f --- /dev/null +++ b/almeira-store-app/android/app/capacitor.build.gradle @@ -0,0 +1,19 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/almeira-store-app/android/app/proguard-rules.pro b/almeira-store-app/android/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/almeira-store-app/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/almeira-store-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/almeira-store-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..f2c2217 --- /dev/null +++ b/almeira-store-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.getcapacitor.app", appContext.getPackageName()); + } +} diff --git a/almeira-store-app/android/app/src/main/AndroidManifest.xml b/almeira-store-app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b06ddbf --- /dev/null +++ b/almeira-store-app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/almeira-store-app/android/app/src/main/java/co/almeira/store/MainActivity.java b/almeira-store-app/android/app/src/main/java/co/almeira/store/MainActivity.java new file mode 100644 index 0000000..0cb13d3 --- /dev/null +++ b/almeira-store-app/android/app/src/main/java/co/almeira/store/MainActivity.java @@ -0,0 +1,5 @@ +package co.almeira.store; + +import com.getcapacitor.BridgeActivity; + +public class MainActivity extends BridgeActivity {} diff --git a/almeira-store-app/android/app/src/main/res/drawable-land-hdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-land-hdpi/splash.png new file mode 100644 index 0000000..e31573b Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-land-hdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-land-mdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-land-mdpi/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-land-mdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-land-xhdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-land-xhdpi/splash.png new file mode 100644 index 0000000..8077255 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-land-xhdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png new file mode 100644 index 0000000..14c6c8f Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png new file mode 100644 index 0000000..244ca25 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-port-hdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-port-hdpi/splash.png new file mode 100644 index 0000000..74faaa5 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-port-hdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-port-mdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-port-mdpi/splash.png new file mode 100644 index 0000000..e944f4a Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-port-mdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-port-xhdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-port-xhdpi/splash.png new file mode 100644 index 0000000..564a82f Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-port-xhdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png new file mode 100644 index 0000000..bfabe68 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/almeira-store-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png new file mode 100644 index 0000000..6929071 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/almeira-store-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/almeira-store-app/android/app/src/main/res/drawable/ic_launcher_background.xml b/almeira-store-app/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/almeira-store-app/android/app/src/main/res/drawable/splash.png b/almeira-store-app/android/app/src/main/res/drawable/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/drawable/splash.png differ diff --git a/almeira-store-app/android/app/src/main/res/layout/activity_main.xml b/almeira-store-app/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..b5ad138 --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/almeira-store-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/almeira-store-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/almeira-store-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/almeira-store-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..c023e50 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2127973 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..b441f37 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..72905b8 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..8ed0605 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..9502e47 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..4d1e077 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..df0f158 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..853db04 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..6cdf97c Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2960cbb Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e3093a Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..46de6e2 Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..d2ea9ab Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..a40d73e Binary files /dev/null and b/almeira-store-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/almeira-store-app/android/app/src/main/res/values/ic_launcher_background.xml b/almeira-store-app/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/almeira-store-app/android/app/src/main/res/values/strings.xml b/almeira-store-app/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e00480f --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + Almeira Store + Almeira Store + co.almeira.store + co.almeira.store + diff --git a/almeira-store-app/android/app/src/main/res/values/styles.xml b/almeira-store-app/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..be874e5 --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/almeira-store-app/android/app/src/main/res/xml/file_paths.xml b/almeira-store-app/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..bd0c4d8 --- /dev/null +++ b/almeira-store-app/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/almeira-store-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/almeira-store-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java new file mode 100644 index 0000000..0297327 --- /dev/null +++ b/almeira-store-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java @@ -0,0 +1,18 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} diff --git a/almeira-store-app/android/build.gradle b/almeira-store-app/android/build.gradle new file mode 100644 index 0000000..f8f0e43 --- /dev/null +++ b/almeira-store-app/android/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.13.0' + classpath 'com.google.gms:google-services:4.4.4' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +apply from: "variables.gradle" + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/almeira-store-app/android/capacitor.settings.gradle b/almeira-store-app/android/capacitor.settings.gradle new file mode 100644 index 0000000..9a5fa87 --- /dev/null +++ b/almeira-store-app/android/capacitor.settings.gradle @@ -0,0 +1,3 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') diff --git a/almeira-store-app/android/gradle.properties b/almeira-store-app/android/gradle.properties new file mode 100644 index 0000000..2e87c52 --- /dev/null +++ b/almeira-store-app/android/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true diff --git a/almeira-store-app/android/gradle/wrapper/gradle-wrapper.jar b/almeira-store-app/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/almeira-store-app/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/almeira-store-app/android/gradle/wrapper/gradle-wrapper.properties b/almeira-store-app/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7705927 --- /dev/null +++ b/almeira-store-app/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/almeira-store-app/android/gradlew b/almeira-store-app/android/gradlew new file mode 100644 index 0000000..23d15a9 --- /dev/null +++ b/almeira-store-app/android/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/almeira-store-app/android/gradlew.bat b/almeira-store-app/android/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/almeira-store-app/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/almeira-store-app/android/settings.gradle b/almeira-store-app/android/settings.gradle new file mode 100644 index 0000000..3b4431d --- /dev/null +++ b/almeira-store-app/android/settings.gradle @@ -0,0 +1,5 @@ +include ':app' +include ':capacitor-cordova-android-plugins' +project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') + +apply from: 'capacitor.settings.gradle' \ No newline at end of file diff --git a/almeira-store-app/android/variables.gradle b/almeira-store-app/android/variables.gradle new file mode 100644 index 0000000..ee4ba41 --- /dev/null +++ b/almeira-store-app/android/variables.gradle @@ -0,0 +1,16 @@ +ext { + minSdkVersion = 24 + compileSdkVersion = 36 + targetSdkVersion = 36 + androidxActivityVersion = '1.11.0' + androidxAppCompatVersion = '1.7.1' + androidxCoordinatorLayoutVersion = '1.3.0' + androidxCoreVersion = '1.17.0' + androidxFragmentVersion = '1.8.9' + coreSplashScreenVersion = '1.2.0' + androidxWebkitVersion = '1.14.0' + junitVersion = '4.13.2' + androidxJunitVersion = '1.3.0' + androidxEspressoCoreVersion = '3.7.0' + cordovaAndroidVersion = '14.0.1' +} \ No newline at end of file diff --git a/almeira-store-app/capacitor.config.ts b/almeira-store-app/capacitor.config.ts new file mode 100644 index 0000000..ac2938d --- /dev/null +++ b/almeira-store-app/capacitor.config.ts @@ -0,0 +1,25 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'co.almeira.store', + appName: 'Almeira Store', + webDir: 'public', + server: { + url: 'https://store.almeira.com.co', + cleartext: true, + androidScheme: 'https', + }, + plugins: { + SplashScreen: { + launchShowDuration: 2000, + backgroundColor: '#09090b', + showSpinner: false, + }, + StatusBar: { + style: 'DARK', + backgroundColor: '#09090b', + }, + }, +}; + +export default config; diff --git a/almeira-store-app/eslint.config.mjs b/almeira-store-app/eslint.config.mjs new file mode 100644 index 0000000..05e726d --- /dev/null +++ b/almeira-store-app/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/almeira-store-app/next.config.ts b/almeira-store-app/next.config.ts new file mode 100644 index 0000000..5b406fe --- /dev/null +++ b/almeira-store-app/next.config.ts @@ -0,0 +1,12 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", + images: { + remotePatterns: [ + { protocol: "https", hostname: "**" }, + ], + }, +}; + +export default nextConfig; diff --git a/almeira-store-app/package-lock.json b/almeira-store-app/package-lock.json new file mode 100644 index 0000000..f994536 --- /dev/null +++ b/almeira-store-app/package-lock.json @@ -0,0 +1,8446 @@ +{ + "name": "almeira-store-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "almeira-store-app", + "version": "0.1.0", + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capacitor/android": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.5.0.tgz", + "integrity": "sha512-Rb3prJeQiTp0pQhSSOReJuG9VgibOGMG4ECs+UhMwr6TCCHZ3NCZO811bDA0HxD0xrT/gCrJAsY5yfEATu84JQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.5.0" + } + }, + "node_modules/@capacitor/cli": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.5.0.tgz", + "integrity": "sha512-rLdzMUM5QV4WITcqoWv04p32i14BXgUH2diqEH6MWQlWaJfiyNrvOyt/+d5vHAfOxOm1klBu637VDEobctlwBA==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xcode": "^3.0.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@capacitor/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.5.0.tgz", + "integrity": "sha512-Ca4krtqH1hothjtBIwf2J2TW7IhYq1ujp8QeItTiJohNsqij8ja2DYYH3DU0l8RmxCWaBAFTGA2TgOgOMCSNsQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@google/genai": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-2.19.0.tgz", + "integrity": "sha512-IM3u1FjpOLyOPsPh0smGA6Ntj2olUWCPbTs/WQj7cA/2AKCGw/652W7IaySx0XtwuscFnMYBoraebQusSZ0zSQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@next/env": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.3.tgz", + "integrity": "sha512-U2eYQRwXj+dsqxV79zFqExDdatnNY/ZWc2nsJU1p/OgT7fd3dXwlF6OjYaFQCfMoeTA19PWq+wVmYgimVA+V+g==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.3.tgz", + "integrity": "sha512-pbEh30vvjKpDoTAmo1v3q2uM4JUi8QaEBpbmjWvGfoec2jLghy/WNtvzAT0bk+Ik9oz6etjt4YjXEk4BQnicCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "4.9.1", + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.3.tgz", + "integrity": "sha512-8Hiv32QJPwdV6KYJ8meR9SBA061tQqnIKTJDocvOXlEQqib0xMFpzArosuffFUUc0sslbh7QQ8a3Yey1QV8EIw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.3.tgz", + "integrity": "sha512-A1lgKgwVchRYmSe467zdwhxT9040dd8lH+o65sL5Jet8fjB4kegw/rDyPIpYVRb6jAqwXFOJpjIXJLxQKLiE3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.3.tgz", + "integrity": "sha512-bf0FIssMFueU2dm7vQEWWxk0c8UjKTdW0yzuh0sQsD8pf1+KCLDdaqhYZNMYGmXwEOiHAUzgBKudovIlcvvBjg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.3.tgz", + "integrity": "sha512-W7viwCk9JY/cAkdz/A273rd5bb3RgT/IHwR7Upv90tunjBWNtAAhGhoecHh+teRNRSinuAFmE+l7fwZ4YKkrXg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.3.tgz", + "integrity": "sha512-0W46zw1N3ODpI6n0GeivHvvob1pooozgZVqy65k0mh4/7vr+FbY9+WpHzNVXjHipJf/A3FDheBG19H1s5A25rA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.3.tgz", + "integrity": "sha512-H4mBso8ZTMBPtdT0PN0pBx2ayTvQuTuvS6qT13d77yVFJXAPCxkyIhLTmdMaGTJs0krQYI/qpzdHijCeihXhbg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.3.tgz", + "integrity": "sha512-cTMUJpcEGmeywofCUfhR+rSsoE33+rVPnPEYNTNdLNlsOeEg/vktOsKUSTb28vUGqD2jkm4Zaskcwn7OCI6FQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.3.tgz", + "integrity": "sha512-2VR4cTBzHXaBjnGsuH6GyJjENzQOmHeAh11uY1iUhjm3j5dEUrVJuUj+VL78jaGi/Dik8xS76zEj18BsFhlVZQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/canvas-confetti": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz", + "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz", + "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/type-utils": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.68.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz", + "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz", + "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.68.0", + "@typescript-eslint/types": "^8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz", + "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz", + "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz", + "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz", + "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.68.0", + "@typescript-eslint/tsconfig-utils": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz", + "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz", + "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-26.2.0.tgz", + "integrity": "sha512-8TCd4mMKhhUxGF9sjZ6W2V1gesnj43v1SFZoeAue/0O0ikMXIU92p96PiRn0D4nAVvFM/92bluTTb/PoXH5mnQ==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", + "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.415", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.415.tgz", + "integrity": "sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==", + "dev": true, + "license": "ISC" + }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.3.tgz", + "integrity": "sha512-teqtsR26tnlfXFHfVLTM/4tzEzU8DMu6GS1sddZzhfGzgd2f2ofbgDUcsk6cssSCzX6Tk6fmWifJcdANSdPJrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "16.3.3", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "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.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.577.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz", + "integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/native-run": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", + "integrity": "sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==", + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" + }, + "bin": { + "native-run": "bin/native-run" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.3.tgz", + "integrity": "sha512-tuRTx1nQ/yVw83cwJBo9F+njGUgMn3UHQycreWHB8XsStvvAh1AthbI8/4IpKnFaF58F+iSiHejYOlMQ/eq83g==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.3", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.3", + "@next/swc-darwin-x64": "16.3.3", + "@next/swc-linux-arm64-gnu": "16.3.3", + "@next/swc-linux-arm64-musl": "16.3.3", + "@next/swc-linux-x64-gnu": "16.3.3", + "@next/swc-linux-x64-musl": "16.3.3", + "@next/swc-win32-arm64-msvc": "16.3.3", + "@next/swc-win32-x64-msvc": "16.3.3", + "sharp": "^0.35.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-26.2.0.tgz", + "integrity": "sha512-rRToHOuG05F5Q3BGRoJNNIcO69zrYul/V9HOTxfcMSqhdw3TwInAl7pnSnMRW7D0MOQcvaLb8iZIwE1P8TP9Cw==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0", + "undici": "^6.26.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "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": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "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/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.68.0.tgz", + "integrity": "sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.68.0", + "@typescript-eslint/parser": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/almeira-store-app/package.json b/almeira-store-app/package.json new file mode 100644 index 0000000..75afe6f --- /dev/null +++ b/almeira-store-app/package.json @@ -0,0 +1,38 @@ +{ + "name": "almeira-store-app", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev -H 0.0.0.0 -p 3001", + "build": "next build", + "start": "next start -H 0.0.0.0 -p 3001", + "lint": "next lint" + }, + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } +} \ No newline at end of file diff --git a/almeira-store-app/postcss.config.mjs b/almeira-store-app/postcss.config.mjs new file mode 100644 index 0000000..61e3684 --- /dev/null +++ b/almeira-store-app/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/almeira-store-app/public/file.svg b/almeira-store-app/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/almeira-store-app/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/almeira-store-app/public/globe.svg b/almeira-store-app/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/almeira-store-app/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/almeira-store-app/public/icon.svg b/almeira-store-app/public/icon.svg new file mode 100644 index 0000000..3d52343 --- /dev/null +++ b/almeira-store-app/public/icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + A + + diff --git a/almeira-store-app/public/manifest.json b/almeira-store-app/public/manifest.json new file mode 100644 index 0000000..e6cde15 --- /dev/null +++ b/almeira-store-app/public/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "Almeira Store • Sneakers", + "short_name": "Almeira Store", + "description": "Tienda de calzado y zapatillas con entregas contraentrega en Cali y todo Colombia.", + "start_url": "/", + "display": "standalone", + "background_color": "#020617", + "theme_color": "#06b6d4", + "orientation": "portrait", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any maskable" + } + ] +} diff --git a/almeira-store-app/public/next.svg b/almeira-store-app/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/almeira-store-app/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/almeira-store-app/public/vercel.svg b/almeira-store-app/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/almeira-store-app/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/almeira-store-app/public/window.svg b/almeira-store-app/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/almeira-store-app/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/almeira-store-app/scripts/setup-appwrite.js b/almeira-store-app/scripts/setup-appwrite.js new file mode 100644 index 0000000..8a34246 --- /dev/null +++ b/almeira-store-app/scripts/setup-appwrite.js @@ -0,0 +1,131 @@ +/** + * Script de inicialización de la Base de Datos Independiente en Appwrite + * Ejecutar con: node scripts/setup-appwrite.js + */ +const { Client, Databases, Storage, Permission, Role } = require('node-appwrite'); +const fs = require('fs'); +const path = require('path'); + +// Leer variables de .env.local manualmente si dotenv no está disponible en este script +const envPath = path.resolve(__dirname, '../.env.local'); +if (fs.existsSync(envPath)) { + const envContent = fs.readFileSync(envPath, 'utf8'); + envContent.split('\n').forEach((line) => { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#')) { + const [k, ...v] = trimmed.split('='); + if (k && v) process.env[k.trim()] = v.join('=').trim(); + } + }); +} + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; +const apiKey = process.env.APPWRITE_API_KEY; +const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +const bucketId = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +if (!apiKey) { + console.error('❌ Falta APPWRITE_API_KEY en .env.local'); + process.exit(1); +} + +const client = new Client() + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey); + +const databases = new Databases(client); +const storage = new Storage(client); + +async function setup() { + console.log('🚀 Iniciando configuración de la Base de Datos Independiente para la Tienda...'); + console.log(`Endpoint: ${endpoint}`); + console.log(`Database ID: ${databaseId}`); + console.log(`Bucket ID: ${bucketId}`); + + // 1. Crear Base de Datos Independiente si no existe + try { + await databases.get(databaseId); + console.log(`✅ Base de datos independiente "${databaseId}" ya existe.`); + } catch (e) { + console.log(`Creando base de datos independiente "${databaseId}"...`); + await databases.create(databaseId, 'Sneakers Multi-Store DB'); + console.log(`✅ Base de datos "${databaseId}" creada con éxito.`); + } + + // 2. Crear Storage Bucket Independiente si no existe + try { + await storage.getBucket(bucketId); + console.log(`✅ Storage Bucket "${bucketId}" ya existe.`); + } catch (e) { + console.log(`Creando Storage Bucket "${bucketId}"...`); + try { + await storage.createBucket( + bucketId, + 'Sneakers Media Assets', + [Permission.read(Role.any()), Permission.create(Role.any())], + false, // fileSecurity + true, // enabled + 50000000, // 50MB max file size + ['jpg', 'png', 'webp', 'jpeg'] + ); + console.log(`✅ Storage Bucket "${bucketId}" creado con éxito.`); + } catch (bErr) { + console.warn('Nota sobre creación de bucket:', bErr.message); + } + } + + // 3. Crear Colecciones Independientes + const collections = [ + { + id: 'products', + name: 'Productos y Zapatillas', + }, + { + id: 'cities', + name: 'Ciudades y Envíos', + }, + { + id: 'payment_methods', + name: 'Métodos de Pago', + }, + { + id: 'orders', + name: 'Pedidos de Clientes', + }, + { + id: 'supplier_posts', + name: 'Feed de Mensajes WhatsApp', + }, + ]; + + for (const col of collections) { + try { + await databases.getCollection(databaseId, col.id); + console.log(`✅ Colección "${col.name}" (${col.id}) ya existe.`); + } catch (e) { + console.log(`Creando colección "${col.name}" (${col.id})...`); + try { + await databases.createCollection( + databaseId, + col.id, + col.name, + [ + Permission.read(Role.any()), + Permission.create(Role.any()), + Permission.update(Role.any()), + Permission.delete(Role.any()), + ] + ); + console.log(`✅ Colección creada: ${col.id}`); + } catch (cErr) { + console.warn(`Error creando colección ${col.id}:`, cErr.message); + } + } + } + + console.log('🎉 ¡Base de datos y colecciones independientes configuradas al 100%!'); +} + +setup().catch((err) => console.error('Error configurando Appwrite:', err)); diff --git a/almeira-store-app/src/app/admin/ciudades/page.tsx b/almeira-store-app/src/app/admin/ciudades/page.tsx new file mode 100644 index 0000000..0ffbbca --- /dev/null +++ b/almeira-store-app/src/app/admin/ciudades/page.tsx @@ -0,0 +1,249 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { MapPin, Plus, Save, Trash2, Check, X, Truck, ShieldCheck } from 'lucide-react'; +import { City } from '@/types'; +import { INITIAL_CITIES } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminCitiesPage() { + const [cities, setCities] = useState(INITIAL_CITIES); + const [isSaving, setIsSaving] = useState(false); + const [message, setMessage] = useState(null); + + // New city form + const [newName, setNewName] = useState(''); + const [newDepartment, setNewDepartment] = useState(''); + const [newShippingCost, setNewShippingCost] = useState('0'); + const [newDeliveryTime, setNewDeliveryTime] = useState('Entrega en 24 Horas'); + const [newAllowCod, setNewAllowCod] = useState(true); + const [newFirstExchangeFree, setNewFirstExchangeFree] = useState(true); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + }, []); + + const handleToggleExchangeFree = async (city: City) => { + const updated = { ...city, firstExchangeFree: !city.firstExchangeFree }; + setCities((prev) => prev.map((c) => (c.id === city.id ? updated : c))); + + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: city.id, updates: { firstExchangeFree: updated.firstExchangeFree } }), + }); + setMessage(`Política de 1er cambio gratis para "${city.name}" ${updated.firstExchangeFree ? 'ACTIVADA' : 'DESACTIVADA'}.`); + }; + + const handleUpdateShipping = async (cityId: string, cost: number) => { + setCities((prev) => prev.map((c) => (c.id === cityId ? { ...c, shippingCost: cost } : c))); + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: cityId, updates: { shippingCost: cost } }), + }); + setMessage('Tarifa de envío actualizada.'); + }; + + const handleAddCity = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newName) return; + + const payload = { + name: newName, + department: newDepartment || 'Colombia', + shippingCost: parseInt(newShippingCost, 10) || 0, + deliveryTime: newDeliveryTime, + allowsContraentrega: newAllowCod, + firstExchangeFree: newFirstExchangeFree, + exchangePolicyNote: newFirstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${newName} (posteriores con flete estándar)` + : `Cambio de talla garantizado (flete logístico asumido por el cliente)`, + }; + + const res = await fetch('/api/cities', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + const data = await res.json(); + if (data.success) { + setCities((prev) => [...prev, data.city]); + setNewName(''); + setNewDepartment(''); + setMessage(`Ciudad "${data.city.name}" agregada con éxito.`); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Ciudades, Fletes y Garantía de Cambio +

+

+ Administra las tarifas de envío, tiempos de entrega y configura si el 1er cambio de talla es gratis o si el cliente asume el flete para cada ciudad. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Add New City Card */} +
+

+ + Registrar Nueva Ciudad o Municipio +

+ +
+
+ + setNewName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDepartment(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewShippingCost(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDeliveryTime(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+
+ +
+
+ + + +
+ + +
+
+ + {/* Cities List */} +
+

Ciudades y Zonas Registradas ({cities.length})

+ +
+ {cities.map((city) => ( +
+
+
+ {city.name} + ({city.department}) + {city.allowsContraentrega ? ( + + Contraentrega Activo + + ) : ( + + Solo Despacho Nacional + + )} +
+

+ + {city.deliveryTime} +

+
+ + {/* Actions & Policy Toggle */} +
+ {/* 1st Exchange Free Toggle Button */} + + + {/* Shipping cost edit */} +
+ Flete: + handleUpdateShipping(city.id, parseInt(e.target.value, 10) || 0)} + className="w-20 bg-transparent text-xs font-bold text-white outline-hidden text-right" + /> + COP +
+
+
+ ))} +
+
+
+ ); +} diff --git a/almeira-store-app/src/app/admin/configuracion/page.tsx b/almeira-store-app/src/app/admin/configuracion/page.tsx new file mode 100644 index 0000000..0ff958a --- /dev/null +++ b/almeira-store-app/src/app/admin/configuracion/page.tsx @@ -0,0 +1,352 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Store, Mail, Phone, MessageCircle, Instagram, MapPin, CreditCard, Save, CheckCircle2, DollarSign, Percent, ShieldCheck, QrCode, ExternalLink, Zap } from 'lucide-react'; +import { StoreSettings } from '@/types'; + +export default function AdminSettingsPage() { + const [settings, setSettings] = useState({ + storeName: 'Almeira Store', + slogan: 'Sneakers & Moda Urbana', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@almeirastore.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }); + + const [isSaving, setIsSaving] = useState(false); + const [toast, setToast] = useState(null); + + useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setSettings(d.settings)) + .catch(() => {}); + }, []); + + const handleChange = (field: keyof StoreSettings, value: any) => { + setSettings((prev) => ({ ...prev, [field]: value })); + }; + + const handlePhoneChange = (val: string) => { + const cleanDigits = val.replace(/\D/g, ''); + const cleanWa = cleanDigits.startsWith('57') ? cleanDigits : `57${cleanDigits}`; + setSettings((prev) => ({ + ...prev, + phone: cleanDigits, + whatsappNumber: cleanWa, + })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSaving(true); + + try { + const res = await fetch('/api/settings', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settings), + }); + const data = await res.json(); + if (data.success) { + setToast('✅ ¡Datos de la tienda, WhatsApp oficial y pasarela Bold.co actualizados exitosamente!'); + setTimeout(() => setToast(null), 4500); + } + } catch (err) { + console.error(err); + } finally { + setIsSaving(false); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Información de la Tienda & Medios de Pago +

+

+ Configura los datos oficiales del negocio: WhatsApp oficial de atención, correo electrónico, pasarela Bold.co (Link de pago, QR y botón), Nequi, Daviplata y reglas de margen. +

+
+ + {toast && ( +
+ {toast} + +
+ )} + +
+ {/* Section 1: Identidad & WhatsApp Oficial */} +
+

+ + Identidad & WhatsApp Oficial de Atención +

+ +
+
+ + handleChange('storeName', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white font-semibold outline-hidden focus:border-cyan-400" + /> +
+ +
+ + handleChange('slogan', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400" + /> +
+ +
+ + handleChange('email', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400 font-mono" + /> +
+ +
+ +
+ handlePhoneChange(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-emerald-300 font-bold outline-hidden focus:border-emerald-400" + /> + +
+

+ Link generado: https://wa.me/{settings.whatsappNumber} +

+
+ +
+ + handleChange('instagramHandle', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400" + /> +
+ +
+ + handleChange('city', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400" + /> +
+
+
+ + {/* Section 2: Pasarela Bold.co (Link de Pago, QR o Botón) */} +
+
+

+ + Integración con Bold.co (Link de Pago, Botón & QR) +

+ +
+ +
+
+ +
+ handleChange('boldPaymentLink', e.target.value)} + className="w-full bg-slate-950 border border-indigo-500/40 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> + +
+

+ Tus clientes podrán pagar por PSE, Tarjeta de Crédito/Débito o Nequi directamente con este enlace oficial de Bold. +

+
+ +
+ + handleChange('boldQrUrl', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-indigo-400" + /> +
+ +
+ + handleChange('boldApiKey', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> +
+
+
+ + {/* Section 3: Cuentas de Recaudo Nequi / Daviplata */} +
+

+ + Cuentas para Recaudo de Anticipos ($10.000 COP) +

+ +
+
+ + handleChange('accountHolder', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400 font-bold" + /> +
+ +
+ + handleChange('nequiAccount', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400" + /> +
+ +
+ + handleChange('daviplataAccount', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-cyan-400" + /> +
+
+
+ + {/* Section 4: Reglas de Precios y Anticipo */} +
+

+ + Reglas Comerciales de Ganancia & Redondeo +

+ +
+
+ +
+ handleChange('defaultProfitMargin', Number(e.target.value))} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-cyan-400" + /> + +
+

+ El sistema calcula el precio y lo redondea al siguiente múltiplo de $5.000 COP (ej: $132.000 ➔ $135.000). +

+
+ +
+ +
+ handleChange('defaultDepositAmount', Number(e.target.value))} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-cyan-400" + /> + +
+

+ Valor solicitado al comprador para apartar el calzado con el proveedor. +

+
+
+
+ + {/* Submit Bar */} +
+

+ Todos los cambios se reflejan inmediatamente en la tienda pública, el carrito y los mensajes de WhatsApp. +

+ +
+
+
+ ); +} diff --git a/almeira-store-app/src/app/admin/feed-whatsapp/page.tsx b/almeira-store-app/src/app/admin/feed-whatsapp/page.tsx new file mode 100644 index 0000000..a1866cb --- /dev/null +++ b/almeira-store-app/src/app/admin/feed-whatsapp/page.tsx @@ -0,0 +1,365 @@ +'use client'; + +import React, { useState } from 'react'; +import { Radio, Sparkles, Share2, AlertTriangle, ShieldCheck, Plus, Send, Layers } from 'lucide-react'; +import { SupplierPost, Product } from '@/types'; +import { INITIAL_SUPPLIER_POSTS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { checkProductDuplicate } from '@/lib/deduplication-engine'; +import { formatCOP } from '@/lib/pricing-engine'; +import { BRANDS, BrandId } from '@/config/brands'; + +export default function SupplierFeedPage() { + const [posts, setPosts] = useState(INITIAL_SUPPLIER_POSTS); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [isProcessing, setIsProcessing] = useState(false); + const [actionMessage, setActionMessage] = useState(null); + + // Target brand selector for publishing + const [targetBrand, setTargetBrand] = useState('almeira'); + + // Simulación de nuevo mensaje entrante de grupo para probar en vivo + const [testText, setTestText] = useState( + '🔥 LLEGANDO A BODEGA HOY 🔥\nNike Air Max 90 White Black\nTallas: 38 a 43\nMayorista: $90.000 c/u\nEnvío inmediato contraentrega' + ); + const [testGroup, setTestGroup] = useState('Canal Mayorista A'); + + const handleSimulateIncoming = async () => { + setIsProcessing(true); + try { + const res = await fetch('/api/webhook/whatsapp', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + text: testText, + groupInfo: { subject: testGroup }, + }), + }); + const data = await res.json(); + if (data.success && data.post) { + setPosts((prev) => [data.post, ...prev]); + setActionMessage('✅ Nuevo mensaje de WhatsApp procesado con IA.'); + } + } catch (err) { + console.error(err); + } finally { + setIsProcessing(false); + } + }; + + const handlePublishFacebook = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + setIsProcessing(true); + try { + const brandName = targetBrand === 'all' ? 'Todas las Tiendas' : BRANDS[targetBrand].name; + const res = await fetch('/api/publish/facebook', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + productName: post.extractedProduct.name, + brand: post.extractedProduct.brand, + retailPrice: post.extractedProduct.suggestedRetailPrice, + sizes: post.extractedProduct.sizes, + images: post.rawImages, + }), + }); + const data = await res.json(); + if (data.success) { + setActionMessage(`🚀 ¡Publicado en Facebook bajo la marca "${brandName}"! (ID: ${data.postId})`); + } + } catch (e) { + console.error(e); + } finally { + setIsProcessing(false); + } + }; + + const handleAddToStore = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + const brandLabel = targetBrand === 'all' ? 'Multi-Marca' : BRANDS[targetBrand].shortName; + const newProduct: Product = { + id: `snk-${Date.now()}`, + name: post.extractedProduct.name, + brand: post.extractedProduct.brand, + supplierPrice: post.extractedProduct.supplierPrice, + retailPrice: post.extractedProduct.suggestedRetailPrice, + originalPrice: Math.round(post.extractedProduct.suggestedRetailPrice * 1.35), + sizes: post.extractedProduct.sizes, + images: post.rawImages, + description: `Zapatillas calidad premium garantizada para entrega inmediata.`, + category: post.extractedProduct.category, + inStock: true, + isActive: true, + originBadge: `Bodega Central`, + supplierName: post.supplierName || post.channelName || 'DIFUSION JOVIC STORE', + supplierPhone: post.supplierPhone || '573134848203', + }; + + try { + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProduct), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setActionMessage(`✨ "${newProduct.name}" habilitado en el catálogo para ${brandLabel}.`); + } + } catch (e) { + console.error(e); + } + }; + + return ( +
+ {/* Header */} +
+
+

+ + Feed de Entrada & Publicador Multi-Marca +

+

+ Recepción automática con IA, prevención de duplicados y distribución hacia las 4 marcas (Almeira Store, Sneaky, Zapply, DripZone). +

+
+ + {/* Target Brand Selector Pill Bar */} +
+ + Destino: + + + {Object.values(BRANDS).map((b) => ( + + ))} +
+
+ + {actionMessage && ( +
+ {actionMessage} + +
+ )} + + {/* Live Simulator for Test Messages */} +
+
+ + Simulador de Recepción en Tiempo Real +
+ +
+
+ + +
+ +
+ +
+ setTestText(e.target.value)} + className="flex-1 bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> + +
+
+
+
+ + {/* Intercepted Posts Feed */} +
+

Mensajes Procesados Recientemente

+ +
+ {posts.map((post) => { + const extracted = post.extractedProduct; + const duplicateCheck = extracted + ? checkProductDuplicate( + { + name: extracted.name, + brand: extracted.brand, + sizes: extracted.sizes, + supplierPrice: extracted.supplierPrice, + }, + products + ) + : null; + + return ( +
+ {/* Header of post */} +
+
+ + {post.channelName || 'Canal Mayorista'} + + {post.receivedAt} +
+ + {/* Anti-Duplicate Status Badge */} + {duplicateCheck && ( +
+ {duplicateCheck.isDuplicate ? ( + <> + + Duplicado Detectado ({Math.round(duplicateCheck.similarityScore * 100)}% Similitud) + + ) : ( + <> + + Producto Nuevo (0% Duplicados) + + )} +
+ )} +
+ + {/* Content Grid */} +
+ {/* Left: Raw WhatsApp Message (5 cols) */} +
+ Mensaje de Entrada: +

+ {post.rawMessage} +

+ {post.rawImages.length > 0 && ( +
+ +
+ )} +
+ + {/* Right: AI Extracted & Pricing Calculation (7 cols) */} +
+ {extracted ? ( +
+
+
+ + {extracted.brand} • {extracted.category} + +

{extracted.name}

+
+ + IA: {Math.round(extracted.confidence * 100)}% certeza + +
+ + {/* Pricing breakdown */} +
+
+ Costo Base: + + {formatCOP(extracted.supplierPrice)} + +
+
+ Precio Venta (+ Margen): + + {formatCOP(extracted.suggestedRetailPrice)} + +
+
+ + {/* Sizes */} +
+ + Tallas extraídas: + +
+ {extracted.sizes.map((s) => ( + + {s} + + ))} +
+
+ + {/* Duplicate warning note */} + {duplicateCheck?.isDuplicate && ( +
+ {duplicateCheck.message} +
+ )} + + {/* Actions */} +
+ + + +
+
+ ) : ( +

Extrayendo datos...

+ )} +
+
+
+ ); + })} +
+
+
+ ); +} diff --git a/almeira-store-app/src/app/admin/grupos-whatsapp/page.tsx b/almeira-store-app/src/app/admin/grupos-whatsapp/page.tsx new file mode 100644 index 0000000..f4a568d --- /dev/null +++ b/almeira-store-app/src/app/admin/grupos-whatsapp/page.tsx @@ -0,0 +1,586 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { + MessageSquare, + RefreshCw, + Search, + CheckCircle2, + XCircle, + ShieldCheck, + Zap, + Radio, + Sliders, + Users, + Sparkles, + ExternalLink, + Plus, + ArrowUpRight, + Filter, + CheckSquare, + Square, + X +} from 'lucide-react'; +import { MonitoredWhatsAppGroup } from '@/types'; + +export default function AdminWhatsAppGroupsPage() { + const [groups, setGroups] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [filterMode, setFilterMode] = useState<'all' | 'monitored' | 'unmonitored'>('all'); + const [toast, setToast] = useState(null); + const [scanningGroupId, setScanningGroupId] = useState(null); + + // Group Picker Modal State + const [isPickerOpen, setIsPickerOpen] = useState(false); + const [liveGroups, setLiveGroups] = useState([]); + const [isLoadingLive, setIsLoadingLive] = useState(false); + const [pickerSearch, setPickerSearch] = useState(''); + const [selectedJids, setSelectedJids] = useState>(new Set()); + + const fetchLocalGroups = async () => { + setIsLoading(true); + try { + const res = await fetch('/api/whatsapp-groups'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setGroups(data.groups); + } + } catch (err) { + console.error(err); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchLocalGroups(); + }, []); + + const handleOpenPicker = async () => { + setIsPickerOpen(true); + setIsLoadingLive(true); + try { + const res = await fetch('/api/whatsapp-groups?fetchLive=true'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setLiveGroups(data.groups); + // Pre-select already monitored groups + const initialSelected = new Set(); + data.groups.forEach((g: MonitoredWhatsAppGroup) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + // Also add local groups + groups.forEach((g) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + setSelectedJids(initialSelected); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleSelectJid = (jid: string) => { + setSelectedJids((prev) => { + const next = new Set(prev); + if (next.has(jid)) next.delete(jid); + else next.add(jid); + return next; + }); + }; + + const handleSelectAllFiltered = (filtered: MonitoredWhatsAppGroup[]) => { + setSelectedJids((prev) => { + const next = new Set(prev); + filtered.forEach((g) => next.add(g.jid)); + return next; + }); + }; + + const handleDeselectAll = () => { + setSelectedJids(new Set()); + }; + + const handleSaveSelectedGroups = async () => { + setIsLoadingLive(true); + try { + const updatedGroups: MonitoredWhatsAppGroup[] = liveGroups.map((lg) => ({ + ...lg, + isMonitored: selectedJids.has(lg.jid), + autoPublish: true, + profitMarginOverride: 35, + })); + + const res = await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ groups: updatedGroups }), + }); + + const data = await res.json(); + if (data.success) { + setGroups(data.groups); + setIsPickerOpen(false); + setToast(`✅ ¡Se actualizaron los grupos monitoreados! (${selectedJids.size} activos)`); + setTimeout(() => setToast(null), 4000); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleGroup = async (group: MonitoredWhatsAppGroup) => { + const nextState = !group.isMonitored; + const updatedList = groups.map((g) => + g.jid === group.jid || g.id === group.id ? { ...g, isMonitored: nextState } : g + ); + setGroups(updatedList); + + try { + await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'toggle', + idOrJid: group.jid || group.id, + isMonitored: nextState, + }), + }); + + setToast( + nextState + ? `🟢 Grupo "${group.name}" ahora está siendo MONITOREADO en tiempo real.` + : `⚪ Grupo "${group.name}" fue desactivado del monitoreo.` + ); + setTimeout(() => setToast(null), 3500); + } catch (err) { + console.error(err); + } + }; + + const handleScanGroup = async (group: MonitoredWhatsAppGroup) => { + setScanningGroupId(group.id); + try { + await new Promise((r) => setTimeout(r, 1200)); + setToast(`✨ Mensajes recientes de "${group.name}" analizados con IA y catálogo actualizado.`); + setTimeout(() => setToast(null), 4000); + } finally { + setScanningGroupId(null); + } + }; + + const filteredGroups = groups.filter((g) => { + const matchesSearch = + g.name.toLowerCase().includes(searchQuery.toLowerCase()) || + g.jid.toLowerCase().includes(searchQuery.toLowerCase()) || + (g.notes && g.notes.toLowerCase().includes(searchQuery.toLowerCase())); + + if (filterMode === 'monitored') return matchesSearch && g.isMonitored; + if (filterMode === 'unmonitored') return matchesSearch && !g.isMonitored; + return matchesSearch; + }); + + const filteredPickerGroups = liveGroups.filter((g) => + g.name.toLowerCase().includes(pickerSearch.toLowerCase()) || + g.jid.toLowerCase().includes(pickerSearch.toLowerCase()) + ); + + const monitoredCount = groups.filter((g) => g.isMonitored).length; + + return ( +
+ {/* Header */} +
+
+

+ + Monitoreo de Grupos de WhatsApp +

+

+ Busca y selecciona los grupos de proveedores que el bot de Evolution API & Gemini debe escuchar 24/7 para auto-publicar zapatillas. +

+
+ + {/* Big Search and Select Button */} + +
+ + {/* Toast Notification */} + {toast && ( +
+ {toast} + +
+ )} + + {/* Stats Bar */} +
+
+
+

Grupos en tu WhatsApp

+

{groups.length}

+
+
+ +
+
+ +
+
+

Grupos Monitoreados (Activos)

+

{monitoredCount}

+
+
+ +
+
+ +
+
+

Evolution API (WhatsApp)

+

+ + AutomataAlmeira (En línea) +

+
+
+ +
+
+
+ + {/* Filter and Search Toolbar */} +
+
+ + setSearchQuery(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3 py-2 text-xs text-white outline-hidden focus:border-cyan-400" + /> +
+ +
+ + + +
+
+ + {/* Active Monitored Groups List */} +
+ {isLoading ? ( +
+ +

Cargando grupos de proveedores...

+
+ ) : filteredGroups.length === 0 ? ( +
+ +

No tienes grupos seleccionados para monitorear.

+ +
+ ) : ( + filteredGroups.map((group) => { + const isMonitored = group.isMonitored; + + return ( +
+ {/* Header */} +
+
+
+ +

+ {group.name} +

+
+

+ {group.jid} +

+
+ + {/* Toggle Switch */} + +
+ + {/* Info Pills */} +
+
+ Margen Aplicado + + +{group.profitMarginOverride || 35}% (Redondeo a $5.000) + +
+ +
+ Modo de Ingreso + + Auto-Publicar Directo + +
+
+ + {group.notes && ( +

+ ℹ️ {group.notes} +

+ )} + + {/* Action footer */} +
+ + {group.participantsCount ? `👥 ${group.participantsCount} miembros` : 'Canal Mayorista'} + + + +
+
+ ); + }) + )} +
+ + {/* ========================================================= */} + {/* MODAL: Group Picker (Buscar y Seleccionar Grupos) */} + {/* ========================================================= */} + {isPickerOpen && ( +
+
+ {/* Modal Header */} +
+
+
+ +
+
+

Seleccionar Grupos de WhatsApp

+

+ Marca los grupos que deseas monitorear con IA para auto-publicar calzado. +

+
+
+ +
+ + {/* Search and Action Toolbar in Modal */} +
+
+ + setPickerSearch(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-xs text-white outline-hidden focus:border-cyan-400 font-semibold" + /> +
+ +
+ + Mostrando {filteredPickerGroups.length} grupos encontrados + +
+ + • + +
+
+
+ + {/* Groups Scrollable List */} +
+ {isLoadingLive ? ( +
+ +

Consultando grupos en vivo desde Evolution API...

+

Conectando con WhatsApp...

+
+ ) : filteredPickerGroups.length === 0 ? ( +
+

No se encontraron grupos con el término "{pickerSearch}".

+
+ ) : ( + filteredPickerGroups.map((group) => { + const isSelected = selectedJids.has(group.jid); + + return ( +
handleToggleSelectJid(group.jid)} + className={`p-3.5 rounded-2xl border transition-all cursor-pointer flex items-center justify-between gap-3 ${ + isSelected + ? 'bg-cyan-950/30 border-cyan-500/50 shadow-md ring-1 ring-cyan-500/20' + : 'bg-slate-950 border-slate-800 hover:border-slate-700' + }`} + > +
+
+ {isSelected && } +
+ +
+

+ {group.name} +

+

+ {group.jid} +

+
+
+ +
+ {isSelected ? ( + + Monitorear + + ) : ( + + Ignorar + + )} +
+
+ ); + }) + )} +
+ + {/* Modal Footer */} +
+
+ Seleccionados: + {selectedJids.size} + grupos para monitorear +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/almeira-store-app/src/app/admin/layout.tsx b/almeira-store-app/src/app/admin/layout.tsx new file mode 100644 index 0000000..ae22bc5 --- /dev/null +++ b/almeira-store-app/src/app/admin/layout.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { + LayoutDashboard, + Radio, + Package, + MapPin, + CreditCard, + ShoppingBag, + ArrowLeft, + Sparkles, + Store, + Users, + MessageSquare, +} from 'lucide-react'; + +export default function AdminLayout({ children }: { children: React.ReactNode }) { + const pathname = usePathname(); + + const NAV_ITEMS = [ + { href: '/admin', label: 'Resumen & KPIs', icon: LayoutDashboard }, + { href: '/admin/grupos-whatsapp', label: 'Grupos WhatsApp', icon: MessageSquare, badge: 'Monitoreo 24/7' }, + { href: '/admin/usuarios', label: 'Control de Usuarios', icon: Users, badge: 'Roles & Accesos' }, + { href: '/admin/configuracion', label: 'Datos de la Tienda', icon: Store }, + { href: '/admin/feed-whatsapp', label: 'Feed WhatsApp & IA', icon: Radio, badge: 'Anti-Duplicados' }, + { href: '/admin/productos', label: 'Catálogo de Zapatillas', icon: Package }, + { href: '/admin/ciudades', label: 'Ciudades & Fletes', icon: MapPin }, + { href: '/admin/metodos-pago', label: 'Medios de Pago & Anticipos', icon: CreditCard }, + { href: '/admin/pedidos', label: 'Pedidos & Logística', icon: ShoppingBag }, + ]; + + return ( +
+ {/* Sidebar */} + + + {/* Main Content Area */} +
+ {children} +
+
+ ); +} diff --git a/almeira-store-app/src/app/admin/metodos-pago/page.tsx b/almeira-store-app/src/app/admin/metodos-pago/page.tsx new file mode 100644 index 0000000..3b61284 --- /dev/null +++ b/almeira-store-app/src/app/admin/metodos-pago/page.tsx @@ -0,0 +1,163 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { CreditCard, Zap, Save, Check, ShieldCheck, QrCode } from 'lucide-react'; +import { PaymentMethod } from '@/types'; +import { INITIAL_PAYMENT_METHODS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminPaymentMethodsPage() { + const [methods, setMethods] = useState(INITIAL_PAYMENT_METHODS); + const [message, setMessage] = useState(null); + + useEffect(() => { + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setMethods(d.paymentMethods)) + .catch(() => {}); + }, []); + + const handleToggleActive = async (method: PaymentMethod) => { + const updated = { ...method, isActive: !method.isActive }; + setMethods((prev) => prev.map((m) => (m.id === method.id ? updated : m))); + + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: { isActive: updated.isActive } }), + }); + setMessage(`Método "${method.name}" ${updated.isActive ? 'activado' : 'desactivado'}.`); + }; + + const handleUpdateField = (id: string, field: keyof PaymentMethod, val: any) => { + setMethods((prev) => + prev.map((m) => (m.id === id ? { ...m, [field]: val } : m)) + ); + }; + + const handleSaveMethod = async (method: PaymentMethod) => { + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: method }), + }); + setMessage(`✅ Cambios guardados para "${method.name}".`); + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Medios de Pago & Anticipos +

+

+ Habilita métodos de pago, configura el valor de separación de $10.000 COP y personaliza los datos de Nequi / Daviplata. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Methods Cards */} +
+ {methods.map((method) => ( +
+
+
+
+ {method.type === 'contraentrega' ? : } +
+
+

{method.name}

+ Tipo: {method.type} +
+
+ +
+ +
+
+ +
+
+ + handleUpdateField(method.id, 'name', e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + handleUpdateField(method.id, 'description', e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ + {method.requiresDeposit && ( +
+ + handleUpdateField(method.id, 'depositAmount', parseInt(e.target.value, 10) || 0)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden font-bold" + /> + + (El saldo restante se cobra contraentrega al recibir) + +
+ )} + +
+ + handleUpdateField(method.id, 'accountInfo', e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + placeholder="Ej. Nequi / Daviplata: 316 745 5877" + /> +
+
+ +
+ +
+
+ ))} +
+
+ ); +} diff --git a/almeira-store-app/src/app/admin/page.tsx b/almeira-store-app/src/app/admin/page.tsx new file mode 100644 index 0000000..8d400b5 --- /dev/null +++ b/almeira-store-app/src/app/admin/page.tsx @@ -0,0 +1,159 @@ +'use client'; + +import React, { useState } from 'react'; +import Link from 'next/link'; +import { Package, Radio, MapPin, Zap, CheckCircle2, ArrowUpRight, Sparkles } from 'lucide-react'; +import { INITIAL_PRODUCTS, INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_SUPPLIER_POSTS } from '@/lib/data-service'; + +export default function AdminDashboardPage() { + const [productsCount] = useState(INITIAL_PRODUCTS.length); + const [postsCount] = useState(INITIAL_SUPPLIER_POSTS.length); + const [citiesCount] = useState(INITIAL_CITIES.length); + + return ( +
+ {/* Header */} +
+
+

+ + Centro de Control • Almeira Store +

+

+ Automatización inteligente de calzado, publicaciones a Facebook y gestión de despachos. +

+
+ +
+ + + Ver Feed de WhatsApp + +
+
+ + {/* KPI Cards */} +
+
+
+ Zapatillas Activas + +
+
{productsCount}
+

+ Catálogo sincronizado +

+
+ +
+
+ Margen Promedio + +
+
+ +$30.000 COP +
+

+ (Costo: $90k ➔ Venta: $120k) +

+
+ +
+
+ Entradas Procesadas + +
+
{postsCount}
+

+ IA Gemini + Anti-duplicados +

+
+ +
+
+ Ciudades Habilitadas + +
+
{citiesCount}
+

+ Contraentrega activo en Cali +

+
+
+ + {/* Quick Actions & Automation Status */} +
+ {/* Left: WhatsApp Evolution API Status */} +
+
+
+
+

Estado del Listener de WhatsApp

+
+ + Activo + +
+ +
+
+ Instancia Evolution API: + AutomataAlmeira +
+
+ Servidor: + evolution.almeira.com.co +
+
+ Motor de Inteligencia Artificial: + Gemini 2.5 Flash +
+
+ Filtro Anti-Duplicados: + Activo (>75% Similitud) +
+
+ + + Ver últimos mensajes procesados + + +
+ + {/* Right: Meta / Facebook Automation */} +
+
+

Publicador a Fanpage de Facebook

+ + Listo para Publicar + +
+ +
+

✨ Plantilla de Copy Vendedor Integrada:

+

+ "✨ ALMEIRA STORE • NUEVA COLECCIÓN EXCLUSIVA ✨
+ 👟 NIKE DUNK LOW PANDA
+ 📏 Tallas: 37 a 43 | 💎 Precio: $120.000 COP
+ 🚚 ¡Entrega a Domicilio en Cali con Pago Contraentrega!" +

+
+ + + Publicar Producto de Prueba en Facebook + + +
+
+
+ ); +} diff --git a/almeira-store-app/src/app/admin/pedidos/page.tsx b/almeira-store-app/src/app/admin/pedidos/page.tsx new file mode 100644 index 0000000..82562a2 --- /dev/null +++ b/almeira-store-app/src/app/admin/pedidos/page.tsx @@ -0,0 +1,283 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { ShoppingBag, Truck, CheckCircle2, Clock, Phone, MapPin, Search, MessageCircle, Send, ShieldCheck, UserCheck } from 'lucide-react'; +import { Order, OrderItem } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminOrdersPage() { + const [orders, setOrders] = useState([]); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState('all'); + + useEffect(() => { + fetch('/api/orders') + .then((r) => r.json()) + .then((d) => d.success && setOrders(d.orders)) + .catch(() => {}); + }, []); + + const handleStatusChange = async (orderId: string, newStatus: Order['status']) => { + setOrders((prev) => + prev.map((o) => (o.id === orderId ? { ...o, status: newStatus } : o)) + ); + + await fetch('/api/orders', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: orderId, status: newStatus }), + }).catch(() => {}); + }; + + const handleNotifySupplier = (order: Order, item: OrderItem) => { + const supplierPhone = item.supplierPhone || '573134848203'; + const supplierName = item.supplierName || 'Proveedor Mayorista'; + const supplierCost = item.supplierPrice ? formatCOP(item.supplierPrice) : 'Precio Mayorista'; + + const message = `👋 Hola *${supplierName}*!\n\nPor favor *sepárame este par* para despacho inmediato:\n\n👟 *Modelo:* ${item.productName}\n📏 *Talla:* ${item.size}\n📦 *Cantidad:* ${item.quantity} par(es)\n💵 *Costo Base:* ${supplierCost}\n\n🏷️ *Orden Interna:* #${order.id}\n📍 *Ciudad Destino:* ${order.cityName}\n\n¿Me confirmas si lo tienes listo para recoger / enviar? ¡Muchas gracias!`; + + const url = `https://wa.me/${supplierPhone}?text=${encodeURIComponent(message)}`; + window.open(url, '_blank'); + + // Auto-update status to supplier_notified if still pending + if (order.status === 'pending' || order.status === 'deposit_received') { + handleStatusChange(order.id, 'supplier_notified'); + } + }; + + const getStatusBadge = (status: Order['status']) => { + switch (status) { + case 'pending': + return Pendiente Confirmar; + case 'deposit_received': + return Separación $10k Pagada; + case 'supplier_notified': + return Proveedor Notificado; + case 'dispatched': + return En Ruta con Mensajero; + case 'delivered': + return Entregado & Cobrado; + case 'cancelled': + return Cancelado; + } + }; + + const filteredOrders = orders.filter((o) => { + const matchesSearch = + o.customerName.toLowerCase().includes(search.toLowerCase()) || + o.customerPhone.includes(search) || + o.cityName.toLowerCase().includes(search.toLowerCase()) || + o.id.toLowerCase().includes(search.toLowerCase()); + + if (!matchesSearch) return false; + if (statusFilter !== 'all' && o.status !== statusFilter) return false; + return true; + }); + + return ( +
+ {/* Header */} +
+

+ + Gestión de Pedidos & Separación con Proveedores ({orders.length}) +

+

+ Control logístico de pedidos contraentrega, cobro de anticipos de $10.000 COP y notificación inmediata de separación al proveedor vía WhatsApp. +

+
+ + {/* Toolbar */} +
+
+ + + + +
+ +
+ setSearch(e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-cyan-400" + /> +
+
+ + {filteredOrders.length === 0 ? ( +
+
+ +
+

No hay pedidos en esta sección

+

+ Cuando los clientes hagan un pedido en la tienda web o por WhatsApp, aparecerán aquí con el botón para separar inmediatamente con el proveedor correspondiente. +

+
+ ) : ( +
+ {filteredOrders.map((order) => ( +
+ {/* Top Order bar */} +
+
+ Orden #{order.id} + • {new Date(order.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} +
+ {getStatusBadge(order.status)} +
+ +
+ {/* Customer Details */} +
+ + Cliente & Entrega (24 Horas) + +

{order.customerName}

+

+ {order.customerPhone} +

+

+ {order.address} ({order.cityName}) +

+
+ + {/* Items and Supplier Separation Action */} +
+ + Zapatillas & Proveedor Asignado: + +
+ {order.items.map((it, idx) => { + const suppName = it.supplierName || 'DIFUSION JOVIC STORE'; + return ( +
+
+
+

{it.productName}

+

+ Talla {it.size} • Cant: {it.quantity} +

+
+ + Prov: {suppName} + +
+ + {/* 1-Click WhatsApp Separation Button */} + +
+ ); + })} +
+
+ + {/* Payment Breakdown */} +
+ + Cobro & Pagos Contraentrega + +
+

+ Total de la Orden: + {formatCOP(order.totalAmount)} +

+ {order.depositAmount > 0 ? ( + <> +

+ Anticipo / Separación: + {formatCOP(order.depositAmount)} +

+

+ Saldo al Mensajero: + {formatCOP(order.balanceDue)} +

+ + ) : ( +

+ 100% Contraentrega al recibir +

+ )} +
+
+
+ + {/* Order Status Action Buttons */} +
+ Método: {order.paymentMethodName} + +
+ + + + +
+
+
+ ))} +
+ )} +
+ ); +} diff --git a/almeira-store-app/src/app/admin/productos/page.tsx b/almeira-store-app/src/app/admin/productos/page.tsx new file mode 100644 index 0000000..3df1249 --- /dev/null +++ b/almeira-store-app/src/app/admin/productos/page.tsx @@ -0,0 +1,472 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Package, Plus, Eye, EyeOff, Check, X, Sparkles, Filter, Phone, MessageCircle, Truck } from 'lucide-react'; +import { Product, Supplier } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_SUPPLIERS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminProductsPage() { + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [suppliers, setSuppliers] = useState(INITIAL_SUPPLIERS); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [supplierFilter, setSupplierFilter] = useState('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New product form + const [name, setName] = useState(''); + const [brand, setBrand] = useState('Nike'); + const [selectedSupplierId, setSelectedSupplierId] = useState('sup-1'); + const [supplierPrice, setSupplierPrice] = useState('90000'); + const [retailPrice, setRetailPrice] = useState('125000'); + const [sizesInput, setSizesInput] = useState('37, 38, 39, 40, 41, 42, 43'); + const [imageUrl, setImageUrl] = useState( + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' + ); + const [category, setCategory] = useState('Sneakers / Urbano'); + const [isActiveNew, setIsActiveNew] = useState(true); + + useEffect(() => { + fetch('/api/products?all=true') + .then((r) => r.json()) + .then((d) => d.success && setProducts(d.products)) + .catch(() => {}); + }, []); + + const handleToggleProductStatus = async (product: Product) => { + const newStatus = product.isActive === false ? true : false; + + setProducts((prev) => + prev.map((p) => (p.id === product.id ? { ...p, isActive: newStatus } : p)) + ); + + try { + const res = await fetch('/api/products', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + id: product.id, + updates: { isActive: newStatus }, + }), + }); + + const data = await res.json(); + if (data.success) { + setToastMessage( + `Zapatilla "${product.name}" ahora está ${newStatus ? '🟢 ACTIVA (Visible en la tienda)' : '⚪ INACTIVA (Oculta de la tienda)'}.` + ); + } + } catch (e) { + console.error('Error toggling status:', e); + } + }; + + const handleContactSupplier = (product: Product) => { + const phone = product.supplierPhone || '573134848203'; + const suppName = product.supplierName || 'Proveedor Mayorista'; + const text = encodeURIComponent( + `Hola ${suppName}! 👋 Consulta sobre disponibilidad del modelo *${product.name}* (Costo base: ${formatCOP(product.supplierPrice)}).` + ); + window.open(`https://wa.me/${phone}?text=${text}`, '_blank'); + }; + + const handleCreateProduct = async (e: React.FormEvent) => { + e.preventDefault(); + const sizes = sizesInput + .split(',') + .map((s) => s.trim()) + .filter(Boolean); + + const chosenSupplier = suppliers.find((s) => s.id === selectedSupplierId) || suppliers[0]; + + const newProd: Product = { + id: `snk-${Date.now()}`, + name, + brand, + supplierPrice: parseInt(supplierPrice, 10) || 90000, + retailPrice: parseInt(retailPrice, 10) || 125000, + originalPrice: Math.round((parseInt(retailPrice, 10) || 125000) * 1.35), + sizes, + images: [imageUrl], + description: 'Zapatillas de alta calidad garantizada para entrega inmediata.', + category, + inStock: true, + isActive: isActiveNew, + originBadge: 'Bodega Central', + supplierId: chosenSupplier.id, + supplierName: chosenSupplier.name, + supplierPhone: chosenSupplier.phone, + }; + + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProd), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setIsModalOpen(false); + setName(''); + setToastMessage(`✨ "${newProd.name}" registrada con proveedor [${chosenSupplier.name}].`); + } + }; + + const filtered = products.filter((p) => { + const matchesSearch = + p.name.toLowerCase().includes(search.toLowerCase()) || + p.brand.toLowerCase().includes(search.toLowerCase()) || + (p.supplierName && p.supplierName.toLowerCase().includes(search.toLowerCase())); + + if (!matchesSearch) return false; + if (statusFilter === 'active' && p.isActive === false) return false; + if (statusFilter === 'inactive' && p.isActive !== false) return false; + if (supplierFilter !== 'all' && p.supplierName !== supplierFilter) return false; + return true; + }); + + const activeCount = products.filter((p) => p.isActive !== false).length; + const inactiveCount = products.filter((p) => p.isActive === false).length; + + return ( +
+ {/* Header */} +
+
+

+ + Catálogo General de Zapatillas & Proveedores ({products.length}) +

+

+ Visualiza cada modelo con su proveedor asignado, costo mayorista y activa/inactiva publicaciones para la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* Filters & Search Toolbar */} +
+ {/* Status filter pills */} +
+ + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-cyan-400" + /> +
+
+ + {/* Products Table */} +
+
+ + + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((prod) => { + const isActive = prod.isActive !== false; + const margin = prod.retailPrice - prod.supplierPrice; + const suppName = prod.supplierName || 'DIFUSION JOVIC STORE'; + const suppPhone = prod.supplierPhone || '573134848203'; + + return ( + + {/* Estado Toggle Button */} + + + {/* Product Name & Image */} + + + {/* Supplier Column */} + + + + + + + + + + + ); + }) + )} + +
Estado PublicaciónProductoProveedor Asignado (Interno)MarcaCosto BasePrecio VentaMargen GananciaTallas
+ No hay zapatillas que coincidan con el filtro seleccionado. +
+ + + +
+

{prod.name}

+ {prod.category} +
+
+
+ + 🏢 {suppName} + + +
+
{prod.brand}{formatCOP(prod.supplierPrice)}{formatCOP(prod.retailPrice)} + + +{formatCOP(margin)} + + +
+ {prod.sizes.map((s) => ( + + {s} + + ))} +
+
+
+
+ + {/* Modal Add Product */} + {isModalOpen && ( +
+
+

Registrar Nueva Zapatilla

+ +
+
+ + setName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ + {/* Supplier Selection */} +
+ + +

+ Este proveedor recibirá la notificación para separar el par cuando se haga un pedido. +

+
+ +
+
+ + +
+ +
+ + setCategory(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+
+ + setSupplierPrice(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setRetailPrice(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setSizesInput(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setImageUrl(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/almeira-store-app/src/app/admin/usuarios/page.tsx b/almeira-store-app/src/app/admin/usuarios/page.tsx new file mode 100644 index 0000000..a90615d --- /dev/null +++ b/almeira-store-app/src/app/admin/usuarios/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Users, UserPlus, Shield, ShieldCheck, UserCheck, MessageCircle, Mail, Phone, MapPin, Eye, EyeOff, Trash2, Edit, Check, X } from 'lucide-react'; +import { User } from '@/types'; + +export default function AdminUsersPage() { + const [users, setUsers] = useState([]); + const [search, setSearch] = useState(''); + const [roleFilter, setRoleFilter] = useState<'all' | 'admin' | 'operator' | 'customer'>('all'); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New user modal form + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [role, setRole] = useState<'admin' | 'operator' | 'customer'>('operator'); + + useEffect(() => { + fetchUsers(); + }, []); + + const fetchUsers = async () => { + try { + const res = await fetch('/api/users'); + const data = await res.json(); + if (data.success) { + setUsers(data.users); + } + } catch (e) { + console.error(e); + } + }; + + const handleToggleStatus = async (user: User) => { + const newStatus = !user.isActive; + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, isActive: newStatus } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { isActive: newStatus } }), + }); + setToastMessage(`Estado de ${user.name} actualizado a ${newStatus ? '🟢 ACTIVO' : '⚪ INACTIVO'}.`); + } catch (e) { + console.error(e); + } + }; + + const handleChangeRole = async (user: User, newRole: 'admin' | 'operator' | 'customer') => { + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, role: newRole } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { role: newRole } }), + }); + setToastMessage(`Rol de ${user.name} actualizado a [${newRole.toUpperCase()}].`); + } catch (e) { + console.error(e); + } + }; + + const handleDeleteUser = async (id: string, name: string) => { + if (!confirm(`¿Estás seguro de eliminar al usuario ${name}?`)) return; + + setUsers((prev) => prev.filter((u) => u.id !== id)); + try { + await fetch(`/api/users?id=${id}`, { method: 'DELETE' }); + setToastMessage(`Usuario ${name} eliminado.`); + } catch (e) { + console.error(e); + } + }; + + const handleCreateUser = async (e: React.FormEvent) => { + e.preventDefault(); + try { + const res = await fetch('/api/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, phone, city, address, role }), + }); + const data = await res.json(); + if (data.success) { + setUsers((prev) => [data.user, ...prev]); + setIsModalOpen(false); + setName(''); + setEmail(''); + setPhone(''); + setAddress(''); + setToastMessage(`✨ Usuario "${data.user.name}" registrado con éxito.`); + } else { + alert(data.error); + } + } catch (e) { + console.error(e); + } + }; + + const handleWhatsApp = (user: User) => { + const cleanPhone = user.phone.startsWith('57') ? user.phone : `57${user.phone}`; + const text = encodeURIComponent(`Hola ${user.name}! Te escribimos del equipo de Almeira Store 👋`); + window.open(`https://wa.me/${cleanPhone}?text=${text}`, '_blank'); + }; + + const filtered = users.filter((u) => { + const matchSearch = + u.name.toLowerCase().includes(search.toLowerCase()) || + u.email.toLowerCase().includes(search.toLowerCase()) || + u.phone.includes(search) || + (u.city && u.city.toLowerCase().includes(search.toLowerCase())); + + if (!matchSearch) return false; + if (roleFilter !== 'all' && u.role !== roleFilter) return false; + if (statusFilter === 'active' && !u.isActive) return false; + if (statusFilter === 'inactive' && u.isActive) return false; + return true; + }); + + const adminsCount = users.filter((u) => u.role === 'admin').length; + const operatorsCount = users.filter((u) => u.role === 'operator').length; + const customersCount = users.filter((u) => u.role === 'customer').length; + + return ( +
+ {/* Header */} +
+
+

+ + Control de Usuarios, Roles & Registro ({users.length}) +

+

+ Administra los accesos de administradores, operadores de logística y clientes registrados de la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* KPI Stats Cards */} +
+
+
+ +
+
+

Administradores

+

{adminsCount}

+
+
+ +
+
+ +
+
+

Operadores Logísticos

+

{operatorsCount}

+
+
+ +
+
+ +
+
+

Clientes Registrados

+

{customersCount}

+
+
+
+ + {/* Filters Toolbar */} +
+ {/* Role Pills */} +
+ + + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-cyan-400" + /> +
+
+ + {/* Users Table */} +
+
+ + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((user) => { + return ( + + {/* Active Status Toggle */} + + + {/* User Avatar & Name */} + + + {/* Contact */} + + + {/* City */} + + + {/* Role Dropdown */} + + + {/* Last Login */} + + + {/* Actions */} + + + ); + }) + )} + +
EstadoUsuarioContacto DirectoCiudad / DirecciónRol & PermisosÚltimo AccesoAcciones
+ No se encontraron usuarios con el filtro seleccionado. +
+ + +
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+ {user.email} +
+
+
+ +
+
+
+ {user.city || 'Cali'} + {user.address &&

{user.address}

} +
+
+ + + {user.lastLogin || user.createdAt} + + +
+
+
+ + {/* Modal Create User */} + {isModalOpen && ( +
+
+

Registrar Nuevo Usuario / Operador

+ +
+
+ + setName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setEmail(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+
+ + setPhone(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setCity(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/almeira-store-app/src/app/api/auth/login/route.ts b/almeira-store-app/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..acc7162 --- /dev/null +++ b/almeira-store-app/src/app/api/auth/login/route.ts @@ -0,0 +1,31 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function POST(request: Request) { + try { + const { identifier } = await request.json(); // email o teléfono + if (!identifier) { + return NextResponse.json({ success: false, error: 'Ingresa tu correo o celular' }, { status: 400 }); + } + const user = dataService.authenticate(identifier); + if (!user) { + return NextResponse.json( + { success: false, error: 'Usuario no encontrado. Verifica tu correo o celular.' }, + { status: 404 } + ); + } + if (!user.isActive) { + return NextResponse.json( + { success: false, error: 'Esta cuenta se encuentra inactiva. Contacta a soporte.' }, + { status: 403 } + ); + } + + // Actualizar lastLogin + dataService.updateUser(user.id, { lastLogin: 'Justo ahora' }); + + return NextResponse.json({ success: true, user }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/auth/register/route.ts b/almeira-store-app/src/app/api/auth/register/route.ts new file mode 100644 index 0000000..62b2a63 --- /dev/null +++ b/almeira-store-app/src/app/api/auth/register/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function POST(request: Request) { + try { + const { name, email, phone, city, address } = await request.json(); + if (!name || !email || !phone) { + return NextResponse.json( + { success: false, error: 'Nombre, correo y celular son obligatorios' }, + { status: 400 } + ); + } + + const existing = dataService.authenticate(email) || dataService.authenticate(phone); + if (existing) { + return NextResponse.json( + { success: false, error: 'Ya existe una cuenta con este correo o celular' }, + { status: 409 } + ); + } + + const newUser: User = { + id: `usr-${Date.now()}`, + name, + email, + phone, + city: city || 'Cali', + address: address || '', + role: 'customer', + isActive: true, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + lastLogin: 'Justo ahora', + }; + + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/cities/route.ts b/almeira-store-app/src/app/api/cities/route.ts new file mode 100644 index 0000000..3ecd601 --- /dev/null +++ b/almeira-store-app/src/app/api/cities/route.ts @@ -0,0 +1,27 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const cities = dataService.getCities(); + return NextResponse.json({ success: true, cities }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateCity(id, updates); + return NextResponse.json({ success: true, city: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const created = dataService.addCity(body); + return NextResponse.json({ success: true, city: created }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/orders/route.ts b/almeira-store-app/src/app/api/orders/route.ts new file mode 100644 index 0000000..9c996b6 --- /dev/null +++ b/almeira-store-app/src/app/api/orders/route.ts @@ -0,0 +1,30 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { sendWhatsAppMessage, buildOrderConfirmationMessage } from '@/lib/evolution-api'; + +export async function GET() { + const orders = dataService.getOrders(); + return NextResponse.json({ success: true, orders }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newOrder = dataService.createOrder(body); + + // Enviar confirmación por WhatsApp en background si tiene teléfono válido + if (newOrder.customerPhone) { + try { + const msg = buildOrderConfirmationMessage(newOrder); + // Intentar enviar WhatsApp + await sendWhatsAppMessage(newOrder.customerPhone, msg); + } catch (waErr) { + console.warn('No se pudo enviar WhatsApp automático:', waErr); + } + } + + return NextResponse.json({ success: true, order: newOrder }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/payment-methods/route.ts b/almeira-store-app/src/app/api/payment-methods/route.ts new file mode 100644 index 0000000..b49c62d --- /dev/null +++ b/almeira-store-app/src/app/api/payment-methods/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const methods = dataService.getPaymentMethods(); + return NextResponse.json({ success: true, paymentMethods: methods }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updatePaymentMethod(id, updates); + return NextResponse.json({ success: true, paymentMethod: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/products/route.ts b/almeira-store-app/src/app/api/products/route.ts new file mode 100644 index 0000000..98e5b1e --- /dev/null +++ b/almeira-store-app/src/app/api/products/route.ts @@ -0,0 +1,47 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const includeAll = searchParams.get('all') === 'true'; + + let products = dataService.getProducts(); + if (!includeAll) { + // Para la tienda pública, solo mostrar productos activos (isActive !== false) + products = products.filter((p) => p.isActive !== false); + } + + return NextResponse.json({ success: true, products }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newProduct = dataService.addProduct({ + ...body, + isActive: body.isActive !== undefined ? body.isActive : true, + }); + return NextResponse.json({ success: true, product: newProduct }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const { id, updates } = body; + if (!id) { + return NextResponse.json({ success: false, error: 'ID de producto requerido' }, { status: 400 }); + } + + const updated = dataService.updateProduct(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Producto no encontrado' }, { status: 404 }); + } + + return NextResponse.json({ success: true, product: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/publish/facebook/route.ts b/almeira-store-app/src/app/api/publish/facebook/route.ts new file mode 100644 index 0000000..d2db7a3 --- /dev/null +++ b/almeira-store-app/src/app/api/publish/facebook/route.ts @@ -0,0 +1,12 @@ +import { NextResponse } from 'next/server'; +import { publishToFacebookPage } from '@/lib/facebook-publisher'; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const result = await publishToFacebookPage(body); + return NextResponse.json(result); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/almeira-store-app/src/app/api/settings/route.ts b/almeira-store-app/src/app/api/settings/route.ts new file mode 100644 index 0000000..6073d91 --- /dev/null +++ b/almeira-store-app/src/app/api/settings/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const settings = dataService.getSettings(); + return NextResponse.json({ success: true, settings }); +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const updated = dataService.updateSettings(body); + return NextResponse.json({ success: true, settings: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/users/route.ts b/almeira-store-app/src/app/api/users/route.ts new file mode 100644 index 0000000..8b62fad --- /dev/null +++ b/almeira-store-app/src/app/api/users/route.ts @@ -0,0 +1,57 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function GET() { + const users = dataService.getUsers(); + return NextResponse.json({ success: true, users }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newUser: User = { + id: `usr-${Date.now()}`, + name: body.name, + email: body.email, + phone: body.phone, + city: body.city || 'Cali', + address: body.address || '', + role: body.role || 'customer', + isActive: body.isActive !== false, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + }; + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateUser(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Usuario no encontrado' }, { status: 404 }); + } + return NextResponse.json({ success: true, user: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function DELETE(request: Request) { + try { + const { searchParams } = new URL(request.url); + const id = searchParams.get('id'); + if (!id) { + return NextResponse.json({ success: false, error: 'ID requerido' }, { status: 400 }); + } + const deleted = dataService.deleteUser(id); + return NextResponse.json({ success: deleted }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/almeira-store-app/src/app/api/webhook/whatsapp/route.ts b/almeira-store-app/src/app/api/webhook/whatsapp/route.ts new file mode 100644 index 0000000..ae1555b --- /dev/null +++ b/almeira-store-app/src/app/api/webhook/whatsapp/route.ts @@ -0,0 +1,163 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { parseSupplierMessage } from '@/lib/gemini-parser'; +import { SupplierPost, Product } from '@/types'; +import { calculateRetailPrice } from '@/lib/pricing-engine'; + +export async function GET() { + const posts = dataService.getSupplierPosts(); + const settings = dataService.getSettings(); + return NextResponse.json({ + success: true, + autoPublishEnabled: settings.autoPublishSupplierPosts ?? true, + postsCount: posts.length, + posts, + }); +} + +export async function POST(request: Request) { + try { + const payload = await request.json(); + console.log('📥 [WhatsApp Webhook] Mensaje recibido:', JSON.stringify(payload).slice(0, 300)); + + const data = payload.data || payload; + const settings = dataService.getSettings(); + + // 1. Extraer texto del mensaje de WhatsApp + const messageContent = + data.message?.conversation || + data.message?.extendedTextMessage?.text || + data.message?.imageMessage?.caption || + data.text || + ''; + + // 2. Extraer nombre del canal o grupo + const senderPhone = data.key?.remoteJid?.replace(/\D/g, '') || ''; + const isGroup = data.key?.remoteJid?.includes('g.us'); + const channelName = + data.groupInfo?.subject || + data.pushName || + (isGroup ? 'Grupo Mayorista WhatsApp' : 'Chat Proveedor Directo'); + + if (!messageContent || messageContent.trim().length < 6) { + return NextResponse.json({ + success: true, + ignored: 'Mensaje sin texto suficiente para extraer calzado.', + }); + } + + // 3. Buscar proveedor asociado por teléfono o grupo + const suppliers = dataService.getSuppliers(); + const matchedSupplier = suppliers.find( + (s) => + s.phone.includes(senderPhone) || + (channelName && s.name.toLowerCase().includes(channelName.toLowerCase())) || + (channelName && channelName.toLowerCase().includes(s.name.toLowerCase())) + ); + + const supplierName = matchedSupplier?.name || channelName; + const supplierPhone = matchedSupplier?.phone || senderPhone || '573167455877'; + + // 4. Procesar y extraer información con Gemini AI + const extracted = await parseSupplierMessage(messageContent); + + // Recalcular precio con el margen y redondeo al $5.000 oficial + const finalRetailPrice = calculateRetailPrice( + extracted.supplierPrice, + settings.defaultProfitMargin || 35 + ); + + // Extraer imágenes (si Evolution API envió imagen adjunta o usar fotos de alta resolución) + const images: string[] = []; + if (data.message?.imageMessage?.url) { + images.push(data.message.imageMessage.url); + } else { + images.push( + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' + ); + } + + // 5. Verificar Anti-Duplicados en el Catálogo + const existingProducts = dataService.getProducts(); + const duplicateProduct = existingProducts.find( + (p) => p.name.toLowerCase() === extracted.name.toLowerCase() + ); + + let registeredProduct: Product | null = null; + const autoPublish = settings.autoPublishSupplierPosts ?? true; + + if (autoPublish) { + if (duplicateProduct) { + // Actualizar stock y tallas existentes sin duplicar + const mergedSizes = Array.from(new Set([...duplicateProduct.sizes, ...extracted.sizes])); + registeredProduct = dataService.updateProduct(duplicateProduct.id, { + supplierPrice: extracted.supplierPrice, + retailPrice: finalRetailPrice, + sizes: mergedSizes, + inStock: true, + isActive: true, + supplierName, + supplierPhone, + }); + console.log(`🔄 [Auto-Sync] Zapatilla "${extracted.name}" actualizada en catálogo (Anti-Duplicados).`); + } else { + // Registrar y publicar automáticamente + registeredProduct = dataService.addProduct({ + name: extracted.name, + brand: extracted.brand, + supplierPrice: extracted.supplierPrice, + retailPrice: finalRetailPrice, + originalPrice: Math.round(finalRetailPrice * 1.35), + sizes: extracted.sizes, + images, + description: `Zapatillas ${extracted.brand} ${extracted.name} garantizadas. Calidad seleccionada con horma nacional y suela antideslizante.`, + category: extracted.category || 'Sneakers / Urbano', + inStock: true, + isActive: true, + isFlashDeal: true, + rating: 4.9, + reviewsCount: 15, + salesCount: 30, + originBadge: 'Bodega Mayorista', + supplierId: matchedSupplier?.id || 'sup-auto', + supplierName, + supplierPhone, + }); + console.log(`✨ [Auto-Publish] Nueva zapatilla "${extracted.name}" publicada automáticamente en tienda.`); + } + } + + // 6. Registrar en el historial de publicaciones recibidas + const newPost: SupplierPost = { + id: `post-${Date.now()}`, + channelName, + supplierName, + supplierPhone, + rawMessage: messageContent, + rawImages: images, + extractedProduct: { + ...extracted, + suggestedRetailPrice: finalRetailPrice, + supplierName, + supplierPhone, + }, + status: autoPublish ? 'published_store' : 'pending_review', + receivedAt: 'Justo ahora', + }; + + dataService.addSupplierPost(newPost); + + return NextResponse.json({ + success: true, + autoPublished: autoPublish, + product: registeredProduct, + post: newPost, + message: autoPublish + ? `🔥 ¡Zapatilla "${extracted.name}" procesada y publicada AUTOMÁTICAMENTE en la tienda!` + : `Mensaje ingresado al feed para aprobación manual.`, + }); + } catch (error: any) { + console.error('Error procesando webhook de WhatsApp:', error); + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/almeira-store-app/src/app/api/whatsapp-groups/route.ts b/almeira-store-app/src/app/api/whatsapp-groups/route.ts new file mode 100644 index 0000000..6f78a1c --- /dev/null +++ b/almeira-store-app/src/app/api/whatsapp-groups/route.ts @@ -0,0 +1,104 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { MonitoredWhatsAppGroup } from '@/types'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url); + const fetchLive = searchParams.get('fetchLive') === 'true'; + + const localGroups = dataService.getMonitoredGroups(); + + if (!fetchLive) { + return NextResponse.json({ + success: true, + groups: localGroups, + }); + } + + // Consultar grupos en vivo desde Evolution API + try { + const response = await fetch( + `${EVOLUTION_API_URL}/group/fetchAllGroups/${EVOLUTION_INSTANCE_NAME}?getParticipants=false`, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + + const liveGroups = await response.json(); + + if (Array.isArray(liveGroups)) { + const merged: MonitoredWhatsAppGroup[] = liveGroups.map((lg: any) => { + const jid = lg.id || lg.jid; + const name = lg.subject || lg.name || 'Grupo Sin Nombre'; + const existing = localGroups.find((g) => g.jid === jid || g.name.toLowerCase() === name.toLowerCase()); + + return { + id: existing?.id || `grp-${jid.replace(/\D/g, '').slice(-6)}`, + jid, + name, + isMonitored: existing ? existing.isMonitored : false, + supplierId: existing?.supplierId, + supplierName: existing?.supplierName || name, + profitMarginOverride: existing?.profitMarginOverride || 35, + autoPublish: existing?.autoPublish ?? true, + participantsCount: lg.size || (lg.participants ? lg.participants.length : undefined), + notes: existing?.notes || '', + }; + }); + + // Asegurar que los locales que no vinieron en live sigan presentes + localGroups.forEach((lg) => { + if (!merged.some((m) => m.jid === lg.jid || m.id === lg.id)) { + merged.unshift(lg); + } + }); + + return NextResponse.json({ + success: true, + isLive: true, + totalLive: liveGroups.length, + groups: merged, + }); + } + } catch (err: any) { + console.warn('No se pudo conectar con Evolution API en vivo:', err.message); + } + + return NextResponse.json({ + success: true, + isLive: false, + groups: localGroups, + }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + + if (body.action === 'toggle') { + const { idOrJid, isMonitored } = body; + const updated = dataService.toggleGroupMonitoring(idOrJid, isMonitored); + return NextResponse.json({ success: true, group: updated }); + } + + if (Array.isArray(body.groups)) { + const saved = dataService.saveMonitoredGroups(body.groups); + return NextResponse.json({ success: true, groups: saved }); + } + + return NextResponse.json({ success: false, error: 'Datos no válidos' }, { status: 400 }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/almeira-store-app/src/app/checkout/page.tsx b/almeira-store-app/src/app/checkout/page.tsx new file mode 100644 index 0000000..241fd16 --- /dev/null +++ b/almeira-store-app/src/app/checkout/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { ArrowLeft, CheckCircle2, ShieldCheck, Truck, Zap, QrCode, Phone, MapPin, User, MessageCircle, ExternalLink, CreditCard } from 'lucide-react'; +import { City, PaymentMethod, Order, StoreSettings } from '@/types'; +import { INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; +import confetti from 'canvas-confetti'; + +export default function CheckoutPage() { + const { currentBrand } = useBrand(); + + const [customerName, setCustomerName] = useState(''); + const [customerPhone, setCustomerPhone] = useState(''); + const [address, setAddress] = useState(''); + const [neighborhood, setNeighborhood] = useState(''); + const [notes, setNotes] = useState(''); + + const [cities, setCities] = useState(INITIAL_CITIES); + const [paymentMethods, setPaymentMethods] = useState(INITIAL_PAYMENT_METHODS); + const [selectedCityId, setSelectedCityId] = useState('city-cali'); + const [selectedPaymentId, setSelectedPaymentId] = useState('pay-deposit-10k'); + const [storeSettings, setStoreSettings] = useState(null); + + const [checkoutItems] = useState>([ + { + productId: INITIAL_PRODUCTS[0].id, + productName: INITIAL_PRODUCTS[0].name, + brand: INITIAL_PRODUCTS[0].brand, + size: '39', + quantity: 1, + price: INITIAL_PRODUCTS[0].retailPrice, + image: INITIAL_PRODUCTS[0].images[0], + }, + ]); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [orderCompleted, setOrderCompleted] = useState(null); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setPaymentMethods(d.paymentMethods)) + .catch(() => {}); + + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setStoreSettings(d.settings)) + .catch(() => {}); + }, []); + + const activeCity = cities.find((c) => c.id === selectedCityId) || cities[0]; + const activePayment = paymentMethods.find((p) => p.id === selectedPaymentId) || paymentMethods[0]; + + const subtotal = checkoutItems.reduce((acc, it) => acc + it.price * it.quantity, 0); + const shippingCost = activeCity.shippingCost; + const totalAmount = subtotal + shippingCost; + + const depositAmount = activePayment.requiresDeposit ? activePayment.depositAmount : 0; + const balanceDue = totalAmount - depositAmount; + + const officialWhatsapp = storeSettings?.whatsappNumber || '573167455877'; + const boldLink = storeSettings?.boldPaymentLink || 'https://bold.co/p/carlos-lasso'; + + const handleSubmitOrder = async (e: React.FormEvent) => { + e.preventDefault(); + if (!customerName || !customerPhone || !address) { + alert('Por favor completa tu nombre, celular y dirección para el despacho.'); + return; + } + + setIsSubmitting(true); + + try { + const orderPayload = { + customerName, + customerPhone, + address: `${address} - Barrio: ${neighborhood || 'Centro'}`, + cityId: activeCity.id, + cityName: activeCity.name, + items: checkoutItems, + subtotal, + shippingCost, + totalAmount, + depositAmount, + balanceDue, + paymentMethodId: activePayment.id, + paymentMethodName: activePayment.name, + notes, + }; + + const res = await fetch('/api/orders', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(orderPayload), + }); + + const data = await res.json(); + if (data.success) { + setOrderCompleted(data.order); + confetti({ + particleCount: 100, + spread: 70, + origin: { y: 0.6 }, + }); + } + } catch (err) { + console.error('Error creando orden:', err); + } finally { + setIsSubmitting(false); + } + }; + + const handleOpenWhatsAppOrder = (order: Order) => { + const text = `🎉 *CONFIRMACIÓN DE PEDIDO EN ${currentBrand.name} #${order.id}* 🎉 + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *Artículos:* +${order.items.map((i) => `• ${i.productName} (Talla ${i.size}) x${i.quantity} = ${formatCOP(i.price * i.quantity)}`).join('\n')} + +💰 *Total:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +¡Hola ${currentBrand.shortName}! Acabo de registrar mi pedido en la web. ¿Me confirman despacho por favor?`; + + window.open(`https://wa.me/${officialWhatsapp}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + if (orderCompleted) { + return ( +
+
+
+ +
+ +
+ + ¡Pedido Registrado con Éxito! + +

Orden #{orderCompleted.id}

+

+ Hemos recibido tu solicitud para entrega en {orderCompleted.cityName} con {currentBrand.name}. +

+
+ + {/* Bold.co or Nequi Separation Box */} + {orderCompleted.depositAmount > 0 ? ( +
+
+ + Paso 2: Realiza la separación de $10.000 COP +
+

+ Paga de inmediato con Link de Pago Bold.co (PSE / Tarjeta / Nequi) o transfiere a nuestra cuenta oficial: +

+ + {boldLink && ( + + + Pagar $10.000 COP con Bold.co (PSE / Tarjetas) + + + )} + +
+ 📱 Nequi / Daviplata: {storeSettings?.nequiAccount || '316 745 5877'} ({storeSettings?.accountHolder || 'Carlos Andrés Lasso'}) +
+

+ 🤝 Cancelas el saldo de {formatCOP(orderCompleted.balanceDue)} al recibir el paquete en tu casa. +

+
+ ) : ( +
+

+ Tu pedido quedó programado para entrega contraentrega en 24 horas. ¡Nos pondremos en contacto contigo por WhatsApp! +

+
+ )} + +
+ + + + Volver a la Tienda + +
+
+
+ ); + } + + return ( +
+
+ {/* Header */} +
+ + + Regresar a {currentBrand.name} + +
+ + Compra Segura & Garantizada +
+
+ +
+ {/* Left Column: Shipping & Payment Details (7 cols) */} +
+ {/* 1. Datos del Cliente */} +
+

+ + 1. Datos de Entrega +

+ +
+
+ + setCustomerName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-white outline-hidden" + /> +
+
+ + setCustomerPhone(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-white outline-hidden" + /> +
+
+ + {/* City Selection */} +
+ + +
+ +
+
+ + setAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-white outline-hidden" + /> +
+
+ + setNeighborhood(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-white outline-hidden" + /> +
+
+
+ + {/* 2. Método de Pago */} +
+

+ + 2. Selecciona tu Método de Pago +

+ +
+ {paymentMethods.map((method) => { + const isSelected = selectedPaymentId === method.id; + return ( +
setSelectedPaymentId(method.id)} + className={`p-4 rounded-2xl border transition-all cursor-pointer space-y-1.5 ${ + isSelected + ? `border-cyan-400 bg-cyan-950/20 shadow-md` + : 'border-slate-800 hover:border-slate-700 bg-slate-950' + }`} + > +
+
+
+ {isSelected &&
} +
+ {method.name} +
+ + {method.requiresDeposit && ( + + Separa con $10.000 + + )} +
+ +

{method.description}

+ + {isSelected && (method.accountInfo || (method.type === 'bold' && boldLink)) && ( +
+ {method.accountInfo &&

{method.accountInfo}

} + {method.type === 'bold' && boldLink && ( + + + Abrir Link de Pago Bold.co + + )} +
+ )} +
+ ); + })} +
+
+
+ + {/* Right Column: Summary (5 cols) */} +
+
+

Resumen del Pedido

+ + {/* Items */} +
+ {checkoutItems.map((item, i) => ( +
+ +
+

{item.productName}

+

Talla: {item.size} | Cant: {item.quantity}

+

+ {formatCOP(item.price * item.quantity)} +

+
+
+ ))} +
+ + {/* Breakdown */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Envío ({activeCity.name}): + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total a Pagar: + + {formatCOP(totalAmount)} + +
+ + {depositAmount > 0 && ( +
+
+ Separación por Bold / Nequi / Daviplata: + {formatCOP(depositAmount)} +
+
+ Saldo a pagar al mensajero: + {formatCOP(balanceDue)} +
+
+ )} + +
+
+ + Garantía en {activeCity.name}: +
+

+ {activeCity.firstExchangeFree + ? '1er Cambio de Talla 100% GRATIS (cambios posteriores con flete estándar).' + : 'Cambios de talla 100% garantizados (los costos de envío son asumidos por el cliente).'} +

+
+
+ + + +

+ Al confirmar, se guardará tu pedido y recibirás asistencia inmediata por WhatsApp oficial ({officialWhatsapp}) para el seguimiento de tu entrega en 24 horas. +

+
+
+ +
+
+ ); +} diff --git a/almeira-store-app/src/app/favicon.ico b/almeira-store-app/src/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/almeira-store-app/src/app/favicon.ico differ diff --git a/almeira-store-app/src/app/globals.css b/almeira-store-app/src/app/globals.css new file mode 100644 index 0000000..a2dc41e --- /dev/null +++ b/almeira-store-app/src/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/almeira-store-app/src/app/layout.tsx b/almeira-store-app/src/app/layout.tsx new file mode 100644 index 0000000..badf73c --- /dev/null +++ b/almeira-store-app/src/app/layout.tsx @@ -0,0 +1,61 @@ +import type { Metadata, Viewport } from 'next'; +import { Geist, Geist_Mono } from 'next/font/google'; +import './globals.css'; +import { BrandProvider } from '@/context/BrandContext'; +import { AuthProvider } from '@/context/AuthContext'; + +const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], +}); + +const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], +}); + +export const viewport: Viewport = { + themeColor: '#06b6d4', + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + viewportFit: 'cover', +}; + +export const metadata: Metadata = { + title: 'Almeira Store • Sneakers & Moda Urbana', + description: 'Tienda oficial de calzado y zapatillas con entregas contraentrega en 24 horas.', + manifest: '/manifest.json', + appleWebApp: { + capable: true, + statusBarStyle: 'black-translucent', + title: 'Almeira Store', + }, + icons: { + icon: '/icon.svg', + apple: '/icon.svg', + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + + + + {children} + + + + + ); +} diff --git a/almeira-store-app/src/app/page.tsx b/almeira-store-app/src/app/page.tsx new file mode 100644 index 0000000..e4b60ff --- /dev/null +++ b/almeira-store-app/src/app/page.tsx @@ -0,0 +1,284 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Navbar } from '@/components/store/Navbar'; +import { FlashDealsBanner } from '@/components/store/FlashDealsBanner'; +import { CategoryPills } from '@/components/store/CategoryPills'; +import { ProductCard } from '@/components/store/ProductCard'; +import { ProductModal } from '@/components/store/ProductModal'; +import { CartDrawer } from '@/components/store/CartDrawer'; +import { CitySelectorModal } from '@/components/store/CitySelectorModal'; +import { MobileBottomDock } from '@/components/mobile/MobileBottomDock'; +import { MobileInstallBanner } from '@/components/mobile/MobileInstallBanner'; +import { AuthModal } from '@/components/auth/AuthModal'; +import { Product, City, CartItem } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_CITIES } from '@/lib/data-service'; +import { Sparkles, ShieldCheck, Truck, RefreshCw, Zap } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export default function StoreHomePage() { + const { currentBrand } = useBrand(); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [cities, setCities] = useState(INITIAL_CITIES); + const [selectedCity, setSelectedCity] = useState(INITIAL_CITIES[0]); // Cali + const [activeCategory, setActiveCategory] = useState('all'); + const [searchQuery, setSearchQuery] = useState(''); + + // Modals & Drawers state + const [selectedProduct, setSelectedProduct] = useState(null); + const [isCartOpen, setIsCartOpen] = useState(false); + const [isCityModalOpen, setIsCityModalOpen] = useState(false); + const [isInstallModalOpen, setIsInstallModalOpen] = useState(false); + const [cartItems, setCartItems] = useState([]); + + const cartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + useEffect(() => { + fetch('/api/products') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.products?.length > 0) { + setProducts(data.products); + } + }) + .catch((e) => console.log('Usando catálogo inicial:', e)); + + fetch('/api/cities') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.cities?.length > 0) { + setCities(data.cities); + const defaultCali = data.cities.find((c: City) => c.name.toLowerCase().includes('cali')); + if (defaultCali) setSelectedCity(defaultCali); + } + }) + .catch((e) => console.log('Usando ciudades iniciales:', e)); + }, []); + + const filteredProducts = products.filter((p) => { + if (searchQuery.trim()) { + const q = searchQuery.toLowerCase(); + const matchName = p.name.toLowerCase().includes(q); + const matchBrand = p.brand.toLowerCase().includes(q); + const matchSize = p.sizes.some((s) => s.includes(q)); + if (!matchName && !matchBrand && !matchSize) return false; + } + + if (activeCategory === 'flash') return p.isFlashDeal; + if (activeCategory === 'under120') return p.retailPrice <= 120000; + if (activeCategory !== 'all') { + return p.brand.toLowerCase() === activeCategory.toLowerCase(); + } + return true; + }); + + const handleAddToCart = (product: Product, size: string) => { + setCartItems((prev) => { + const existingIdx = prev.findIndex( + (item) => item.product.id === product.id && item.selectedSize === size + ); + if (existingIdx > -1) { + const next = [...prev]; + next[existingIdx].quantity += 1; + return next; + } + return [...prev, { product, selectedSize: size, quantity: 1 }]; + }); + setIsCartOpen(true); + }; + + const handleRemoveFromCart = (productId: string, size: string) => { + setCartItems((prev) => + prev.filter((item) => !(item.product.id === productId && item.selectedSize === size)) + ); + }; + + const handleUpdateQuantity = (productId: string, size: string, delta: number) => { + setCartItems((prev) => + prev + .map((item) => { + if (item.product.id === productId && item.selectedSize === size) { + const newQty = item.quantity + delta; + return newQty > 0 ? { ...item, quantity: newQty } : null; + } + return item; + }) + .filter(Boolean) as CartItem[] + ); + }; + + const totalCartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + return ( +
+ {/* Navigation Header */} + setIsCartOpen(true)} + selectedCity={selectedCity} + onOpenCitySelector={() => setIsCityModalOpen(true)} + searchQuery={searchQuery} + onSearchChange={setSearchQuery} + /> + + {/* Main Container */} +
+ {/* Flash Deals Hero Banner */} + + + {/* Value Props Strip */} +
+
+
+ +
+
+

Entrega en 24 Horas

+

Directo en Cali

+
+
+ +
+
+ +
+
+

Pago Contraentrega

+

Cancelas al recibir

+
+
+ +
+
+ +
+
+

Separa con $10.000

+

Aparta tu talla

+
+
+ +
+
+ +
+
+

Garantía Total

+

Cambio asegurado

+
+
+
+ + {/* Category & Brand Filters */} +
+
+

+ + Colección de Calzado & Sneakers +

+ + {filteredProducts.length} {filteredProducts.length === 1 ? 'modelo' : 'modelos'} + +
+ + +
+ + {/* Product Grid */} + {filteredProducts.length === 0 ? ( +
+
+ +
+

No encontramos zapatillas con ese criterio

+

Intenta buscar otra marca o restablecer los filtros.

+ +
+ ) : ( +
+ {filteredProducts.map((product) => ( + handleAddToCart(p, size)} + /> + ))} +
+ )} +
+ + {/* Footer */} +
+
+
+
+ {currentBrand.logo.iconText} +
+ {currentBrand.name} +
+

© 2026 {currentBrand.name}. Despachos urbanos y nacionales con pago contraentrega.

+
+ + {currentBrand.badge} +
+
+
+ + {/* Modals & Drawers */} + setSelectedProduct(null)} + onAddToCart={handleAddToCart} + selectedCity={selectedCity} + /> + + setIsCartOpen(false)} + cartItems={cartItems} + onRemoveItem={handleRemoveFromCart} + onUpdateQuantity={handleUpdateQuantity} + selectedCity={selectedCity} + onOpenCitySelector={() => { + setIsCartOpen(false); + setIsCityModalOpen(true); + }} + /> + + setIsCityModalOpen(false)} + cities={cities} + selectedCity={selectedCity} + onSelectCity={setSelectedCity} + /> + + {/* Mobile App Dock & Install Banner */} + setIsCartOpen(true)} + onOpenInstallModal={() => setIsInstallModalOpen(true)} + /> + + setIsInstallModalOpen(false)} + /> + + {/* User Auth Modal */} + +
+ ); +} diff --git a/almeira-store-app/src/components/auth/AuthModal.tsx b/almeira-store-app/src/components/auth/AuthModal.tsx new file mode 100644 index 0000000..8a39a9f --- /dev/null +++ b/almeira-store-app/src/components/auth/AuthModal.tsx @@ -0,0 +1,255 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, User, Lock, Mail, Phone, MapPin, Sparkles, LogIn, UserPlus, Shield, LogOut } from 'lucide-react'; +import { useAuth } from '@/context/AuthContext'; +import { useBrand } from '@/context/BrandContext'; +import Link from 'next/link'; + +export const AuthModal: React.FC = () => { + const { user, login, register, logout, isAuthModalOpen, closeAuthModal } = useAuth(); + const { currentBrand } = useBrand(); + + const [mode, setMode] = useState<'login' | 'register'>('login'); + const [identifier, setIdentifier] = useState(''); + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + if (!isAuthModalOpen) return null; + + const handleLoginSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await login(identifier); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al iniciar sesión'); + } + }; + + const handleRegisterSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await register({ name, email, phone, city, address }); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al registrarse'); + } + }; + + return ( +
+
+ + + {/* If user is already logged in: View Profile */} + {user ? ( +
+
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+

{user.email}

+
+ + {user.role === 'admin' ? '👑 Administrador' : user.role === 'operator' ? '📦 Operador Logística' : '🛍️ Cliente Registrado'} + +
+
+ +
+

📱 Celular: {user.phone}

+

📍 Ciudad: {user.city || 'Cali'}

+ {user.address &&

🏠 Dirección: {user.address}

} +
+ + {user.role === 'admin' || user.role === 'operator' ? ( + + + Ir al Panel de Control Admin + + ) : null} + + +
+ ) : ( + /* Login or Register */ +
+
+
+ {currentBrand.shortName[0]} +
+
+

+ {mode === 'login' ? 'Iniciar Sesión' : 'Crear Cuenta'} +

+

+ {mode === 'login' + ? 'Accede para gestionar pedidos o entrar como admin' + : 'Regístrate para compras rápidas y seguimiento'} +

+
+
+ + {/* Mode Switch Tabs */} +
+ + +
+ + {error && ( +
+ {error} +
+ )} + + {mode === 'login' ? ( +
+
+ + setIdentifier(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2.5 text-white outline-hidden focus:border-cyan-400" + /> +
+ + + +

+ Tip Admin: Puedes ingresar con carlos@almeira.com.co o 3134848203. +

+
+ ) : ( +
+
+ + setName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-cyan-400" + /> +
+ +
+
+ + setEmail(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-cyan-400" + /> +
+ +
+ + setPhone(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-cyan-400" + /> +
+
+ +
+
+ + setCity(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-cyan-400" + /> +
+
+ + setAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-cyan-400" + /> +
+
+ + +
+ )} +
+ )} +
+
+ ); +}; diff --git a/almeira-store-app/src/components/mobile/MobileBottomDock.tsx b/almeira-store-app/src/components/mobile/MobileBottomDock.tsx new file mode 100644 index 0000000..ce0db6c --- /dev/null +++ b/almeira-store-app/src/components/mobile/MobileBottomDock.tsx @@ -0,0 +1,104 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { Home, Search, ShoppingBag, MessageCircle, Download, Check } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileBottomDockProps { + cartCount: number; + onOpenCart: () => void; + onOpenSearch?: () => void; + onOpenInstallModal: () => void; +} + +export const MobileBottomDock: React.FC = ({ + cartCount, + onOpenCart, + onOpenSearch, + onOpenInstallModal, +}) => { + const { currentBrand } = useBrand(); + const [activeTab, setActiveTab] = useState('home'); + + const handleWhatsApp = () => { + const text = encodeURIComponent( + `Hola ${currentBrand.name}! 👋 Quiero consultar la disponibilidad de unas zapatillas para despacho contraentrega en 24 horas.` + ); + window.open(`https://wa.me/${currentBrand.whatsappNumber}?text=${text}`, '_blank'); + }; + + return ( +
+
+ {/* 1. Inicio */} + setActiveTab('home')} + className={`flex flex-col items-center gap-0.5 cursor-pointer transition-all ${ + activeTab === 'home' ? 'text-white' : 'text-slate-400 hover:text-slate-200' + }`} + > + + Inicio + + + {/* 2. Buscar */} + + + {/* 3. Carrito con Badge */} + + + {/* 4. WhatsApp Asesoría */} + + + {/* 5. Instalar App */} + +
+
+ ); +}; diff --git a/almeira-store-app/src/components/mobile/MobileInstallBanner.tsx b/almeira-store-app/src/components/mobile/MobileInstallBanner.tsx new file mode 100644 index 0000000..f6e1fdd --- /dev/null +++ b/almeira-store-app/src/components/mobile/MobileInstallBanner.tsx @@ -0,0 +1,130 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Download, Sparkles, X, Smartphone, CheckCircle, Share2, PlusSquare } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileInstallBannerProps { + isOpen: boolean; + onClose: () => void; +} + +export const MobileInstallBanner: React.FC = ({ isOpen, onClose }) => { + const { currentBrand } = useBrand(); + const [deferredPrompt, setDeferredPrompt] = useState(null); + const [isInstalled, setIsInstalled] = useState(false); + const [isIOS, setIsIOS] = useState(false); + + useEffect(() => { + // Detect iOS + const userAgent = window.navigator.userAgent.toLowerCase(); + const isIosDevice = /iphone|ipad|ipod/.test(userAgent); + setIsIOS(isIosDevice); + + // Detect if already running standalone + const isStandalone = window.matchMedia('(display-mode: standalone)').matches; + if (isStandalone) { + setIsInstalled(true); + } + + // Capture install prompt event for Android/Chrome + const handleBeforeInstall = (e: Event) => { + e.preventDefault(); + setDeferredPrompt(e); + }; + + window.addEventListener('beforeinstallprompt', handleBeforeInstall); + return () => window.removeEventListener('beforeinstallprompt', handleBeforeInstall); + }, []); + + const handleInstallClick = async () => { + if (deferredPrompt) { + deferredPrompt.prompt(); + const { outcome } = await deferredPrompt.userChoice; + if (outcome === 'accepted') { + setIsInstalled(true); + onClose(); + } + setDeferredPrompt(null); + } + }; + + if (!isOpen) return null; + + return ( +
+
+ + +
+
+ {currentBrand.shortName[0]} +
+
+

Instalar {currentBrand.name}

+

Aplicación Móvil para Android & iPhone

+
+
+ + {/* Benefits list */} +
+
+ + Acceso instantáneo desde la pantalla de inicio de tu celular +
+
+ + Notificaciones de lanzamientos y drops exclusivos +
+
+ + Navegación ultra rápida sin consumir espacio de memoria +
+
+ + {/* Action / Platform Instructions */} + {isIOS ? ( +
+

+ + Instrucciones para iPhone (Safari): +

+
    +
  1. Toca el botón Compartir abajo en Safari.
  2. +
  3. Desliza hacia abajo y selecciona "Agregar a Inicio ".
  4. +
  5. ¡Listo! El icono de {currentBrand.shortName} aparecerá en tu teléfono.
  6. +
+
+ ) : deferredPrompt ? ( + + ) : ( +
+
+

Para instalar en tu navegador:

+

+ Abre el menú de opciones del navegador (los 3 puntos arriba a la derecha) y toca "Instalar aplicación" o "Agregar a pantalla principal". +

+
+ +
+ )} +
+
+ ); +}; diff --git a/almeira-store-app/src/components/store/CartDrawer.tsx b/almeira-store-app/src/components/store/CartDrawer.tsx new file mode 100644 index 0000000..bca5a6d --- /dev/null +++ b/almeira-store-app/src/components/store/CartDrawer.tsx @@ -0,0 +1,254 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { X, Trash2, ShoppingBag, ArrowRight, Zap, Truck, MessageCircle } from 'lucide-react'; +import { CartItem, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface CartDrawerProps { + isOpen: boolean; + onClose: () => void; + cartItems: CartItem[]; + onRemoveItem: (productId: string, size: string) => void; + onUpdateQuantity: (productId: string, size: string, delta: number) => void; + selectedCity: City; + onOpenCitySelector: () => void; +} + +export const CartDrawer: React.FC = ({ + isOpen, + onClose, + cartItems, + onRemoveItem, + onUpdateQuantity, + selectedCity, + onOpenCitySelector, +}) => { + const { currentBrand } = useBrand(); + const [officialPhone, setOfficialPhone] = React.useState('573167455877'); + + React.useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => { + if (d.success && d.settings?.whatsappNumber) { + setOfficialPhone(d.settings.whatsappNumber); + } + }) + .catch(() => {}); + }, []); + + if (!isOpen) return null; + + const subtotal = cartItems.reduce((acc, item) => acc + item.product.retailPrice * item.quantity, 0); + const shippingCost = selectedCity.shippingCost; + const totalAmount = subtotal + shippingCost; + const separation = calculateSeparationBreakdown(totalAmount); + + const handleWhatsAppCheckout = () => { + const itemsList = cartItems + .map((item) => `👟 *${item.product.name}* (Talla: *${item.selectedSize}*, Cant: ${item.quantity}) - ${formatCOP(item.product.retailPrice * item.quantity)}`) + .join('\n'); + + const text = `🔥 *NUEVO PEDIDO DESDE ${currentBrand.name}* 🔥 + +📦 *Productos seleccionados:* +${itemsList} + +📍 *Ciudad de entrega:* ${selectedCity.name} +💵 *Subtotal:* ${formatCOP(subtotal)} +🚚 *Envío:* ${shippingCost === 0 ? 'GRATIS' : formatCOP(shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(totalAmount)} COP + +⚡ *Condición de Pago:* Pago Contraentrega (Separo con $10.000 COP vía Bold/Nequi y cancelo saldo de ${formatCOP(separation.balanceDue)} al recibir). + +Por favor confírmenme para enviarles los datos de mi dirección.`; + + window.open(`https://wa.me/${officialPhone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+ {/* Backdrop */} +
+ +
+
+ {/* Header */} +
+
+
+ +
+
+

Tu Carrito • {currentBrand.shortName}

+

{cartItems.length} {cartItems.length === 1 ? 'artículo' : 'artículos'}

+
+
+ +
+ + {/* Items List */} +
+ {cartItems.length === 0 ? ( +
+
+ +
+

Tu carrito está vacío

+

+ Aprovecha las ofertas de calzado con pago contraentrega en Cali y despachos nacionales. +

+ +
+ ) : ( + cartItems.map((item, idx) => ( +
+ {item.product.name} +
+
+
+

+ {item.product.name} +

+ +
+
+ + Talla {item.selectedSize} + + + {item.product.brand} + +
+
+ +
+ + {formatCOP(item.product.retailPrice * item.quantity)} + +
+ + {item.quantity} + +
+
+
+
+ )) + )} +
+ + {/* Footer & Checkout Breakdown */} + {cartItems.length > 0 && ( +
+ {/* City Delivery selector pill */} +
+
+ + Destino: {selectedCity.name} +
+ +
+ + {/* Price Calculations */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Costo de Envío: + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total de la Orden: + + {formatCOP(totalAmount)} + +
+
+ + {/* Separation Highlight Banner */} +
+

+ + Opción de Separación con $10.000 COP +

+

+ Separas con {formatCOP(separation.depositAmount)} y pagas {formatCOP(separation.balanceDue)} al recibir contraentrega en tu casa. +

+

+ 🛡️ {selectedCity.firstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${selectedCity.name}` + : `Garantía de cambio en ${selectedCity.name} (flete asumido por cliente)`} +

+
+ + {/* Action Buttons */} +
+ + Proceder al Pago Contraentrega + + + + +
+
+ )} +
+
+
+ ); +}; diff --git a/almeira-store-app/src/components/store/CategoryPills.tsx b/almeira-store-app/src/components/store/CategoryPills.tsx new file mode 100644 index 0000000..be49b4b --- /dev/null +++ b/almeira-store-app/src/components/store/CategoryPills.tsx @@ -0,0 +1,48 @@ +'use client'; + +import React from 'react'; +import { useBrand } from '@/context/BrandContext'; + +interface CategoryPillsProps { + activeCategory: string; + onSelectCategory: (category: string) => void; +} + +const CATEGORIES = [ + { id: 'all', label: '🔥 Todas las Zapatillas' }, + { id: 'Nike', label: '👟 Nike' }, + { id: 'Jordan', label: '🏀 Air Jordan' }, + { id: 'Adidas', label: '🛹 Adidas' }, + { id: 'New Balance', label: '🌿 New Balance' }, + { id: 'Puma', label: '🐆 Puma' }, + { id: 'flash', label: '⚡ Ofertas Flash' }, + { id: 'under120', label: '💰 Menos de $120k' }, +]; + +export const CategoryPills: React.FC = ({ + activeCategory, + onSelectCategory, +}) => { + const { currentBrand } = useBrand(); + + return ( +
+ {CATEGORIES.map((cat) => { + const isActive = activeCategory === cat.id; + return ( + + ); + })} +
+ ); +}; diff --git a/almeira-store-app/src/components/store/CitySelectorModal.tsx b/almeira-store-app/src/components/store/CitySelectorModal.tsx new file mode 100644 index 0000000..1ff580b --- /dev/null +++ b/almeira-store-app/src/components/store/CitySelectorModal.tsx @@ -0,0 +1,109 @@ +'use client'; + +import React from 'react'; +import { X, MapPin, Check, Truck } from 'lucide-react'; +import { City } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +interface CitySelectorModalProps { + isOpen: boolean; + onClose: () => void; + cities: City[]; + selectedCity: City; + onSelectCity: (city: City) => void; +} + +export const CitySelectorModal: React.FC = ({ + isOpen, + onClose, + cities, + selectedCity, + onSelectCity, +}) => { + if (!isOpen) return null; + + return ( +
+
+ {/* Header */} +
+
+
+ +
+
+

Selecciona tu Ciudad

+

Calculamos tiempos y tarifas oficiales

+
+
+ +
+ + {/* City list */} +
+ {cities + .filter((c) => c.isActive !== false) + .map((city) => { + const isSelected = selectedCity.id === city.id; + const hasCod = city.allowsContraentrega || city.allowCod; + + return ( +
{ + onSelectCity(city); + onClose(); + }} + className={`p-3 rounded-2xl border transition-all cursor-pointer flex items-center justify-between ${ + isSelected + ? 'border-cyan-400 bg-cyan-950/50 shadow-[0_0_15px_rgba(6,182,212,0.2)]' + : 'border-slate-800 hover:border-slate-700 bg-slate-950' + }`} + > +
+
+ {city.name} + {hasCod && ( + + Contraentrega + + )} +
+

+ + {city.deliveryTime} +

+
+ +
+ + {city.shippingCost === 0 ? ( + Gratis + ) : ( + formatCOP(city.shippingCost) + )} + + {isSelected && ( +
+ +
+ )} +
+
+ ); + })} +
+ + {/* Info footer */} +
+ 💡 En Cali y zona metropolitana: entregas el mismo día con mensajería directa y pago contraentrega. +
+
+
+ ); +}; diff --git a/almeira-store-app/src/components/store/FlashDealsBanner.tsx b/almeira-store-app/src/components/store/FlashDealsBanner.tsx new file mode 100644 index 0000000..e26b007 --- /dev/null +++ b/almeira-store-app/src/components/store/FlashDealsBanner.tsx @@ -0,0 +1,83 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Zap, Clock, Gift } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export const FlashDealsBanner: React.FC = () => { + const { currentBrand } = useBrand(); + const [timeLeft, setTimeLeft] = useState({ hours: 4, minutes: 27, seconds: 15 }); + + useEffect(() => { + const timer = setInterval(() => { + setTimeLeft((prev) => { + if (prev.seconds > 0) { + return { ...prev, seconds: prev.seconds - 1 }; + } else if (prev.minutes > 0) { + return { ...prev, minutes: 59, seconds: 59 }; + } else if (prev.hours > 0) { + return { hours: prev.hours - 1, minutes: 59, seconds: 59 }; + } + return { hours: 5, minutes: 59, seconds: 59 }; + }); + }, 1000); + return () => clearInterval(timer); + }, []); + + const pad = (n: number) => n.toString().padStart(2, '0'); + + return ( +
+ {/* Background glow meshes */} +
+
+ +
+ {/* Left text */} +
+
+ + {currentBrand.shortName.toUpperCase()} DROPS • OFERTAS FLASH +
+

+ Zapatillas Premium hasta con{' '} + + 35% OFF + +

+

+ Lanzamientos exclusivos directos de bodega. Separa tu par con $10.000 COP y paga el saldo en efectivo o transferencia con Pago Contraentrega en tu casa. +

+
+ + {/* Right Countdown Box */} +
+
+ + Oferta expira en: +
+
+
+ {pad(timeLeft.hours)} + Horas +
+ : +
+ {pad(timeLeft.minutes)} + Min +
+ : +
+ {pad(timeLeft.seconds)} + Seg +
+
+
+ + Cupón: {currentBrand.couponCode} aplicado +
+
+
+
+ ); +}; diff --git a/almeira-store-app/src/components/store/Navbar.tsx b/almeira-store-app/src/components/store/Navbar.tsx new file mode 100644 index 0000000..4412286 --- /dev/null +++ b/almeira-store-app/src/components/store/Navbar.tsx @@ -0,0 +1,153 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { ShoppingBag, Search, MapPin, Zap, Sparkles, ShieldCheck, Store, User as UserIcon } from 'lucide-react'; +import { City } from '@/types'; +import { useBrand } from '@/context/BrandContext'; +import { useAuth } from '@/context/AuthContext'; + +interface NavbarProps { + cartCount: number; + onOpenCart: () => void; + selectedCity: City; + onOpenCitySelector: () => void; + searchQuery: string; + onSearchChange: (q: string) => void; +} + +export const Navbar: React.FC = ({ + cartCount, + onOpenCart, + selectedCity, + onOpenCitySelector, + searchQuery, + onSearchChange, +}) => { + const { currentBrand } = useBrand(); + const { user, openAuthModal } = useAuth(); + + return ( +
+ {/* Top Banner Urgency */} +
+
+
+ + 🔥 ENVÍOS CONTRAENTREGA EN {selectedCity.name.toUpperCase()} Y TODO COLOMBIA +
+
+ + + Separa tu par con solo $10.000 COP + + • + + + {selectedCity.firstExchangeFree + ? `1er Cambio GRATIS en ${selectedCity.name}` + : `Garantía de Cambio (${selectedCity.name})`} + +
+
+
+ + {/* Main Navbar */} +
+ {/* Brand Logo */} + +
+
+ + {currentBrand.logo.iconText} + +
+
+
+
+ {currentBrand.logo.mainText} + + {currentBrand.logo.accentText} + +
+

{currentBrand.tagline}

+
+ + + {/* City Selector Pill */} + + + {/* Search Bar */} +
+
+ onSearchChange(e.target.value)} + className="w-full bg-slate-900/90 text-white placeholder-slate-400 text-xs sm:text-sm rounded-full pl-10 pr-4 py-2 border border-slate-700 focus:border-cyan-400 focus:ring-2 focus:ring-cyan-500/20 transition-all outline-hidden" + /> + +
+
+ + {/* Right Actions */} +
+ {/* User Auth Button */} + + + {/* Admin Link */} + + + Admin + + + {/* Cart Button */} + +
+
+
+ ); +}; + diff --git a/almeira-store-app/src/components/store/ProductCard.tsx b/almeira-store-app/src/components/store/ProductCard.tsx new file mode 100644 index 0000000..9ba227c --- /dev/null +++ b/almeira-store-app/src/components/store/ProductCard.tsx @@ -0,0 +1,132 @@ +'use client'; + +import React from 'react'; +import { Star, Zap, Truck, ShoppingBag } from 'lucide-react'; +import { Product } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductCardProps { + product: Product; + onOpenDetail: (product: Product) => void; + onQuickAdd: (product: Product, size: string) => void; +} + +export const ProductCard: React.FC = ({ + product, + onOpenDetail, +}) => { + const { currentBrand } = useBrand(); + const discountPercent = product.originalPrice + ? Math.round(((product.originalPrice - product.retailPrice) / product.originalPrice) * 100) + : 28; + + const separation = calculateSeparationBreakdown(product.retailPrice); + + return ( +
onOpenDetail(product)} + className={`group rounded-2xl border transition-all duration-300 flex flex-col cursor-pointer overflow-hidden ${currentBrand.colors.cardBg}`} + > + {/* Image Container */} +
+ {product.name} + + {/* Badges */} +
+ + -{discountPercent}% OFF + + {product.isFlashDeal && ( + + FLASH + + )} +
+ +
+ + Contraentrega + + + {product.brand} + +
+
+ + {/* Product Info */} +
+
+ {/* Rating and Sales */} +
+
+ + {product.rating || 4.9} + ({product.reviewsCount || 89}) +
+ + +{product.salesCount || 150} pedidos + +
+ + {/* Product Title */} +

+ {product.name} +

+ + {/* Available Sizes Pills */} +
+ Tallas: + {product.sizes.slice(0, 5).map((size) => ( + + {size} + + ))} + {product.sizes.length > 5 && ( + +{product.sizes.length - 5} + )} +
+
+ + {/* Pricing & Separation terms */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ +

+ ⚡ Separa con {formatCOP(separation.depositAmount)} y cancelas {formatCOP(separation.balanceDue)} al recibir. +

+ + {/* Quick Action Button */} +
+ +
+
+
+
+ ); +}; diff --git a/almeira-store-app/src/components/store/ProductModal.tsx b/almeira-store-app/src/components/store/ProductModal.tsx new file mode 100644 index 0000000..d50aa74 --- /dev/null +++ b/almeira-store-app/src/components/store/ProductModal.tsx @@ -0,0 +1,222 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, Star, Truck, ShieldCheck, Zap, MessageCircle, ShoppingBag, Check } from 'lucide-react'; +import { Product, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductModalProps { + product: Product | null; + onClose: () => void; + onAddToCart: (product: Product, size: string) => void; + selectedCity: City; +} + +export const ProductModal: React.FC = ({ + product, + onClose, + onAddToCart, + selectedCity, +}) => { + const { currentBrand } = useBrand(); + if (!product) return null; + + const [selectedSize, setSelectedSize] = useState(product.sizes[0] || '39'); + const [selectedImage, setSelectedImage] = useState(product.images[0]); + const [added, setAdded] = useState(false); + + const separation = calculateSeparationBreakdown(product.retailPrice); + + const handleAdd = () => { + onAddToCart(product, selectedSize); + setAdded(true); + setTimeout(() => { + setAdded(false); + onClose(); + }, 1200); + }; + + const handleWhatsAppDirect = () => { + const phone = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203'; + const text = `Hola ${currentBrand.name}! Quiero pedir las zapatillas: +👟 *${product.name}* (${product.brand}) +📏 Talla: *${selectedSize}* (Horma Nacional) +💎 Precio: *${formatCOP(product.retailPrice)} COP* +🚚 Entrega en: *${selectedCity.name}* (Pago Contraentrega) +⚡ Deseo separar con $10.000 COP y cancelar el saldo en mi casa. + +¿Me confirman disponibilidad para despacho por favor?`; + window.open(`https://wa.me/${phone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+
+ {/* Close Button */} + + + {/* Left: Images */} +
+
+ {product.name} + + -{Math.round(((product.originalPrice || 170000) - product.retailPrice) / (product.originalPrice || 170000) * 100)}% OFF + +
+ + {/* Thumbnails */} + {product.images.length > 1 && ( +
+ {product.images.map((img, i) => ( + + ))} +
+ )} + + {/* Trust note */} +
+ + + {selectedCity.firstExchangeFree ? ( + <>1er Cambio de Talla GRATIS en {selectedCity.name} • Cambios posteriores: el cliente asume el flete + ) : ( + <>Garantía de Cambio en {selectedCity.name} • El cliente asume los costos de flete + )} + +
+
+ + {/* Right: Product Details & Actions */} +
+
+
+ {product.brand} +

{product.name}

+
+
+ + {product.rating || 4.9} +
+ • + +{product.salesCount || 200} pares entregados +
+
+ + {/* Price Box */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ + {/* Separation breakdown banner */} +
+

+ + ¡Pago Contraentrega en {selectedCity.name}! +

+

+ Separas con solo {formatCOP(separation.depositAmount)} y pagas los {formatCOP(separation.balanceDue)} al recibir en tu puerta. +

+
+
+ + {/* Size Selector */} +
+
+ Selecciona tu Talla (Nacional CO): + Guía de Tallas +
+
+ {product.sizes.map((size) => ( + + ))} +
+
+ + {/* Description */} +
+

{product.description}

+
+ + {/* Shipping note */} +
+ +
+ {selectedCity.name}: + {selectedCity.deliveryTime} ({selectedCity.shippingCost === 0 ? 'Envío Gratis' : formatCOP(selectedCity.shippingCost)}) +
+
+
+ + {/* Action Buttons */} +
+ + + +
+
+
+
+ ); +}; diff --git a/almeira-store-app/src/config/brands.ts b/almeira-store-app/src/config/brands.ts new file mode 100644 index 0000000..fe598a2 --- /dev/null +++ b/almeira-store-app/src/config/brands.ts @@ -0,0 +1,151 @@ +export type BrandId = 'almeira' | 'sneaky' | 'zapply' | 'dripzone'; + +export interface BrandTheme { + id: BrandId; + name: string; + shortName: string; + tagline: string; + badge: string; + couponCode: string; + whatsappNumber: string; + + // Clases y colores de diseño personalizados para cada una de las 4 marcas + colors: { + primaryGradient: string; + secondaryGradient: string; + heroGradient: string; + accentGlow: string; + headerBg: string; + bodyBg: string; + cardBg: string; + border: string; + textAccent: string; + badgeBg: string; + badgeText: string; + cartBadge: string; + }; + + logo: { + iconText: string; + mainText: string; + accentText: string; + }; +} + +export const BRANDS: Record = { + almeira: { + id: 'almeira', + name: 'ALMEIRA STORE', + shortName: 'Almeira', + tagline: 'Sneakers & Moda Urbana', + badge: 'Garantía Certificada', + couponCode: 'ALMEIRA-10K', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-cyan-500 via-blue-600 to-pink-500', + secondaryGradient: 'from-cyan-400 to-blue-500', + heroGradient: 'from-slate-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(6,182,212,0.35)]', + headerBg: 'bg-slate-950/95 border-cyan-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-cyan-500/40', + border: 'border-cyan-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-pink-400 to-pink-500', + badgeBg: 'bg-cyan-500/20 border-cyan-500/30 text-cyan-300', + badgeText: 'text-cyan-300', + cartBadge: 'bg-pink-500 text-white', + }, + logo: { + iconText: 'A', + mainText: 'ALMEIRA', + accentText: 'STORE', + }, + }, + + sneaky: { + id: 'sneaky', + name: 'SNEAKY DROPS', + shortName: 'Sneaky', + tagline: 'Viral Kicks & Flash Deals', + badge: 'Oferta Flash', + couponCode: 'SNEAKY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-red-600 via-orange-500 to-amber-500', + secondaryGradient: 'from-red-500 to-orange-500', + heroGradient: 'from-red-950 via-gray-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(239,68,68,0.35)]', + headerBg: 'bg-gray-950/95 border-orange-500/20', + bodyBg: 'bg-gray-950 text-gray-100', + cardBg: 'bg-gray-900/80 border-gray-800 hover:border-orange-500/40', + border: 'border-orange-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-red-500 via-orange-400 to-amber-400', + badgeBg: 'bg-orange-500/20 border-orange-500/30 text-orange-300', + badgeText: 'text-orange-300', + cartBadge: 'bg-amber-400 text-gray-950', + }, + logo: { + iconText: 'S', + mainText: 'SNEAKY', + accentText: 'DROPS', + }, + }, + + zapply: { + id: 'zapply', + name: 'ZAPPLY CALI', + shortName: 'Zapply', + tagline: 'Zapatillas & Entrega Inmediata', + badge: 'Envío Express 24h', + couponCode: 'ZAPPLY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-emerald-500 via-teal-500 to-cyan-600', + secondaryGradient: 'from-emerald-400 to-teal-500', + heroGradient: 'from-emerald-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-slate-950/95 border-emerald-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-emerald-500/40', + border: 'border-emerald-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-teal-300 to-cyan-400', + badgeBg: 'bg-emerald-500/20 border-emerald-500/30 text-emerald-300', + badgeText: 'text-emerald-300', + cartBadge: 'bg-emerald-400 text-slate-950', + }, + logo: { + iconText: 'Z', + mainText: 'ZAPPLY', + accentText: 'CALI', + }, + }, + + dripzone: { + id: 'dripzone', + name: 'DRIPZONE', + shortName: 'DripZone', + tagline: 'Streetwear & Sneakers Exclusivos', + badge: 'Edición Limitada', + couponCode: 'DRIP-VIP', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-purple-600 via-fuchsia-500 to-pink-600', + secondaryGradient: 'from-purple-500 to-pink-500', + heroGradient: 'from-purple-950 via-neutral-900 to-neutral-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-neutral-950/95 border-purple-500/20', + bodyBg: 'bg-neutral-950 text-neutral-100', + cardBg: 'bg-neutral-900/80 border-neutral-800 hover:border-purple-500/40', + border: 'border-purple-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-fuchsia-400 to-pink-400', + badgeBg: 'bg-purple-500/20 border-purple-500/30 text-purple-300', + badgeText: 'text-purple-300', + cartBadge: 'bg-fuchsia-500 text-white', + }, + logo: { + iconText: 'D', + mainText: 'DRIP', + accentText: 'ZONE', + }, + }, +}; diff --git a/almeira-store-app/src/context/AuthContext.tsx b/almeira-store-app/src/context/AuthContext.tsx new file mode 100644 index 0000000..a279c94 --- /dev/null +++ b/almeira-store-app/src/context/AuthContext.tsx @@ -0,0 +1,100 @@ +'use client'; + +import React, { createContext, useContext, useState, useEffect } from 'react'; +import { User } from '@/types'; + +interface AuthContextType { + user: User | null; + login: (identifier: string) => Promise<{ success: boolean; error?: string }>; + register: (data: { name: string; email: string; phone: string; city?: string; address?: string }) => Promise<{ success: boolean; error?: string }>; + logout: () => void; + isAuthModalOpen: boolean; + openAuthModal: () => void; + closeAuthModal: () => void; +} + +const AuthContext = createContext(undefined); + +export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [user, setUser] = useState(null); + const [isAuthModalOpen, setIsAuthModalOpen] = useState(false); + + useEffect(() => { + const saved = localStorage.getItem('almeira_user'); + if (saved) { + try { + setUser(JSON.parse(saved)); + } catch (e) { } + } + }, []); + + const login = async (identifier: string) => { + try { + const res = await fetch('/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ identifier }), + }); + const data = await res.json(); + if (data.success && data.user) { + setUser(data.user); + localStorage.setItem('almeira_user', JSON.stringify(data.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: data.error || 'Error al iniciar sesión' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const register = async (data: { name: string; email: string; phone: string; city?: string; address?: string }) => { + try { + const res = await fetch('/api/auth/register', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }); + const resData = await res.json(); + if (resData.success && resData.user) { + setUser(resData.user); + localStorage.setItem('almeira_user', JSON.stringify(resData.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: resData.error || 'Error al registrarse' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const logout = () => { + setUser(null); + localStorage.removeItem('almeira_user'); + }; + + const openAuthModal = () => setIsAuthModalOpen(true); + const closeAuthModal = () => setIsAuthModalOpen(false); + + return ( + + {children} + + ); +}; + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) throw new Error('useAuth must be used within an AuthProvider'); + return context; +}; diff --git a/almeira-store-app/src/context/BrandContext.tsx b/almeira-store-app/src/context/BrandContext.tsx new file mode 100644 index 0000000..e0b9e92 --- /dev/null +++ b/almeira-store-app/src/context/BrandContext.tsx @@ -0,0 +1,22 @@ +'use client'; + +import React, { createContext, useContext } from 'react'; +import { BrandTheme, BRANDS } from '@/config/brands'; + +interface BrandContextType { + currentBrand: BrandTheme; +} + +const BrandContext = createContext({ + currentBrand: BRANDS.almeira, +}); + +export const BrandProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return ( + + {children} + + ); +}; + +export const useBrand = () => useContext(BrandContext); diff --git a/almeira-store-app/src/lib/appwrite.ts b/almeira-store-app/src/lib/appwrite.ts new file mode 100644 index 0000000..2cd0209 --- /dev/null +++ b/almeira-store-app/src/lib/appwrite.ts @@ -0,0 +1,25 @@ +import { Client, Databases, Storage, Account } from 'appwrite'; + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + +export const client = new Client(); +client.setEndpoint(endpoint).setProject(projectId); + +export const databases = new Databases(client); +export const storage = new Storage(client); +export const account = new Account(client); + +// Base de datos y Bucket 100% aislados e independientes +export const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +export const BUCKET_ID = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +// Colecciones independientes +export const COLLECTIONS = { + PRODUCTS: 'products', + CITIES: 'cities', + PAYMENT_METHODS: 'payment_methods', + ORDERS: 'orders', + SETTINGS: 'settings', + SUPPLIER_POSTS: 'supplier_posts', +}; diff --git a/almeira-store-app/src/lib/data-service.ts b/almeira-store-app/src/lib/data-service.ts new file mode 100644 index 0000000..a594e18 --- /dev/null +++ b/almeira-store-app/src/lib/data-service.ts @@ -0,0 +1,2371 @@ +import { Product, City, PaymentMethod, Order, SupplierPost, StoreSettings, Supplier, MonitoredWhatsAppGroup, User } from '@/types'; + +// Directorio Interno de Proveedores de Zapatillas +export const INITIAL_SUPPLIERS: Supplier[] = [ + { + "id": "sup-jovic", + "name": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "phone": "573167455877", + "contactPerson": "Asesor Jovic Store", + "address": "Centro / Bodega Cali", + "notes": "Proveedor oficial Nike, Jordan, Nocta y Vomero calidades Top.", + "isActive": true + }, + { + "id": "sup-ccmio", + "name": "EXCLUSIVE CC MÍO 3B", + "phone": "573159876543", + "contactPerson": "Despachos CC MÍO 3B", + "address": "CC MÍO Local 3B, Cali", + "notes": "Especialista en Adidas, Coach, Timberland y Skatewear.", + "isActive": true + }, + { + "id": "sup-central", + "name": "BODEGA CENTRAL MAYORISTA", + "phone": "573101234567", + "contactPerson": "Logística Despachos", + "address": "San Andresito / Cali", + "notes": "Despacho rápido en 24 horas para separación inmediata.", + "isActive": true + } +]; + +// Ciudades configurables (con entrega en 24 horas y política por ciudad) +export const INITIAL_CITIES: City[] = [ + { + id: 'city-cali', + name: 'Cali', + department: 'Valle del Cauca', + shippingCost: 0, + deliveryTime: 'Entrega en 24 Horas (Domicilio Local)', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Cali (posteriores con flete estándar)', + }, + { + id: 'city-jamundi', + name: 'Jamundí', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Jamundí (posteriores con flete estándar)', + }, + { + id: 'city-palmira', + name: 'Palmira', + department: 'Valle del Cauca', + shippingCost: 7000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Palmira (posteriores con flete estándar)', + }, + { + id: 'city-yumbo', + name: 'Yumbo', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Yumbo (posteriores con flete estándar)', + }, + { + id: 'city-bogota', + name: 'Bogotá D.C.', + department: 'Cundinamarca', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-medellin', + name: 'Medellín', + department: 'Antioquia', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-barranquilla', + name: 'Barranquilla', + department: 'Atlántico', + shippingCost: 14000, + deliveryTime: '3 a 4 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-nacional', + name: 'Otras Ciudades / Resto del País', + department: 'Colombia', + shippingCost: 15000, + deliveryTime: '2 a 5 días hábiles', + allowsContraentrega: false, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete nacional asumido por el cliente)', + }, +]; + +// Métodos de Pago configurables por el Admin +export const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [ + { + id: 'pay-bold-link', + name: 'Bold.co • PSE, Tarjetas Débito/Crédito, Nequi o QR (Oficial)', + type: 'bold', + description: 'Paga de forma rápida y 100% segura con tu cuenta Bold. Acepta PSE, Tarjetas Visa/Mastercard y QR de cualquier banco.', + requiresDeposit: false, + depositAmount: 0, + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + accountInfo: 'Pasarela Oficial Bold.co • PSE / Tarjetas / QR', + isActive: true, + }, + { + id: 'pay-deposit-10k', + name: 'Separación con $10.000 + Saldo Contraentrega', + type: 'contraentrega', + description: 'Asegura tu talla con solo $10.000 COP vía Bold/Nequi/Daviplata y cancelas el saldo restante en efectivo o transferencia cuando el mensajero llegue a tu casa.', + requiresDeposit: true, + depositAmount: 10000, + accountInfo: 'Nequi / Daviplata Oficial: 316 745 5877 (Carlos Andrés Lasso)', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + isActive: true, + }, + { + id: 'pay-cod-full', + name: 'Pago 100% Contraentrega (Cali y Alrededores)', + type: 'contraentrega', + description: 'Pagas el 100% del valor total al recibir en tu puerta (válido para entregas urbanas en 24 horas).', + requiresDeposit: false, + depositAmount: 0, + isActive: true, + }, + { + id: 'pay-nequi-full', + name: 'Transferencia Total Anticipada Nequi / Daviplata', + type: 'nequi', + description: 'Paga el 100% anticipado y recibe prioridad de despacho express en 24 horas.', + requiresDeposit: false, + depositAmount: 0, + accountInfo: 'Nequi / Daviplata: 316 745 5877 (Carlos Andrés Lasso)', + isActive: true, + }, +]; + +// Catálogo Inicial de Sneakers con datos internos del proveedor +export const INITIAL_PRODUCTS: Product[] = [ + { + "id": "snk-real-1", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 36, + "salesCount": 183, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-2", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 73, + "salesCount": 225, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-3", + "name": "Nike Coach Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 78, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-4", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 44, + "salesCount": 239, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-5", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 242, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-6", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-7", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 81, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-8", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 96, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-9", + "name": "Louis Vuitton Calvin Klein Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 56, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-10", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 52, + "salesCount": 243, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-11", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 92, + "salesCount": 58, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-12", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 65, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-13", + "name": "Nike Michael Kors Dama \udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 70, + "salesCount": 230, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-14", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 146, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-15", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 103, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-16", + "name": "Nike Clemont Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 74, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-17", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 176, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-18", + "name": "Louis Vuitton Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 196, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-19", + "name": "Nike \udf1fbapesta\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 41, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-20", + "name": "Timberland Nueva Mercancía", + "brand": "Timberland", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1520639888713-7851133b1ed0?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 121, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-21", + "name": "\udf1fnike Internacional\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 29, + "salesCount": 112, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-22", + "name": "Nike \udecdalexander Mcqueen\udecd", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 97, + "salesCount": 90, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-23", + "name": "\udf1fnike Af1 Bape\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-24", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "36", + "37", + "38", + "39", + "40" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 21, + "salesCount": 126, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-25", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 82, + "salesCount": 154, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-26", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 241, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-27", + "name": "Karl Lagerfeld Caballero \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 60, + "salesCount": 215, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-28", + "name": "Nike Streetwear Sneaker", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 53, + "salesCount": 114, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-29", + "name": "Nike 7 Camaras Hombre", + "brand": "Nike", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 229, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-30", + "name": "Nike Retro 1 Dama,37 Y 40", + "brand": "Nike", + "supplierPrice": 105000, + "retailPrice": 145000, + "originalPrice": 200000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 67, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-31", + "name": "Nike Vomero Hombre", + "brand": "Nike", + "supplierPrice": 110000, + "retailPrice": 150000, + "originalPrice": 205000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 78, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-32", + "name": "Nike Lebron Dama Y 45", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 113, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-33", + "name": "Nike Kyrie Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 208, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-34", + "name": "Nike Gt Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 54, + "salesCount": 243, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-35", + "name": "Adidas Hombre ,43,44 Y 45", + "brand": "Adidas", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 109, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-36", + "name": "Adidas Courtic Hombre", + "brand": "Adidas", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 91, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-37", + "name": "Nike Total 90 Dama,42,43,44 Y 45", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 94, + "salesCount": 166, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-38", + "name": "Nike Total 90 Hombre", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44", + "45" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 35, + "salesCount": 74, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-39", + "name": "Nike Nocta Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 81, + "salesCount": 139, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-40", + "name": "Nike Total 90 Hombre ,43 Y 44", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 86, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-41", + "name": "Nike Tn Hombre", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 50, + "salesCount": 152, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-42", + "name": "Nike Kyrie Dama Y Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 153, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-43", + "name": "Nike Easyon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 90, + "salesCount": 115, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-44", + "name": "Nike Fast Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 199, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-45", + "name": "Nike Af1 Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 62, + "salesCount": 245, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-46", + "name": "Adidas Forum Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-47", + "name": "Nike Sb Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 74, + "salesCount": 213, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-48", + "name": "Tommy Hilfiger Caballero", + "brand": "Tommy Hilfiger", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 117, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-49", + "name": "Louis Vuitton Skate Dama", + "brand": "Louis Vuitton", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 242, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-50", + "name": "Adidas Yeezy Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 170, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-51", + "name": "Nike Metcon Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 76, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-52", + "name": "Nike Metcon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 189, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-53", + "name": "New Balance Caballero", + "brand": "New Balance", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1539185441755-769473a23570?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 79, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-54", + "name": "Nike Air Max Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 84, + "salesCount": 121, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-55", + "name": "Nike Zoom Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 31, + "salesCount": 200, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-56", + "name": "Nike Skate Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 98, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-57", + "name": "Reebok Caballero", + "brand": "Reebok", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 93, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-58", + "name": "Dior Caballero", + "brand": "Dior", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 201, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-59", + "name": "Jordan Retro 1 Bota Dama", + "brand": "Jordan", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1552346154-21d32810aba3?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 63, + "salesCount": 177, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-60", + "name": "Diesel Caballero", + "brand": "Diesel", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 133, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + } +]; + +// Feed inicial de publicaciones de WhatsApp recibidas +export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [ + { + id: 'post-1', + channelName: 'DIFUSION JOVIC STORE', + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + rawMessage: `🔥 DISPONIBLE HOY 🔥\nNike Air Force 1 All White\nTallas: 37 al 43\nMayorista: $90.000 c/u\nDespacho inmediato Cali`, + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Nike Air Force 1 Low 07 White Triple', + brand: 'Nike', + sizes: ['37', '38', '39', '40', '41', '42', '43'], + supplierPrice: 90000, + suggestedRetailPrice: 125000, + category: 'Sneakers / Urbano', + confidence: 0.96, + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + }, + status: 'published_store', + receivedAt: 'Hoy, 09:15 AM', + }, + { + id: 'post-2', + channelName: 'EXCLUSIVE CC MIO 3B', + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + rawMessage: `👟 JORDAN 4 MILITARY BLACK 👟\nFull calidad AAA, caja original\nTallas 38 a 43\nPrecio: $95.000\nDomicilio pago contraentrega`, + rawImages: [ + 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Air Jordan 4 Retro Military Black', + brand: 'Jordan', + sizes: ['38', '39', '40', '41', '42', '43'], + supplierPrice: 95000, + suggestedRetailPrice: 130000, + category: 'Sneakers / Colección', + confidence: 0.94, + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + }, + status: 'published_store', + receivedAt: 'Hoy, 10:40 AM', + }, +]; + +// Memoria centralizada de la aplicación + +export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ + { + id: 'grp-jovic', + jid: '120363049363072784@g.us', + name: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + isMonitored: true, + supplierId: 'sup-jovic', + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 450, + notes: 'Proveedor oficial Nike, Jordan, Vomero, Nocta y AF1.', + }, + { + id: 'grp-ccmio', + jid: '120363024823901923@g.us', + name: 'EXCLUSIVE CC MÍO 3B', + isMonitored: true, + supplierId: 'sup-ccmio', + supplierName: 'EXCLUSIVE CC MÍO 3B', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 380, + notes: 'Proveedor oficial Adidas, Coach, Timberland y Skatewear.', + }, +]; + +class DataService { + private products: Product[] = [...INITIAL_PRODUCTS]; + private cities: City[] = [...INITIAL_CITIES]; + private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; + private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; + private orders: Order[] = []; + private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; + + // Productos + getProducts(): Product[] { + return this.products; + } + + getProductById(id: string): Product | undefined { + return this.products.find((p) => p.id === id); + } + + addProduct(product: Product): Product { + this.products.unshift(product); + return product; + } + + updateProduct(id: string, updates: Partial): Product | null { + const idx = this.products.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.products[idx] = { ...this.products[idx], ...updates }; + return this.products[idx]; + } + + deleteProduct(id: string): boolean { + const initialLen = this.products.length; + this.products = this.products.filter((p) => p.id !== id); + return this.products.length < initialLen; + } + + // Proveedores + getSuppliers(): Supplier[] { + return this.suppliers; + } + + getSupplierById(id: string): Supplier | undefined { + return this.suppliers.find((s) => s.id === id); + } + + addSupplier(supplier: Supplier): Supplier { + this.suppliers.push(supplier); + return supplier; + } + + // Ciudades + getCities(): City[] { + return this.cities; + } + + getCityById(id: string): City | undefined { + return this.cities.find((c) => c.id === id); + } + + addCity(city: City): City { + this.cities.push(city); + return city; + } + + updateCity(id: string, updates: Partial): City | null { + const idx = this.cities.findIndex((c) => c.id === id); + if (idx === -1) return null; + this.cities[idx] = { ...this.cities[idx], ...updates }; + return this.cities[idx]; + } + + // Métodos de Pago + getPaymentMethods(): PaymentMethod[] { + return this.paymentMethods; + } + + updatePaymentMethod(id: string, updates: Partial): PaymentMethod | null { + const idx = this.paymentMethods.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.paymentMethods[idx] = { ...this.paymentMethods[idx], ...updates }; + return this.paymentMethods[idx]; + } + + // Pedidos + getOrders(): Order[] { + return this.orders; + } + + addOrder(order: Order): Order { + this.orders.unshift(order); + return order; + } + + updateOrderStatus(orderId: string, status: Order['status']): Order | null { + const order = this.orders.find((o) => o.id === orderId); + if (!order) return null; + order.status = status; + return order; + } + + // Configuración de la Tienda + private settings: StoreSettings = { + storeName: 'Almeira Store', + slogan: 'Sneakers & Moda Urbana', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@almeirastore.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }; + + getSettings(): StoreSettings { + return this.settings; + } + + updateSettings(updates: Partial): StoreSettings { + this.settings = { ...this.settings, ...updates }; + return this.settings; + } + + // Control de Usuarios + private users: User[] = [ + { + id: 'usr-admin-1', + name: 'Carlos Andrés Lasso', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + city: 'Cali', + address: 'Centro / Bodega Principal', + role: 'admin', + isActive: true, + createdAt: '2026-01-10', + totalOrders: 0, + lastLogin: 'Hoy, 08:15 PM', + }, + { + id: 'usr-operator-1', + name: 'Andrés Operador Despachos', + email: 'despachos@almeira.com.co', + phone: '3159876543', + city: 'Cali', + role: 'operator', + isActive: true, + createdAt: '2026-02-01', + totalOrders: 0, + lastLogin: 'Hoy, 05:30 PM', + }, + { + id: 'usr-cust-1', + name: 'Mateo Gómez (Cliente VIP)', + email: 'mateo.sneakers@gmail.com', + phone: '3112345678', + city: 'Cali', + address: 'Calle 5 # 34-12 Apto 402', + role: 'customer', + isActive: true, + createdAt: '2026-02-15', + totalOrders: 3, + lastLogin: 'Ayer, 08:20 PM', + }, + ]; + + getUsers(): User[] { + return this.users; + } + + addUser(user: User): User { + this.users.unshift(user); + return user; + } + + updateUser(id: string, updates: Partial): User | null { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return null; + this.users[idx] = { ...this.users[idx], ...updates }; + return this.users[idx]; + } + + deleteUser(id: string): boolean { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return false; + this.users.splice(idx, 1); + return true; + } + + authenticate(emailOrPhone: string): User | null { + const q = emailOrPhone.trim().toLowerCase(); + const user = this.users.find( + (u) => u.email.toLowerCase() === q || u.phone === q || u.phone.includes(q) + ); + return user || null; + } + + private monitoredGroups: MonitoredWhatsAppGroup[] = [...INITIAL_MONITORED_GROUPS]; + + getMonitoredGroups(): MonitoredWhatsAppGroup[] { + return this.monitoredGroups; + } + + saveMonitoredGroups(groups: MonitoredWhatsAppGroup[]): MonitoredWhatsAppGroup[] { + this.monitoredGroups = groups; + return this.monitoredGroups; + } + + toggleGroupMonitoring(idOrJid: string, isMonitored: boolean): MonitoredWhatsAppGroup | null { + const grp = this.monitoredGroups.find((g) => g.id === idOrJid || g.jid === idOrJid); + if (grp) { + grp.isMonitored = isMonitored; + return grp; + } + return null; + } + +} + +export const dataService = new DataService(); diff --git a/almeira-store-app/src/lib/deduplication-engine.ts b/almeira-store-app/src/lib/deduplication-engine.ts new file mode 100644 index 0000000..3023854 --- /dev/null +++ b/almeira-store-app/src/lib/deduplication-engine.ts @@ -0,0 +1,105 @@ +import { Product } from '@/types'; + +/** + * Normaliza un string para comparación (minúsculas, sin acentos, sin caracteres especiales) + */ +export function normalizeText(text: string): string { + if (!text) return ''; + return text + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/[^a-z0-9\s]/g, ' ') + .replace(/\s+/g, ' ') + .trim(); +} + +/** + * Calcula la similitud de Jaccard / Coeficiente de Dados entre dos textos + * Devuelve un valor entre 0 (totalmente diferente) y 1.0 (idéntico) + */ +export function calculateTextSimilarity(textA: string, textB: string): number { + const normA = normalizeText(textA); + const normB = normalizeText(textB); + + if (!normA || !normB) return 0; + if (normA === normB) return 1.0; + + // Si uno contiene al otro por completo + if (normA.includes(normB) || normB.includes(normA)) { + const ratio = Math.min(normA.length, normB.length) / Math.max(normA.length, normB.length); + if (ratio > 0.7) return 0.92; + } + + const tokensA = new Set(normA.split(' ').filter((w) => w.length > 2)); + const tokensB = new Set(normB.split(' ').filter((w) => w.length > 2)); + + if (tokensA.size === 0 || tokensB.size === 0) return 0; + + const intersection = new Set([...tokensA].filter((t) => tokensB.has(t))); + const union = new Set([...tokensA, ...tokensB]); + + return intersection.size / union.size; +} + +export interface DuplicateCheckResult { + isDuplicate: boolean; + similarityScore: number; + existingProduct?: Product; + recommendation: 'create_new' | 'update_stock_and_sizes' | 'skip_duplicate'; + message: string; +} + +/** + * Verifica si un producto entrante ya existe en el catálogo para evitar duplicados + */ +export function checkProductDuplicate( + incoming: { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + }, + existingCatalog: Product[], + threshold = 0.75 +): DuplicateCheckResult { + let highestScore = 0; + let bestMatch: Product | undefined; + + for (const product of existingCatalog) { + // 1. Si la marca no coincide, penalizar + const brandMatch = normalizeText(incoming.brand) === normalizeText(product.brand); + const score = calculateTextSimilarity(incoming.name, product.name); + const finalScore = brandMatch ? score : score * 0.5; + + if (finalScore > highestScore) { + highestScore = finalScore; + bestMatch = product; + } + } + + // Si la similitud supera el umbral (75%) + if (highestScore >= threshold && bestMatch) { + // Verificar si aporta nuevas tallas + const incomingSizesSet = new Set(incoming.sizes); + const existingSizesSet = new Set(bestMatch.sizes); + const hasNewSizes = incoming.sizes.some((s) => !existingSizesSet.has(s)); + + return { + isDuplicate: true, + similarityScore: Math.round(highestScore * 100) / 100, + existingProduct: bestMatch, + recommendation: hasNewSizes ? 'update_stock_and_sizes' : 'skip_duplicate', + message: hasNewSizes + ? `Producto ya registrado ("${bestMatch.name}"). Se detectaron nuevas tallas para actualizar.` + : `Producto ya registrado ("${bestMatch.name}") con similitud del ${Math.round(highestScore * 100)}%. Se previene duplicación en la tienda y Facebook.`, + }; + } + + return { + isDuplicate: false, + similarityScore: Math.round(highestScore * 100) / 100, + recommendation: 'create_new', + message: 'Producto nuevo verificado sin duplicados. Listo para publicar.', + }; +} diff --git a/almeira-store-app/src/lib/evolution-api.ts b/almeira-store-app/src/lib/evolution-api.ts new file mode 100644 index 0000000..bd654f0 --- /dev/null +++ b/almeira-store-app/src/lib/evolution-api.ts @@ -0,0 +1,105 @@ +import axios from 'axios'; +import { formatCOP } from './pricing-engine'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +/** + * Enviar mensaje de texto por WhatsApp a través de Evolution API + */ +export async function sendWhatsAppMessage(toPhone: string, message: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendText/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1200, + presence: 'composing', + }, + textMessage: { + text: message, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando mensaje de WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Enviar mensaje con foto/catálogo a través de Evolution API + */ +export async function sendWhatsAppMedia(toPhone: string, imageUrl: string, caption: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendMedia/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1500, + presence: 'composing', + }, + mediaMessage: { + mediatype: 'image', + caption, + media: imageUrl, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando media por WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Genera el mensaje de confirmación de pedido para el cliente y el administrador + */ +export function buildOrderConfirmationMessage(order: any): string { + const itemsText = order.items + .map((item: any) => `👟 *${item.productName}*\n 📏 Talla: *${item.size}* | Cantidad: ${item.quantity} | Valor: ${formatCOP(item.price)}`) + .join('\n\n'); + + return `🎉 *¡GRACIAS POR TU PEDIDO EN SNEAKERS CALI!* 🎉 +📌 *No. de Orden:* #${order.id} + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *DETALLE DE TU COMPRA:* +${itemsText} + +💵 *Subtotal:* ${formatCOP(order.subtotal)} +🚚 *Envío:* ${order.shippingCost === 0 ? 'GRATIS' : formatCOP(order.shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación / Anticipo:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo a Pagar Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega al recibir en tu casa.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +Estamos alistando tu paquete. Te enviaremos el número de guía o notificación de entrega. ¡Muchas gracias por tu confianza! ✨`; +} diff --git a/almeira-store-app/src/lib/facebook-publisher.ts b/almeira-store-app/src/lib/facebook-publisher.ts new file mode 100644 index 0000000..1e55ec7 --- /dev/null +++ b/almeira-store-app/src/lib/facebook-publisher.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; +import { generateSalesCopy } from './pricing-engine'; + +export interface PublishToFacebookParams { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + images: string[]; + cityName?: string; + whatsappNumber?: string; + pageId?: string; + accessToken?: string; +} + +export interface PublishResult { + success: boolean; + postId?: string; + postUrl?: string; + generatedCopy: string; + error?: string; +} + +/** + * Publicador automático en Páginas de Facebook mediante Meta Graph API + */ +export async function publishToFacebookPage(params: PublishToFacebookParams): Promise { + const { + productName, + brand, + retailPrice, + sizes, + images, + cityName = 'Cali', + whatsappNumber = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203', + pageId = process.env.FACEBOOK_PAGE_ID, + accessToken = process.env.FACEBOOK_ACCESS_TOKEN, + } = params; + + const copy = generateSalesCopy({ + productName, + brand, + retailPrice, + sizes, + cityName, + whatsappNumber, + }); + + // Si no hay token de Facebook configurado, simular publicación exitosa para pruebas + if (!pageId || !accessToken) { + const mockPostId = `fb_${Date.now()}_${Math.floor(Math.random() * 10000)}`; + return { + success: true, + postId: mockPostId, + postUrl: `https://facebook.com/${mockPostId}`, + generatedCopy: copy, + }; + } + + try { + // Si tiene una imagen principal, publicamos como photo post con caption + const primaryImage = images[0]; + const fbEndpoint = `https://graph.facebook.com/v19.0/${pageId}/photos`; + + const response = await axios.post(fbEndpoint, { + url: primaryImage, + caption: copy, + access_token: accessToken, + }); + + return { + success: true, + postId: response.data.id || response.data.post_id, + postUrl: `https://facebook.com/${response.data.id}`, + generatedCopy: copy, + }; + } catch (error: any) { + console.error('Error publicando en Facebook Graph API:', error?.response?.data || error?.message); + return { + success: false, + error: error?.response?.data?.error?.message || error.message, + generatedCopy: copy, + }; + } +} diff --git a/almeira-store-app/src/lib/gemini-parser.ts b/almeira-store-app/src/lib/gemini-parser.ts new file mode 100644 index 0000000..cd0fdc5 --- /dev/null +++ b/almeira-store-app/src/lib/gemini-parser.ts @@ -0,0 +1,122 @@ +import { GoogleGenAI } from '@google/genai'; +import { calculateRetailPrice } from './pricing-engine'; + +const apiKey = process.env.GEMINI_API_KEY || ''; + +/** + * Parser inteligente de mensajes de grupos mayoristas de WhatsApp + */ +export async function parseSupplierMessage(text: string, imageUrl?: string): Promise<{ + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + suggestedRetailPrice: number; + category: string; + confidence: number; +}> { + // Regex fallback si no hay API key configurada o falla la red + const fallbackExtract = () => { + // Buscar precio (ej: 90000, 90.000, 90mil, 95k) + let price = 90000; + const priceMatch = text.match(/(?:\$|precio|mayorista|mayor|c\/u|\b)(\d{2,3})[.,]?(\d{3})?|\b(\d{2,3})\s*(?:mil|k)\b/i); + if (priceMatch) { + if (priceMatch[3]) { + price = parseInt(priceMatch[3], 10) * 1000; + } else if (priceMatch[1] && priceMatch[2]) { + price = parseInt(priceMatch[1] + priceMatch[2], 10); + } else if (priceMatch[1] && parseInt(priceMatch[1], 10) >= 40 && parseInt(priceMatch[1], 10) <= 250) { + price = parseInt(priceMatch[1], 10) * 1000; + } + } + + // Detectar tallas (ej: 37 a 43, 38-42, 36,37,38) + const sizes: string[] = []; + const sizeRangeMatch = text.match(/(\d{2})\s*(?:a|al|-)\s*(\d{2})/i); + if (sizeRangeMatch) { + const start = parseInt(sizeRangeMatch[1], 10); + const end = parseInt(sizeRangeMatch[2], 10); + if (start >= 34 && end <= 46 && start <= end) { + for (let s = start; s <= end; s++) sizes.push(s.toString()); + } + } else { + const individualSizes = text.match(/\b(3[4-9]|4[0-6])\b/g); + if (individualSizes) { + sizes.push(...Array.from(new Set(individualSizes))); + } + } + if (sizes.length === 0) { + sizes.push('37', '38', '39', '40', '41', '42', '43'); + } + + // Detectar Marca + let brand = 'Nike'; + if (/jordan/i.test(text)) brand = 'Jordan'; + else if (/adidas|bad bunny|campus|forum/i.test(text)) brand = 'Adidas'; + else if (/new balance|nb/i.test(text)) brand = 'New Balance'; + else if (/puma/i.test(text)) brand = 'Puma'; + else if (/asics/i.test(text)) brand = 'Asics'; + else if (/vans/i.test(text)) brand = 'Vans'; + + const cleanLines = text.split('\n').filter((l) => l.trim().length > 0 && !/🔥|🔴|llegando|promo/i.test(l)); + const name = cleanLines[0] || `${brand} Sneakers Urban Edition`; + + return { + name: name.replace(/tallas?:.*|precio:.*|\$/gi, '').trim() || `${brand} Zapatillas`, + brand, + sizes, + supplierPrice: price, + suggestedRetailPrice: calculateRetailPrice(price, 35, 30000), + category: 'Calzado / Sneakers', + confidence: 0.85, + }; + }; + + if (!apiKey) { + return fallbackExtract(); + } + + try { + const ai = new GoogleGenAI({ apiKey }); + const prompt = `Eres un asistente experto en e-commerce y calzado deportivo en Colombia. +Analiza el siguiente mensaje extraído de un grupo mayorista de WhatsApp ("DIFUSION JOVIC STORE" o "EXCLUSIVE CC MIO 3B"). +Extrae los siguientes campos en formato JSON estricto: +- "name": Nombre comercial limpio del modelo (ej: "Nike Dunk Low Retro Panda", "Air Jordan 4 Military Black"). +- "brand": Marca ("Nike", "Jordan", "Adidas", "New Balance", "Puma", "Asics", etc.). +- "sizes": Array de tallas en horma colombiana/europea (ej: ["38", "39", "40", "41", "42", "43"]). Si dice "38 al 43", expande todas las tallas intermedias. +- "supplierPrice": Precio de compra mayorista como número entero en COP (ej: 90000, 95000). Si dice "90mil" o "90", es 90000. +- "category": Categoría ("Sneakers / Colección", "Urbano / Casual", "Running / Deportivo", etc.). + +Mensaje del grupo: +""" +${text} +""" + +Responde ÚNICAMENTE con el objeto JSON sin bloques de código markdown ni texto adicional.`; + + const response = await ai.models.generateContent({ + model: 'gemini-2.5-flash', + contents: prompt, + }); + + const outputText = response.text || ''; + const cleanJson = outputText.replace(/```json|```/gi, '').trim(); + const parsed = JSON.parse(cleanJson); + + const supplierPrice = typeof parsed.supplierPrice === 'number' ? parsed.supplierPrice : 90000; + const sizes = Array.isArray(parsed.sizes) && parsed.sizes.length > 0 ? parsed.sizes.map(String) : ['37', '38', '39', '40', '41', '42', '43']; + + return { + name: parsed.name || 'Zapatilla Urbana', + brand: parsed.brand || 'Nike', + sizes, + supplierPrice, + suggestedRetailPrice: calculateRetailPrice(supplierPrice, 35, 30000), + category: parsed.category || 'Sneakers', + confidence: 0.98, + }; + } catch (err) { + console.warn('Fallo llamada Gemini, utilizando extractor regex fallback:', err); + return fallbackExtract(); + } +} diff --git a/almeira-store-app/src/lib/pricing-engine.ts b/almeira-store-app/src/lib/pricing-engine.ts new file mode 100644 index 0000000..9af445b --- /dev/null +++ b/almeira-store-app/src/lib/pricing-engine.ts @@ -0,0 +1,137 @@ +/** + * Motor de Precios, Políticas de Cambio y Redondeo Automático al 5.000 Siguiente + */ + +export const DEFAULT_MIN_PROFIT_MARGIN_PERCENT = 35; // % Mínimo de ganancia +export const DEFAULT_MIN_PROFIT_COP = 30000; // Margen mínimo en pesos +export const DEFAULT_SEPARATION_DEPOSIT_COP = 10000; // Separación fija +export const ROUND_STEP_COP = 5000; // Redondeo siempre al múltiplo de $5.000 superior + +export const EXCHANGE_POLICY = { + firstExchangeFree: true, + badgeText: '1er Cambio de Talla GRATIS', + shortNotice: 'Primer cambio de talla gratis. Cambios posteriores con flete estándar.', + fullTerms: 'Cuentas con 1er cambio de talla 100% GRATIS dentro de los primeros 5 días. Para cambios adicionales o posteriores, el cliente asume el costo logístico del flete.', +}; + +export function formatCOP(amount: number): string { + if (isNaN(amount)) return '$0'; + return '$' + Math.round(amount).toLocaleString('es-CO'); +} + +/** + * Redondea cualquier valor hacia arriba al siguiente múltiplo de $5.000 COP + * Ejemplos: + * 132.000 -> 135.000 + * 121.500 -> 125.000 + * 130.000 -> 130.000 + * 130.001 -> 135.000 + */ +export function roundUpToNearest5000(amount: number): number { + if (!amount || amount <= 0) return 0; + return Math.ceil(amount / ROUND_STEP_COP) * ROUND_STEP_COP; +} + +/** + * Calcula el precio de venta sugerido asegurando el % mínimo de ganancia + * y redondeando al $5.000 superior para proteger el margen. + */ +export function calculateRetailPrice( + supplierPrice: number, + minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT, + minMarginCop: number = DEFAULT_MIN_PROFIT_COP +): number { + if (!supplierPrice || supplierPrice <= 0) return 0; + + // 1. Ganancia calculada por porcentaje + const priceByPercent = supplierPrice * (1 + minMarginPercent / 100); + + // 2. Ganancia calculada por monto fijo mínimo (para calzado de costo bajo) + const priceByFixed = supplierPrice + minMarginCop; + + // 3. Tomamos el precio más seguro para nunca perforar el margen mínimo + const baseTargetPrice = Math.max(priceByPercent, priceByFixed); + + // 4. Redondeo automático al 5.000 siguiente + return roundUpToNearest5000(baseTargetPrice); +} + +/** + * Obtiene el desglose financiero exacto de la publicación + */ +export function getPricingBreakdown(supplierCost: number, minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT) { + const retailPrice = calculateRetailPrice(supplierCost, minMarginPercent); + const grossProfit = retailPrice - supplierCost; + const realMarginPercent = Math.round((grossProfit / supplierCost) * 100); + + return { + supplierCost, + retailPrice, + grossProfit, + realMarginPercent, + isCeiledTo5k: true, + }; +} + +export function calculateAnchorPrice(retailPrice: number, discountPercentage: number = 30): number { + if (!retailPrice || retailPrice <= 0) return 0; + const anchor = retailPrice / (1 - discountPercentage / 100); + return roundUpToNearest5000(anchor); +} + +export function calculateSeparationBreakdown( + totalAmount: number, + depositAmount: number = DEFAULT_SEPARATION_DEPOSIT_COP +) { + const deposit = Math.min(depositAmount, totalAmount); + const balanceDue = Math.max(0, totalAmount - deposit); + + return { + totalAmount, + depositAmount: deposit, + balanceDue, + summaryText: `Separas hoy con ${formatCOP(deposit)} y cancelas ${formatCOP(balanceDue)} al recibir contraentrega en tu puerta.`, + exchangeTerms: EXCHANGE_POLICY.shortNotice, + }; +} + +export function generateSalesCopy(params: { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + storeName?: string; + cityName?: string; + whatsappNumber?: string; +}): string { + const { + productName, + brand, + retailPrice, + sizes, + storeName = 'TIENDA DE CALZADO', + cityName = 'Cali', + whatsappNumber = '573134848203', + } = params; + + const breakdown = calculateSeparationBreakdown(retailPrice); + const sizesFormatted = sizes.join(' - '); + const waLink = `https://wa.me/${whatsappNumber}?text=${encodeURIComponent(`Hola ${storeName}! Quiero pedir las zapatillas ${productName} (${brand}) en talla ___ para entrega contraentrega en ${cityName}.`)}`; + + return `✨ ${storeName.toUpperCase()} • LANZAMIENTO EXCLUSIVO ✨ +👟 ${productName.toUpperCase()} (${brand}) + +📏 Tallas Disponibles: ${sizesFormatted} (Horma Nacional) +💎 PRECIO DE VENTA: ${formatCOP(retailPrice)} COP + +🚚 ¡DOMICILIO EN ${cityName.toUpperCase()} Y ENVÍOS A TODO EL PAÍS! +🤝 PAGO CONTRAENTREGA: Cancelas al recibir el producto en tus manos. +⚡ SEPARA CON SOLO ${formatCOP(breakdown.depositAmount)} COP y cancelas ${formatCOP(breakdown.balanceDue)} al recibir. + +🛡️ POLÍTICA DE GARANTÍA: +✅ Calidad Premium 100% garantizada +✅ ${EXCHANGE_POLICY.badgeText} (posteriores con flete estándar) + +📲 ¡Pídelas antes de que se agote tu talla! +👉 Pedir directo por WhatsApp: ${waLink}`; +} diff --git a/almeira-store-app/src/types/index.ts b/almeira-store-app/src/types/index.ts new file mode 100644 index 0000000..9f8a915 --- /dev/null +++ b/almeira-store-app/src/types/index.ts @@ -0,0 +1,176 @@ +export interface Supplier { + id: string; + name: string; + phone: string; + contactPerson?: string; + address?: string; + notes?: string; + isActive: boolean; +} + +export interface User { + id: string; + name: string; + email: string; + phone: string; + city?: string; + address?: string; + role: 'admin' | 'operator' | 'customer'; + isActive: boolean; + createdAt: string; + totalOrders?: number; + lastLogin?: string; +} + +export interface Product { + id: string; + name: string; + brand: string; + supplierPrice: number; + retailPrice: number; + originalPrice?: number; + sizes: string[]; + images: string[]; + description: string; + category: string; + inStock: boolean; + isActive?: boolean; + isFlashDeal?: boolean; + rating?: number; + reviewsCount?: number; + salesCount?: number; + originBadge?: string; + + supplierId?: string; + supplierName?: string; + supplierPhone?: string; + supplierSku?: string; +} + +export interface City { + id: string; + name: string; + department: string; + shippingCost: number; + deliveryTime: string; + allowsContraentrega: boolean; + allowCod?: boolean; + isActive?: boolean; + firstExchangeFree?: boolean; + exchangePolicyNote?: string; +} + +export interface PaymentMethod { + id: string; + name: string; + code?: string; + type: 'contraentrega' | 'nequi' | 'daviplata' | 'bancolombia' | 'tarjeta' | 'bold'; + description: string; + requiresDeposit: boolean; + depositAmount: number; + accountInfo?: string; + boldPaymentLink?: string; + boldQrUrl?: string; + isActive: boolean; +} + +export interface OrderItem { + productId: string; + productName: string; + brand: string; + size: string; + quantity: number; + price: number; + supplierPrice?: number; + supplierName?: string; + supplierPhone?: string; + image: string; +} + +export interface Order { + id: string; + userId?: string; + customerName: string; + customerPhone: string; + address: string; + cityId: string; + cityName: string; + items: OrderItem[]; + subtotal: number; + shippingCost: number; + totalAmount: number; + depositAmount: number; + balanceDue: number; + paymentMethodId: string; + paymentMethodName: string; + status: 'pending' | 'deposit_received' | 'supplier_notified' | 'dispatched' | 'delivered' | 'cancelled'; + notes?: string; + createdAt: string; +} + +export interface SupplierPost { + id: string; + channelName: string; + supplierName?: string; + supplierPhone?: string; + rawMessage: string; + rawImages: string[]; + extractedProduct?: ExtractedProductData; + status: 'pending_review' | 'published_facebook' | 'published_store' | 'ignored'; + receivedAt: string; +} + +export interface ExtractedProductData { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + suggestedRetailPrice: number; + category: string; + confidence: number; + supplierName?: string; + supplierPhone?: string; +} + +export interface CartItem { + product: Product; + selectedSize: string; + quantity: number; +} + +export interface StoreSettings { + storeName: string; + slogan?: string; + email: string; + phone: string; + whatsappNumber: string; + instagramHandle?: string; + address?: string; + city: string; + nequiAccount?: string; + daviplataAccount?: string; + accountHolder?: string; + boldPaymentLink?: string; + boldApiKey?: string; + boldMerchantId?: string; + boldQrUrl?: string; + boldEnabled?: boolean; + autoPublishSupplierPosts?: boolean; + defaultProfitMargin: number; + defaultDepositAmount: number; + facebookPageId?: string; +} + +export interface MonitoredWhatsAppGroup { + id: string; + jid: string; + name: string; + isMonitored: boolean; + supplierId?: string; + supplierName?: string; + profitMarginOverride?: number; + autoPublish: boolean; + participantsCount?: number; + lastMessageAt?: string; + notes?: string; +} diff --git a/almeira-store-app/tsconfig.json b/almeira-store-app/tsconfig.json new file mode 100644 index 0000000..cf9c65d --- /dev/null +++ b/almeira-store-app/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +} diff --git a/deploy_dripzone_vps.py b/deploy_dripzone_vps.py new file mode 100644 index 0000000..b775552 --- /dev/null +++ b/deploy_dripzone_vps.py @@ -0,0 +1,76 @@ +import paramiko +import tarfile +import os +import sys +import io + +# Force UTF-8 stdout on Windows +if sys.platform == 'win32': + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace') + +HOST = "161.97.93.156" +USER = "carlos" +PASSWORD = "Innova1978+*?" +LOCAL_DIR = r"c:\Users\Carlos\dev\almeira-web\dripzone-app" +ARCHIVE_NAME = r"c:\Users\Carlos\dev\almeira-web\dripzone_deploy.tar.gz" +REMOTE_DIR = "/home/carlos/apps/dripzone-app" +REMOTE_TAR = "/home/carlos/apps/dripzone_deploy.tar.gz" + +def create_tar(): + print("[1/4] Empaquetando dripzone-app para despliegue de produccion...") + with tarfile.open(ARCHIVE_NAME, "w:gz") as tar: + for root, dirs, files in os.walk(LOCAL_DIR): + # Excluir node_modules, .next, android (para mantener paquete ligero) + dirs[:] = [d for d in dirs if d not in ['node_modules', '.next', 'android', '.git']] + for file in files: + full_path = os.path.join(root, file) + rel_path = os.path.relpath(full_path, LOCAL_DIR) + tar.add(full_path, arcname=rel_path) + size_mb = os.path.getsize(ARCHIVE_NAME) / (1024 * 1024) + print(f"[OK] Archivo generado: {ARCHIVE_NAME} ({size_mb:.2f} MB)") + +def deploy(): + create_tar() + print(f"[2/4] Conectando a VPS {HOST} via SSH / SFTP...") + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(hostname=HOST, username=USER, password=PASSWORD, timeout=30) + + sftp = client.open_sftp() + print("[3/4] Subiendo archivo al servidor...") + sftp.put(ARCHIVE_NAME, REMOTE_TAR) + sftp.close() + print("[OK] Archivo subido exitosamente.") + + commands = f""" + mkdir -p {REMOTE_DIR} + tar -xzf {REMOTE_TAR} -C {REMOTE_DIR} + rm {REMOTE_TAR} + cd {REMOTE_DIR} + docker compose -f docker-compose.prod.yml down --remove-orphans || true + docker compose -f docker-compose.prod.yml up -d --build + docker ps | grep dripzone + """ + + print("[4/4] Ejecutando compilacion y levantando contenedor en Produccion...") + stdin, stdout, stderr = client.exec_command(commands) + + while not stdout.channel.exit_status_ready(): + line = stdout.readline() + if line: + print(line.strip()) + + for line in stdout.readlines(): + print(line.strip()) + + err = stderr.read().decode('utf-8', errors='ignore') + if err: + print("[Logs/Avisos]:", err) + + status = stdout.channel.recv_exit_status() + print(f"[EXIT STATUS]: {status}") + client.close() + +if __name__ == "__main__": + deploy() diff --git a/docker-compose-production-multistore.yml b/docker-compose-production-multistore.yml new file mode 100644 index 0000000..b7747ba --- /dev/null +++ b/docker-compose-production-multistore.yml @@ -0,0 +1,102 @@ +version: '3.8' + +services: + dripzone-store: + build: + context: ./dripzone-app + dockerfile: Dockerfile + container_name: dripzone-production + restart: always + environment: + - PORT=3000 + - NODE_ENV=production + - NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 + - NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c + - NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db + - NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + - APPWRITE_API_KEY=standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3 + - EVOLUTION_API_URL=https://evolution.almeira.com.co + - EVOLUTION_API_KEY=EE49029EEB85-4568-8F81-C9FDFC6E2943 + - EVOLUTION_INSTANCE_NAME=AutomataAlmeira + - GEMINI_API_KEY=AIzaSyC7JMkREYxl4qoEUGzd4hzbJ6RFg_YMxx0 + labels: + - "coolify.managed=true" + - "coolify.name=DripZone Luxury Store" + - "coolify.fqdn=https://dripzone.almeira.com.co" + ports: + - "3004:3000" + + sneaky-store: + build: + context: ./sneaky-app + dockerfile: Dockerfile + container_name: sneaky-production + restart: always + environment: + - PORT=3000 + - NODE_ENV=production + - NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 + - NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c + - NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db + - NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + - APPWRITE_API_KEY=standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3 + - EVOLUTION_API_URL=https://evolution.almeira.com.co + - EVOLUTION_API_KEY=EE49029EEB85-4568-8F81-C9FDFC6E2943 + - EVOLUTION_INSTANCE_NAME=AutomataAlmeira + - GEMINI_API_KEY=AIzaSyC7JMkREYxl4qoEUGzd4hzbJ6RFg_YMxx0 + labels: + - "coolify.managed=true" + - "coolify.name=Sneaky Drops Store" + - "coolify.fqdn=https://sneaky.almeira.com.co" + ports: + - "3002:3000" + + zapply-store: + build: + context: ./zapply-app + dockerfile: Dockerfile + container_name: zapply-production + restart: always + environment: + - PORT=3000 + - NODE_ENV=production + - NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 + - NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c + - NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db + - NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + - APPWRITE_API_KEY=standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3 + - EVOLUTION_API_URL=https://evolution.almeira.com.co + - EVOLUTION_API_KEY=EE49029EEB85-4568-8F81-C9FDFC6E2943 + - EVOLUTION_INSTANCE_NAME=AutomataAlmeira + - GEMINI_API_KEY=AIzaSyC7JMkREYxl4qoEUGzd4hzbJ6RFg_YMxx0 + labels: + - "coolify.managed=true" + - "coolify.name=Zapply Cali Quick Delivery" + - "coolify.fqdn=https://zapply.almeira.com.co" + ports: + - "3003:3000" + + almeira-store: + build: + context: ./almeira-store-app + dockerfile: Dockerfile + container_name: almeira-store-production + restart: always + environment: + - PORT=3000 + - NODE_ENV=production + - NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 + - NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c + - NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db + - NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + - APPWRITE_API_KEY=standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3 + - EVOLUTION_API_URL=https://evolution.almeira.com.co + - EVOLUTION_API_KEY=EE49029EEB85-4568-8F81-C9FDFC6E2943 + - EVOLUTION_INSTANCE_NAME=AutomataAlmeira + - GEMINI_API_KEY=AIzaSyC7JMkREYxl4qoEUGzd4hzbJ6RFg_YMxx0 + labels: + - "coolify.managed=true" + - "coolify.name=Almeira Multistore" + - "coolify.fqdn=https://store.almeira.com.co" + ports: + - "3001:3000" diff --git a/dripzone-app/.gitignore b/dripzone-app/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/dripzone-app/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/dripzone-app/AGENTS.md b/dripzone-app/AGENTS.md new file mode 100644 index 0000000..643577d --- /dev/null +++ b/dripzone-app/AGENTS.md @@ -0,0 +1,9 @@ + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/dripzone-app/CLAUDE.md b/dripzone-app/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/dripzone-app/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/dripzone-app/Dockerfile b/dripzone-app/Dockerfile new file mode 100644 index 0000000..80966a7 --- /dev/null +++ b/dripzone-app/Dockerfile @@ -0,0 +1,54 @@ +FROM node:20-alpine AS base + +# 1. Install dependencies +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +COPY package.json package-lock.json* ./ +RUN npm ci + +# 2. Build the app +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +# Appwrite and Public Envs for Build Phase +ARG NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 +ARG NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c +ARG NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db +ARG NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + +ENV NEXT_PUBLIC_APPWRITE_ENDPOINT=$NEXT_PUBLIC_APPWRITE_ENDPOINT +ENV NEXT_PUBLIC_APPWRITE_PROJECT_ID=$NEXT_PUBLIC_APPWRITE_PROJECT_ID +ENV NEXT_PUBLIC_APPWRITE_DATABASE_ID=$NEXT_PUBLIC_APPWRITE_DATABASE_ID +ENV NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=$NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID + +RUN npm run build + +# 3. Production Runner +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy standalone output & public static files +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/dripzone-app/README.md b/dripzone-app/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/dripzone-app/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/dripzone-app/android/.gitignore b/dripzone-app/android/.gitignore new file mode 100644 index 0000000..48354a3 --- /dev/null +++ b/dripzone-app/android/.gitignore @@ -0,0 +1,101 @@ +# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore + +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +# Cordova plugins for Capacitor +capacitor-cordova-android-plugins + +# Copied web assets +app/src/main/assets/public + +# Generated Config files +app/src/main/assets/capacitor.config.json +app/src/main/assets/capacitor.plugins.json +app/src/main/res/xml/config.xml diff --git a/dripzone-app/android/app/.gitignore b/dripzone-app/android/app/.gitignore new file mode 100644 index 0000000..043df80 --- /dev/null +++ b/dripzone-app/android/app/.gitignore @@ -0,0 +1,2 @@ +/build/* +!/build/.npmkeep diff --git a/dripzone-app/android/app/build.gradle b/dripzone-app/android/app/build.gradle new file mode 100644 index 0000000..ab9f6a9 --- /dev/null +++ b/dripzone-app/android/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + namespace = "co.dripzone.app" + compileSdk = rootProject.ext.compileSdkVersion + defaultConfig { + applicationId "co.dripzone.app" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + aaptOptions { + // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. + // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 + ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +repositories { + flatDir{ + dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" + implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" + implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" + implementation project(':capacitor-android') + testImplementation "junit:junit:$junitVersion" + androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" + implementation project(':capacitor-cordova-android-plugins') +} + +apply from: 'capacitor.build.gradle' + +try { + def servicesJSON = file('google-services.json') + if (servicesJSON.text) { + apply plugin: 'com.google.gms.google-services' + } +} catch(Exception e) { + logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") +} diff --git a/dripzone-app/android/app/capacitor.build.gradle b/dripzone-app/android/app/capacitor.build.gradle new file mode 100644 index 0000000..bbfb44f --- /dev/null +++ b/dripzone-app/android/app/capacitor.build.gradle @@ -0,0 +1,19 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/dripzone-app/android/app/proguard-rules.pro b/dripzone-app/android/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/dripzone-app/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/dripzone-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/dripzone-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..f2c2217 --- /dev/null +++ b/dripzone-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.getcapacitor.app", appContext.getPackageName()); + } +} diff --git a/dripzone-app/android/app/src/main/AndroidManifest.xml b/dripzone-app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b06ddbf --- /dev/null +++ b/dripzone-app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dripzone-app/android/app/src/main/java/co/dripzone/app/MainActivity.java b/dripzone-app/android/app/src/main/java/co/dripzone/app/MainActivity.java new file mode 100644 index 0000000..e0a017f --- /dev/null +++ b/dripzone-app/android/app/src/main/java/co/dripzone/app/MainActivity.java @@ -0,0 +1,5 @@ +package co.dripzone.app; + +import com.getcapacitor.BridgeActivity; + +public class MainActivity extends BridgeActivity {} diff --git a/dripzone-app/android/app/src/main/res/drawable-land-hdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-land-hdpi/splash.png new file mode 100644 index 0000000..e31573b Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-land-hdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-land-mdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-land-mdpi/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-land-mdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-land-xhdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-land-xhdpi/splash.png new file mode 100644 index 0000000..8077255 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-land-xhdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png new file mode 100644 index 0000000..14c6c8f Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png new file mode 100644 index 0000000..244ca25 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-port-hdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-port-hdpi/splash.png new file mode 100644 index 0000000..74faaa5 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-port-hdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-port-mdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-port-mdpi/splash.png new file mode 100644 index 0000000..e944f4a Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-port-mdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-port-xhdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-port-xhdpi/splash.png new file mode 100644 index 0000000..564a82f Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-port-xhdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png new file mode 100644 index 0000000..bfabe68 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/dripzone-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png new file mode 100644 index 0000000..6929071 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/dripzone-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/dripzone-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/dripzone-app/android/app/src/main/res/drawable/ic_launcher_background.xml b/dripzone-app/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/dripzone-app/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dripzone-app/android/app/src/main/res/drawable/splash.png b/dripzone-app/android/app/src/main/res/drawable/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/drawable/splash.png differ diff --git a/dripzone-app/android/app/src/main/res/layout/activity_main.xml b/dripzone-app/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..b5ad138 --- /dev/null +++ b/dripzone-app/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/dripzone-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/dripzone-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/dripzone-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dripzone-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/dripzone-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/dripzone-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..c023e50 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2127973 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..b441f37 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..72905b8 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..8ed0605 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..9502e47 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..4d1e077 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..df0f158 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..853db04 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..6cdf97c Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2960cbb Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e3093a Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..46de6e2 Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..d2ea9ab Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..a40d73e Binary files /dev/null and b/dripzone-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/dripzone-app/android/app/src/main/res/values/ic_launcher_background.xml b/dripzone-app/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/dripzone-app/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/dripzone-app/android/app/src/main/res/values/strings.xml b/dripzone-app/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..fcfa3a4 --- /dev/null +++ b/dripzone-app/android/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + DripZone Sneakers + DripZone Sneakers + co.dripzone.app + co.dripzone.app + diff --git a/dripzone-app/android/app/src/main/res/values/styles.xml b/dripzone-app/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..be874e5 --- /dev/null +++ b/dripzone-app/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/dripzone-app/android/app/src/main/res/xml/file_paths.xml b/dripzone-app/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..bd0c4d8 --- /dev/null +++ b/dripzone-app/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dripzone-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/dripzone-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java new file mode 100644 index 0000000..0297327 --- /dev/null +++ b/dripzone-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java @@ -0,0 +1,18 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} diff --git a/dripzone-app/android/build.gradle b/dripzone-app/android/build.gradle new file mode 100644 index 0000000..f8f0e43 --- /dev/null +++ b/dripzone-app/android/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.13.0' + classpath 'com.google.gms:google-services:4.4.4' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +apply from: "variables.gradle" + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/dripzone-app/android/capacitor.settings.gradle b/dripzone-app/android/capacitor.settings.gradle new file mode 100644 index 0000000..9a5fa87 --- /dev/null +++ b/dripzone-app/android/capacitor.settings.gradle @@ -0,0 +1,3 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') diff --git a/dripzone-app/android/gradle.properties b/dripzone-app/android/gradle.properties new file mode 100644 index 0000000..2e87c52 --- /dev/null +++ b/dripzone-app/android/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true diff --git a/dripzone-app/android/gradle/wrapper/gradle-wrapper.jar b/dripzone-app/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/dripzone-app/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/dripzone-app/android/gradle/wrapper/gradle-wrapper.properties b/dripzone-app/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7705927 --- /dev/null +++ b/dripzone-app/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/dripzone-app/android/gradlew b/dripzone-app/android/gradlew new file mode 100644 index 0000000..23d15a9 --- /dev/null +++ b/dripzone-app/android/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/dripzone-app/android/gradlew.bat b/dripzone-app/android/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/dripzone-app/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/dripzone-app/android/settings.gradle b/dripzone-app/android/settings.gradle new file mode 100644 index 0000000..3b4431d --- /dev/null +++ b/dripzone-app/android/settings.gradle @@ -0,0 +1,5 @@ +include ':app' +include ':capacitor-cordova-android-plugins' +project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') + +apply from: 'capacitor.settings.gradle' \ No newline at end of file diff --git a/dripzone-app/android/variables.gradle b/dripzone-app/android/variables.gradle new file mode 100644 index 0000000..ee4ba41 --- /dev/null +++ b/dripzone-app/android/variables.gradle @@ -0,0 +1,16 @@ +ext { + minSdkVersion = 24 + compileSdkVersion = 36 + targetSdkVersion = 36 + androidxActivityVersion = '1.11.0' + androidxAppCompatVersion = '1.7.1' + androidxCoordinatorLayoutVersion = '1.3.0' + androidxCoreVersion = '1.17.0' + androidxFragmentVersion = '1.8.9' + coreSplashScreenVersion = '1.2.0' + androidxWebkitVersion = '1.14.0' + junitVersion = '4.13.2' + androidxJunitVersion = '1.3.0' + androidxEspressoCoreVersion = '3.7.0' + cordovaAndroidVersion = '14.0.1' +} \ No newline at end of file diff --git a/dripzone-app/capacitor.config.ts b/dripzone-app/capacitor.config.ts new file mode 100644 index 0000000..c643642 --- /dev/null +++ b/dripzone-app/capacitor.config.ts @@ -0,0 +1,25 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'co.dripzone.app', + appName: 'DripZone Sneakers', + webDir: 'public', + server: { + url: 'https://dripzone.almeira.com.co', + cleartext: true, + androidScheme: 'https', + }, + plugins: { + SplashScreen: { + launchShowDuration: 2000, + backgroundColor: '#09090b', + showSpinner: false, + }, + StatusBar: { + style: 'DARK', + backgroundColor: '#09090b', + }, + }, +}; + +export default config; diff --git a/dripzone-app/docker-compose.prod.yml b/dripzone-app/docker-compose.prod.yml new file mode 100644 index 0000000..d13bd2e --- /dev/null +++ b/dripzone-app/docker-compose.prod.yml @@ -0,0 +1,36 @@ +version: '3.8' + +services: + dripzone: + build: + context: . + dockerfile: Dockerfile + container_name: dripzone-production + restart: always + environment: + - PORT=3000 + - NODE_ENV=production + - NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 + - NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c + - NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db + - NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + - APPWRITE_API_KEY=standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3 + - EVOLUTION_API_URL=https://evolution.almeira.com.co + - EVOLUTION_API_KEY=EE49029EEB85-4568-8F81-C9FDFC6E2943 + - EVOLUTION_INSTANCE_NAME=AutomataAlmeira + - GEMINI_API_KEY=AIzaSyC7JMkREYxl4qoEUGzd4hzbJ6RFg_YMxx0 + networks: + - coolify + labels: + - "traefik.enable=true" + - "traefik.http.routers.dripzone-http.rule=Host(`dripzone.almeira.com.co`)" + - "traefik.http.routers.dripzone-http.entrypoints=http" + - "traefik.http.routers.dripzone-https.rule=Host(`dripzone.almeira.com.co`)" + - "traefik.http.routers.dripzone-https.entrypoints=https" + - "traefik.http.routers.dripzone-https.tls=true" + - "traefik.http.routers.dripzone-https.tls.certresolver=letsencrypt" + - "traefik.http.services.dripzone.loadbalancer.server.port=3000" + +networks: + coolify: + external: true diff --git a/dripzone-app/eslint.config.mjs b/dripzone-app/eslint.config.mjs new file mode 100644 index 0000000..05e726d --- /dev/null +++ b/dripzone-app/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/dripzone-app/next.config.ts b/dripzone-app/next.config.ts new file mode 100644 index 0000000..5b406fe --- /dev/null +++ b/dripzone-app/next.config.ts @@ -0,0 +1,12 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", + images: { + remotePatterns: [ + { protocol: "https", hostname: "**" }, + ], + }, +}; + +export default nextConfig; diff --git a/dripzone-app/package-lock.json b/dripzone-app/package-lock.json new file mode 100644 index 0000000..481e408 --- /dev/null +++ b/dripzone-app/package-lock.json @@ -0,0 +1,8446 @@ +{ + "name": "dripzone-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dripzone-app", + "version": "0.1.0", + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capacitor/android": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.5.0.tgz", + "integrity": "sha512-Rb3prJeQiTp0pQhSSOReJuG9VgibOGMG4ECs+UhMwr6TCCHZ3NCZO811bDA0HxD0xrT/gCrJAsY5yfEATu84JQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.5.0" + } + }, + "node_modules/@capacitor/cli": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.5.0.tgz", + "integrity": "sha512-rLdzMUM5QV4WITcqoWv04p32i14BXgUH2diqEH6MWQlWaJfiyNrvOyt/+d5vHAfOxOm1klBu637VDEobctlwBA==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xcode": "^3.0.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@capacitor/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.5.0.tgz", + "integrity": "sha512-Ca4krtqH1hothjtBIwf2J2TW7IhYq1ujp8QeItTiJohNsqij8ja2DYYH3DU0l8RmxCWaBAFTGA2TgOgOMCSNsQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@google/genai": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-2.19.0.tgz", + "integrity": "sha512-IM3u1FjpOLyOPsPh0smGA6Ntj2olUWCPbTs/WQj7cA/2AKCGw/652W7IaySx0XtwuscFnMYBoraebQusSZ0zSQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@next/env": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.3.tgz", + "integrity": "sha512-U2eYQRwXj+dsqxV79zFqExDdatnNY/ZWc2nsJU1p/OgT7fd3dXwlF6OjYaFQCfMoeTA19PWq+wVmYgimVA+V+g==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.3.tgz", + "integrity": "sha512-pbEh30vvjKpDoTAmo1v3q2uM4JUi8QaEBpbmjWvGfoec2jLghy/WNtvzAT0bk+Ik9oz6etjt4YjXEk4BQnicCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "4.9.1", + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.3.tgz", + "integrity": "sha512-8Hiv32QJPwdV6KYJ8meR9SBA061tQqnIKTJDocvOXlEQqib0xMFpzArosuffFUUc0sslbh7QQ8a3Yey1QV8EIw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.3.tgz", + "integrity": "sha512-A1lgKgwVchRYmSe467zdwhxT9040dd8lH+o65sL5Jet8fjB4kegw/rDyPIpYVRb6jAqwXFOJpjIXJLxQKLiE3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.3.tgz", + "integrity": "sha512-bf0FIssMFueU2dm7vQEWWxk0c8UjKTdW0yzuh0sQsD8pf1+KCLDdaqhYZNMYGmXwEOiHAUzgBKudovIlcvvBjg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.3.tgz", + "integrity": "sha512-W7viwCk9JY/cAkdz/A273rd5bb3RgT/IHwR7Upv90tunjBWNtAAhGhoecHh+teRNRSinuAFmE+l7fwZ4YKkrXg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.3.tgz", + "integrity": "sha512-0W46zw1N3ODpI6n0GeivHvvob1pooozgZVqy65k0mh4/7vr+FbY9+WpHzNVXjHipJf/A3FDheBG19H1s5A25rA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.3.tgz", + "integrity": "sha512-H4mBso8ZTMBPtdT0PN0pBx2ayTvQuTuvS6qT13d77yVFJXAPCxkyIhLTmdMaGTJs0krQYI/qpzdHijCeihXhbg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.3.tgz", + "integrity": "sha512-cTMUJpcEGmeywofCUfhR+rSsoE33+rVPnPEYNTNdLNlsOeEg/vktOsKUSTb28vUGqD2jkm4Zaskcwn7OCI6FQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.3.tgz", + "integrity": "sha512-2VR4cTBzHXaBjnGsuH6GyJjENzQOmHeAh11uY1iUhjm3j5dEUrVJuUj+VL78jaGi/Dik8xS76zEj18BsFhlVZQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/canvas-confetti": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz", + "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz", + "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/type-utils": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.68.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz", + "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz", + "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.68.0", + "@typescript-eslint/types": "^8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz", + "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz", + "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz", + "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz", + "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.68.0", + "@typescript-eslint/tsconfig-utils": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz", + "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz", + "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-26.2.0.tgz", + "integrity": "sha512-8TCd4mMKhhUxGF9sjZ6W2V1gesnj43v1SFZoeAue/0O0ikMXIU92p96PiRn0D4nAVvFM/92bluTTb/PoXH5mnQ==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", + "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.415", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.415.tgz", + "integrity": "sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==", + "dev": true, + "license": "ISC" + }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.3.tgz", + "integrity": "sha512-teqtsR26tnlfXFHfVLTM/4tzEzU8DMu6GS1sddZzhfGzgd2f2ofbgDUcsk6cssSCzX6Tk6fmWifJcdANSdPJrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "16.3.3", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "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.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.577.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz", + "integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/native-run": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", + "integrity": "sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==", + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" + }, + "bin": { + "native-run": "bin/native-run" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.3.tgz", + "integrity": "sha512-tuRTx1nQ/yVw83cwJBo9F+njGUgMn3UHQycreWHB8XsStvvAh1AthbI8/4IpKnFaF58F+iSiHejYOlMQ/eq83g==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.3", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.3", + "@next/swc-darwin-x64": "16.3.3", + "@next/swc-linux-arm64-gnu": "16.3.3", + "@next/swc-linux-arm64-musl": "16.3.3", + "@next/swc-linux-x64-gnu": "16.3.3", + "@next/swc-linux-x64-musl": "16.3.3", + "@next/swc-win32-arm64-msvc": "16.3.3", + "@next/swc-win32-x64-msvc": "16.3.3", + "sharp": "^0.35.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-26.2.0.tgz", + "integrity": "sha512-rRToHOuG05F5Q3BGRoJNNIcO69zrYul/V9HOTxfcMSqhdw3TwInAl7pnSnMRW7D0MOQcvaLb8iZIwE1P8TP9Cw==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0", + "undici": "^6.26.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "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": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "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/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.68.0.tgz", + "integrity": "sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.68.0", + "@typescript-eslint/parser": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/dripzone-app/package.json b/dripzone-app/package.json new file mode 100644 index 0000000..a9268ef --- /dev/null +++ b/dripzone-app/package.json @@ -0,0 +1,38 @@ +{ + "name": "dripzone-app", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev -H 0.0.0.0 -p 3004", + "build": "next build", + "start": "next start -H 0.0.0.0 -p 3004", + "lint": "next lint" + }, + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/dripzone-app/postcss.config.mjs b/dripzone-app/postcss.config.mjs new file mode 100644 index 0000000..61e3684 --- /dev/null +++ b/dripzone-app/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/dripzone-app/public/file.svg b/dripzone-app/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/dripzone-app/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dripzone-app/public/globe.svg b/dripzone-app/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/dripzone-app/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dripzone-app/public/icon.svg b/dripzone-app/public/icon.svg new file mode 100644 index 0000000..f981e52 --- /dev/null +++ b/dripzone-app/public/icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + D + + diff --git a/dripzone-app/public/manifest.json b/dripzone-app/public/manifest.json new file mode 100644 index 0000000..b3a93fa --- /dev/null +++ b/dripzone-app/public/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "DripZone • Luxury Streetwear", + "short_name": "DripZone", + "description": "Zapatillas exclusivas y calzado de colección con despacho contraentrega en 24 horas.", + "start_url": "/", + "display": "standalone", + "background_color": "#09090b", + "theme_color": "#8b5cf6", + "orientation": "portrait", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any maskable" + } + ] +} diff --git a/dripzone-app/public/next.svg b/dripzone-app/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/dripzone-app/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dripzone-app/public/vercel.svg b/dripzone-app/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/dripzone-app/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dripzone-app/public/window.svg b/dripzone-app/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/dripzone-app/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dripzone-app/scripts/setup-appwrite.js b/dripzone-app/scripts/setup-appwrite.js new file mode 100644 index 0000000..8a34246 --- /dev/null +++ b/dripzone-app/scripts/setup-appwrite.js @@ -0,0 +1,131 @@ +/** + * Script de inicialización de la Base de Datos Independiente en Appwrite + * Ejecutar con: node scripts/setup-appwrite.js + */ +const { Client, Databases, Storage, Permission, Role } = require('node-appwrite'); +const fs = require('fs'); +const path = require('path'); + +// Leer variables de .env.local manualmente si dotenv no está disponible en este script +const envPath = path.resolve(__dirname, '../.env.local'); +if (fs.existsSync(envPath)) { + const envContent = fs.readFileSync(envPath, 'utf8'); + envContent.split('\n').forEach((line) => { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#')) { + const [k, ...v] = trimmed.split('='); + if (k && v) process.env[k.trim()] = v.join('=').trim(); + } + }); +} + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; +const apiKey = process.env.APPWRITE_API_KEY; +const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +const bucketId = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +if (!apiKey) { + console.error('❌ Falta APPWRITE_API_KEY en .env.local'); + process.exit(1); +} + +const client = new Client() + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey); + +const databases = new Databases(client); +const storage = new Storage(client); + +async function setup() { + console.log('🚀 Iniciando configuración de la Base de Datos Independiente para la Tienda...'); + console.log(`Endpoint: ${endpoint}`); + console.log(`Database ID: ${databaseId}`); + console.log(`Bucket ID: ${bucketId}`); + + // 1. Crear Base de Datos Independiente si no existe + try { + await databases.get(databaseId); + console.log(`✅ Base de datos independiente "${databaseId}" ya existe.`); + } catch (e) { + console.log(`Creando base de datos independiente "${databaseId}"...`); + await databases.create(databaseId, 'Sneakers Multi-Store DB'); + console.log(`✅ Base de datos "${databaseId}" creada con éxito.`); + } + + // 2. Crear Storage Bucket Independiente si no existe + try { + await storage.getBucket(bucketId); + console.log(`✅ Storage Bucket "${bucketId}" ya existe.`); + } catch (e) { + console.log(`Creando Storage Bucket "${bucketId}"...`); + try { + await storage.createBucket( + bucketId, + 'Sneakers Media Assets', + [Permission.read(Role.any()), Permission.create(Role.any())], + false, // fileSecurity + true, // enabled + 50000000, // 50MB max file size + ['jpg', 'png', 'webp', 'jpeg'] + ); + console.log(`✅ Storage Bucket "${bucketId}" creado con éxito.`); + } catch (bErr) { + console.warn('Nota sobre creación de bucket:', bErr.message); + } + } + + // 3. Crear Colecciones Independientes + const collections = [ + { + id: 'products', + name: 'Productos y Zapatillas', + }, + { + id: 'cities', + name: 'Ciudades y Envíos', + }, + { + id: 'payment_methods', + name: 'Métodos de Pago', + }, + { + id: 'orders', + name: 'Pedidos de Clientes', + }, + { + id: 'supplier_posts', + name: 'Feed de Mensajes WhatsApp', + }, + ]; + + for (const col of collections) { + try { + await databases.getCollection(databaseId, col.id); + console.log(`✅ Colección "${col.name}" (${col.id}) ya existe.`); + } catch (e) { + console.log(`Creando colección "${col.name}" (${col.id})...`); + try { + await databases.createCollection( + databaseId, + col.id, + col.name, + [ + Permission.read(Role.any()), + Permission.create(Role.any()), + Permission.update(Role.any()), + Permission.delete(Role.any()), + ] + ); + console.log(`✅ Colección creada: ${col.id}`); + } catch (cErr) { + console.warn(`Error creando colección ${col.id}:`, cErr.message); + } + } + } + + console.log('🎉 ¡Base de datos y colecciones independientes configuradas al 100%!'); +} + +setup().catch((err) => console.error('Error configurando Appwrite:', err)); diff --git a/dripzone-app/src/app/admin/ciudades/page.tsx b/dripzone-app/src/app/admin/ciudades/page.tsx new file mode 100644 index 0000000..53756a2 --- /dev/null +++ b/dripzone-app/src/app/admin/ciudades/page.tsx @@ -0,0 +1,249 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { MapPin, Plus, Save, Trash2, Check, X, Truck, ShieldCheck } from 'lucide-react'; +import { City } from '@/types'; +import { INITIAL_CITIES } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminCitiesPage() { + const [cities, setCities] = useState(INITIAL_CITIES); + const [isSaving, setIsSaving] = useState(false); + const [message, setMessage] = useState(null); + + // New city form + const [newName, setNewName] = useState(''); + const [newDepartment, setNewDepartment] = useState(''); + const [newShippingCost, setNewShippingCost] = useState('0'); + const [newDeliveryTime, setNewDeliveryTime] = useState('Entrega en 24 Horas'); + const [newAllowCod, setNewAllowCod] = useState(true); + const [newFirstExchangeFree, setNewFirstExchangeFree] = useState(true); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + }, []); + + const handleToggleExchangeFree = async (city: City) => { + const updated = { ...city, firstExchangeFree: !city.firstExchangeFree }; + setCities((prev) => prev.map((c) => (c.id === city.id ? updated : c))); + + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: city.id, updates: { firstExchangeFree: updated.firstExchangeFree } }), + }); + setMessage(`Política de 1er cambio gratis para "${city.name}" ${updated.firstExchangeFree ? 'ACTIVADA' : 'DESACTIVADA'}.`); + }; + + const handleUpdateShipping = async (cityId: string, cost: number) => { + setCities((prev) => prev.map((c) => (c.id === cityId ? { ...c, shippingCost: cost } : c))); + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: cityId, updates: { shippingCost: cost } }), + }); + setMessage('Tarifa de envío actualizada.'); + }; + + const handleAddCity = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newName) return; + + const payload = { + name: newName, + department: newDepartment || 'Colombia', + shippingCost: parseInt(newShippingCost, 10) || 0, + deliveryTime: newDeliveryTime, + allowsContraentrega: newAllowCod, + firstExchangeFree: newFirstExchangeFree, + exchangePolicyNote: newFirstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${newName} (posteriores con flete estándar)` + : `Cambio de talla garantizado (flete logístico asumido por el cliente)`, + }; + + const res = await fetch('/api/cities', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + const data = await res.json(); + if (data.success) { + setCities((prev) => [...prev, data.city]); + setNewName(''); + setNewDepartment(''); + setMessage(`Ciudad "${data.city.name}" agregada con éxito.`); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Ciudades, Fletes y Garantía de Cambio +

+

+ Administra las tarifas de envío, tiempos de entrega y configura si el 1er cambio de talla es gratis o si el cliente asume el flete para cada ciudad. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Add New City Card */} +
+

+ + Registrar Nueva Ciudad o Municipio +

+ +
+
+ + setNewName(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDepartment(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewShippingCost(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDeliveryTime(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+
+ +
+
+ + + +
+ + +
+
+ + {/* Cities List */} +
+

Ciudades y Zonas Registradas ({cities.length})

+ +
+ {cities.map((city) => ( +
+
+
+ {city.name} + ({city.department}) + {city.allowsContraentrega ? ( + + Contraentrega Activo + + ) : ( + + Solo Despacho Nacional + + )} +
+

+ + {city.deliveryTime} +

+
+ + {/* Actions & Policy Toggle */} +
+ {/* 1st Exchange Free Toggle Button */} + + + {/* Shipping cost edit */} +
+ Flete: + handleUpdateShipping(city.id, parseInt(e.target.value, 10) || 0)} + className="w-20 bg-transparent text-xs font-bold text-white outline-hidden text-right" + /> + COP +
+
+
+ ))} +
+
+
+ ); +} diff --git a/dripzone-app/src/app/admin/configuracion/page.tsx b/dripzone-app/src/app/admin/configuracion/page.tsx new file mode 100644 index 0000000..8afa8fe --- /dev/null +++ b/dripzone-app/src/app/admin/configuracion/page.tsx @@ -0,0 +1,352 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Store, Mail, Phone, MessageCircle, Instagram, MapPin, CreditCard, Save, CheckCircle2, DollarSign, Percent, ShieldCheck, QrCode, ExternalLink, Zap } from 'lucide-react'; +import { StoreSettings } from '@/types'; + +export default function AdminSettingsPage() { + const [settings, setSettings] = useState({ + storeName: 'DripZone', + slogan: 'Luxury Streetwear & Collectibles', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@dripzone.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }); + + const [isSaving, setIsSaving] = useState(false); + const [toast, setToast] = useState(null); + + useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setSettings(d.settings)) + .catch(() => {}); + }, []); + + const handleChange = (field: keyof StoreSettings, value: any) => { + setSettings((prev) => ({ ...prev, [field]: value })); + }; + + const handlePhoneChange = (val: string) => { + const cleanDigits = val.replace(/\D/g, ''); + const cleanWa = cleanDigits.startsWith('57') ? cleanDigits : `57${cleanDigits}`; + setSettings((prev) => ({ + ...prev, + phone: cleanDigits, + whatsappNumber: cleanWa, + })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSaving(true); + + try { + const res = await fetch('/api/settings', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settings), + }); + const data = await res.json(); + if (data.success) { + setToast('✅ ¡Datos de DripZone, WhatsApp oficial y pasarela Bold.co actualizados exitosamente!'); + setTimeout(() => setToast(null), 4500); + } + } catch (err) { + console.error(err); + } finally { + setIsSaving(false); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Información de la Tienda & Medios de Pago +

+

+ Configura los datos oficiales del negocio: WhatsApp oficial de atención, correo electrónico, pasarela Bold.co (Link de pago, QR y botón), Nequi, Daviplata y reglas de margen. +

+
+ + {toast && ( +
+ {toast} + +
+ )} + +
+ {/* Section 1: Identidad & WhatsApp Oficial */} +
+

+ + Identidad & WhatsApp Oficial de Atención +

+ +
+
+ + handleChange('storeName', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white font-semibold outline-hidden focus:border-purple-400" + /> +
+ +
+ + handleChange('slogan', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400" + /> +
+ +
+ + handleChange('email', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400 font-mono" + /> +
+ +
+ +
+ handlePhoneChange(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl pl-9 pr-3.5 py-2.5 text-emerald-300 font-bold outline-hidden focus:border-emerald-400" + /> + +
+

+ Link generado: https://wa.me/{settings.whatsappNumber} +

+
+ +
+ + handleChange('instagramHandle', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400" + /> +
+ +
+ + handleChange('city', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400" + /> +
+
+
+ + {/* Section 2: Pasarela Bold.co (Link de Pago, QR o Botón) */} +
+
+

+ + Integración con Bold.co (Link de Pago, Botón & QR) +

+ +
+ +
+
+ +
+ handleChange('boldPaymentLink', e.target.value)} + className="w-full bg-neutral-950 border border-indigo-500/40 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> + +
+

+ Tus clientes podrán pagar por PSE, Tarjeta de Crédito/Débito o Nequi directamente con este enlace oficial de Bold. +

+
+ +
+ + handleChange('boldQrUrl', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-indigo-400" + /> +
+ +
+ + handleChange('boldApiKey', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> +
+
+
+ + {/* Section 3: Cuentas de Recaudo Nequi / Daviplata */} +
+

+ + Cuentas para Recaudo de Anticipos ($10.000 COP) +

+ +
+
+ + handleChange('accountHolder', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400 font-bold" + /> +
+ +
+ + handleChange('nequiAccount', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400" + /> +
+ +
+ + handleChange('daviplataAccount', e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-purple-400" + /> +
+
+
+ + {/* Section 4: Reglas de Precios y Anticipo */} +
+

+ + Reglas Comerciales de Ganancia & Redondeo +

+ +
+
+ +
+ handleChange('defaultProfitMargin', Number(e.target.value))} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-purple-400" + /> + +
+

+ El sistema calcula el precio y lo redondea al siguiente múltiplo de $5.000 COP (ej: $132.000 ➔ $135.000). +

+
+ +
+ +
+ handleChange('defaultDepositAmount', Number(e.target.value))} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-purple-400" + /> + +
+

+ Valor solicitado al comprador para apartar el calzado con el proveedor. +

+
+
+
+ + {/* Submit Bar */} +
+

+ Todos los cambios se reflejan inmediatamente en la tienda pública, el carrito y los mensajes de WhatsApp. +

+ +
+
+
+ ); +} diff --git a/dripzone-app/src/app/admin/feed-whatsapp/page.tsx b/dripzone-app/src/app/admin/feed-whatsapp/page.tsx new file mode 100644 index 0000000..a1866cb --- /dev/null +++ b/dripzone-app/src/app/admin/feed-whatsapp/page.tsx @@ -0,0 +1,365 @@ +'use client'; + +import React, { useState } from 'react'; +import { Radio, Sparkles, Share2, AlertTriangle, ShieldCheck, Plus, Send, Layers } from 'lucide-react'; +import { SupplierPost, Product } from '@/types'; +import { INITIAL_SUPPLIER_POSTS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { checkProductDuplicate } from '@/lib/deduplication-engine'; +import { formatCOP } from '@/lib/pricing-engine'; +import { BRANDS, BrandId } from '@/config/brands'; + +export default function SupplierFeedPage() { + const [posts, setPosts] = useState(INITIAL_SUPPLIER_POSTS); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [isProcessing, setIsProcessing] = useState(false); + const [actionMessage, setActionMessage] = useState(null); + + // Target brand selector for publishing + const [targetBrand, setTargetBrand] = useState('almeira'); + + // Simulación de nuevo mensaje entrante de grupo para probar en vivo + const [testText, setTestText] = useState( + '🔥 LLEGANDO A BODEGA HOY 🔥\nNike Air Max 90 White Black\nTallas: 38 a 43\nMayorista: $90.000 c/u\nEnvío inmediato contraentrega' + ); + const [testGroup, setTestGroup] = useState('Canal Mayorista A'); + + const handleSimulateIncoming = async () => { + setIsProcessing(true); + try { + const res = await fetch('/api/webhook/whatsapp', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + text: testText, + groupInfo: { subject: testGroup }, + }), + }); + const data = await res.json(); + if (data.success && data.post) { + setPosts((prev) => [data.post, ...prev]); + setActionMessage('✅ Nuevo mensaje de WhatsApp procesado con IA.'); + } + } catch (err) { + console.error(err); + } finally { + setIsProcessing(false); + } + }; + + const handlePublishFacebook = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + setIsProcessing(true); + try { + const brandName = targetBrand === 'all' ? 'Todas las Tiendas' : BRANDS[targetBrand].name; + const res = await fetch('/api/publish/facebook', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + productName: post.extractedProduct.name, + brand: post.extractedProduct.brand, + retailPrice: post.extractedProduct.suggestedRetailPrice, + sizes: post.extractedProduct.sizes, + images: post.rawImages, + }), + }); + const data = await res.json(); + if (data.success) { + setActionMessage(`🚀 ¡Publicado en Facebook bajo la marca "${brandName}"! (ID: ${data.postId})`); + } + } catch (e) { + console.error(e); + } finally { + setIsProcessing(false); + } + }; + + const handleAddToStore = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + const brandLabel = targetBrand === 'all' ? 'Multi-Marca' : BRANDS[targetBrand].shortName; + const newProduct: Product = { + id: `snk-${Date.now()}`, + name: post.extractedProduct.name, + brand: post.extractedProduct.brand, + supplierPrice: post.extractedProduct.supplierPrice, + retailPrice: post.extractedProduct.suggestedRetailPrice, + originalPrice: Math.round(post.extractedProduct.suggestedRetailPrice * 1.35), + sizes: post.extractedProduct.sizes, + images: post.rawImages, + description: `Zapatillas calidad premium garantizada para entrega inmediata.`, + category: post.extractedProduct.category, + inStock: true, + isActive: true, + originBadge: `Bodega Central`, + supplierName: post.supplierName || post.channelName || 'DIFUSION JOVIC STORE', + supplierPhone: post.supplierPhone || '573134848203', + }; + + try { + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProduct), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setActionMessage(`✨ "${newProduct.name}" habilitado en el catálogo para ${brandLabel}.`); + } + } catch (e) { + console.error(e); + } + }; + + return ( +
+ {/* Header */} +
+
+

+ + Feed de Entrada & Publicador Multi-Marca +

+

+ Recepción automática con IA, prevención de duplicados y distribución hacia las 4 marcas (Almeira Store, Sneaky, Zapply, DripZone). +

+
+ + {/* Target Brand Selector Pill Bar */} +
+ + Destino: + + + {Object.values(BRANDS).map((b) => ( + + ))} +
+
+ + {actionMessage && ( +
+ {actionMessage} + +
+ )} + + {/* Live Simulator for Test Messages */} +
+
+ + Simulador de Recepción en Tiempo Real +
+ +
+
+ + +
+ +
+ +
+ setTestText(e.target.value)} + className="flex-1 bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> + +
+
+
+
+ + {/* Intercepted Posts Feed */} +
+

Mensajes Procesados Recientemente

+ +
+ {posts.map((post) => { + const extracted = post.extractedProduct; + const duplicateCheck = extracted + ? checkProductDuplicate( + { + name: extracted.name, + brand: extracted.brand, + sizes: extracted.sizes, + supplierPrice: extracted.supplierPrice, + }, + products + ) + : null; + + return ( +
+ {/* Header of post */} +
+
+ + {post.channelName || 'Canal Mayorista'} + + {post.receivedAt} +
+ + {/* Anti-Duplicate Status Badge */} + {duplicateCheck && ( +
+ {duplicateCheck.isDuplicate ? ( + <> + + Duplicado Detectado ({Math.round(duplicateCheck.similarityScore * 100)}% Similitud) + + ) : ( + <> + + Producto Nuevo (0% Duplicados) + + )} +
+ )} +
+ + {/* Content Grid */} +
+ {/* Left: Raw WhatsApp Message (5 cols) */} +
+ Mensaje de Entrada: +

+ {post.rawMessage} +

+ {post.rawImages.length > 0 && ( +
+ +
+ )} +
+ + {/* Right: AI Extracted & Pricing Calculation (7 cols) */} +
+ {extracted ? ( +
+
+
+ + {extracted.brand} • {extracted.category} + +

{extracted.name}

+
+ + IA: {Math.round(extracted.confidence * 100)}% certeza + +
+ + {/* Pricing breakdown */} +
+
+ Costo Base: + + {formatCOP(extracted.supplierPrice)} + +
+
+ Precio Venta (+ Margen): + + {formatCOP(extracted.suggestedRetailPrice)} + +
+
+ + {/* Sizes */} +
+ + Tallas extraídas: + +
+ {extracted.sizes.map((s) => ( + + {s} + + ))} +
+
+ + {/* Duplicate warning note */} + {duplicateCheck?.isDuplicate && ( +
+ {duplicateCheck.message} +
+ )} + + {/* Actions */} +
+ + + +
+
+ ) : ( +

Extrayendo datos...

+ )} +
+
+
+ ); + })} +
+
+
+ ); +} diff --git a/dripzone-app/src/app/admin/grupos-whatsapp/page.tsx b/dripzone-app/src/app/admin/grupos-whatsapp/page.tsx new file mode 100644 index 0000000..db9b690 --- /dev/null +++ b/dripzone-app/src/app/admin/grupos-whatsapp/page.tsx @@ -0,0 +1,585 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { + MessageSquare, + RefreshCw, + Search, + CheckCircle2, + XCircle, + ShieldCheck, + Zap, + Radio, + Sliders, + Users, + Sparkles, + ExternalLink, + Plus, + ArrowUpRight, + Filter, + CheckSquare, + Square, + X +} from 'lucide-react'; +import { MonitoredWhatsAppGroup } from '@/types'; + +export default function AdminWhatsAppGroupsPage() { + const [groups, setGroups] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [filterMode, setFilterMode] = useState<'all' | 'monitored' | 'unmonitored'>('all'); + const [toast, setToast] = useState(null); + const [scanningGroupId, setScanningGroupId] = useState(null); + + // Group Picker Modal State + const [isPickerOpen, setIsPickerOpen] = useState(false); + const [liveGroups, setLiveGroups] = useState([]); + const [isLoadingLive, setIsLoadingLive] = useState(false); + const [pickerSearch, setPickerSearch] = useState(''); + const [selectedJids, setSelectedJids] = useState>(new Set()); + + const fetchLocalGroups = async () => { + setIsLoading(true); + try { + const res = await fetch('/api/whatsapp-groups'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setGroups(data.groups); + } + } catch (err) { + console.error(err); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchLocalGroups(); + }, []); + + const handleOpenPicker = async () => { + setIsPickerOpen(true); + setIsLoadingLive(true); + try { + const res = await fetch('/api/whatsapp-groups?fetchLive=true'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setLiveGroups(data.groups); + // Pre-select already monitored groups + const initialSelected = new Set(); + data.groups.forEach((g: MonitoredWhatsAppGroup) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + groups.forEach((g) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + setSelectedJids(initialSelected); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleSelectJid = (jid: string) => { + setSelectedJids((prev) => { + const next = new Set(prev); + if (next.has(jid)) next.delete(jid); + else next.add(jid); + return next; + }); + }; + + const handleSelectAllFiltered = (filtered: MonitoredWhatsAppGroup[]) => { + setSelectedJids((prev) => { + const next = new Set(prev); + filtered.forEach((g) => next.add(g.jid)); + return next; + }); + }; + + const handleDeselectAll = () => { + setSelectedJids(new Set()); + }; + + const handleSaveSelectedGroups = async () => { + setIsLoadingLive(true); + try { + const updatedGroups: MonitoredWhatsAppGroup[] = liveGroups.map((lg) => ({ + ...lg, + isMonitored: selectedJids.has(lg.jid), + autoPublish: true, + profitMarginOverride: 35, + })); + + const res = await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ groups: updatedGroups }), + }); + + const data = await res.json(); + if (data.success) { + setGroups(data.groups); + setIsPickerOpen(false); + setToast(`✅ ¡Se actualizaron los grupos monitoreados! (${selectedJids.size} activos)`); + setTimeout(() => setToast(null), 4000); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleGroup = async (group: MonitoredWhatsAppGroup) => { + const nextState = !group.isMonitored; + const updatedList = groups.map((g) => + g.jid === group.jid || g.id === group.id ? { ...g, isMonitored: nextState } : g + ); + setGroups(updatedList); + + try { + await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'toggle', + idOrJid: group.jid || group.id, + isMonitored: nextState, + }), + }); + + setToast( + nextState + ? `🟢 Grupo "${group.name}" ahora está siendo MONITOREADO en tiempo real.` + : `⚪ Grupo "${group.name}" fue desactivado del monitoreo.` + ); + setTimeout(() => setToast(null), 3500); + } catch (err) { + console.error(err); + } + }; + + const handleScanGroup = async (group: MonitoredWhatsAppGroup) => { + setScanningGroupId(group.id); + try { + await new Promise((r) => setTimeout(r, 1200)); + setToast(`✨ Mensajes recientes de "${group.name}" analizados con IA y catálogo actualizado.`); + setTimeout(() => setToast(null), 4000); + } finally { + setScanningGroupId(null); + } + }; + + const filteredGroups = groups.filter((g) => { + const matchesSearch = + g.name.toLowerCase().includes(searchQuery.toLowerCase()) || + g.jid.toLowerCase().includes(searchQuery.toLowerCase()) || + (g.notes && g.notes.toLowerCase().includes(searchQuery.toLowerCase())); + + if (filterMode === 'monitored') return matchesSearch && g.isMonitored; + if (filterMode === 'unmonitored') return matchesSearch && !g.isMonitored; + return matchesSearch; + }); + + const filteredPickerGroups = liveGroups.filter((g) => + g.name.toLowerCase().includes(pickerSearch.toLowerCase()) || + g.jid.toLowerCase().includes(pickerSearch.toLowerCase()) + ); + + const monitoredCount = groups.filter((g) => g.isMonitored).length; + + return ( +
+ {/* Header */} +
+
+

+ + Monitoreo de Grupos de WhatsApp +

+

+ Busca y selecciona los grupos de proveedores que el bot de Evolution API & Gemini debe escuchar 24/7 para auto-publicar zapatillas. +

+
+ + {/* Big Search and Select Button */} + +
+ + {/* Toast Notification */} + {toast && ( +
+ {toast} + +
+ )} + + {/* Stats Bar */} +
+
+
+

Grupos en tu WhatsApp

+

{groups.length}

+
+
+ +
+
+ +
+
+

Grupos Monitoreados (Activos)

+

{monitoredCount}

+
+
+ +
+
+ +
+
+

Evolution API (WhatsApp)

+

+ + AutomataAlmeira (En línea) +

+
+
+ +
+
+
+ + {/* Filter and Search Toolbar */} +
+
+ + setSearchQuery(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl pl-9 pr-3 py-2 text-xs text-white outline-hidden focus:border-purple-400" + /> +
+ +
+ + + +
+
+ + {/* Active Monitored Groups List */} +
+ {isLoading ? ( +
+ +

Cargando grupos de proveedores...

+
+ ) : filteredGroups.length === 0 ? ( +
+ +

No tienes grupos seleccionados para monitorear.

+ +
+ ) : ( + filteredGroups.map((group) => { + const isMonitored = group.isMonitored; + + return ( +
+ {/* Header */} +
+
+
+ +

+ {group.name} +

+
+

+ {group.jid} +

+
+ + {/* Toggle Switch */} + +
+ + {/* Info Pills */} +
+
+ Margen Aplicado + + +{group.profitMarginOverride || 35}% (Redondeo a $5.000) + +
+ +
+ Modo de Ingreso + + Auto-Publicar Directo + +
+
+ + {group.notes && ( +

+ ℹ️ {group.notes} +

+ )} + + {/* Action footer */} +
+ + {group.participantsCount ? `👥 ${group.participantsCount} miembros` : 'Canal Mayorista'} + + + +
+
+ ); + }) + )} +
+ + {/* ========================================================= */} + {/* MODAL: Group Picker (Buscar y Seleccionar Grupos) */} + {/* ========================================================= */} + {isPickerOpen && ( +
+
+ {/* Modal Header */} +
+
+
+ +
+
+

Seleccionar Grupos de WhatsApp

+

+ Marca los grupos que deseas monitorear con IA para auto-publicar calzado. +

+
+
+ +
+ + {/* Search and Action Toolbar in Modal */} +
+
+ + setPickerSearch(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl pl-9 pr-3.5 py-2.5 text-xs text-white outline-hidden focus:border-purple-400 font-semibold" + /> +
+ +
+ + Mostrando {filteredPickerGroups.length} grupos encontrados + +
+ + • + +
+
+
+ + {/* Groups Scrollable List */} +
+ {isLoadingLive ? ( +
+ +

Consultando grupos en vivo desde Evolution API...

+

Conectando con WhatsApp...

+
+ ) : filteredPickerGroups.length === 0 ? ( +
+

No se encontraron grupos con el término "{pickerSearch}".

+
+ ) : ( + filteredPickerGroups.map((group) => { + const isSelected = selectedJids.has(group.jid); + + return ( +
handleToggleSelectJid(group.jid)} + className={`p-3.5 rounded-2xl border transition-all cursor-pointer flex items-center justify-between gap-3 ${ + isSelected + ? 'bg-purple-950/30 border-purple-500/50 shadow-md ring-1 ring-purple-500/20' + : 'bg-neutral-950 border-neutral-800 hover:border-neutral-700' + }`} + > +
+
+ {isSelected && } +
+ +
+

+ {group.name} +

+

+ {group.jid} +

+
+
+ +
+ {isSelected ? ( + + Monitorear + + ) : ( + + Ignorar + + )} +
+
+ ); + }) + )} +
+ + {/* Modal Footer */} +
+
+ Seleccionados: + {selectedJids.size} + grupos para monitorear +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/dripzone-app/src/app/admin/layout.tsx b/dripzone-app/src/app/admin/layout.tsx new file mode 100644 index 0000000..3b2802a --- /dev/null +++ b/dripzone-app/src/app/admin/layout.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { + LayoutDashboard, + Radio, + Package, + MapPin, + CreditCard, + ShoppingBag, + ArrowLeft, + Sparkles, + Store, + Users, + MessageSquare, +} from 'lucide-react'; + +export default function AdminLayout({ children }: { children: React.ReactNode }) { + const pathname = usePathname(); + + const NAV_ITEMS = [ + { href: '/admin', label: 'Resumen & KPIs', icon: LayoutDashboard }, + { href: '/admin/grupos-whatsapp', label: 'Grupos WhatsApp', icon: MessageSquare, badge: 'Monitoreo 24/7' }, + { href: '/admin/usuarios', label: 'Control de Usuarios', icon: Users, badge: 'Roles & Accesos' }, + { href: '/admin/configuracion', label: 'Datos de la Tienda', icon: Store }, + { href: '/admin/feed-whatsapp', label: 'Feed WhatsApp & IA', icon: Radio, badge: 'Anti-Duplicados' }, + { href: '/admin/productos', label: 'Catálogo de Zapatillas', icon: Package }, + { href: '/admin/ciudades', label: 'Ciudades & Fletes', icon: MapPin }, + { href: '/admin/metodos-pago', label: 'Medios de Pago & Anticipos', icon: CreditCard }, + { href: '/admin/pedidos', label: 'Pedidos & Logística', icon: ShoppingBag }, + ]; + + return ( +
+ {/* Sidebar */} + + + {/* Main Content Area */} +
+ {children} +
+
+ ); +} diff --git a/dripzone-app/src/app/admin/metodos-pago/page.tsx b/dripzone-app/src/app/admin/metodos-pago/page.tsx new file mode 100644 index 0000000..f80adad --- /dev/null +++ b/dripzone-app/src/app/admin/metodos-pago/page.tsx @@ -0,0 +1,163 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { CreditCard, Zap, Save, Check, ShieldCheck, QrCode } from 'lucide-react'; +import { PaymentMethod } from '@/types'; +import { INITIAL_PAYMENT_METHODS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminPaymentMethodsPage() { + const [methods, setMethods] = useState(INITIAL_PAYMENT_METHODS); + const [message, setMessage] = useState(null); + + useEffect(() => { + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setMethods(d.paymentMethods)) + .catch(() => {}); + }, []); + + const handleToggleActive = async (method: PaymentMethod) => { + const updated = { ...method, isActive: !method.isActive }; + setMethods((prev) => prev.map((m) => (m.id === method.id ? updated : m))); + + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: { isActive: updated.isActive } }), + }); + setMessage(`Método "${method.name}" ${updated.isActive ? 'activado' : 'desactivado'}.`); + }; + + const handleUpdateField = (id: string, field: keyof PaymentMethod, val: any) => { + setMethods((prev) => + prev.map((m) => (m.id === id ? { ...m, [field]: val } : m)) + ); + }; + + const handleSaveMethod = async (method: PaymentMethod) => { + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: method }), + }); + setMessage(`✅ Cambios guardados para "${method.name}".`); + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Medios de Pago & Anticipos +

+

+ Habilita métodos de pago, configura el valor de separación de $10.000 COP y personaliza los datos de Nequi / Daviplata. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Methods Cards */} +
+ {methods.map((method) => ( +
+
+
+
+ {method.type === 'contraentrega' ? : } +
+
+

{method.name}

+ Tipo: {method.type} +
+
+ +
+ +
+
+ +
+
+ + handleUpdateField(method.id, 'name', e.target.value)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + handleUpdateField(method.id, 'description', e.target.value)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ + {method.requiresDeposit && ( +
+ + handleUpdateField(method.id, 'depositAmount', parseInt(e.target.value, 10) || 0)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden font-bold" + /> + + (El saldo restante se cobra contraentrega al recibir) + +
+ )} + +
+ + handleUpdateField(method.id, 'accountInfo', e.target.value)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + placeholder="Ej. Nequi / Daviplata: 316 745 5877" + /> +
+
+ +
+ +
+
+ ))} +
+
+ ); +} diff --git a/dripzone-app/src/app/admin/page.tsx b/dripzone-app/src/app/admin/page.tsx new file mode 100644 index 0000000..8d400b5 --- /dev/null +++ b/dripzone-app/src/app/admin/page.tsx @@ -0,0 +1,159 @@ +'use client'; + +import React, { useState } from 'react'; +import Link from 'next/link'; +import { Package, Radio, MapPin, Zap, CheckCircle2, ArrowUpRight, Sparkles } from 'lucide-react'; +import { INITIAL_PRODUCTS, INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_SUPPLIER_POSTS } from '@/lib/data-service'; + +export default function AdminDashboardPage() { + const [productsCount] = useState(INITIAL_PRODUCTS.length); + const [postsCount] = useState(INITIAL_SUPPLIER_POSTS.length); + const [citiesCount] = useState(INITIAL_CITIES.length); + + return ( +
+ {/* Header */} +
+
+

+ + Centro de Control • Almeira Store +

+

+ Automatización inteligente de calzado, publicaciones a Facebook y gestión de despachos. +

+
+ +
+ + + Ver Feed de WhatsApp + +
+
+ + {/* KPI Cards */} +
+
+
+ Zapatillas Activas + +
+
{productsCount}
+

+ Catálogo sincronizado +

+
+ +
+
+ Margen Promedio + +
+
+ +$30.000 COP +
+

+ (Costo: $90k ➔ Venta: $120k) +

+
+ +
+
+ Entradas Procesadas + +
+
{postsCount}
+

+ IA Gemini + Anti-duplicados +

+
+ +
+
+ Ciudades Habilitadas + +
+
{citiesCount}
+

+ Contraentrega activo en Cali +

+
+
+ + {/* Quick Actions & Automation Status */} +
+ {/* Left: WhatsApp Evolution API Status */} +
+
+
+
+

Estado del Listener de WhatsApp

+
+ + Activo + +
+ +
+
+ Instancia Evolution API: + AutomataAlmeira +
+
+ Servidor: + evolution.almeira.com.co +
+
+ Motor de Inteligencia Artificial: + Gemini 2.5 Flash +
+
+ Filtro Anti-Duplicados: + Activo (>75% Similitud) +
+
+ + + Ver últimos mensajes procesados + + +
+ + {/* Right: Meta / Facebook Automation */} +
+
+

Publicador a Fanpage de Facebook

+ + Listo para Publicar + +
+ +
+

✨ Plantilla de Copy Vendedor Integrada:

+

+ "✨ ALMEIRA STORE • NUEVA COLECCIÓN EXCLUSIVA ✨
+ 👟 NIKE DUNK LOW PANDA
+ 📏 Tallas: 37 a 43 | 💎 Precio: $120.000 COP
+ 🚚 ¡Entrega a Domicilio en Cali con Pago Contraentrega!" +

+
+ + + Publicar Producto de Prueba en Facebook + + +
+
+
+ ); +} diff --git a/dripzone-app/src/app/admin/pedidos/page.tsx b/dripzone-app/src/app/admin/pedidos/page.tsx new file mode 100644 index 0000000..25ca97f --- /dev/null +++ b/dripzone-app/src/app/admin/pedidos/page.tsx @@ -0,0 +1,275 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { ShoppingBag, Truck, CheckCircle2, Clock, Phone, MapPin, Search, MessageCircle, Send, ShieldCheck, UserCheck } from 'lucide-react'; +import { Order, OrderItem } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminOrdersPage() { + const [orders, setOrders] = useState([]); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState('all'); + + useEffect(() => { + fetch('/api/orders') + .then((r) => r.json()) + .then((d) => d.success && setOrders(d.orders)) + .catch(() => {}); + }, []); + + const handleStatusChange = async (orderId: string, newStatus: Order['status']) => { + setOrders((prev) => + prev.map((o) => (o.id === orderId ? { ...o, status: newStatus } : o)) + ); + + await fetch('/api/orders', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: orderId, status: newStatus }), + }).catch(() => {}); + }; + + const handleNotifySupplier = (order: Order, item: OrderItem) => { + const supplierPhone = item.supplierPhone || '573134848203'; + const supplierName = item.supplierName || 'Proveedor Mayorista'; + const supplierCost = item.supplierPrice ? formatCOP(item.supplierPrice) : 'Precio Mayorista'; + + const message = `👋 Hola *${supplierName}*!\n\nPor favor *sepárame este par* para despacho inmediato:\n\n👟 *Modelo:* ${item.productName}\n📏 *Talla:* ${item.size}\n📦 *Cantidad:* ${item.quantity} par(es)\n💵 *Costo Base:* ${supplierCost}\n\n🏷️ *Orden Interna:* #${order.id}\n📍 *Ciudad Destino:* ${order.cityName}\n\n¿Me confirmas si lo tienes listo para recoger / enviar? ¡Muchas gracias!`; + + const url = `https://wa.me/${supplierPhone}?text=${encodeURIComponent(message)}`; + window.open(url, '_blank'); + + if (order.status === 'pending' || order.status === 'deposit_received') { + handleStatusChange(order.id, 'supplier_notified'); + } + }; + + const getStatusBadge = (status: Order['status']) => { + switch (status) { + case 'pending': + return Pendiente Confirmar; + case 'deposit_received': + return Separación $10k Pagada; + case 'supplier_notified': + return Proveedor Notificado; + case 'dispatched': + return En Ruta con Mensajero; + case 'delivered': + return Entregado & Cobrado; + case 'cancelled': + return Cancelado; + } + }; + + const filteredOrders = orders.filter((o) => { + const matchesSearch = + o.customerName.toLowerCase().includes(search.toLowerCase()) || + o.customerPhone.includes(search) || + o.cityName.toLowerCase().includes(search.toLowerCase()) || + o.id.toLowerCase().includes(search.toLowerCase()); + + if (!matchesSearch) return false; + if (statusFilter !== 'all' && o.status !== statusFilter) return false; + return true; + }); + + return ( +
+ {/* Header */} +
+

+ + Gestión de Pedidos & Separación con Proveedores ({orders.length}) +

+

+ Control logístico de pedidos contraentrega, cobro de anticipos de $10.000 COP y notificación inmediata de separación al proveedor vía WhatsApp. +

+
+ + {/* Toolbar */} +
+
+ + + + +
+ +
+ setSearch(e.target.value)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-purple-400" + /> +
+
+ + {filteredOrders.length === 0 ? ( +
+
+ +
+

No hay pedidos en esta sección

+

+ Cuando los clientes hagan un pedido en la tienda web o por WhatsApp, aparecerán aquí con el botón para separar inmediatamente con el proveedor correspondiente. +

+
+ ) : ( +
+ {filteredOrders.map((order) => ( +
+
+
+ Orden #{order.id} + • {new Date(order.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} +
+ {getStatusBadge(order.status)} +
+ +
+
+ + Cliente & Entrega (24 Horas) + +

{order.customerName}

+

+ {order.customerPhone} +

+

+ {order.address} ({order.cityName}) +

+
+ +
+ + Zapatillas & Proveedor Asignado: + +
+ {order.items.map((it, idx) => { + const suppName = it.supplierName || 'DIFUSION JOVIC STORE'; + return ( +
+
+
+

{it.productName}

+

+ Talla {it.size} • Cant: {it.quantity} +

+
+ + Prov: {suppName} + +
+ + +
+ ); + })} +
+
+ +
+ + Cobro & Pagos Contraentrega + +
+

+ Total de la Orden: + {formatCOP(order.totalAmount)} +

+ {order.depositAmount > 0 ? ( + <> +

+ Anticipo / Separación: + {formatCOP(order.depositAmount)} +

+

+ Saldo al Mensajero: + {formatCOP(order.balanceDue)} +

+ + ) : ( +

+ 100% Contraentrega al recibir +

+ )} +
+
+
+ +
+ Método: {order.paymentMethodName} + +
+ + + + +
+
+
+ ))} +
+ )} +
+ ); +} diff --git a/dripzone-app/src/app/admin/productos/page.tsx b/dripzone-app/src/app/admin/productos/page.tsx new file mode 100644 index 0000000..01e38fc --- /dev/null +++ b/dripzone-app/src/app/admin/productos/page.tsx @@ -0,0 +1,472 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Package, Plus, Eye, EyeOff, Check, X, Sparkles, Filter, Phone, MessageCircle, Truck } from 'lucide-react'; +import { Product, Supplier } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_SUPPLIERS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminProductsPage() { + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [suppliers, setSuppliers] = useState(INITIAL_SUPPLIERS); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [supplierFilter, setSupplierFilter] = useState('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New product form + const [name, setName] = useState(''); + const [brand, setBrand] = useState('Nike'); + const [selectedSupplierId, setSelectedSupplierId] = useState('sup-1'); + const [supplierPrice, setSupplierPrice] = useState('90000'); + const [retailPrice, setRetailPrice] = useState('125000'); + const [sizesInput, setSizesInput] = useState('37, 38, 39, 40, 41, 42, 43'); + const [imageUrl, setImageUrl] = useState( + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' + ); + const [category, setCategory] = useState('Sneakers / Urbano'); + const [isActiveNew, setIsActiveNew] = useState(true); + + useEffect(() => { + fetch('/api/products?all=true') + .then((r) => r.json()) + .then((d) => d.success && setProducts(d.products)) + .catch(() => {}); + }, []); + + const handleToggleProductStatus = async (product: Product) => { + const newStatus = product.isActive === false ? true : false; + + setProducts((prev) => + prev.map((p) => (p.id === product.id ? { ...p, isActive: newStatus } : p)) + ); + + try { + const res = await fetch('/api/products', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + id: product.id, + updates: { isActive: newStatus }, + }), + }); + + const data = await res.json(); + if (data.success) { + setToastMessage( + `Zapatilla "${product.name}" ahora está ${newStatus ? '🟢 ACTIVA (Visible en la tienda)' : '⚪ INACTIVA (Oculta de la tienda)'}.` + ); + } + } catch (e) { + console.error('Error toggling status:', e); + } + }; + + const handleContactSupplier = (product: Product) => { + const phone = product.supplierPhone || '573134848203'; + const suppName = product.supplierName || 'Proveedor Mayorista'; + const text = encodeURIComponent( + `Hola ${suppName}! 👋 Consulta sobre disponibilidad del modelo *${product.name}* (Costo base: ${formatCOP(product.supplierPrice)}).` + ); + window.open(`https://wa.me/${phone}?text=${text}`, '_blank'); + }; + + const handleCreateProduct = async (e: React.FormEvent) => { + e.preventDefault(); + const sizes = sizesInput + .split(',') + .map((s) => s.trim()) + .filter(Boolean); + + const chosenSupplier = suppliers.find((s) => s.id === selectedSupplierId) || suppliers[0]; + + const newProd: Product = { + id: `snk-${Date.now()}`, + name, + brand, + supplierPrice: parseInt(supplierPrice, 10) || 90000, + retailPrice: parseInt(retailPrice, 10) || 125000, + originalPrice: Math.round((parseInt(retailPrice, 10) || 125000) * 1.35), + sizes, + images: [imageUrl], + description: 'Zapatillas de alta calidad garantizada para entrega inmediata.', + category, + inStock: true, + isActive: isActiveNew, + originBadge: 'Bodega Central', + supplierId: chosenSupplier.id, + supplierName: chosenSupplier.name, + supplierPhone: chosenSupplier.phone, + }; + + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProd), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setIsModalOpen(false); + setName(''); + setToastMessage(`✨ "${newProd.name}" registrada con proveedor [${chosenSupplier.name}].`); + } + }; + + const filtered = products.filter((p) => { + const matchesSearch = + p.name.toLowerCase().includes(search.toLowerCase()) || + p.brand.toLowerCase().includes(search.toLowerCase()) || + (p.supplierName && p.supplierName.toLowerCase().includes(search.toLowerCase())); + + if (!matchesSearch) return false; + if (statusFilter === 'active' && p.isActive === false) return false; + if (statusFilter === 'inactive' && p.isActive !== false) return false; + if (supplierFilter !== 'all' && p.supplierName !== supplierFilter) return false; + return true; + }); + + const activeCount = products.filter((p) => p.isActive !== false).length; + const inactiveCount = products.filter((p) => p.isActive === false).length; + + return ( +
+ {/* Header */} +
+
+

+ + Catálogo General de Zapatillas & Proveedores ({products.length}) +

+

+ Visualiza cada modelo con su proveedor asignado, costo mayorista y activa/inactiva publicaciones para la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* Filters & Search Toolbar */} +
+ {/* Status filter pills */} +
+ + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-purple-400" + /> +
+
+ + {/* Products Table */} +
+
+ + + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((prod) => { + const isActive = prod.isActive !== false; + const margin = prod.retailPrice - prod.supplierPrice; + const suppName = prod.supplierName || 'DIFUSION JOVIC STORE'; + const suppPhone = prod.supplierPhone || '573134848203'; + + return ( + + {/* Estado Toggle Button */} + + + {/* Product Name & Image */} + + + {/* Supplier Column */} + + + + + + + + + + + ); + }) + )} + +
Estado PublicaciónProductoProveedor Asignado (Interno)MarcaCosto BasePrecio VentaMargen GananciaTallas
+ No hay zapatillas que coincidan con el filtro seleccionado. +
+ + + +
+

{prod.name}

+ {prod.category} +
+
+
+ + 🏢 {suppName} + + +
+
{prod.brand}{formatCOP(prod.supplierPrice)}{formatCOP(prod.retailPrice)} + + +{formatCOP(margin)} + + +
+ {prod.sizes.map((s) => ( + + {s} + + ))} +
+
+
+
+ + {/* Modal Add Product */} + {isModalOpen && ( +
+
+

Registrar Nueva Zapatilla

+ +
+
+ + setName(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ + {/* Supplier Selection */} +
+ + +

+ Este proveedor recibirá la notificación para separar el par cuando se haga un pedido. +

+
+ +
+
+ + +
+ +
+ + setCategory(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+
+ + setSupplierPrice(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setRetailPrice(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setSizesInput(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setImageUrl(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/dripzone-app/src/app/admin/usuarios/page.tsx b/dripzone-app/src/app/admin/usuarios/page.tsx new file mode 100644 index 0000000..9d07cdd --- /dev/null +++ b/dripzone-app/src/app/admin/usuarios/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Users, UserPlus, Shield, ShieldCheck, UserCheck, MessageCircle, Mail, Phone, MapPin, Eye, EyeOff, Trash2, Edit, Check, X } from 'lucide-react'; +import { User } from '@/types'; + +export default function AdminUsersPage() { + const [users, setUsers] = useState([]); + const [search, setSearch] = useState(''); + const [roleFilter, setRoleFilter] = useState<'all' | 'admin' | 'operator' | 'customer'>('all'); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New user modal form + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [role, setRole] = useState<'admin' | 'operator' | 'customer'>('operator'); + + useEffect(() => { + fetchUsers(); + }, []); + + const fetchUsers = async () => { + try { + const res = await fetch('/api/users'); + const data = await res.json(); + if (data.success) { + setUsers(data.users); + } + } catch (e) { + console.error(e); + } + }; + + const handleToggleStatus = async (user: User) => { + const newStatus = !user.isActive; + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, isActive: newStatus } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { isActive: newStatus } }), + }); + setToastMessage(`Estado de ${user.name} actualizado a ${newStatus ? '🟢 ACTIVO' : '⚪ INACTIVO'}.`); + } catch (e) { + console.error(e); + } + }; + + const handleChangeRole = async (user: User, newRole: 'admin' | 'operator' | 'customer') => { + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, role: newRole } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { role: newRole } }), + }); + setToastMessage(`Rol de ${user.name} actualizado a [${newRole.toUpperCase()}].`); + } catch (e) { + console.error(e); + } + }; + + const handleDeleteUser = async (id: string, name: string) => { + if (!confirm(`¿Estás seguro de eliminar al usuario ${name}?`)) return; + + setUsers((prev) => prev.filter((u) => u.id !== id)); + try { + await fetch(`/api/users?id=${id}`, { method: 'DELETE' }); + setToastMessage(`Usuario ${name} eliminado.`); + } catch (e) { + console.error(e); + } + }; + + const handleCreateUser = async (e: React.FormEvent) => { + e.preventDefault(); + try { + const res = await fetch('/api/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, phone, city, address, role }), + }); + const data = await res.json(); + if (data.success) { + setUsers((prev) => [data.user, ...prev]); + setIsModalOpen(false); + setName(''); + setEmail(''); + setPhone(''); + setAddress(''); + setToastMessage(`✨ Usuario "${data.user.name}" registrado con éxito.`); + } else { + alert(data.error); + } + } catch (e) { + console.error(e); + } + }; + + const handleWhatsApp = (user: User) => { + const cleanPhone = user.phone.startsWith('57') ? user.phone : `57${user.phone}`; + const text = encodeURIComponent(`Hola ${user.name}! Te escribimos del equipo de DripZone 🟣`); + window.open(`https://wa.me/${cleanPhone}?text=${text}`, '_blank'); + }; + + const filtered = users.filter((u) => { + const matchSearch = + u.name.toLowerCase().includes(search.toLowerCase()) || + u.email.toLowerCase().includes(search.toLowerCase()) || + u.phone.includes(search) || + (u.city && u.city.toLowerCase().includes(search.toLowerCase())); + + if (!matchSearch) return false; + if (roleFilter !== 'all' && u.role !== roleFilter) return false; + if (statusFilter === 'active' && !u.isActive) return false; + if (statusFilter === 'inactive' && u.isActive) return false; + return true; + }); + + const adminsCount = users.filter((u) => u.role === 'admin').length; + const operatorsCount = users.filter((u) => u.role === 'operator').length; + const customersCount = users.filter((u) => u.role === 'customer').length; + + return ( +
+ {/* Header */} +
+
+

+ + Control de Usuarios, Roles & Registro ({users.length}) +

+

+ Administra los accesos de administradores, operadores de logística y clientes registrados de la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* KPI Stats Cards */} +
+
+
+ +
+
+

Administradores

+

{adminsCount}

+
+
+ +
+
+ +
+
+

Operadores Logísticos

+

{operatorsCount}

+
+
+ +
+
+ +
+
+

Clientes Registrados

+

{customersCount}

+
+
+
+ + {/* Filters Toolbar */} +
+ {/* Role Pills */} +
+ + + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-neutral-900 border border-neutral-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-purple-400" + /> +
+
+ + {/* Users Table */} +
+
+ + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((user) => { + return ( + + {/* Active Status Toggle */} + + + {/* User Avatar & Name */} + + + {/* Contact */} + + + {/* City */} + + + {/* Role Dropdown */} + + + {/* Last Login */} + + + {/* Actions */} + + + ); + }) + )} + +
EstadoUsuarioContacto DirectoCiudad / DirecciónRol & PermisosÚltimo AccesoAcciones
+ No se encontraron usuarios con el filtro seleccionado. +
+ + +
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+ {user.email} +
+
+
+ +
+
+
+ {user.city || 'Cali'} + {user.address &&

{user.address}

} +
+
+ + + {user.lastLogin || user.createdAt} + + +
+
+
+ + {/* Modal Create User */} + {isModalOpen && ( +
+
+

Registrar Nuevo Usuario / Operador

+ +
+
+ + setName(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setEmail(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+
+ + setPhone(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setCity(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setAddress(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/dripzone-app/src/app/api/auth/login/route.ts b/dripzone-app/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..a2ae66e --- /dev/null +++ b/dripzone-app/src/app/api/auth/login/route.ts @@ -0,0 +1,29 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function POST(request: Request) { + try { + const { identifier } = await request.json(); + if (!identifier) { + return NextResponse.json({ success: false, error: 'Ingresa tu correo o celular' }, { status: 400 }); + } + const user = dataService.authenticate(identifier); + if (!user) { + return NextResponse.json( + { success: false, error: 'Usuario no encontrado. Verifica tu correo o celular.' }, + { status: 404 } + ); + } + if (!user.isActive) { + return NextResponse.json( + { success: false, error: 'Esta cuenta se encuentra inactiva. Contacta a soporte.' }, + { status: 403 } + ); + } + + dataService.updateUser(user.id, { lastLogin: 'Justo ahora' }); + return NextResponse.json({ success: true, user }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/auth/register/route.ts b/dripzone-app/src/app/api/auth/register/route.ts new file mode 100644 index 0000000..62b2a63 --- /dev/null +++ b/dripzone-app/src/app/api/auth/register/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function POST(request: Request) { + try { + const { name, email, phone, city, address } = await request.json(); + if (!name || !email || !phone) { + return NextResponse.json( + { success: false, error: 'Nombre, correo y celular son obligatorios' }, + { status: 400 } + ); + } + + const existing = dataService.authenticate(email) || dataService.authenticate(phone); + if (existing) { + return NextResponse.json( + { success: false, error: 'Ya existe una cuenta con este correo o celular' }, + { status: 409 } + ); + } + + const newUser: User = { + id: `usr-${Date.now()}`, + name, + email, + phone, + city: city || 'Cali', + address: address || '', + role: 'customer', + isActive: true, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + lastLogin: 'Justo ahora', + }; + + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/cities/route.ts b/dripzone-app/src/app/api/cities/route.ts new file mode 100644 index 0000000..3ecd601 --- /dev/null +++ b/dripzone-app/src/app/api/cities/route.ts @@ -0,0 +1,27 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const cities = dataService.getCities(); + return NextResponse.json({ success: true, cities }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateCity(id, updates); + return NextResponse.json({ success: true, city: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const created = dataService.addCity(body); + return NextResponse.json({ success: true, city: created }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/orders/route.ts b/dripzone-app/src/app/api/orders/route.ts new file mode 100644 index 0000000..9c996b6 --- /dev/null +++ b/dripzone-app/src/app/api/orders/route.ts @@ -0,0 +1,30 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { sendWhatsAppMessage, buildOrderConfirmationMessage } from '@/lib/evolution-api'; + +export async function GET() { + const orders = dataService.getOrders(); + return NextResponse.json({ success: true, orders }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newOrder = dataService.createOrder(body); + + // Enviar confirmación por WhatsApp en background si tiene teléfono válido + if (newOrder.customerPhone) { + try { + const msg = buildOrderConfirmationMessage(newOrder); + // Intentar enviar WhatsApp + await sendWhatsAppMessage(newOrder.customerPhone, msg); + } catch (waErr) { + console.warn('No se pudo enviar WhatsApp automático:', waErr); + } + } + + return NextResponse.json({ success: true, order: newOrder }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/payment-methods/route.ts b/dripzone-app/src/app/api/payment-methods/route.ts new file mode 100644 index 0000000..b49c62d --- /dev/null +++ b/dripzone-app/src/app/api/payment-methods/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const methods = dataService.getPaymentMethods(); + return NextResponse.json({ success: true, paymentMethods: methods }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updatePaymentMethod(id, updates); + return NextResponse.json({ success: true, paymentMethod: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/products/route.ts b/dripzone-app/src/app/api/products/route.ts new file mode 100644 index 0000000..9ebf898 --- /dev/null +++ b/dripzone-app/src/app/api/products/route.ts @@ -0,0 +1,46 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const includeAll = searchParams.get('all') === 'true'; + + let products = dataService.getProducts(); + if (!includeAll) { + products = products.filter((p) => p.isActive !== false); + } + + return NextResponse.json({ success: true, products }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newProduct = dataService.addProduct({ + ...body, + isActive: body.isActive !== undefined ? body.isActive : true, + }); + return NextResponse.json({ success: true, product: newProduct }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const { id, updates } = body; + if (!id) { + return NextResponse.json({ success: false, error: 'ID de producto requerido' }, { status: 400 }); + } + + const updated = dataService.updateProduct(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Producto no encontrado' }, { status: 404 }); + } + + return NextResponse.json({ success: true, product: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/publish/facebook/route.ts b/dripzone-app/src/app/api/publish/facebook/route.ts new file mode 100644 index 0000000..d2db7a3 --- /dev/null +++ b/dripzone-app/src/app/api/publish/facebook/route.ts @@ -0,0 +1,12 @@ +import { NextResponse } from 'next/server'; +import { publishToFacebookPage } from '@/lib/facebook-publisher'; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const result = await publishToFacebookPage(body); + return NextResponse.json(result); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/dripzone-app/src/app/api/settings/route.ts b/dripzone-app/src/app/api/settings/route.ts new file mode 100644 index 0000000..6073d91 --- /dev/null +++ b/dripzone-app/src/app/api/settings/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const settings = dataService.getSettings(); + return NextResponse.json({ success: true, settings }); +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const updated = dataService.updateSettings(body); + return NextResponse.json({ success: true, settings: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/users/route.ts b/dripzone-app/src/app/api/users/route.ts new file mode 100644 index 0000000..8b62fad --- /dev/null +++ b/dripzone-app/src/app/api/users/route.ts @@ -0,0 +1,57 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function GET() { + const users = dataService.getUsers(); + return NextResponse.json({ success: true, users }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newUser: User = { + id: `usr-${Date.now()}`, + name: body.name, + email: body.email, + phone: body.phone, + city: body.city || 'Cali', + address: body.address || '', + role: body.role || 'customer', + isActive: body.isActive !== false, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + }; + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateUser(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Usuario no encontrado' }, { status: 404 }); + } + return NextResponse.json({ success: true, user: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function DELETE(request: Request) { + try { + const { searchParams } = new URL(request.url); + const id = searchParams.get('id'); + if (!id) { + return NextResponse.json({ success: false, error: 'ID requerido' }, { status: 400 }); + } + const deleted = dataService.deleteUser(id); + return NextResponse.json({ success: deleted }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/dripzone-app/src/app/api/webhook/whatsapp/route.ts b/dripzone-app/src/app/api/webhook/whatsapp/route.ts new file mode 100644 index 0000000..3227db1 --- /dev/null +++ b/dripzone-app/src/app/api/webhook/whatsapp/route.ts @@ -0,0 +1,60 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { parseSupplierMessage } from '@/lib/gemini-parser'; +import { SupplierPost } from '@/types'; + +export async function GET() { + const posts = dataService.getSupplierPosts(); + return NextResponse.json({ success: true, posts }); +} + +export async function POST(request: Request) { + try { + const payload = await request.json(); + console.log('📥 Webhook Evolution API recibido:', JSON.stringify(payload).slice(0, 300)); + + const data = payload.data || payload; + + const messageContent = + data.message?.conversation || + data.message?.extendedTextMessage?.text || + data.message?.imageMessage?.caption || + data.text || + ''; + + const channelName = + data.pushName || + data.groupInfo?.subject || + (data.key?.remoteJid?.includes('g.us') ? 'Canal Mayorista Entrada' : 'Recepción Directa'); + + if (!messageContent || messageContent.trim().length < 5) { + return NextResponse.json({ success: true, ignored: 'Mensaje vacío o sin texto relevante' }); + } + + // Parsear con Gemini AI + const extracted = await parseSupplierMessage(messageContent); + + const newPost: SupplierPost = { + id: `post-${Date.now()}`, + channelName: data.groupInfo?.subject || channelName, + rawMessage: messageContent, + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: extracted, + status: 'pending_review', + receivedAt: 'Justo ahora', + }; + + dataService.addSupplierPost(newPost); + + return NextResponse.json({ + success: true, + message: 'Mensaje procesado con IA e ingresado al feed interno', + post: newPost, + }); + } catch (error: any) { + console.error('Error procesando webhook de WhatsApp:', error); + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/dripzone-app/src/app/api/whatsapp-groups/route.ts b/dripzone-app/src/app/api/whatsapp-groups/route.ts new file mode 100644 index 0000000..6f78a1c --- /dev/null +++ b/dripzone-app/src/app/api/whatsapp-groups/route.ts @@ -0,0 +1,104 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { MonitoredWhatsAppGroup } from '@/types'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url); + const fetchLive = searchParams.get('fetchLive') === 'true'; + + const localGroups = dataService.getMonitoredGroups(); + + if (!fetchLive) { + return NextResponse.json({ + success: true, + groups: localGroups, + }); + } + + // Consultar grupos en vivo desde Evolution API + try { + const response = await fetch( + `${EVOLUTION_API_URL}/group/fetchAllGroups/${EVOLUTION_INSTANCE_NAME}?getParticipants=false`, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + + const liveGroups = await response.json(); + + if (Array.isArray(liveGroups)) { + const merged: MonitoredWhatsAppGroup[] = liveGroups.map((lg: any) => { + const jid = lg.id || lg.jid; + const name = lg.subject || lg.name || 'Grupo Sin Nombre'; + const existing = localGroups.find((g) => g.jid === jid || g.name.toLowerCase() === name.toLowerCase()); + + return { + id: existing?.id || `grp-${jid.replace(/\D/g, '').slice(-6)}`, + jid, + name, + isMonitored: existing ? existing.isMonitored : false, + supplierId: existing?.supplierId, + supplierName: existing?.supplierName || name, + profitMarginOverride: existing?.profitMarginOverride || 35, + autoPublish: existing?.autoPublish ?? true, + participantsCount: lg.size || (lg.participants ? lg.participants.length : undefined), + notes: existing?.notes || '', + }; + }); + + // Asegurar que los locales que no vinieron en live sigan presentes + localGroups.forEach((lg) => { + if (!merged.some((m) => m.jid === lg.jid || m.id === lg.id)) { + merged.unshift(lg); + } + }); + + return NextResponse.json({ + success: true, + isLive: true, + totalLive: liveGroups.length, + groups: merged, + }); + } + } catch (err: any) { + console.warn('No se pudo conectar con Evolution API en vivo:', err.message); + } + + return NextResponse.json({ + success: true, + isLive: false, + groups: localGroups, + }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + + if (body.action === 'toggle') { + const { idOrJid, isMonitored } = body; + const updated = dataService.toggleGroupMonitoring(idOrJid, isMonitored); + return NextResponse.json({ success: true, group: updated }); + } + + if (Array.isArray(body.groups)) { + const saved = dataService.saveMonitoredGroups(body.groups); + return NextResponse.json({ success: true, groups: saved }); + } + + return NextResponse.json({ success: false, error: 'Datos no válidos' }, { status: 400 }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/dripzone-app/src/app/checkout/page.tsx b/dripzone-app/src/app/checkout/page.tsx new file mode 100644 index 0000000..45c7980 --- /dev/null +++ b/dripzone-app/src/app/checkout/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { ArrowLeft, CheckCircle2, ShieldCheck, Truck, Zap, QrCode, Phone, MapPin, User, MessageCircle, ExternalLink, CreditCard } from 'lucide-react'; +import { City, PaymentMethod, Order, StoreSettings } from '@/types'; +import { INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; +import confetti from 'canvas-confetti'; + +export default function CheckoutPage() { + const { currentBrand } = useBrand(); + + const [customerName, setCustomerName] = useState(''); + const [customerPhone, setCustomerPhone] = useState(''); + const [address, setAddress] = useState(''); + const [neighborhood, setNeighborhood] = useState(''); + const [notes, setNotes] = useState(''); + + const [cities, setCities] = useState(INITIAL_CITIES); + const [paymentMethods, setPaymentMethods] = useState(INITIAL_PAYMENT_METHODS); + const [selectedCityId, setSelectedCityId] = useState('city-cali'); + const [selectedPaymentId, setSelectedPaymentId] = useState('pay-deposit-10k'); + const [storeSettings, setStoreSettings] = useState(null); + + const [checkoutItems] = useState>([ + { + productId: INITIAL_PRODUCTS[0].id, + productName: INITIAL_PRODUCTS[0].name, + brand: INITIAL_PRODUCTS[0].brand, + size: '39', + quantity: 1, + price: INITIAL_PRODUCTS[0].retailPrice, + image: INITIAL_PRODUCTS[0].images[0], + }, + ]); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [orderCompleted, setOrderCompleted] = useState(null); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setPaymentMethods(d.paymentMethods)) + .catch(() => {}); + + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setStoreSettings(d.settings)) + .catch(() => {}); + }, []); + + const activeCity = cities.find((c) => c.id === selectedCityId) || cities[0]; + const activePayment = paymentMethods.find((p) => p.id === selectedPaymentId) || paymentMethods[0]; + + const subtotal = checkoutItems.reduce((acc, it) => acc + it.price * it.quantity, 0); + const shippingCost = activeCity.shippingCost; + const totalAmount = subtotal + shippingCost; + + const depositAmount = activePayment.requiresDeposit ? activePayment.depositAmount : 0; + const balanceDue = totalAmount - depositAmount; + + const officialWhatsapp = storeSettings?.whatsappNumber || '573167455877'; + const boldLink = storeSettings?.boldPaymentLink || 'https://bold.co/p/carlos-lasso'; + + const handleSubmitOrder = async (e: React.FormEvent) => { + e.preventDefault(); + if (!customerName || !customerPhone || !address) { + alert('Por favor completa tu nombre, celular y dirección para el despacho.'); + return; + } + + setIsSubmitting(true); + + try { + const orderPayload = { + customerName, + customerPhone, + address: `${address} - Barrio: ${neighborhood || 'Centro'}`, + cityId: activeCity.id, + cityName: activeCity.name, + items: checkoutItems, + subtotal, + shippingCost, + totalAmount, + depositAmount, + balanceDue, + paymentMethodId: activePayment.id, + paymentMethodName: activePayment.name, + notes, + }; + + const res = await fetch('/api/orders', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(orderPayload), + }); + + const data = await res.json(); + if (data.success) { + setOrderCompleted(data.order); + confetti({ + particleCount: 100, + spread: 70, + origin: { y: 0.6 }, + }); + } + } catch (err) { + console.error('Error creando orden:', err); + } finally { + setIsSubmitting(false); + } + }; + + const handleOpenWhatsAppOrder = (order: Order) => { + const text = `🎉 *CONFIRMACIÓN DE PEDIDO EN ${currentBrand.name} #${order.id}* 🎉 + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *Artículos:* +${order.items.map((i) => `• ${i.productName} (Talla ${i.size}) x${i.quantity} = ${formatCOP(i.price * i.quantity)}`).join('\n')} + +💰 *Total:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +¡Hola ${currentBrand.shortName}! Acabo de registrar mi pedido en la web. ¿Me confirman despacho por favor?`; + + window.open(`https://wa.me/${officialWhatsapp}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + if (orderCompleted) { + return ( +
+
+
+ +
+ +
+ + ¡Pedido Registrado con Éxito! + +

Orden #{orderCompleted.id}

+

+ Hemos recibido tu solicitud para entrega en {orderCompleted.cityName} con {currentBrand.name}. +

+
+ + {/* Bold.co or Nequi Separation Box */} + {orderCompleted.depositAmount > 0 ? ( +
+
+ + Paso 2: Realiza la separación de $10.000 COP +
+

+ Paga de inmediato con Link de Pago Bold.co (PSE / Tarjeta / Nequi) o transfiere a nuestra cuenta oficial: +

+ + {boldLink && ( + + + Pagar $10.000 COP con Bold.co (PSE / Tarjetas) + + + )} + +
+ 📱 Nequi / Daviplata: {storeSettings?.nequiAccount || '316 745 5877'} ({storeSettings?.accountHolder || 'Carlos Andrés Lasso'}) +
+

+ 🤝 Cancelas el saldo de {formatCOP(orderCompleted.balanceDue)} al recibir el paquete en tu casa. +

+
+ ) : ( +
+

+ Tu pedido quedó programado para entrega contraentrega en 24 horas. ¡Nos pondremos en contacto contigo por WhatsApp! +

+
+ )} + +
+ + + + Volver a la Tienda + +
+
+
+ ); + } + + return ( +
+
+ {/* Header */} +
+ + + Regresar a {currentBrand.name} + +
+ + Compra Segura & Garantizada +
+
+ +
+ {/* Left Column: Shipping & Payment Details (7 cols) */} +
+ {/* 1. Datos del Cliente */} +
+

+ + 1. Datos de Entrega +

+ +
+
+ + setCustomerName(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-sm text-white focus:border-purple-400 outline-hidden" + /> +
+
+ + setCustomerPhone(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-sm text-white focus:border-purple-400 outline-hidden" + /> +
+
+ + {/* City Selection */} +
+ + +
+ +
+
+ + setAddress(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-sm text-white focus:border-purple-400 outline-hidden" + /> +
+
+ + setNeighborhood(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-sm text-white focus:border-purple-400 outline-hidden" + /> +
+
+
+ + {/* 2. Método de Pago */} +
+

+ + 2. Selecciona tu Método de Pago +

+ +
+ {paymentMethods.map((method) => { + const isSelected = selectedPaymentId === method.id; + return ( +
setSelectedPaymentId(method.id)} + className={`p-4 rounded-2xl border transition-all cursor-pointer space-y-1.5 ${ + isSelected + ? `border-purple-400 bg-purple-950/20 shadow-md` + : 'border-neutral-800 hover:border-neutral-700 bg-neutral-950' + }`} + > +
+
+
+ {isSelected &&
} +
+ {method.name} +
+ + {method.requiresDeposit && ( + + Separa con $10.000 + + )} +
+ +

{method.description}

+ + {isSelected && (method.accountInfo || (method.type === 'bold' && boldLink)) && ( +
+ {method.accountInfo &&

{method.accountInfo}

} + {method.type === 'bold' && boldLink && ( + + + Abrir Link de Pago Bold.co + + )} +
+ )} +
+ ); + })} +
+
+
+ + {/* Right Column: Summary (5 cols) */} +
+
+

Resumen del Pedido

+ + {/* Items */} +
+ {checkoutItems.map((item, i) => ( +
+ +
+

{item.productName}

+

Talla: {item.size} | Cant: {item.quantity}

+

+ {formatCOP(item.price * item.quantity)} +

+
+
+ ))} +
+ + {/* Breakdown */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Envío ({activeCity.name}): + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total a Pagar: + + {formatCOP(totalAmount)} + +
+ + {depositAmount > 0 && ( +
+
+ Separación por Bold / Nequi / Daviplata: + {formatCOP(depositAmount)} +
+
+ Saldo a pagar al mensajero: + {formatCOP(balanceDue)} +
+
+ )} + +
+
+ + Garantía en {activeCity.name}: +
+

+ {activeCity.firstExchangeFree + ? '1er Cambio de Talla 100% GRATIS (cambios posteriores con flete estándar).' + : 'Cambios de talla 100% garantizados (los costos de envío son asumidos por el cliente).'} +

+
+
+ + + +

+ Al confirmar, se guardará tu pedido y recibirás asistencia inmediata por WhatsApp oficial ({officialWhatsapp}) para el seguimiento de tu entrega en 24 horas. +

+
+
+ +
+
+ ); +} diff --git a/dripzone-app/src/app/favicon.ico b/dripzone-app/src/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/dripzone-app/src/app/favicon.ico differ diff --git a/dripzone-app/src/app/globals.css b/dripzone-app/src/app/globals.css new file mode 100644 index 0000000..a2dc41e --- /dev/null +++ b/dripzone-app/src/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/dripzone-app/src/app/layout.tsx b/dripzone-app/src/app/layout.tsx new file mode 100644 index 0000000..6e94495 --- /dev/null +++ b/dripzone-app/src/app/layout.tsx @@ -0,0 +1,61 @@ +import type { Metadata, Viewport } from 'next'; +import { Geist, Geist_Mono } from 'next/font/google'; +import './globals.css'; +import { BrandProvider } from '@/context/BrandContext'; +import { AuthProvider } from '@/context/AuthContext'; + +const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], +}); + +const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], +}); + +export const viewport: Viewport = { + themeColor: '#8b5cf6', + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + viewportFit: 'cover', +}; + +export const metadata: Metadata = { + title: 'DripZone • Luxury Streetwear', + description: 'Zapatillas exclusivas y calzado de colección con despacho contraentrega en 24 horas.', + manifest: '/manifest.json', + appleWebApp: { + capable: true, + statusBarStyle: 'black-translucent', + title: 'DripZone', + }, + icons: { + icon: '/icon.svg', + apple: '/icon.svg', + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + + + + {children} + + + + + ); +} diff --git a/dripzone-app/src/app/page.tsx b/dripzone-app/src/app/page.tsx new file mode 100644 index 0000000..e4b60ff --- /dev/null +++ b/dripzone-app/src/app/page.tsx @@ -0,0 +1,284 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Navbar } from '@/components/store/Navbar'; +import { FlashDealsBanner } from '@/components/store/FlashDealsBanner'; +import { CategoryPills } from '@/components/store/CategoryPills'; +import { ProductCard } from '@/components/store/ProductCard'; +import { ProductModal } from '@/components/store/ProductModal'; +import { CartDrawer } from '@/components/store/CartDrawer'; +import { CitySelectorModal } from '@/components/store/CitySelectorModal'; +import { MobileBottomDock } from '@/components/mobile/MobileBottomDock'; +import { MobileInstallBanner } from '@/components/mobile/MobileInstallBanner'; +import { AuthModal } from '@/components/auth/AuthModal'; +import { Product, City, CartItem } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_CITIES } from '@/lib/data-service'; +import { Sparkles, ShieldCheck, Truck, RefreshCw, Zap } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export default function StoreHomePage() { + const { currentBrand } = useBrand(); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [cities, setCities] = useState(INITIAL_CITIES); + const [selectedCity, setSelectedCity] = useState(INITIAL_CITIES[0]); // Cali + const [activeCategory, setActiveCategory] = useState('all'); + const [searchQuery, setSearchQuery] = useState(''); + + // Modals & Drawers state + const [selectedProduct, setSelectedProduct] = useState(null); + const [isCartOpen, setIsCartOpen] = useState(false); + const [isCityModalOpen, setIsCityModalOpen] = useState(false); + const [isInstallModalOpen, setIsInstallModalOpen] = useState(false); + const [cartItems, setCartItems] = useState([]); + + const cartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + useEffect(() => { + fetch('/api/products') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.products?.length > 0) { + setProducts(data.products); + } + }) + .catch((e) => console.log('Usando catálogo inicial:', e)); + + fetch('/api/cities') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.cities?.length > 0) { + setCities(data.cities); + const defaultCali = data.cities.find((c: City) => c.name.toLowerCase().includes('cali')); + if (defaultCali) setSelectedCity(defaultCali); + } + }) + .catch((e) => console.log('Usando ciudades iniciales:', e)); + }, []); + + const filteredProducts = products.filter((p) => { + if (searchQuery.trim()) { + const q = searchQuery.toLowerCase(); + const matchName = p.name.toLowerCase().includes(q); + const matchBrand = p.brand.toLowerCase().includes(q); + const matchSize = p.sizes.some((s) => s.includes(q)); + if (!matchName && !matchBrand && !matchSize) return false; + } + + if (activeCategory === 'flash') return p.isFlashDeal; + if (activeCategory === 'under120') return p.retailPrice <= 120000; + if (activeCategory !== 'all') { + return p.brand.toLowerCase() === activeCategory.toLowerCase(); + } + return true; + }); + + const handleAddToCart = (product: Product, size: string) => { + setCartItems((prev) => { + const existingIdx = prev.findIndex( + (item) => item.product.id === product.id && item.selectedSize === size + ); + if (existingIdx > -1) { + const next = [...prev]; + next[existingIdx].quantity += 1; + return next; + } + return [...prev, { product, selectedSize: size, quantity: 1 }]; + }); + setIsCartOpen(true); + }; + + const handleRemoveFromCart = (productId: string, size: string) => { + setCartItems((prev) => + prev.filter((item) => !(item.product.id === productId && item.selectedSize === size)) + ); + }; + + const handleUpdateQuantity = (productId: string, size: string, delta: number) => { + setCartItems((prev) => + prev + .map((item) => { + if (item.product.id === productId && item.selectedSize === size) { + const newQty = item.quantity + delta; + return newQty > 0 ? { ...item, quantity: newQty } : null; + } + return item; + }) + .filter(Boolean) as CartItem[] + ); + }; + + const totalCartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + return ( +
+ {/* Navigation Header */} + setIsCartOpen(true)} + selectedCity={selectedCity} + onOpenCitySelector={() => setIsCityModalOpen(true)} + searchQuery={searchQuery} + onSearchChange={setSearchQuery} + /> + + {/* Main Container */} +
+ {/* Flash Deals Hero Banner */} + + + {/* Value Props Strip */} +
+
+
+ +
+
+

Entrega en 24 Horas

+

Directo en Cali

+
+
+ +
+
+ +
+
+

Pago Contraentrega

+

Cancelas al recibir

+
+
+ +
+
+ +
+
+

Separa con $10.000

+

Aparta tu talla

+
+
+ +
+
+ +
+
+

Garantía Total

+

Cambio asegurado

+
+
+
+ + {/* Category & Brand Filters */} +
+
+

+ + Colección de Calzado & Sneakers +

+ + {filteredProducts.length} {filteredProducts.length === 1 ? 'modelo' : 'modelos'} + +
+ + +
+ + {/* Product Grid */} + {filteredProducts.length === 0 ? ( +
+
+ +
+

No encontramos zapatillas con ese criterio

+

Intenta buscar otra marca o restablecer los filtros.

+ +
+ ) : ( +
+ {filteredProducts.map((product) => ( + handleAddToCart(p, size)} + /> + ))} +
+ )} +
+ + {/* Footer */} +
+
+
+
+ {currentBrand.logo.iconText} +
+ {currentBrand.name} +
+

© 2026 {currentBrand.name}. Despachos urbanos y nacionales con pago contraentrega.

+
+ + {currentBrand.badge} +
+
+
+ + {/* Modals & Drawers */} + setSelectedProduct(null)} + onAddToCart={handleAddToCart} + selectedCity={selectedCity} + /> + + setIsCartOpen(false)} + cartItems={cartItems} + onRemoveItem={handleRemoveFromCart} + onUpdateQuantity={handleUpdateQuantity} + selectedCity={selectedCity} + onOpenCitySelector={() => { + setIsCartOpen(false); + setIsCityModalOpen(true); + }} + /> + + setIsCityModalOpen(false)} + cities={cities} + selectedCity={selectedCity} + onSelectCity={setSelectedCity} + /> + + {/* Mobile App Dock & Install Banner */} + setIsCartOpen(true)} + onOpenInstallModal={() => setIsInstallModalOpen(true)} + /> + + setIsInstallModalOpen(false)} + /> + + {/* User Auth Modal */} + +
+ ); +} diff --git a/dripzone-app/src/components/auth/AuthModal.tsx b/dripzone-app/src/components/auth/AuthModal.tsx new file mode 100644 index 0000000..d0a6fa7 --- /dev/null +++ b/dripzone-app/src/components/auth/AuthModal.tsx @@ -0,0 +1,255 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, User, Lock, Mail, Phone, MapPin, Sparkles, LogIn, UserPlus, Shield, LogOut } from 'lucide-react'; +import { useAuth } from '@/context/AuthContext'; +import { useBrand } from '@/context/BrandContext'; +import Link from 'next/link'; + +export const AuthModal: React.FC = () => { + const { user, login, register, logout, isAuthModalOpen, closeAuthModal } = useAuth(); + const { currentBrand } = useBrand(); + + const [mode, setMode] = useState<'login' | 'register'>('login'); + const [identifier, setIdentifier] = useState(''); + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + if (!isAuthModalOpen) return null; + + const handleLoginSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await login(identifier); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al iniciar sesión'); + } + }; + + const handleRegisterSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await register({ name, email, phone, city, address }); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al registrarse'); + } + }; + + return ( +
+
+ + + {/* If user is already logged in: View Profile */} + {user ? ( +
+
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+

{user.email}

+
+ + {user.role === 'admin' ? '👑 Administrador' : user.role === 'operator' ? '📦 Operador Logística' : '🛍️ Cliente Registrado'} + +
+
+ +
+

📱 Celular: {user.phone}

+

📍 Ciudad: {user.city || 'Cali'}

+ {user.address &&

🏠 Dirección: {user.address}

} +
+ + {user.role === 'admin' || user.role === 'operator' ? ( + + + Ir al Panel de Control Admin + + ) : null} + + +
+ ) : ( + /* Login or Register */ +
+
+
+ {currentBrand.shortName[0]} +
+
+

+ {mode === 'login' ? 'Iniciar Sesión' : 'Crear Cuenta'} +

+

+ {mode === 'login' + ? 'Accede para gestionar pedidos o entrar como admin' + : 'Regístrate para compras rápidas y seguimiento'} +

+
+
+ + {/* Mode Switch Tabs */} +
+ + +
+ + {error && ( +
+ {error} +
+ )} + + {mode === 'login' ? ( +
+
+ + setIdentifier(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2.5 text-white outline-hidden focus:border-purple-400" + /> +
+ + + +

+ Tip Admin: Puedes ingresar con carlos@dripzone.co o 3134848203. +

+
+ ) : ( +
+
+ + setName(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400" + /> +
+ +
+
+ + setEmail(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400" + /> +
+ +
+ + setPhone(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400" + /> +
+
+ +
+
+ + setCity(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400" + /> +
+
+ + setAddress(e.target.value)} + className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400" + /> +
+
+ + +
+ )} +
+ )} +
+
+ ); +}; diff --git a/dripzone-app/src/components/mobile/MobileBottomDock.tsx b/dripzone-app/src/components/mobile/MobileBottomDock.tsx new file mode 100644 index 0000000..059a3ba --- /dev/null +++ b/dripzone-app/src/components/mobile/MobileBottomDock.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { Home, Search, ShoppingBag, MessageCircle, Download, Check } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileBottomDockProps { + cartCount: number; + onOpenCart: () => void; + onOpenSearch?: () => void; + onOpenInstallModal: () => void; +} + +export const MobileBottomDock: React.FC = ({ + cartCount, + onOpenCart, + onOpenSearch, + onOpenInstallModal, +}) => { + const { currentBrand } = useBrand(); + const [activeTab, setActiveTab] = useState('home'); + + const handleWhatsApp = () => { + const text = encodeURIComponent( + `Hola ${currentBrand.name}! 👋 Quiero consultar la disponibilidad de unas zapatillas para despacho contraentrega en 24 horas.` + ); + window.open(`https://wa.me/${currentBrand.whatsappNumber}?text=${text}`, '_blank'); + }; + + return ( +
+
+ setActiveTab('home')} + className={`flex flex-col items-center gap-0.5 cursor-pointer transition-all ${ + activeTab === 'home' ? 'text-white' : 'text-neutral-400 hover:text-neutral-200' + }`} + > + + Inicio + + + + + + + + + +
+
+ ); +}; diff --git a/dripzone-app/src/components/mobile/MobileInstallBanner.tsx b/dripzone-app/src/components/mobile/MobileInstallBanner.tsx new file mode 100644 index 0000000..1c64ca5 --- /dev/null +++ b/dripzone-app/src/components/mobile/MobileInstallBanner.tsx @@ -0,0 +1,125 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Download, Sparkles, X, Smartphone, CheckCircle, Share2, PlusSquare } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileInstallBannerProps { + isOpen: boolean; + onClose: () => void; +} + +export const MobileInstallBanner: React.FC = ({ isOpen, onClose }) => { + const { currentBrand } = useBrand(); + const [deferredPrompt, setDeferredPrompt] = useState(null); + const [isInstalled, setIsInstalled] = useState(false); + const [isIOS, setIsIOS] = useState(false); + + useEffect(() => { + const userAgent = window.navigator.userAgent.toLowerCase(); + const isIosDevice = /iphone|ipad|ipod/.test(userAgent); + setIsIOS(isIosDevice); + + const isStandalone = window.matchMedia('(display-mode: standalone)').matches; + if (isStandalone) { + setIsInstalled(true); + } + + const handleBeforeInstall = (e: Event) => { + e.preventDefault(); + setDeferredPrompt(e); + }; + + window.addEventListener('beforeinstallprompt', handleBeforeInstall); + return () => window.removeEventListener('beforeinstallprompt', handleBeforeInstall); + }, []); + + const handleInstallClick = async () => { + if (deferredPrompt) { + deferredPrompt.prompt(); + const { outcome } = await deferredPrompt.userChoice; + if (outcome === 'accepted') { + setIsInstalled(true); + onClose(); + } + setDeferredPrompt(null); + } + }; + + if (!isOpen) return null; + + return ( +
+
+ + +
+
+ {currentBrand.shortName[0]} +
+
+

Instalar {currentBrand.name}

+

Aplicación Móvil para Android & iPhone

+
+
+ +
+
+ + Acceso instantáneo desde la pantalla de inicio de tu celular +
+
+ + Drops exclusivos y lanzamientos de sneakers limitados +
+
+ + Navegación ultra rápida sin consumir espacio de memoria +
+
+ + {isIOS ? ( +
+

+ + Instrucciones para iPhone (Safari): +

+
    +
  1. Toca el botón Compartir abajo en Safari.
  2. +
  3. Desliza hacia abajo y selecciona "Agregar a Inicio ".
  4. +
  5. ¡Listo! El icono de {currentBrand.shortName} aparecerá en tu teléfono.
  6. +
+
+ ) : deferredPrompt ? ( + + ) : ( +
+
+

Para instalar en tu navegador:

+

+ Abre el menú de opciones del navegador (los 3 puntos arriba a la derecha) y toca "Instalar aplicación" o "Agregar a pantalla principal". +

+
+ +
+ )} +
+
+ ); +}; diff --git a/dripzone-app/src/components/store/CartDrawer.tsx b/dripzone-app/src/components/store/CartDrawer.tsx new file mode 100644 index 0000000..bca5a6d --- /dev/null +++ b/dripzone-app/src/components/store/CartDrawer.tsx @@ -0,0 +1,254 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { X, Trash2, ShoppingBag, ArrowRight, Zap, Truck, MessageCircle } from 'lucide-react'; +import { CartItem, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface CartDrawerProps { + isOpen: boolean; + onClose: () => void; + cartItems: CartItem[]; + onRemoveItem: (productId: string, size: string) => void; + onUpdateQuantity: (productId: string, size: string, delta: number) => void; + selectedCity: City; + onOpenCitySelector: () => void; +} + +export const CartDrawer: React.FC = ({ + isOpen, + onClose, + cartItems, + onRemoveItem, + onUpdateQuantity, + selectedCity, + onOpenCitySelector, +}) => { + const { currentBrand } = useBrand(); + const [officialPhone, setOfficialPhone] = React.useState('573167455877'); + + React.useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => { + if (d.success && d.settings?.whatsappNumber) { + setOfficialPhone(d.settings.whatsappNumber); + } + }) + .catch(() => {}); + }, []); + + if (!isOpen) return null; + + const subtotal = cartItems.reduce((acc, item) => acc + item.product.retailPrice * item.quantity, 0); + const shippingCost = selectedCity.shippingCost; + const totalAmount = subtotal + shippingCost; + const separation = calculateSeparationBreakdown(totalAmount); + + const handleWhatsAppCheckout = () => { + const itemsList = cartItems + .map((item) => `👟 *${item.product.name}* (Talla: *${item.selectedSize}*, Cant: ${item.quantity}) - ${formatCOP(item.product.retailPrice * item.quantity)}`) + .join('\n'); + + const text = `🔥 *NUEVO PEDIDO DESDE ${currentBrand.name}* 🔥 + +📦 *Productos seleccionados:* +${itemsList} + +📍 *Ciudad de entrega:* ${selectedCity.name} +💵 *Subtotal:* ${formatCOP(subtotal)} +🚚 *Envío:* ${shippingCost === 0 ? 'GRATIS' : formatCOP(shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(totalAmount)} COP + +⚡ *Condición de Pago:* Pago Contraentrega (Separo con $10.000 COP vía Bold/Nequi y cancelo saldo de ${formatCOP(separation.balanceDue)} al recibir). + +Por favor confírmenme para enviarles los datos de mi dirección.`; + + window.open(`https://wa.me/${officialPhone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+ {/* Backdrop */} +
+ +
+
+ {/* Header */} +
+
+
+ +
+
+

Tu Carrito • {currentBrand.shortName}

+

{cartItems.length} {cartItems.length === 1 ? 'artículo' : 'artículos'}

+
+
+ +
+ + {/* Items List */} +
+ {cartItems.length === 0 ? ( +
+
+ +
+

Tu carrito está vacío

+

+ Aprovecha las ofertas de calzado con pago contraentrega en Cali y despachos nacionales. +

+ +
+ ) : ( + cartItems.map((item, idx) => ( +
+ {item.product.name} +
+
+
+

+ {item.product.name} +

+ +
+
+ + Talla {item.selectedSize} + + + {item.product.brand} + +
+
+ +
+ + {formatCOP(item.product.retailPrice * item.quantity)} + +
+ + {item.quantity} + +
+
+
+
+ )) + )} +
+ + {/* Footer & Checkout Breakdown */} + {cartItems.length > 0 && ( +
+ {/* City Delivery selector pill */} +
+
+ + Destino: {selectedCity.name} +
+ +
+ + {/* Price Calculations */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Costo de Envío: + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total de la Orden: + + {formatCOP(totalAmount)} + +
+
+ + {/* Separation Highlight Banner */} +
+

+ + Opción de Separación con $10.000 COP +

+

+ Separas con {formatCOP(separation.depositAmount)} y pagas {formatCOP(separation.balanceDue)} al recibir contraentrega en tu casa. +

+

+ 🛡️ {selectedCity.firstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${selectedCity.name}` + : `Garantía de cambio en ${selectedCity.name} (flete asumido por cliente)`} +

+
+ + {/* Action Buttons */} +
+ + Proceder al Pago Contraentrega + + + + +
+
+ )} +
+
+
+ ); +}; diff --git a/dripzone-app/src/components/store/CategoryPills.tsx b/dripzone-app/src/components/store/CategoryPills.tsx new file mode 100644 index 0000000..be49b4b --- /dev/null +++ b/dripzone-app/src/components/store/CategoryPills.tsx @@ -0,0 +1,48 @@ +'use client'; + +import React from 'react'; +import { useBrand } from '@/context/BrandContext'; + +interface CategoryPillsProps { + activeCategory: string; + onSelectCategory: (category: string) => void; +} + +const CATEGORIES = [ + { id: 'all', label: '🔥 Todas las Zapatillas' }, + { id: 'Nike', label: '👟 Nike' }, + { id: 'Jordan', label: '🏀 Air Jordan' }, + { id: 'Adidas', label: '🛹 Adidas' }, + { id: 'New Balance', label: '🌿 New Balance' }, + { id: 'Puma', label: '🐆 Puma' }, + { id: 'flash', label: '⚡ Ofertas Flash' }, + { id: 'under120', label: '💰 Menos de $120k' }, +]; + +export const CategoryPills: React.FC = ({ + activeCategory, + onSelectCategory, +}) => { + const { currentBrand } = useBrand(); + + return ( +
+ {CATEGORIES.map((cat) => { + const isActive = activeCategory === cat.id; + return ( + + ); + })} +
+ ); +}; diff --git a/dripzone-app/src/components/store/CitySelectorModal.tsx b/dripzone-app/src/components/store/CitySelectorModal.tsx new file mode 100644 index 0000000..200d468 --- /dev/null +++ b/dripzone-app/src/components/store/CitySelectorModal.tsx @@ -0,0 +1,109 @@ +'use client'; + +import React from 'react'; +import { X, MapPin, Check, Truck } from 'lucide-react'; +import { City } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +interface CitySelectorModalProps { + isOpen: boolean; + onClose: () => void; + cities: City[]; + selectedCity: City; + onSelectCity: (city: City) => void; +} + +export const CitySelectorModal: React.FC = ({ + isOpen, + onClose, + cities, + selectedCity, + onSelectCity, +}) => { + if (!isOpen) return null; + + return ( +
+
+ {/* Header */} +
+
+
+ +
+
+

Selecciona tu Ciudad

+

Calculamos tiempos y tarifas oficiales

+
+
+ +
+ + {/* City list */} +
+ {cities + .filter((c) => c.isActive !== false) + .map((city) => { + const isSelected = selectedCity.id === city.id; + const hasCod = city.allowsContraentrega || city.allowCod; + + return ( +
{ + onSelectCity(city); + onClose(); + }} + className={`p-3 rounded-2xl border transition-all cursor-pointer flex items-center justify-between ${ + isSelected + ? 'border-purple-400 bg-purple-950/50 shadow-[0_0_15px_rgba(168,85,247,0.2)]' + : 'border-neutral-800 hover:border-neutral-700 bg-neutral-950' + }`} + > +
+
+ {city.name} + {hasCod && ( + + Contraentrega + + )} +
+

+ + {city.deliveryTime} +

+
+ +
+ + {city.shippingCost === 0 ? ( + Gratis + ) : ( + formatCOP(city.shippingCost) + )} + + {isSelected && ( +
+ +
+ )} +
+
+ ); + })} +
+ + {/* Info footer */} +
+ 💡 En Cali y zona metropolitana: entregas el mismo día con mensajería directa y pago contraentrega. +
+
+
+ ); +}; diff --git a/dripzone-app/src/components/store/FlashDealsBanner.tsx b/dripzone-app/src/components/store/FlashDealsBanner.tsx new file mode 100644 index 0000000..e26b007 --- /dev/null +++ b/dripzone-app/src/components/store/FlashDealsBanner.tsx @@ -0,0 +1,83 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Zap, Clock, Gift } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export const FlashDealsBanner: React.FC = () => { + const { currentBrand } = useBrand(); + const [timeLeft, setTimeLeft] = useState({ hours: 4, minutes: 27, seconds: 15 }); + + useEffect(() => { + const timer = setInterval(() => { + setTimeLeft((prev) => { + if (prev.seconds > 0) { + return { ...prev, seconds: prev.seconds - 1 }; + } else if (prev.minutes > 0) { + return { ...prev, minutes: 59, seconds: 59 }; + } else if (prev.hours > 0) { + return { hours: prev.hours - 1, minutes: 59, seconds: 59 }; + } + return { hours: 5, minutes: 59, seconds: 59 }; + }); + }, 1000); + return () => clearInterval(timer); + }, []); + + const pad = (n: number) => n.toString().padStart(2, '0'); + + return ( +
+ {/* Background glow meshes */} +
+
+ +
+ {/* Left text */} +
+
+ + {currentBrand.shortName.toUpperCase()} DROPS • OFERTAS FLASH +
+

+ Zapatillas Premium hasta con{' '} + + 35% OFF + +

+

+ Lanzamientos exclusivos directos de bodega. Separa tu par con $10.000 COP y paga el saldo en efectivo o transferencia con Pago Contraentrega en tu casa. +

+
+ + {/* Right Countdown Box */} +
+
+ + Oferta expira en: +
+
+
+ {pad(timeLeft.hours)} + Horas +
+ : +
+ {pad(timeLeft.minutes)} + Min +
+ : +
+ {pad(timeLeft.seconds)} + Seg +
+
+
+ + Cupón: {currentBrand.couponCode} aplicado +
+
+
+
+ ); +}; diff --git a/dripzone-app/src/components/store/Navbar.tsx b/dripzone-app/src/components/store/Navbar.tsx new file mode 100644 index 0000000..67afae7 --- /dev/null +++ b/dripzone-app/src/components/store/Navbar.tsx @@ -0,0 +1,152 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { ShoppingBag, Search, MapPin, Zap, Sparkles, ShieldCheck, Store, User as UserIcon } from 'lucide-react'; +import { City } from '@/types'; +import { useBrand } from '@/context/BrandContext'; +import { useAuth } from '@/context/AuthContext'; + +interface NavbarProps { + cartCount: number; + onOpenCart: () => void; + selectedCity: City; + onOpenCitySelector: () => void; + searchQuery: string; + onSearchChange: (q: string) => void; +} + +export const Navbar: React.FC = ({ + cartCount, + onOpenCart, + selectedCity, + onOpenCitySelector, + searchQuery, + onSearchChange, +}) => { + const { currentBrand } = useBrand(); + const { user, openAuthModal } = useAuth(); + + return ( +
+ {/* Top Banner Urgency */} +
+
+
+ + 🔥 ENVÍOS CONTRAENTREGA EN {selectedCity.name.toUpperCase()} Y TODO COLOMBIA +
+
+ + + Separa tu par con solo $10.000 COP + + • + + + {selectedCity.firstExchangeFree + ? `1er Cambio GRATIS en ${selectedCity.name}` + : `Garantía de Cambio (${selectedCity.name})`} + +
+
+
+ + {/* Main Navbar */} +
+ {/* Brand Logo */} + +
+
+ + {currentBrand.logo.iconText} + +
+
+
+
+ {currentBrand.logo.mainText} + + {currentBrand.logo.accentText} + +
+

{currentBrand.tagline}

+
+ + + {/* City Selector Pill */} + + + {/* Search Bar */} +
+
+ onSearchChange(e.target.value)} + className="w-full bg-neutral-900/90 text-white placeholder-neutral-400 text-xs sm:text-sm rounded-full pl-10 pr-4 py-2 border border-neutral-700 focus:border-purple-400 focus:ring-2 focus:ring-purple-500/20 transition-all outline-hidden" + /> + +
+
+ + {/* Right Actions */} +
+ {/* User Auth Button */} + + + {/* Admin Link */} + + + Admin + + + {/* Cart Button */} + +
+
+
+ ); +}; diff --git a/dripzone-app/src/components/store/ProductCard.tsx b/dripzone-app/src/components/store/ProductCard.tsx new file mode 100644 index 0000000..9ba227c --- /dev/null +++ b/dripzone-app/src/components/store/ProductCard.tsx @@ -0,0 +1,132 @@ +'use client'; + +import React from 'react'; +import { Star, Zap, Truck, ShoppingBag } from 'lucide-react'; +import { Product } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductCardProps { + product: Product; + onOpenDetail: (product: Product) => void; + onQuickAdd: (product: Product, size: string) => void; +} + +export const ProductCard: React.FC = ({ + product, + onOpenDetail, +}) => { + const { currentBrand } = useBrand(); + const discountPercent = product.originalPrice + ? Math.round(((product.originalPrice - product.retailPrice) / product.originalPrice) * 100) + : 28; + + const separation = calculateSeparationBreakdown(product.retailPrice); + + return ( +
onOpenDetail(product)} + className={`group rounded-2xl border transition-all duration-300 flex flex-col cursor-pointer overflow-hidden ${currentBrand.colors.cardBg}`} + > + {/* Image Container */} +
+ {product.name} + + {/* Badges */} +
+ + -{discountPercent}% OFF + + {product.isFlashDeal && ( + + FLASH + + )} +
+ +
+ + Contraentrega + + + {product.brand} + +
+
+ + {/* Product Info */} +
+
+ {/* Rating and Sales */} +
+
+ + {product.rating || 4.9} + ({product.reviewsCount || 89}) +
+ + +{product.salesCount || 150} pedidos + +
+ + {/* Product Title */} +

+ {product.name} +

+ + {/* Available Sizes Pills */} +
+ Tallas: + {product.sizes.slice(0, 5).map((size) => ( + + {size} + + ))} + {product.sizes.length > 5 && ( + +{product.sizes.length - 5} + )} +
+
+ + {/* Pricing & Separation terms */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ +

+ ⚡ Separa con {formatCOP(separation.depositAmount)} y cancelas {formatCOP(separation.balanceDue)} al recibir. +

+ + {/* Quick Action Button */} +
+ +
+
+
+
+ ); +}; diff --git a/dripzone-app/src/components/store/ProductModal.tsx b/dripzone-app/src/components/store/ProductModal.tsx new file mode 100644 index 0000000..3228c6e --- /dev/null +++ b/dripzone-app/src/components/store/ProductModal.tsx @@ -0,0 +1,222 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, Star, Truck, ShieldCheck, Zap, MessageCircle, ShoppingBag, Check } from 'lucide-react'; +import { Product, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductModalProps { + product: Product | null; + onClose: () => void; + onAddToCart: (product: Product, size: string) => void; + selectedCity: City; +} + +export const ProductModal: React.FC = ({ + product, + onClose, + onAddToCart, + selectedCity, +}) => { + const { currentBrand } = useBrand(); + if (!product) return null; + + const [selectedSize, setSelectedSize] = useState(product.sizes[0] || '39'); + const [selectedImage, setSelectedImage] = useState(product.images[0]); + const [added, setAdded] = useState(false); + + const separation = calculateSeparationBreakdown(product.retailPrice); + + const handleAdd = () => { + onAddToCart(product, selectedSize); + setAdded(true); + setTimeout(() => { + setAdded(false); + onClose(); + }, 1200); + }; + + const handleWhatsAppDirect = () => { + const phone = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203'; + const text = `Hola ${currentBrand.name}! Quiero pedir las zapatillas: +👟 *${product.name}* (${product.brand}) +📏 Talla: *${selectedSize}* (Horma Nacional) +💎 Precio: *${formatCOP(product.retailPrice)} COP* +🚚 Entrega en: *${selectedCity.name}* (Pago Contraentrega) +⚡ Deseo separar con $10.000 COP y cancelar el saldo en mi casa. + +¿Me confirman disponibilidad para despacho por favor?`; + window.open(`https://wa.me/${phone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+
+ {/* Close Button */} + + + {/* Left: Images */} +
+
+ {product.name} + + -{Math.round(((product.originalPrice || 170000) - product.retailPrice) / (product.originalPrice || 170000) * 100)}% OFF + +
+ + {/* Thumbnails */} + {product.images.length > 1 && ( +
+ {product.images.map((img, i) => ( + + ))} +
+ )} + + {/* Trust note */} +
+ + + {selectedCity.firstExchangeFree ? ( + <>1er Cambio de Talla GRATIS en {selectedCity.name} • Cambios posteriores: el cliente asume el flete + ) : ( + <>Garantía de Cambio en {selectedCity.name} • El cliente asume los costos de flete + )} + +
+
+ + {/* Right: Product Details & Actions */} +
+
+
+ {product.brand} +

{product.name}

+
+
+ + {product.rating || 4.9} +
+ • + +{product.salesCount || 200} pares entregados +
+
+ + {/* Price Box */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ + {/* Separation breakdown banner */} +
+

+ + ¡Pago Contraentrega en {selectedCity.name}! +

+

+ Separas con solo {formatCOP(separation.depositAmount)} y pagas los {formatCOP(separation.balanceDue)} al recibir en tu puerta. +

+
+
+ + {/* Size Selector */} +
+
+ Selecciona tu Talla (Nacional CO): + Guía de Tallas +
+
+ {product.sizes.map((size) => ( + + ))} +
+
+ + {/* Description */} +
+

{product.description}

+
+ + {/* Shipping note */} +
+ +
+ {selectedCity.name}: + {selectedCity.deliveryTime} ({selectedCity.shippingCost === 0 ? 'Envío Gratis' : formatCOP(selectedCity.shippingCost)}) +
+
+
+ + {/* Action Buttons */} +
+ + + +
+
+
+
+ ); +}; diff --git a/dripzone-app/src/config/brands.ts b/dripzone-app/src/config/brands.ts new file mode 100644 index 0000000..570a2f5 --- /dev/null +++ b/dripzone-app/src/config/brands.ts @@ -0,0 +1,151 @@ +export type BrandId = 'almeira' | 'sneaky' | 'zapply' | 'dripzone'; + +export interface BrandTheme { + id: BrandId; + name: string; + shortName: string; + tagline: string; + badge: string; + couponCode: string; + whatsappNumber: string; + + // Clases y colores de diseño personalizados para cada una de las 4 marcas + colors: { + primaryGradient: string; + secondaryGradient: string; + heroGradient: string; + accentGlow: string; + headerBg: string; + bodyBg: string; + cardBg: string; + border: string; + textAccent: string; + badgeBg: string; + badgeText: string; + cartBadge: string; + }; + + logo: { + iconText: string; + mainText: string; + accentText: string; + }; +} + +export const BRANDS: Record = { + almeira: { + id: 'almeira', + name: 'ALMEIRA STORE', + shortName: 'Almeira', + tagline: 'Sneakers & Moda Urbana', + badge: 'Garantía Certificada', + couponCode: 'ALMEIRA-10K', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-cyan-500 via-blue-600 to-pink-500', + secondaryGradient: 'from-cyan-400 to-blue-500', + heroGradient: 'from-slate-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(6,182,212,0.35)]', + headerBg: 'bg-slate-950/95 border-cyan-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-cyan-500/40', + border: 'border-cyan-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-pink-400 to-pink-500', + badgeBg: 'bg-cyan-500/20 border-cyan-500/30 text-cyan-300', + badgeText: 'text-cyan-300', + cartBadge: 'bg-pink-500 text-white', + }, + logo: { + iconText: 'A', + mainText: 'ALMEIRA', + accentText: 'STORE', + }, + }, + + sneaky: { + id: 'sneaky', + name: 'SNEAKY DROPS', + shortName: 'Sneaky', + tagline: 'Viral Kicks & Flash Deals', + badge: 'Oferta Flash', + couponCode: 'SNEAKY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-red-600 via-orange-500 to-amber-500', + secondaryGradient: 'from-red-500 to-orange-500', + heroGradient: 'from-red-950 via-gray-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(239,68,68,0.35)]', + headerBg: 'bg-gray-950/95 border-orange-500/20', + bodyBg: 'bg-gray-950 text-gray-100', + cardBg: 'bg-gray-900/80 border-gray-800 hover:border-orange-500/40', + border: 'border-orange-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-red-500 via-orange-400 to-amber-400', + badgeBg: 'bg-orange-500/20 border-orange-500/30 text-orange-300', + badgeText: 'text-orange-300', + cartBadge: 'bg-amber-400 text-gray-950', + }, + logo: { + iconText: 'S', + mainText: 'SNEAKY', + accentText: 'DROPS', + }, + }, + + zapply: { + id: 'zapply', + name: 'ZAPPLY CALI', + shortName: 'Zapply', + tagline: 'Zapatillas & Entrega Inmediata', + badge: 'Envío Express 24h', + couponCode: 'ZAPPLY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-emerald-500 via-teal-500 to-cyan-600', + secondaryGradient: 'from-emerald-400 to-teal-500', + heroGradient: 'from-emerald-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(16,185,129,0.35)]', + headerBg: 'bg-slate-950/95 border-emerald-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-emerald-500/40', + border: 'border-emerald-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-teal-300 to-cyan-400', + badgeBg: 'bg-emerald-500/20 border-emerald-500/30 text-emerald-300', + badgeText: 'text-emerald-300', + cartBadge: 'bg-emerald-400 text-slate-950', + }, + logo: { + iconText: 'Z', + mainText: 'ZAPPLY', + accentText: 'CALI', + }, + }, + + dripzone: { + id: 'dripzone', + name: 'DRIPZONE', + shortName: 'DripZone', + tagline: 'Streetwear & Sneakers Exclusivos', + badge: 'Edición Limitada', + couponCode: 'DRIP-VIP', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-purple-600 via-fuchsia-500 to-pink-600', + secondaryGradient: 'from-purple-500 to-pink-500', + heroGradient: 'from-purple-950 via-neutral-900 to-neutral-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-neutral-950/95 border-purple-500/20', + bodyBg: 'bg-neutral-950 text-neutral-100', + cardBg: 'bg-neutral-900/80 border-neutral-800 hover:border-purple-500/40', + border: 'border-purple-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-fuchsia-400 to-pink-400', + badgeBg: 'bg-purple-500/20 border-purple-500/30 text-purple-300', + badgeText: 'text-purple-300', + cartBadge: 'bg-fuchsia-500 text-white', + }, + logo: { + iconText: 'D', + mainText: 'DRIP', + accentText: 'ZONE', + }, + }, +}; diff --git a/dripzone-app/src/context/AuthContext.tsx b/dripzone-app/src/context/AuthContext.tsx new file mode 100644 index 0000000..f3ab238 --- /dev/null +++ b/dripzone-app/src/context/AuthContext.tsx @@ -0,0 +1,100 @@ +'use client'; + +import React, { createContext, useContext, useState, useEffect } from 'react'; +import { User } from '@/types'; + +interface AuthContextType { + user: User | null; + login: (identifier: string) => Promise<{ success: boolean; error?: string }>; + register: (data: { name: string; email: string; phone: string; city?: string; address?: string }) => Promise<{ success: boolean; error?: string }>; + logout: () => void; + isAuthModalOpen: boolean; + openAuthModal: () => void; + closeAuthModal: () => void; +} + +const AuthContext = createContext(undefined); + +export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [user, setUser] = useState(null); + const [isAuthModalOpen, setIsAuthModalOpen] = useState(false); + + useEffect(() => { + const saved = localStorage.getItem('dripzone_user'); + if (saved) { + try { + setUser(JSON.parse(saved)); + } catch (e) {} + } + }, []); + + const login = async (identifier: string) => { + try { + const res = await fetch('/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ identifier }), + }); + const data = await res.json(); + if (data.success && data.user) { + setUser(data.user); + localStorage.setItem('dripzone_user', JSON.stringify(data.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: data.error || 'Error al iniciar sesión' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const register = async (data: { name: string; email: string; phone: string; city?: string; address?: string }) => { + try { + const res = await fetch('/api/auth/register', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }); + const resData = await res.json(); + if (resData.success && resData.user) { + setUser(resData.user); + localStorage.setItem('dripzone_user', JSON.stringify(resData.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: resData.error || 'Error al registrarse' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const logout = () => { + setUser(null); + localStorage.removeItem('dripzone_user'); + }; + + const openAuthModal = () => setIsAuthModalOpen(true); + const closeAuthModal = () => setIsAuthModalOpen(false); + + return ( + + {children} + + ); +}; + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) throw new Error('useAuth must be used within an AuthProvider'); + return context; +}; diff --git a/dripzone-app/src/context/BrandContext.tsx b/dripzone-app/src/context/BrandContext.tsx new file mode 100644 index 0000000..8105241 --- /dev/null +++ b/dripzone-app/src/context/BrandContext.tsx @@ -0,0 +1,22 @@ +'use client'; + +import React, { createContext, useContext } from 'react'; +import { BrandTheme, BRANDS } from '@/config/brands'; + +interface BrandContextType { + currentBrand: BrandTheme; +} + +const BrandContext = createContext({ + currentBrand: BRANDS.dripzone, +}); + +export const BrandProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return ( + + {children} + + ); +}; + +export const useBrand = () => useContext(BrandContext); diff --git a/dripzone-app/src/lib/appwrite.ts b/dripzone-app/src/lib/appwrite.ts new file mode 100644 index 0000000..2cd0209 --- /dev/null +++ b/dripzone-app/src/lib/appwrite.ts @@ -0,0 +1,25 @@ +import { Client, Databases, Storage, Account } from 'appwrite'; + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + +export const client = new Client(); +client.setEndpoint(endpoint).setProject(projectId); + +export const databases = new Databases(client); +export const storage = new Storage(client); +export const account = new Account(client); + +// Base de datos y Bucket 100% aislados e independientes +export const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +export const BUCKET_ID = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +// Colecciones independientes +export const COLLECTIONS = { + PRODUCTS: 'products', + CITIES: 'cities', + PAYMENT_METHODS: 'payment_methods', + ORDERS: 'orders', + SETTINGS: 'settings', + SUPPLIER_POSTS: 'supplier_posts', +}; diff --git a/dripzone-app/src/lib/data-service.ts b/dripzone-app/src/lib/data-service.ts new file mode 100644 index 0000000..4050f2f --- /dev/null +++ b/dripzone-app/src/lib/data-service.ts @@ -0,0 +1,2393 @@ +import { Product, City, PaymentMethod, Order, SupplierPost, StoreSettings, Supplier, MonitoredWhatsAppGroup, User } from '@/types'; + +export const INITIAL_SUPPLIERS: Supplier[] = [ + { + "id": "sup-jovic", + "name": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "phone": "573167455877", + "contactPerson": "Asesor Jovic Store", + "address": "Centro / Bodega Cali", + "notes": "Proveedor oficial Nike, Jordan, Nocta y Vomero calidades Top.", + "isActive": true + }, + { + "id": "sup-ccmio", + "name": "EXCLUSIVE CC MÍO 3B", + "phone": "573159876543", + "contactPerson": "Despachos CC MÍO 3B", + "address": "CC MÍO Local 3B, Cali", + "notes": "Especialista en Adidas, Coach, Timberland y Skatewear.", + "isActive": true + }, + { + "id": "sup-central", + "name": "BODEGA CENTRAL MAYORISTA", + "phone": "573101234567", + "contactPerson": "Logística Despachos", + "address": "San Andresito / Cali", + "notes": "Despacho rápido en 24 horas para separación inmediata.", + "isActive": true + } +]; + +export const INITIAL_CITIES: City[] = [ + { + id: 'city-cali', + name: 'Cali', + department: 'Valle del Cauca', + shippingCost: 0, + deliveryTime: 'Entrega en 24 Horas (Domicilio Local)', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Cali (posteriores con flete estándar)', + }, + { + id: 'city-jamundi', + name: 'Jamundí', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Jamundí (posteriores con flete estándar)', + }, + { + id: 'city-palmira', + name: 'Palmira', + department: 'Valle del Cauca', + shippingCost: 7000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Palmira (posteriores con flete estándar)', + }, + { + id: 'city-yumbo', + name: 'Yumbo', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Yumbo (posteriores con flete estándar)', + }, + { + id: 'city-bogota', + name: 'Bogotá D.C.', + department: 'Cundinamarca', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-medellin', + name: 'Medellín', + department: 'Antioquia', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-barranquilla', + name: 'Barranquilla', + department: 'Atlántico', + shippingCost: 14000, + deliveryTime: '3 a 4 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-nacional', + name: 'Otras Ciudades / Resto del País', + department: 'Colombia', + shippingCost: 15000, + deliveryTime: '2 a 5 días hábiles', + allowsContraentrega: false, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete nacional asumido por el cliente)', + }, +]; + +// Métodos de Pago configurables por el Admin +export const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [ + { + id: 'pay-bold-link', + name: 'Bold.co • PSE, Tarjetas Débito/Crédito, Nequi o QR (Oficial)', + type: 'bold', + description: 'Paga de forma rápida y 100% segura con tu cuenta Bold. Acepta PSE, Tarjetas Visa/Mastercard y QR de cualquier banco.', + requiresDeposit: false, + depositAmount: 0, + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + accountInfo: 'Pasarela Oficial Bold.co • PSE / Tarjetas / QR', + isActive: true, + }, + { + id: 'pay-deposit-10k', + name: 'Separación con $10.000 + Saldo Contraentrega', + type: 'contraentrega', + description: 'Asegura tu talla con solo $10.000 COP vía Bold/Nequi/Daviplata y cancelas el saldo restante en efectivo o transferencia cuando el mensajero llegue a tu casa.', + requiresDeposit: true, + depositAmount: 10000, + accountInfo: 'Nequi / Daviplata Oficial: 316 745 5877 (Carlos Andrés Lasso)', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + isActive: true, + }, + { + id: 'pay-cod-full', + name: 'Pago 100% Contraentrega (Cali y Alrededores)', + type: 'contraentrega', + description: 'Pagas el 100% del valor total al recibir en tu puerta (válido para entregas urbanas en 24 horas).', + requiresDeposit: false, + depositAmount: 0, + isActive: true, + }, + { + id: 'pay-nequi-full', + name: 'Transferencia Total Anticipada Nequi / Daviplata', + type: 'nequi', + description: 'Paga el 100% anticipado y recibe prioridad de despacho express en 24 horas.', + requiresDeposit: false, + depositAmount: 0, + accountInfo: 'Nequi / Daviplata: 316 745 5877 (Carlos Andrés Lasso)', + isActive: true, + }, +]; + +export const INITIAL_PRODUCTS: Product[] = [ + { + "id": "snk-real-1", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 36, + "salesCount": 183, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-2", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 73, + "salesCount": 225, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-3", + "name": "Nike Coach Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 78, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-4", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 44, + "salesCount": 239, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-5", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 242, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-6", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-7", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 81, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-8", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 96, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-9", + "name": "Louis Vuitton Calvin Klein Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 56, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-10", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 52, + "salesCount": 243, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-11", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 92, + "salesCount": 58, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-12", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 65, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-13", + "name": "Nike Michael Kors Dama \udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 70, + "salesCount": 230, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-14", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 146, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-15", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 103, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-16", + "name": "Nike Clemont Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 74, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-17", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 176, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-18", + "name": "Louis Vuitton Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 196, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-19", + "name": "Nike \udf1fbapesta\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 41, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-20", + "name": "Timberland Nueva Mercancía", + "brand": "Timberland", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1520639888713-7851133b1ed0?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 121, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-21", + "name": "\udf1fnike Internacional\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 29, + "salesCount": 112, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-22", + "name": "Nike \udecdalexander Mcqueen\udecd", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 97, + "salesCount": 90, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-23", + "name": "\udf1fnike Af1 Bape\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-24", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "36", + "37", + "38", + "39", + "40" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 21, + "salesCount": 126, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-25", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 82, + "salesCount": 154, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-26", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 241, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-27", + "name": "Karl Lagerfeld Caballero \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 60, + "salesCount": 215, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-28", + "name": "Nike Streetwear Sneaker", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 53, + "salesCount": 114, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-29", + "name": "Nike 7 Camaras Hombre", + "brand": "Nike", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 229, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-30", + "name": "Nike Retro 1 Dama,37 Y 40", + "brand": "Nike", + "supplierPrice": 105000, + "retailPrice": 145000, + "originalPrice": 200000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 67, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-31", + "name": "Nike Vomero Hombre", + "brand": "Nike", + "supplierPrice": 110000, + "retailPrice": 150000, + "originalPrice": 205000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 78, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-32", + "name": "Nike Lebron Dama Y 45", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 113, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-33", + "name": "Nike Kyrie Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 208, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-34", + "name": "Nike Gt Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 54, + "salesCount": 243, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-35", + "name": "Adidas Hombre ,43,44 Y 45", + "brand": "Adidas", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 109, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-36", + "name": "Adidas Courtic Hombre", + "brand": "Adidas", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 91, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-37", + "name": "Nike Total 90 Dama,42,43,44 Y 45", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 94, + "salesCount": 166, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-38", + "name": "Nike Total 90 Hombre", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44", + "45" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 35, + "salesCount": 74, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-39", + "name": "Nike Nocta Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 81, + "salesCount": 139, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-40", + "name": "Nike Total 90 Hombre ,43 Y 44", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 86, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-41", + "name": "Nike Tn Hombre", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 50, + "salesCount": 152, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-42", + "name": "Nike Kyrie Dama Y Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 153, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-43", + "name": "Nike Easyon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 90, + "salesCount": 115, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-44", + "name": "Nike Fast Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 199, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-45", + "name": "Nike Af1 Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 62, + "salesCount": 245, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-46", + "name": "Adidas Forum Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-47", + "name": "Nike Sb Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 74, + "salesCount": 213, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-48", + "name": "Tommy Hilfiger Caballero", + "brand": "Tommy Hilfiger", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 117, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-49", + "name": "Louis Vuitton Skate Dama", + "brand": "Louis Vuitton", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 242, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-50", + "name": "Adidas Yeezy Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 170, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-51", + "name": "Nike Metcon Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 76, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-52", + "name": "Nike Metcon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 189, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-53", + "name": "New Balance Caballero", + "brand": "New Balance", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1539185441755-769473a23570?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 79, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-54", + "name": "Nike Air Max Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 84, + "salesCount": 121, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-55", + "name": "Nike Zoom Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 31, + "salesCount": 200, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-56", + "name": "Nike Skate Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 98, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-57", + "name": "Reebok Caballero", + "brand": "Reebok", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 93, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-58", + "name": "Dior Caballero", + "brand": "Dior", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 201, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-59", + "name": "Jordan Retro 1 Bota Dama", + "brand": "Jordan", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1552346154-21d32810aba3?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 63, + "salesCount": 177, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-60", + "name": "Diesel Caballero", + "brand": "Diesel", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 133, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + } +]; + +export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [ + { + id: 'post-1', + channelName: 'DIFUSION JOVIC STORE', + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + rawMessage: `🔥 DISPONIBLE HOY 🔥\nNike Air Force 1 All White\nTallas: 37 al 43\nMayorista: $90.000 c/u\nDespacho inmediato Cali`, + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Nike Air Force 1 Low 07 White Triple', + brand: 'Nike', + sizes: ['37', '38', '39', '40', '41', '42', '43'], + supplierPrice: 90000, + suggestedRetailPrice: 125000, + category: 'Sneakers / Urbano', + confidence: 0.96, + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + }, + status: 'published_store', + receivedAt: 'Hoy, 09:15 AM', + }, + { + id: 'post-2', + channelName: 'EXCLUSIVE CC MIO 3B', + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + rawMessage: `👟 JORDAN 4 MILITARY BLACK 👟\nFull calidad AAA, caja original\nTallas 38 a 43\nPrecio: $95.000\nDomicilio pago contraentrega`, + rawImages: [ + 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Air Jordan 4 Retro Military Black', + brand: 'Jordan', + sizes: ['38', '39', '40', '41', '42', '43'], + supplierPrice: 95000, + suggestedRetailPrice: 130000, + category: 'Sneakers / Colección', + confidence: 0.94, + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + }, + status: 'published_store', + receivedAt: 'Hoy, 10:40 AM', + }, +]; + + +export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ + { + id: 'grp-jovic', + jid: '120363049363072784@g.us', + name: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + isMonitored: true, + supplierId: 'sup-jovic', + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 450, + notes: 'Proveedor oficial Nike, Jordan, Vomero, Nocta y AF1.', + }, + { + id: 'grp-ccmio', + jid: '120363024823901923@g.us', + name: 'EXCLUSIVE CC MÍO 3B', + isMonitored: true, + supplierId: 'sup-ccmio', + supplierName: 'EXCLUSIVE CC MÍO 3B', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 380, + notes: 'Proveedor oficial Adidas, Coach, Timberland y Skatewear.', + }, +]; + +class DataService { + private products: Product[] = [...INITIAL_PRODUCTS]; + private cities: City[] = [...INITIAL_CITIES]; + private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; + private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; + private orders: Order[] = []; + private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; + + getProducts(): Product[] { + return this.products; + } + + getProductById(id: string): Product | undefined { + return this.products.find((p) => p.id === id); + } + + addProduct(product: Product): Product { + this.products.unshift(product); + return product; + } + + updateProduct(id: string, updates: Partial): Product | null { + const idx = this.products.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.products[idx] = { ...this.products[idx], ...updates }; + return this.products[idx]; + } + + deleteProduct(id: string): boolean { + const initialLen = this.products.length; + this.products = this.products.filter((p) => p.id !== id); + return this.products.length < initialLen; + } + + getSuppliers(): Supplier[] { + return this.suppliers; + } + + getSupplierById(id: string): Supplier | undefined { + return this.suppliers.find((s) => s.id === id); + } + + addSupplier(supplier: Supplier): Supplier { + this.suppliers.push(supplier); + return supplier; + } + + getCities(): City[] { + return this.cities; + } + + getCityById(id: string): City | undefined { + return this.cities.find((c) => c.id === id); + } + + addCity(city: City): City { + this.cities.push(city); + return city; + } + + updateCity(id: string, updates: Partial): City | null { + const idx = this.cities.findIndex((c) => c.id === id); + if (idx === -1) return null; + this.cities[idx] = { ...this.cities[idx], ...updates }; + return this.cities[idx]; + } + + getPaymentMethods(): PaymentMethod[] { + return this.paymentMethods; + } + + updatePaymentMethod(id: string, updates: Partial): PaymentMethod | null { + const idx = this.paymentMethods.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.paymentMethods[idx] = { ...this.paymentMethods[idx], ...updates }; + return this.paymentMethods[idx]; + } + + getOrders(): Order[] { + return this.orders; + } + + addOrder(order: Order): Order { + this.orders.unshift(order); + return order; + } + + createOrder(orderData: Partial): Order { + const newOrder: Order = { + id: `ord-${Date.now()}`, + customerName: orderData.customerName || 'Cliente', + customerPhone: orderData.customerPhone || '', + address: orderData.address || '', + cityId: orderData.cityId || 'city-cali', + cityName: orderData.cityName || 'Cali', + items: orderData.items || [], + subtotal: orderData.subtotal || 0, + shippingCost: orderData.shippingCost || 0, + totalAmount: orderData.totalAmount || 0, + depositAmount: orderData.depositAmount || 10000, + balanceDue: (orderData.totalAmount || 0) - (orderData.depositAmount || 10000), + paymentMethodId: orderData.paymentMethodId || 'pay-contraentrega', + paymentMethodName: orderData.paymentMethodName || 'Contraentrega', + status: 'pending', + notes: orderData.notes, + createdAt: new Date().toISOString(), + }; + this.orders.unshift(newOrder); + return newOrder; + } + + updateOrderStatus(orderId: string, status: Order['status']): Order | null { + const order = this.orders.find((o) => o.id === orderId); + if (!order) return null; + order.status = status; + return order; + } + + getSupplierPosts(): SupplierPost[] { + return this.supplierPosts; + } + + addSupplierPost(post: SupplierPost): SupplierPost { + this.supplierPosts.unshift(post); + return post; + } + + // Configuración de la Tienda + private settings: StoreSettings = { + storeName: 'DripZone', + slogan: 'Luxury Streetwear & Collectibles', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@dripzone.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }; + + getSettings(): StoreSettings { + return this.settings; + } + + updateSettings(updates: Partial): StoreSettings { + this.settings = { ...this.settings, ...updates }; + return this.settings; + } + + // Control de Usuarios + private users: User[] = [ + { + id: 'usr-admin-1', + name: 'Carlos Andrés Lasso', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + city: 'Cali', + address: 'Centro / Bodega Principal', + role: 'admin', + isActive: true, + createdAt: '2026-01-10', + totalOrders: 0, + lastLogin: 'Hoy, 08:15 PM', + }, + { + id: 'usr-operator-1', + name: 'Andrés Operador Despachos', + email: 'despachos@dripzone.co', + phone: '3159876543', + city: 'Cali', + role: 'operator', + isActive: true, + createdAt: '2026-02-01', + totalOrders: 0, + lastLogin: 'Hoy, 05:30 PM', + }, + { + id: 'usr-cust-1', + name: 'Mateo Gómez (Cliente VIP)', + email: 'mateo.sneakers@gmail.com', + phone: '3112345678', + city: 'Cali', + address: 'Calle 5 # 34-12 Apto 402', + role: 'customer', + isActive: true, + createdAt: '2026-02-15', + totalOrders: 3, + lastLogin: 'Ayer, 08:20 PM', + }, + ]; + + getUsers(): User[] { + return this.users; + } + + addUser(user: User): User { + this.users.unshift(user); + return user; + } + + updateUser(id: string, updates: Partial): User | null { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return null; + this.users[idx] = { ...this.users[idx], ...updates }; + return this.users[idx]; + } + + deleteUser(id: string): boolean { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return false; + this.users.splice(idx, 1); + return true; + } + + authenticate(emailOrPhone: string): User | null { + const q = emailOrPhone.trim().toLowerCase(); + const user = this.users.find( + (u) => u.email.toLowerCase() === q || u.phone === q || u.phone.includes(q) + ); + return user || null; + } + + private monitoredGroups: MonitoredWhatsAppGroup[] = [...INITIAL_MONITORED_GROUPS]; + + getMonitoredGroups(): MonitoredWhatsAppGroup[] { + return this.monitoredGroups; + } + + saveMonitoredGroups(groups: MonitoredWhatsAppGroup[]): MonitoredWhatsAppGroup[] { + this.monitoredGroups = groups; + return this.monitoredGroups; + } + + toggleGroupMonitoring(idOrJid: string, isMonitored: boolean): MonitoredWhatsAppGroup | null { + const grp = this.monitoredGroups.find((g) => g.id === idOrJid || g.jid === idOrJid); + if (grp) { + grp.isMonitored = isMonitored; + return grp; + } + return null; + } +} + +export const dataService = new DataService(); diff --git a/dripzone-app/src/lib/deduplication-engine.ts b/dripzone-app/src/lib/deduplication-engine.ts new file mode 100644 index 0000000..3023854 --- /dev/null +++ b/dripzone-app/src/lib/deduplication-engine.ts @@ -0,0 +1,105 @@ +import { Product } from '@/types'; + +/** + * Normaliza un string para comparación (minúsculas, sin acentos, sin caracteres especiales) + */ +export function normalizeText(text: string): string { + if (!text) return ''; + return text + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/[^a-z0-9\s]/g, ' ') + .replace(/\s+/g, ' ') + .trim(); +} + +/** + * Calcula la similitud de Jaccard / Coeficiente de Dados entre dos textos + * Devuelve un valor entre 0 (totalmente diferente) y 1.0 (idéntico) + */ +export function calculateTextSimilarity(textA: string, textB: string): number { + const normA = normalizeText(textA); + const normB = normalizeText(textB); + + if (!normA || !normB) return 0; + if (normA === normB) return 1.0; + + // Si uno contiene al otro por completo + if (normA.includes(normB) || normB.includes(normA)) { + const ratio = Math.min(normA.length, normB.length) / Math.max(normA.length, normB.length); + if (ratio > 0.7) return 0.92; + } + + const tokensA = new Set(normA.split(' ').filter((w) => w.length > 2)); + const tokensB = new Set(normB.split(' ').filter((w) => w.length > 2)); + + if (tokensA.size === 0 || tokensB.size === 0) return 0; + + const intersection = new Set([...tokensA].filter((t) => tokensB.has(t))); + const union = new Set([...tokensA, ...tokensB]); + + return intersection.size / union.size; +} + +export interface DuplicateCheckResult { + isDuplicate: boolean; + similarityScore: number; + existingProduct?: Product; + recommendation: 'create_new' | 'update_stock_and_sizes' | 'skip_duplicate'; + message: string; +} + +/** + * Verifica si un producto entrante ya existe en el catálogo para evitar duplicados + */ +export function checkProductDuplicate( + incoming: { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + }, + existingCatalog: Product[], + threshold = 0.75 +): DuplicateCheckResult { + let highestScore = 0; + let bestMatch: Product | undefined; + + for (const product of existingCatalog) { + // 1. Si la marca no coincide, penalizar + const brandMatch = normalizeText(incoming.brand) === normalizeText(product.brand); + const score = calculateTextSimilarity(incoming.name, product.name); + const finalScore = brandMatch ? score : score * 0.5; + + if (finalScore > highestScore) { + highestScore = finalScore; + bestMatch = product; + } + } + + // Si la similitud supera el umbral (75%) + if (highestScore >= threshold && bestMatch) { + // Verificar si aporta nuevas tallas + const incomingSizesSet = new Set(incoming.sizes); + const existingSizesSet = new Set(bestMatch.sizes); + const hasNewSizes = incoming.sizes.some((s) => !existingSizesSet.has(s)); + + return { + isDuplicate: true, + similarityScore: Math.round(highestScore * 100) / 100, + existingProduct: bestMatch, + recommendation: hasNewSizes ? 'update_stock_and_sizes' : 'skip_duplicate', + message: hasNewSizes + ? `Producto ya registrado ("${bestMatch.name}"). Se detectaron nuevas tallas para actualizar.` + : `Producto ya registrado ("${bestMatch.name}") con similitud del ${Math.round(highestScore * 100)}%. Se previene duplicación en la tienda y Facebook.`, + }; + } + + return { + isDuplicate: false, + similarityScore: Math.round(highestScore * 100) / 100, + recommendation: 'create_new', + message: 'Producto nuevo verificado sin duplicados. Listo para publicar.', + }; +} diff --git a/dripzone-app/src/lib/evolution-api.ts b/dripzone-app/src/lib/evolution-api.ts new file mode 100644 index 0000000..bd654f0 --- /dev/null +++ b/dripzone-app/src/lib/evolution-api.ts @@ -0,0 +1,105 @@ +import axios from 'axios'; +import { formatCOP } from './pricing-engine'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +/** + * Enviar mensaje de texto por WhatsApp a través de Evolution API + */ +export async function sendWhatsAppMessage(toPhone: string, message: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendText/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1200, + presence: 'composing', + }, + textMessage: { + text: message, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando mensaje de WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Enviar mensaje con foto/catálogo a través de Evolution API + */ +export async function sendWhatsAppMedia(toPhone: string, imageUrl: string, caption: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendMedia/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1500, + presence: 'composing', + }, + mediaMessage: { + mediatype: 'image', + caption, + media: imageUrl, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando media por WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Genera el mensaje de confirmación de pedido para el cliente y el administrador + */ +export function buildOrderConfirmationMessage(order: any): string { + const itemsText = order.items + .map((item: any) => `👟 *${item.productName}*\n 📏 Talla: *${item.size}* | Cantidad: ${item.quantity} | Valor: ${formatCOP(item.price)}`) + .join('\n\n'); + + return `🎉 *¡GRACIAS POR TU PEDIDO EN SNEAKERS CALI!* 🎉 +📌 *No. de Orden:* #${order.id} + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *DETALLE DE TU COMPRA:* +${itemsText} + +💵 *Subtotal:* ${formatCOP(order.subtotal)} +🚚 *Envío:* ${order.shippingCost === 0 ? 'GRATIS' : formatCOP(order.shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación / Anticipo:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo a Pagar Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega al recibir en tu casa.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +Estamos alistando tu paquete. Te enviaremos el número de guía o notificación de entrega. ¡Muchas gracias por tu confianza! ✨`; +} diff --git a/dripzone-app/src/lib/facebook-publisher.ts b/dripzone-app/src/lib/facebook-publisher.ts new file mode 100644 index 0000000..1e55ec7 --- /dev/null +++ b/dripzone-app/src/lib/facebook-publisher.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; +import { generateSalesCopy } from './pricing-engine'; + +export interface PublishToFacebookParams { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + images: string[]; + cityName?: string; + whatsappNumber?: string; + pageId?: string; + accessToken?: string; +} + +export interface PublishResult { + success: boolean; + postId?: string; + postUrl?: string; + generatedCopy: string; + error?: string; +} + +/** + * Publicador automático en Páginas de Facebook mediante Meta Graph API + */ +export async function publishToFacebookPage(params: PublishToFacebookParams): Promise { + const { + productName, + brand, + retailPrice, + sizes, + images, + cityName = 'Cali', + whatsappNumber = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203', + pageId = process.env.FACEBOOK_PAGE_ID, + accessToken = process.env.FACEBOOK_ACCESS_TOKEN, + } = params; + + const copy = generateSalesCopy({ + productName, + brand, + retailPrice, + sizes, + cityName, + whatsappNumber, + }); + + // Si no hay token de Facebook configurado, simular publicación exitosa para pruebas + if (!pageId || !accessToken) { + const mockPostId = `fb_${Date.now()}_${Math.floor(Math.random() * 10000)}`; + return { + success: true, + postId: mockPostId, + postUrl: `https://facebook.com/${mockPostId}`, + generatedCopy: copy, + }; + } + + try { + // Si tiene una imagen principal, publicamos como photo post con caption + const primaryImage = images[0]; + const fbEndpoint = `https://graph.facebook.com/v19.0/${pageId}/photos`; + + const response = await axios.post(fbEndpoint, { + url: primaryImage, + caption: copy, + access_token: accessToken, + }); + + return { + success: true, + postId: response.data.id || response.data.post_id, + postUrl: `https://facebook.com/${response.data.id}`, + generatedCopy: copy, + }; + } catch (error: any) { + console.error('Error publicando en Facebook Graph API:', error?.response?.data || error?.message); + return { + success: false, + error: error?.response?.data?.error?.message || error.message, + generatedCopy: copy, + }; + } +} diff --git a/dripzone-app/src/lib/gemini-parser.ts b/dripzone-app/src/lib/gemini-parser.ts new file mode 100644 index 0000000..268024a --- /dev/null +++ b/dripzone-app/src/lib/gemini-parser.ts @@ -0,0 +1,108 @@ +import { GoogleGenAI } from '@google/genai'; +import { ExtractedProductData } from '@/types'; +import { calculateRetailPrice } from './pricing-engine'; + +export async function parseSupplierMessage(text: string): Promise { + const apiKey = process.env.GEMINI_API_KEY; + + const fallbackExtract = (): ExtractedProductData => { + let price = 90000; + const priceMatch = text.match(/(?:precio|valor|mayorista|costo|\$)\s*[:=]?\s*(\d{2,3}(?:\.\d{3})*|\d{2,3}k?)/i); + if (priceMatch) { + const raw = priceMatch[1].toLowerCase().replace(/\./g, ''); + if (raw.endsWith('k')) { + price = parseInt(raw.replace('k', ''), 10) * 1000; + } else { + const num = parseInt(raw, 10); + price = num < 1000 ? num * 1000 : num; + } + } + + const sizes: string[] = []; + const sizeRangeMatch = text.match(/(\d{2})\s*(?:a|al|-)\s*(\d{2})/i); + if (sizeRangeMatch) { + const start = parseInt(sizeRangeMatch[1], 10); + const end = parseInt(sizeRangeMatch[2], 10); + if (start >= 34 && end <= 46 && start <= end) { + for (let s = start; s <= end; s++) sizes.push(s.toString()); + } + } else { + const individualSizes = text.match(/\b(3[4-9]|4[0-6])\b/g); + if (individualSizes) { + sizes.push(...Array.from(new Set(individualSizes))); + } + } + if (sizes.length === 0) { + sizes.push('37', '38', '39', '40', '41', '42', '43'); + } + + let brand = 'Nike'; + if (/jordan/i.test(text)) brand = 'Jordan'; + else if (/adidas|bad bunny|campus|forum/i.test(text)) brand = 'Adidas'; + else if (/new balance|nb/i.test(text)) brand = 'New Balance'; + else if (/puma/i.test(text)) brand = 'Puma'; + else if (/asics/i.test(text)) brand = 'Asics'; + else if (/vans/i.test(text)) brand = 'Vans'; + + const cleanLines = text.split('\n').filter((l) => l.trim().length > 0 && !/🔥|🔴|llegando|promo/i.test(l)); + const name = cleanLines[0] || `${brand} Sneakers Urban Edition`; + + return { + name: name.replace(/tallas?:.*|precio:.*|\$/gi, '').trim() || `${brand} Zapatillas`, + brand, + sizes, + supplierPrice: price, + suggestedRetailPrice: calculateRetailPrice(price, 35, 30000), + category: 'Calzado / Sneakers', + confidence: 0.85, + }; + }; + + if (!apiKey) { + return fallbackExtract(); + } + + try { + const ai = new GoogleGenAI({ apiKey }); + const prompt = `Eres un asistente experto en e-commerce y calzado deportivo en Colombia. +Analiza el siguiente mensaje extraído de un grupo mayorista de WhatsApp. +Extrae los siguientes campos en formato JSON estricto: +- "name": Nombre comercial limpio del modelo (ej: "Nike Dunk Low Retro Panda", "Air Jordan 4 Military Black"). +- "brand": Marca ("Nike", "Jordan", "Adidas", "New Balance", "Puma", "Asics", etc.). +- "sizes": Array de tallas en horma colombiana/europea (ej: ["38", "39", "40", "41", "42", "43"]). Si dice "38 al 43", expande todas las tallas intermedias. +- "supplierPrice": Precio de compra mayorista como número entero en COP (ej: 90000, 95000). Si dice "90mil" o "90", es 90000. +- "category": Categoría ("Sneakers / Colección", "Urbano / Casual", "Running / Deportivo", etc.). + +Mensaje del grupo: +""" +${text} +""" + +Responde ÚNICAMENTE con el objeto JSON sin bloques de código markdown ni texto adicional.`; + + const response = await ai.models.generateContent({ + model: 'gemini-2.5-flash', + contents: prompt, + }); + + const outputText = response.text || ''; + const cleanJson = outputText.replace(/```json|```/gi, '').trim(); + const parsed = JSON.parse(cleanJson); + + const supplierPrice = typeof parsed.supplierPrice === 'number' ? parsed.supplierPrice : 90000; + const sizes = Array.isArray(parsed.sizes) && parsed.sizes.length > 0 ? parsed.sizes.map(String) : ['37', '38', '39', '40', '41', '42', '43']; + + return { + name: parsed.name || 'Zapatilla Urbana', + brand: parsed.brand || 'Nike', + sizes, + supplierPrice, + suggestedRetailPrice: calculateRetailPrice(supplierPrice, 35, 30000), + category: parsed.category || 'Sneakers', + confidence: 0.98, + }; + } catch (err) { + console.warn('Fallo llamada Gemini, utilizando extractor regex fallback:', err); + return fallbackExtract(); + } +} diff --git a/dripzone-app/src/lib/pricing-engine.ts b/dripzone-app/src/lib/pricing-engine.ts new file mode 100644 index 0000000..640ab12 --- /dev/null +++ b/dripzone-app/src/lib/pricing-engine.ts @@ -0,0 +1,114 @@ +/** + * Motor de Precios, Políticas de Cambio y Redondeo Automático al 5.000 Siguiente + */ + +export const DEFAULT_MIN_PROFIT_MARGIN_PERCENT = 35; // % Mínimo de ganancia +export const DEFAULT_MIN_PROFIT_COP = 30000; // Margen mínimo en pesos +export const DEFAULT_SEPARATION_DEPOSIT_COP = 10000; // Separación fija +export const ROUND_STEP_COP = 5000; // Redondeo siempre al múltiplo de $5.000 superior + +export const EXCHANGE_POLICY = { + firstExchangeFree: true, + badgeText: '1er Cambio de Talla GRATIS', + shortNotice: 'Primer cambio de talla gratis. Cambios posteriores con flete estándar.', + fullTerms: 'Cuentas con 1er cambio de talla 100% GRATIS dentro de los primeros 5 días. Para cambios adicionales o posteriores, el cliente asume el costo logístico del flete.', +}; + +export function formatCOP(amount: number): string { + if (isNaN(amount)) return '$0'; + return '$' + Math.round(amount).toLocaleString('es-CO'); +} + +export function roundUpToNearest5000(amount: number): number { + if (!amount || amount <= 0) return 0; + return Math.ceil(amount / ROUND_STEP_COP) * ROUND_STEP_COP; +} + +export function calculateRetailPrice( + supplierPrice: number, + minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT, + minMarginCop: number = DEFAULT_MIN_PROFIT_COP +): number { + if (!supplierPrice || supplierPrice <= 0) return 0; + const priceByPercent = supplierPrice * (1 + minMarginPercent / 100); + const priceByFixed = supplierPrice + minMarginCop; + const baseTargetPrice = Math.max(priceByPercent, priceByFixed); + return roundUpToNearest5000(baseTargetPrice); +} + +export function getPricingBreakdown(supplierCost: number, minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT) { + const retailPrice = calculateRetailPrice(supplierCost, minMarginPercent); + const grossProfit = retailPrice - supplierCost; + const realMarginPercent = Math.round((grossProfit / supplierCost) * 100); + + return { + supplierCost, + retailPrice, + grossProfit, + realMarginPercent, + isCeiledTo5k: true, + }; +} + +export function calculateAnchorPrice(retailPrice: number, discountPercentage: number = 30): number { + if (!retailPrice || retailPrice <= 0) return 0; + const anchor = retailPrice / (1 - discountPercentage / 100); + return roundUpToNearest5000(anchor); +} + +export function calculateSeparationBreakdown( + totalAmount: number, + depositAmount: number = DEFAULT_SEPARATION_DEPOSIT_COP +) { + const deposit = Math.min(depositAmount, totalAmount); + const balanceDue = Math.max(0, totalAmount - deposit); + + return { + totalAmount, + depositAmount: deposit, + balanceDue, + summaryText: `Separas hoy con ${formatCOP(deposit)} y cancelas ${formatCOP(balanceDue)} al recibir contraentrega en tu puerta.`, + exchangeTerms: EXCHANGE_POLICY.shortNotice, + }; +} + +export function generateSalesCopy(params: { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + storeName?: string; + cityName?: string; + whatsappNumber?: string; +}): string { + const { + productName, + brand, + retailPrice, + sizes, + storeName = 'TIENDA DE CALZADO', + cityName = 'Cali', + whatsappNumber = '573134848203', + } = params; + + const breakdown = calculateSeparationBreakdown(retailPrice); + const sizesFormatted = sizes.join(' - '); + const waLink = `https://wa.me/${whatsappNumber}?text=${encodeURIComponent(`Hola ${storeName}! Quiero pedir las zapatillas ${productName} (${brand}) en talla ___ para entrega contraentrega en ${cityName}.`)}`; + + return `✨ ${storeName.toUpperCase()} • LANZAMIENTO EXCLUSIVO ✨ +👟 ${productName.toUpperCase()} (${brand}) + +📏 Tallas Disponibles: ${sizesFormatted} (Horma Nacional) +💎 PRECIO DE VENTA: ${formatCOP(retailPrice)} COP + +🚚 ¡DOMICILIO EN ${cityName.toUpperCase()} Y ENVÍOS A TODO EL PAÍS! +🤝 PAGO CONTRAENTREGA: Cancelas al recibir el producto en tus manos. +⚡ SEPARA CON SOLO ${formatCOP(breakdown.depositAmount)} COP y cancelas ${formatCOP(breakdown.balanceDue)} al recibir. + +🛡️ POLÍTICA DE GARANTÍA: +✅ Calidad Premium 100% garantizada +✅ ${EXCHANGE_POLICY.badgeText} (posteriores con flete estándar) + +📲 ¡Pídelas antes de que se agote tu talla! +👉 Pedir directo por WhatsApp: ${waLink}`; +} diff --git a/dripzone-app/src/types/index.ts b/dripzone-app/src/types/index.ts new file mode 100644 index 0000000..9f8a915 --- /dev/null +++ b/dripzone-app/src/types/index.ts @@ -0,0 +1,176 @@ +export interface Supplier { + id: string; + name: string; + phone: string; + contactPerson?: string; + address?: string; + notes?: string; + isActive: boolean; +} + +export interface User { + id: string; + name: string; + email: string; + phone: string; + city?: string; + address?: string; + role: 'admin' | 'operator' | 'customer'; + isActive: boolean; + createdAt: string; + totalOrders?: number; + lastLogin?: string; +} + +export interface Product { + id: string; + name: string; + brand: string; + supplierPrice: number; + retailPrice: number; + originalPrice?: number; + sizes: string[]; + images: string[]; + description: string; + category: string; + inStock: boolean; + isActive?: boolean; + isFlashDeal?: boolean; + rating?: number; + reviewsCount?: number; + salesCount?: number; + originBadge?: string; + + supplierId?: string; + supplierName?: string; + supplierPhone?: string; + supplierSku?: string; +} + +export interface City { + id: string; + name: string; + department: string; + shippingCost: number; + deliveryTime: string; + allowsContraentrega: boolean; + allowCod?: boolean; + isActive?: boolean; + firstExchangeFree?: boolean; + exchangePolicyNote?: string; +} + +export interface PaymentMethod { + id: string; + name: string; + code?: string; + type: 'contraentrega' | 'nequi' | 'daviplata' | 'bancolombia' | 'tarjeta' | 'bold'; + description: string; + requiresDeposit: boolean; + depositAmount: number; + accountInfo?: string; + boldPaymentLink?: string; + boldQrUrl?: string; + isActive: boolean; +} + +export interface OrderItem { + productId: string; + productName: string; + brand: string; + size: string; + quantity: number; + price: number; + supplierPrice?: number; + supplierName?: string; + supplierPhone?: string; + image: string; +} + +export interface Order { + id: string; + userId?: string; + customerName: string; + customerPhone: string; + address: string; + cityId: string; + cityName: string; + items: OrderItem[]; + subtotal: number; + shippingCost: number; + totalAmount: number; + depositAmount: number; + balanceDue: number; + paymentMethodId: string; + paymentMethodName: string; + status: 'pending' | 'deposit_received' | 'supplier_notified' | 'dispatched' | 'delivered' | 'cancelled'; + notes?: string; + createdAt: string; +} + +export interface SupplierPost { + id: string; + channelName: string; + supplierName?: string; + supplierPhone?: string; + rawMessage: string; + rawImages: string[]; + extractedProduct?: ExtractedProductData; + status: 'pending_review' | 'published_facebook' | 'published_store' | 'ignored'; + receivedAt: string; +} + +export interface ExtractedProductData { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + suggestedRetailPrice: number; + category: string; + confidence: number; + supplierName?: string; + supplierPhone?: string; +} + +export interface CartItem { + product: Product; + selectedSize: string; + quantity: number; +} + +export interface StoreSettings { + storeName: string; + slogan?: string; + email: string; + phone: string; + whatsappNumber: string; + instagramHandle?: string; + address?: string; + city: string; + nequiAccount?: string; + daviplataAccount?: string; + accountHolder?: string; + boldPaymentLink?: string; + boldApiKey?: string; + boldMerchantId?: string; + boldQrUrl?: string; + boldEnabled?: boolean; + autoPublishSupplierPosts?: boolean; + defaultProfitMargin: number; + defaultDepositAmount: number; + facebookPageId?: string; +} + +export interface MonitoredWhatsAppGroup { + id: string; + jid: string; + name: string; + isMonitored: boolean; + supplierId?: string; + supplierName?: string; + profitMarginOverride?: number; + autoPublish: boolean; + participantsCount?: number; + lastMessageAt?: string; + notes?: string; +} diff --git a/dripzone-app/tsconfig.json b/dripzone-app/tsconfig.json new file mode 100644 index 0000000..cf9c65d --- /dev/null +++ b/dripzone-app/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +} diff --git a/sneaky-app/.gitignore b/sneaky-app/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/sneaky-app/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/sneaky-app/AGENTS.md b/sneaky-app/AGENTS.md new file mode 100644 index 0000000..643577d --- /dev/null +++ b/sneaky-app/AGENTS.md @@ -0,0 +1,9 @@ + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/sneaky-app/CLAUDE.md b/sneaky-app/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/sneaky-app/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/sneaky-app/Dockerfile b/sneaky-app/Dockerfile new file mode 100644 index 0000000..80966a7 --- /dev/null +++ b/sneaky-app/Dockerfile @@ -0,0 +1,54 @@ +FROM node:20-alpine AS base + +# 1. Install dependencies +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +COPY package.json package-lock.json* ./ +RUN npm ci + +# 2. Build the app +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +# Appwrite and Public Envs for Build Phase +ARG NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 +ARG NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c +ARG NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db +ARG NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + +ENV NEXT_PUBLIC_APPWRITE_ENDPOINT=$NEXT_PUBLIC_APPWRITE_ENDPOINT +ENV NEXT_PUBLIC_APPWRITE_PROJECT_ID=$NEXT_PUBLIC_APPWRITE_PROJECT_ID +ENV NEXT_PUBLIC_APPWRITE_DATABASE_ID=$NEXT_PUBLIC_APPWRITE_DATABASE_ID +ENV NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=$NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID + +RUN npm run build + +# 3. Production Runner +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy standalone output & public static files +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/sneaky-app/README.md b/sneaky-app/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/sneaky-app/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/sneaky-app/android/.gitignore b/sneaky-app/android/.gitignore new file mode 100644 index 0000000..48354a3 --- /dev/null +++ b/sneaky-app/android/.gitignore @@ -0,0 +1,101 @@ +# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore + +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +# Cordova plugins for Capacitor +capacitor-cordova-android-plugins + +# Copied web assets +app/src/main/assets/public + +# Generated Config files +app/src/main/assets/capacitor.config.json +app/src/main/assets/capacitor.plugins.json +app/src/main/res/xml/config.xml diff --git a/sneaky-app/android/app/.gitignore b/sneaky-app/android/app/.gitignore new file mode 100644 index 0000000..043df80 --- /dev/null +++ b/sneaky-app/android/app/.gitignore @@ -0,0 +1,2 @@ +/build/* +!/build/.npmkeep diff --git a/sneaky-app/android/app/build.gradle b/sneaky-app/android/app/build.gradle new file mode 100644 index 0000000..06780c9 --- /dev/null +++ b/sneaky-app/android/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + namespace = "co.sneakydrops.app" + compileSdk = rootProject.ext.compileSdkVersion + defaultConfig { + applicationId "co.sneakydrops.app" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + aaptOptions { + // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. + // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 + ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +repositories { + flatDir{ + dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" + implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" + implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" + implementation project(':capacitor-android') + testImplementation "junit:junit:$junitVersion" + androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" + implementation project(':capacitor-cordova-android-plugins') +} + +apply from: 'capacitor.build.gradle' + +try { + def servicesJSON = file('google-services.json') + if (servicesJSON.text) { + apply plugin: 'com.google.gms.google-services' + } +} catch(Exception e) { + logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") +} diff --git a/sneaky-app/android/app/capacitor.build.gradle b/sneaky-app/android/app/capacitor.build.gradle new file mode 100644 index 0000000..bbfb44f --- /dev/null +++ b/sneaky-app/android/app/capacitor.build.gradle @@ -0,0 +1,19 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/sneaky-app/android/app/proguard-rules.pro b/sneaky-app/android/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/sneaky-app/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/sneaky-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/sneaky-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..f2c2217 --- /dev/null +++ b/sneaky-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.getcapacitor.app", appContext.getPackageName()); + } +} diff --git a/sneaky-app/android/app/src/main/AndroidManifest.xml b/sneaky-app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b06ddbf --- /dev/null +++ b/sneaky-app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sneaky-app/android/app/src/main/java/co/sneakydrops/app/MainActivity.java b/sneaky-app/android/app/src/main/java/co/sneakydrops/app/MainActivity.java new file mode 100644 index 0000000..806395d --- /dev/null +++ b/sneaky-app/android/app/src/main/java/co/sneakydrops/app/MainActivity.java @@ -0,0 +1,5 @@ +package co.sneakydrops.app; + +import com.getcapacitor.BridgeActivity; + +public class MainActivity extends BridgeActivity {} diff --git a/sneaky-app/android/app/src/main/res/drawable-land-hdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-land-hdpi/splash.png new file mode 100644 index 0000000..e31573b Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-land-hdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-land-mdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-land-mdpi/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-land-mdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-land-xhdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-land-xhdpi/splash.png new file mode 100644 index 0000000..8077255 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-land-xhdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png new file mode 100644 index 0000000..14c6c8f Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png new file mode 100644 index 0000000..244ca25 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-port-hdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-port-hdpi/splash.png new file mode 100644 index 0000000..74faaa5 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-port-hdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-port-mdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-port-mdpi/splash.png new file mode 100644 index 0000000..e944f4a Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-port-mdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-port-xhdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-port-xhdpi/splash.png new file mode 100644 index 0000000..564a82f Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-port-xhdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png new file mode 100644 index 0000000..bfabe68 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/sneaky-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png new file mode 100644 index 0000000..6929071 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/sneaky-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/sneaky-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/sneaky-app/android/app/src/main/res/drawable/ic_launcher_background.xml b/sneaky-app/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/sneaky-app/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sneaky-app/android/app/src/main/res/drawable/splash.png b/sneaky-app/android/app/src/main/res/drawable/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/drawable/splash.png differ diff --git a/sneaky-app/android/app/src/main/res/layout/activity_main.xml b/sneaky-app/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..b5ad138 --- /dev/null +++ b/sneaky-app/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/sneaky-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/sneaky-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/sneaky-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sneaky-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/sneaky-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/sneaky-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..c023e50 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2127973 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..b441f37 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..72905b8 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..8ed0605 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..9502e47 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..4d1e077 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..df0f158 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..853db04 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..6cdf97c Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2960cbb Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e3093a Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..46de6e2 Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..d2ea9ab Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..a40d73e Binary files /dev/null and b/sneaky-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/sneaky-app/android/app/src/main/res/values/ic_launcher_background.xml b/sneaky-app/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/sneaky-app/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/sneaky-app/android/app/src/main/res/values/strings.xml b/sneaky-app/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e26641d --- /dev/null +++ b/sneaky-app/android/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + Sneaky Drops + Sneaky Drops + co.sneakydrops.app + co.sneakydrops.app + diff --git a/sneaky-app/android/app/src/main/res/values/styles.xml b/sneaky-app/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..be874e5 --- /dev/null +++ b/sneaky-app/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/sneaky-app/android/app/src/main/res/xml/file_paths.xml b/sneaky-app/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..bd0c4d8 --- /dev/null +++ b/sneaky-app/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sneaky-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/sneaky-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java new file mode 100644 index 0000000..0297327 --- /dev/null +++ b/sneaky-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java @@ -0,0 +1,18 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} diff --git a/sneaky-app/android/build.gradle b/sneaky-app/android/build.gradle new file mode 100644 index 0000000..f8f0e43 --- /dev/null +++ b/sneaky-app/android/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.13.0' + classpath 'com.google.gms:google-services:4.4.4' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +apply from: "variables.gradle" + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/sneaky-app/android/capacitor.settings.gradle b/sneaky-app/android/capacitor.settings.gradle new file mode 100644 index 0000000..9a5fa87 --- /dev/null +++ b/sneaky-app/android/capacitor.settings.gradle @@ -0,0 +1,3 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') diff --git a/sneaky-app/android/gradle.properties b/sneaky-app/android/gradle.properties new file mode 100644 index 0000000..2e87c52 --- /dev/null +++ b/sneaky-app/android/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true diff --git a/sneaky-app/android/gradle/wrapper/gradle-wrapper.jar b/sneaky-app/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/sneaky-app/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/sneaky-app/android/gradle/wrapper/gradle-wrapper.properties b/sneaky-app/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7705927 --- /dev/null +++ b/sneaky-app/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/sneaky-app/android/gradlew b/sneaky-app/android/gradlew new file mode 100644 index 0000000..23d15a9 --- /dev/null +++ b/sneaky-app/android/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/sneaky-app/android/gradlew.bat b/sneaky-app/android/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/sneaky-app/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/sneaky-app/android/settings.gradle b/sneaky-app/android/settings.gradle new file mode 100644 index 0000000..3b4431d --- /dev/null +++ b/sneaky-app/android/settings.gradle @@ -0,0 +1,5 @@ +include ':app' +include ':capacitor-cordova-android-plugins' +project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') + +apply from: 'capacitor.settings.gradle' \ No newline at end of file diff --git a/sneaky-app/android/variables.gradle b/sneaky-app/android/variables.gradle new file mode 100644 index 0000000..ee4ba41 --- /dev/null +++ b/sneaky-app/android/variables.gradle @@ -0,0 +1,16 @@ +ext { + minSdkVersion = 24 + compileSdkVersion = 36 + targetSdkVersion = 36 + androidxActivityVersion = '1.11.0' + androidxAppCompatVersion = '1.7.1' + androidxCoordinatorLayoutVersion = '1.3.0' + androidxCoreVersion = '1.17.0' + androidxFragmentVersion = '1.8.9' + coreSplashScreenVersion = '1.2.0' + androidxWebkitVersion = '1.14.0' + junitVersion = '4.13.2' + androidxJunitVersion = '1.3.0' + androidxEspressoCoreVersion = '3.7.0' + cordovaAndroidVersion = '14.0.1' +} \ No newline at end of file diff --git a/sneaky-app/capacitor.config.ts b/sneaky-app/capacitor.config.ts new file mode 100644 index 0000000..dd2eed6 --- /dev/null +++ b/sneaky-app/capacitor.config.ts @@ -0,0 +1,25 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'co.sneakydrops.app', + appName: 'Sneaky Drops', + webDir: 'public', + server: { + url: 'https://sneaky.almeira.com.co', + cleartext: true, + androidScheme: 'https', + }, + plugins: { + SplashScreen: { + launchShowDuration: 2000, + backgroundColor: '#09090b', + showSpinner: false, + }, + StatusBar: { + style: 'DARK', + backgroundColor: '#09090b', + }, + }, +}; + +export default config; diff --git a/sneaky-app/eslint.config.mjs b/sneaky-app/eslint.config.mjs new file mode 100644 index 0000000..05e726d --- /dev/null +++ b/sneaky-app/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/sneaky-app/next.config.ts b/sneaky-app/next.config.ts new file mode 100644 index 0000000..5b406fe --- /dev/null +++ b/sneaky-app/next.config.ts @@ -0,0 +1,12 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", + images: { + remotePatterns: [ + { protocol: "https", hostname: "**" }, + ], + }, +}; + +export default nextConfig; diff --git a/sneaky-app/package-lock.json b/sneaky-app/package-lock.json new file mode 100644 index 0000000..498c24b --- /dev/null +++ b/sneaky-app/package-lock.json @@ -0,0 +1,8446 @@ +{ + "name": "sneaky-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sneaky-app", + "version": "0.1.0", + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capacitor/android": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.5.0.tgz", + "integrity": "sha512-Rb3prJeQiTp0pQhSSOReJuG9VgibOGMG4ECs+UhMwr6TCCHZ3NCZO811bDA0HxD0xrT/gCrJAsY5yfEATu84JQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.5.0" + } + }, + "node_modules/@capacitor/cli": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.5.0.tgz", + "integrity": "sha512-rLdzMUM5QV4WITcqoWv04p32i14BXgUH2diqEH6MWQlWaJfiyNrvOyt/+d5vHAfOxOm1klBu637VDEobctlwBA==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xcode": "^3.0.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@capacitor/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.5.0.tgz", + "integrity": "sha512-Ca4krtqH1hothjtBIwf2J2TW7IhYq1ujp8QeItTiJohNsqij8ja2DYYH3DU0l8RmxCWaBAFTGA2TgOgOMCSNsQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@google/genai": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-2.19.0.tgz", + "integrity": "sha512-IM3u1FjpOLyOPsPh0smGA6Ntj2olUWCPbTs/WQj7cA/2AKCGw/652W7IaySx0XtwuscFnMYBoraebQusSZ0zSQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@next/env": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.3.tgz", + "integrity": "sha512-U2eYQRwXj+dsqxV79zFqExDdatnNY/ZWc2nsJU1p/OgT7fd3dXwlF6OjYaFQCfMoeTA19PWq+wVmYgimVA+V+g==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.3.tgz", + "integrity": "sha512-pbEh30vvjKpDoTAmo1v3q2uM4JUi8QaEBpbmjWvGfoec2jLghy/WNtvzAT0bk+Ik9oz6etjt4YjXEk4BQnicCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "4.9.1", + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.3.tgz", + "integrity": "sha512-8Hiv32QJPwdV6KYJ8meR9SBA061tQqnIKTJDocvOXlEQqib0xMFpzArosuffFUUc0sslbh7QQ8a3Yey1QV8EIw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.3.tgz", + "integrity": "sha512-A1lgKgwVchRYmSe467zdwhxT9040dd8lH+o65sL5Jet8fjB4kegw/rDyPIpYVRb6jAqwXFOJpjIXJLxQKLiE3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.3.tgz", + "integrity": "sha512-bf0FIssMFueU2dm7vQEWWxk0c8UjKTdW0yzuh0sQsD8pf1+KCLDdaqhYZNMYGmXwEOiHAUzgBKudovIlcvvBjg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.3.tgz", + "integrity": "sha512-W7viwCk9JY/cAkdz/A273rd5bb3RgT/IHwR7Upv90tunjBWNtAAhGhoecHh+teRNRSinuAFmE+l7fwZ4YKkrXg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.3.tgz", + "integrity": "sha512-0W46zw1N3ODpI6n0GeivHvvob1pooozgZVqy65k0mh4/7vr+FbY9+WpHzNVXjHipJf/A3FDheBG19H1s5A25rA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.3.tgz", + "integrity": "sha512-H4mBso8ZTMBPtdT0PN0pBx2ayTvQuTuvS6qT13d77yVFJXAPCxkyIhLTmdMaGTJs0krQYI/qpzdHijCeihXhbg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.3.tgz", + "integrity": "sha512-cTMUJpcEGmeywofCUfhR+rSsoE33+rVPnPEYNTNdLNlsOeEg/vktOsKUSTb28vUGqD2jkm4Zaskcwn7OCI6FQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.3.tgz", + "integrity": "sha512-2VR4cTBzHXaBjnGsuH6GyJjENzQOmHeAh11uY1iUhjm3j5dEUrVJuUj+VL78jaGi/Dik8xS76zEj18BsFhlVZQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/canvas-confetti": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz", + "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz", + "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/type-utils": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.68.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz", + "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz", + "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.68.0", + "@typescript-eslint/types": "^8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz", + "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz", + "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz", + "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz", + "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.68.0", + "@typescript-eslint/tsconfig-utils": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz", + "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz", + "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-26.2.0.tgz", + "integrity": "sha512-8TCd4mMKhhUxGF9sjZ6W2V1gesnj43v1SFZoeAue/0O0ikMXIU92p96PiRn0D4nAVvFM/92bluTTb/PoXH5mnQ==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", + "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.415", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.415.tgz", + "integrity": "sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==", + "dev": true, + "license": "ISC" + }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.3.tgz", + "integrity": "sha512-teqtsR26tnlfXFHfVLTM/4tzEzU8DMu6GS1sddZzhfGzgd2f2ofbgDUcsk6cssSCzX6Tk6fmWifJcdANSdPJrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "16.3.3", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "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.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.577.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz", + "integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/native-run": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", + "integrity": "sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==", + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" + }, + "bin": { + "native-run": "bin/native-run" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.3.tgz", + "integrity": "sha512-tuRTx1nQ/yVw83cwJBo9F+njGUgMn3UHQycreWHB8XsStvvAh1AthbI8/4IpKnFaF58F+iSiHejYOlMQ/eq83g==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.3", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.3", + "@next/swc-darwin-x64": "16.3.3", + "@next/swc-linux-arm64-gnu": "16.3.3", + "@next/swc-linux-arm64-musl": "16.3.3", + "@next/swc-linux-x64-gnu": "16.3.3", + "@next/swc-linux-x64-musl": "16.3.3", + "@next/swc-win32-arm64-msvc": "16.3.3", + "@next/swc-win32-x64-msvc": "16.3.3", + "sharp": "^0.35.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-26.2.0.tgz", + "integrity": "sha512-rRToHOuG05F5Q3BGRoJNNIcO69zrYul/V9HOTxfcMSqhdw3TwInAl7pnSnMRW7D0MOQcvaLb8iZIwE1P8TP9Cw==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0", + "undici": "^6.26.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "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": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "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/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.68.0.tgz", + "integrity": "sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.68.0", + "@typescript-eslint/parser": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/sneaky-app/package.json b/sneaky-app/package.json new file mode 100644 index 0000000..adf0475 --- /dev/null +++ b/sneaky-app/package.json @@ -0,0 +1,38 @@ +{ + "name": "sneaky-app", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev -H 0.0.0.0 -p 3002", + "build": "next build", + "start": "next start -H 0.0.0.0 -p 3002", + "lint": "next lint" + }, + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } +} \ No newline at end of file diff --git a/sneaky-app/postcss.config.mjs b/sneaky-app/postcss.config.mjs new file mode 100644 index 0000000..61e3684 --- /dev/null +++ b/sneaky-app/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/sneaky-app/public/file.svg b/sneaky-app/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/sneaky-app/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sneaky-app/public/globe.svg b/sneaky-app/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/sneaky-app/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sneaky-app/public/icon.svg b/sneaky-app/public/icon.svg new file mode 100644 index 0000000..e32700b --- /dev/null +++ b/sneaky-app/public/icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + S + + diff --git a/sneaky-app/public/manifest.json b/sneaky-app/public/manifest.json new file mode 100644 index 0000000..361ef78 --- /dev/null +++ b/sneaky-app/public/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "Sneaky Drops • Viral Sneakers", + "short_name": "Sneaky Drops", + "description": "Zapatillas virales en tendencia, drops exclusivos y pago contraentrega en 24 horas.", + "start_url": "/", + "display": "standalone", + "background_color": "#09090b", + "theme_color": "#dc2626", + "orientation": "portrait", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any maskable" + } + ] +} diff --git a/sneaky-app/public/next.svg b/sneaky-app/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/sneaky-app/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sneaky-app/public/vercel.svg b/sneaky-app/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/sneaky-app/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sneaky-app/public/window.svg b/sneaky-app/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/sneaky-app/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sneaky-app/scripts/setup-appwrite.js b/sneaky-app/scripts/setup-appwrite.js new file mode 100644 index 0000000..8a34246 --- /dev/null +++ b/sneaky-app/scripts/setup-appwrite.js @@ -0,0 +1,131 @@ +/** + * Script de inicialización de la Base de Datos Independiente en Appwrite + * Ejecutar con: node scripts/setup-appwrite.js + */ +const { Client, Databases, Storage, Permission, Role } = require('node-appwrite'); +const fs = require('fs'); +const path = require('path'); + +// Leer variables de .env.local manualmente si dotenv no está disponible en este script +const envPath = path.resolve(__dirname, '../.env.local'); +if (fs.existsSync(envPath)) { + const envContent = fs.readFileSync(envPath, 'utf8'); + envContent.split('\n').forEach((line) => { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#')) { + const [k, ...v] = trimmed.split('='); + if (k && v) process.env[k.trim()] = v.join('=').trim(); + } + }); +} + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; +const apiKey = process.env.APPWRITE_API_KEY; +const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +const bucketId = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +if (!apiKey) { + console.error('❌ Falta APPWRITE_API_KEY en .env.local'); + process.exit(1); +} + +const client = new Client() + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey); + +const databases = new Databases(client); +const storage = new Storage(client); + +async function setup() { + console.log('🚀 Iniciando configuración de la Base de Datos Independiente para la Tienda...'); + console.log(`Endpoint: ${endpoint}`); + console.log(`Database ID: ${databaseId}`); + console.log(`Bucket ID: ${bucketId}`); + + // 1. Crear Base de Datos Independiente si no existe + try { + await databases.get(databaseId); + console.log(`✅ Base de datos independiente "${databaseId}" ya existe.`); + } catch (e) { + console.log(`Creando base de datos independiente "${databaseId}"...`); + await databases.create(databaseId, 'Sneakers Multi-Store DB'); + console.log(`✅ Base de datos "${databaseId}" creada con éxito.`); + } + + // 2. Crear Storage Bucket Independiente si no existe + try { + await storage.getBucket(bucketId); + console.log(`✅ Storage Bucket "${bucketId}" ya existe.`); + } catch (e) { + console.log(`Creando Storage Bucket "${bucketId}"...`); + try { + await storage.createBucket( + bucketId, + 'Sneakers Media Assets', + [Permission.read(Role.any()), Permission.create(Role.any())], + false, // fileSecurity + true, // enabled + 50000000, // 50MB max file size + ['jpg', 'png', 'webp', 'jpeg'] + ); + console.log(`✅ Storage Bucket "${bucketId}" creado con éxito.`); + } catch (bErr) { + console.warn('Nota sobre creación de bucket:', bErr.message); + } + } + + // 3. Crear Colecciones Independientes + const collections = [ + { + id: 'products', + name: 'Productos y Zapatillas', + }, + { + id: 'cities', + name: 'Ciudades y Envíos', + }, + { + id: 'payment_methods', + name: 'Métodos de Pago', + }, + { + id: 'orders', + name: 'Pedidos de Clientes', + }, + { + id: 'supplier_posts', + name: 'Feed de Mensajes WhatsApp', + }, + ]; + + for (const col of collections) { + try { + await databases.getCollection(databaseId, col.id); + console.log(`✅ Colección "${col.name}" (${col.id}) ya existe.`); + } catch (e) { + console.log(`Creando colección "${col.name}" (${col.id})...`); + try { + await databases.createCollection( + databaseId, + col.id, + col.name, + [ + Permission.read(Role.any()), + Permission.create(Role.any()), + Permission.update(Role.any()), + Permission.delete(Role.any()), + ] + ); + console.log(`✅ Colección creada: ${col.id}`); + } catch (cErr) { + console.warn(`Error creando colección ${col.id}:`, cErr.message); + } + } + } + + console.log('🎉 ¡Base de datos y colecciones independientes configuradas al 100%!'); +} + +setup().catch((err) => console.error('Error configurando Appwrite:', err)); diff --git a/sneaky-app/src/app/admin/ciudades/page.tsx b/sneaky-app/src/app/admin/ciudades/page.tsx new file mode 100644 index 0000000..82426ce --- /dev/null +++ b/sneaky-app/src/app/admin/ciudades/page.tsx @@ -0,0 +1,249 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { MapPin, Plus, Save, Trash2, Check, X, Truck, ShieldCheck } from 'lucide-react'; +import { City } from '@/types'; +import { INITIAL_CITIES } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminCitiesPage() { + const [cities, setCities] = useState(INITIAL_CITIES); + const [isSaving, setIsSaving] = useState(false); + const [message, setMessage] = useState(null); + + // New city form + const [newName, setNewName] = useState(''); + const [newDepartment, setNewDepartment] = useState(''); + const [newShippingCost, setNewShippingCost] = useState('0'); + const [newDeliveryTime, setNewDeliveryTime] = useState('Entrega en 24 Horas'); + const [newAllowCod, setNewAllowCod] = useState(true); + const [newFirstExchangeFree, setNewFirstExchangeFree] = useState(true); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + }, []); + + const handleToggleExchangeFree = async (city: City) => { + const updated = { ...city, firstExchangeFree: !city.firstExchangeFree }; + setCities((prev) => prev.map((c) => (c.id === city.id ? updated : c))); + + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: city.id, updates: { firstExchangeFree: updated.firstExchangeFree } }), + }); + setMessage(`Política de 1er cambio gratis para "${city.name}" ${updated.firstExchangeFree ? 'ACTIVADA' : 'DESACTIVADA'}.`); + }; + + const handleUpdateShipping = async (cityId: string, cost: number) => { + setCities((prev) => prev.map((c) => (c.id === cityId ? { ...c, shippingCost: cost } : c))); + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: cityId, updates: { shippingCost: cost } }), + }); + setMessage('Tarifa de envío actualizada.'); + }; + + const handleAddCity = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newName) return; + + const payload = { + name: newName, + department: newDepartment || 'Colombia', + shippingCost: parseInt(newShippingCost, 10) || 0, + deliveryTime: newDeliveryTime, + allowsContraentrega: newAllowCod, + firstExchangeFree: newFirstExchangeFree, + exchangePolicyNote: newFirstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${newName} (posteriores con flete estándar)` + : `Cambio de talla garantizado (flete logístico asumido por el cliente)`, + }; + + const res = await fetch('/api/cities', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + const data = await res.json(); + if (data.success) { + setCities((prev) => [...prev, data.city]); + setNewName(''); + setNewDepartment(''); + setMessage(`Ciudad "${data.city.name}" agregada con éxito.`); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Ciudades, Fletes y Garantía de Cambio +

+

+ Administra las tarifas de envío, tiempos de entrega y configura si el 1er cambio de talla es gratis o si el cliente asume el flete para cada ciudad. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Add New City Card */} +
+

+ + Registrar Nueva Ciudad o Municipio +

+ +
+
+ + setNewName(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDepartment(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewShippingCost(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDeliveryTime(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+
+ +
+
+ + + +
+ + +
+
+ + {/* Cities List */} +
+

Ciudades y Zonas Registradas ({cities.length})

+ +
+ {cities.map((city) => ( +
+
+
+ {city.name} + ({city.department}) + {city.allowsContraentrega ? ( + + Contraentrega Activo + + ) : ( + + Solo Despacho Nacional + + )} +
+

+ + {city.deliveryTime} +

+
+ + {/* Actions & Policy Toggle */} +
+ {/* 1st Exchange Free Toggle Button */} + + + {/* Shipping cost edit */} +
+ Flete: + handleUpdateShipping(city.id, parseInt(e.target.value, 10) || 0)} + className="w-20 bg-transparent text-xs font-bold text-white outline-hidden text-right" + /> + COP +
+
+
+ ))} +
+
+
+ ); +} diff --git a/sneaky-app/src/app/admin/configuracion/page.tsx b/sneaky-app/src/app/admin/configuracion/page.tsx new file mode 100644 index 0000000..d3a2a8f --- /dev/null +++ b/sneaky-app/src/app/admin/configuracion/page.tsx @@ -0,0 +1,352 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Store, Mail, Phone, MessageCircle, Instagram, MapPin, CreditCard, Save, CheckCircle2, DollarSign, Percent, ShieldCheck, QrCode, ExternalLink, Zap } from 'lucide-react'; +import { StoreSettings } from '@/types'; + +export default function AdminSettingsPage() { + const [settings, setSettings] = useState({ + storeName: 'Sneaky Drops', + slogan: 'Viral Sneakers & Exclusivos', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@sneakydrops.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }); + + const [isSaving, setIsSaving] = useState(false); + const [toast, setToast] = useState(null); + + useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setSettings(d.settings)) + .catch(() => {}); + }, []); + + const handleChange = (field: keyof StoreSettings, value: any) => { + setSettings((prev) => ({ ...prev, [field]: value })); + }; + + const handlePhoneChange = (val: string) => { + const cleanDigits = val.replace(/\D/g, ''); + const cleanWa = cleanDigits.startsWith('57') ? cleanDigits : `57${cleanDigits}`; + setSettings((prev) => ({ + ...prev, + phone: cleanDigits, + whatsappNumber: cleanWa, + })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSaving(true); + + try { + const res = await fetch('/api/settings', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settings), + }); + const data = await res.json(); + if (data.success) { + setToast('✅ ¡Datos de Sneaky Drops, WhatsApp oficial y pasarela Bold.co actualizados exitosamente!'); + setTimeout(() => setToast(null), 4500); + } + } catch (err) { + console.error(err); + } finally { + setIsSaving(false); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Información de la Tienda & Medios de Pago +

+

+ Configura los datos oficiales del negocio: WhatsApp oficial de atención, correo electrónico, pasarela Bold.co (Link de pago, QR y botón), Nequi, Daviplata y reglas de margen. +

+
+ + {toast && ( +
+ {toast} + +
+ )} + +
+ {/* Section 1: Identidad & WhatsApp Oficial */} +
+

+ + Identidad & WhatsApp Oficial de Atención +

+ +
+
+ + handleChange('storeName', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white font-semibold outline-hidden focus:border-orange-500" + /> +
+ +
+ + handleChange('slogan', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500" + /> +
+ +
+ + handleChange('email', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500 font-mono" + /> +
+ +
+ +
+ handlePhoneChange(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl pl-9 pr-3.5 py-2.5 text-emerald-300 font-bold outline-hidden focus:border-emerald-400" + /> + +
+

+ Link generado: https://wa.me/{settings.whatsappNumber} +

+
+ +
+ + handleChange('instagramHandle', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500" + /> +
+ +
+ + handleChange('city', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500" + /> +
+
+
+ + {/* Section 2: Pasarela Bold.co (Link de Pago, QR o Botón) */} +
+
+

+ + Integración con Bold.co (Link de Pago, Botón & QR) +

+ +
+ +
+
+ +
+ handleChange('boldPaymentLink', e.target.value)} + className="w-full bg-zinc-950 border border-indigo-500/40 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> + +
+

+ Tus clientes podrán pagar por PSE, Tarjeta de Crédito/Débito o Nequi directamente con este enlace oficial de Bold. +

+
+ +
+ + handleChange('boldQrUrl', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-indigo-400" + /> +
+ +
+ + handleChange('boldApiKey', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> +
+
+
+ + {/* Section 3: Cuentas de Recaudo Nequi / Daviplata */} +
+

+ + Cuentas para Recaudo de Anticipos ($10.000 COP) +

+ +
+
+ + handleChange('accountHolder', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500 font-bold" + /> +
+ +
+ + handleChange('nequiAccount', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500" + /> +
+ +
+ + handleChange('daviplataAccount', e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-orange-500" + /> +
+
+
+ + {/* Section 4: Reglas de Precios y Anticipo */} +
+

+ + Reglas Comerciales de Ganancia & Redondeo +

+ +
+
+ +
+ handleChange('defaultProfitMargin', Number(e.target.value))} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-orange-500" + /> + +
+

+ El sistema calcula el precio y lo redondea al siguiente múltiplo de $5.000 COP (ej: $132.000 ➔ $135.000). +

+
+ +
+ +
+ handleChange('defaultDepositAmount', Number(e.target.value))} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-orange-500" + /> + +
+

+ Valor solicitado al comprador para apartar el calzado con el proveedor. +

+
+
+
+ + {/* Submit Bar */} +
+

+ Todos los cambios se reflejan inmediatamente en la tienda pública, el carrito y los mensajes de WhatsApp. +

+ +
+
+
+ ); +} diff --git a/sneaky-app/src/app/admin/feed-whatsapp/page.tsx b/sneaky-app/src/app/admin/feed-whatsapp/page.tsx new file mode 100644 index 0000000..a1866cb --- /dev/null +++ b/sneaky-app/src/app/admin/feed-whatsapp/page.tsx @@ -0,0 +1,365 @@ +'use client'; + +import React, { useState } from 'react'; +import { Radio, Sparkles, Share2, AlertTriangle, ShieldCheck, Plus, Send, Layers } from 'lucide-react'; +import { SupplierPost, Product } from '@/types'; +import { INITIAL_SUPPLIER_POSTS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { checkProductDuplicate } from '@/lib/deduplication-engine'; +import { formatCOP } from '@/lib/pricing-engine'; +import { BRANDS, BrandId } from '@/config/brands'; + +export default function SupplierFeedPage() { + const [posts, setPosts] = useState(INITIAL_SUPPLIER_POSTS); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [isProcessing, setIsProcessing] = useState(false); + const [actionMessage, setActionMessage] = useState(null); + + // Target brand selector for publishing + const [targetBrand, setTargetBrand] = useState('almeira'); + + // Simulación de nuevo mensaje entrante de grupo para probar en vivo + const [testText, setTestText] = useState( + '🔥 LLEGANDO A BODEGA HOY 🔥\nNike Air Max 90 White Black\nTallas: 38 a 43\nMayorista: $90.000 c/u\nEnvío inmediato contraentrega' + ); + const [testGroup, setTestGroup] = useState('Canal Mayorista A'); + + const handleSimulateIncoming = async () => { + setIsProcessing(true); + try { + const res = await fetch('/api/webhook/whatsapp', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + text: testText, + groupInfo: { subject: testGroup }, + }), + }); + const data = await res.json(); + if (data.success && data.post) { + setPosts((prev) => [data.post, ...prev]); + setActionMessage('✅ Nuevo mensaje de WhatsApp procesado con IA.'); + } + } catch (err) { + console.error(err); + } finally { + setIsProcessing(false); + } + }; + + const handlePublishFacebook = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + setIsProcessing(true); + try { + const brandName = targetBrand === 'all' ? 'Todas las Tiendas' : BRANDS[targetBrand].name; + const res = await fetch('/api/publish/facebook', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + productName: post.extractedProduct.name, + brand: post.extractedProduct.brand, + retailPrice: post.extractedProduct.suggestedRetailPrice, + sizes: post.extractedProduct.sizes, + images: post.rawImages, + }), + }); + const data = await res.json(); + if (data.success) { + setActionMessage(`🚀 ¡Publicado en Facebook bajo la marca "${brandName}"! (ID: ${data.postId})`); + } + } catch (e) { + console.error(e); + } finally { + setIsProcessing(false); + } + }; + + const handleAddToStore = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + const brandLabel = targetBrand === 'all' ? 'Multi-Marca' : BRANDS[targetBrand].shortName; + const newProduct: Product = { + id: `snk-${Date.now()}`, + name: post.extractedProduct.name, + brand: post.extractedProduct.brand, + supplierPrice: post.extractedProduct.supplierPrice, + retailPrice: post.extractedProduct.suggestedRetailPrice, + originalPrice: Math.round(post.extractedProduct.suggestedRetailPrice * 1.35), + sizes: post.extractedProduct.sizes, + images: post.rawImages, + description: `Zapatillas calidad premium garantizada para entrega inmediata.`, + category: post.extractedProduct.category, + inStock: true, + isActive: true, + originBadge: `Bodega Central`, + supplierName: post.supplierName || post.channelName || 'DIFUSION JOVIC STORE', + supplierPhone: post.supplierPhone || '573134848203', + }; + + try { + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProduct), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setActionMessage(`✨ "${newProduct.name}" habilitado en el catálogo para ${brandLabel}.`); + } + } catch (e) { + console.error(e); + } + }; + + return ( +
+ {/* Header */} +
+
+

+ + Feed de Entrada & Publicador Multi-Marca +

+

+ Recepción automática con IA, prevención de duplicados y distribución hacia las 4 marcas (Almeira Store, Sneaky, Zapply, DripZone). +

+
+ + {/* Target Brand Selector Pill Bar */} +
+ + Destino: + + + {Object.values(BRANDS).map((b) => ( + + ))} +
+
+ + {actionMessage && ( +
+ {actionMessage} + +
+ )} + + {/* Live Simulator for Test Messages */} +
+
+ + Simulador de Recepción en Tiempo Real +
+ +
+
+ + +
+ +
+ +
+ setTestText(e.target.value)} + className="flex-1 bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> + +
+
+
+
+ + {/* Intercepted Posts Feed */} +
+

Mensajes Procesados Recientemente

+ +
+ {posts.map((post) => { + const extracted = post.extractedProduct; + const duplicateCheck = extracted + ? checkProductDuplicate( + { + name: extracted.name, + brand: extracted.brand, + sizes: extracted.sizes, + supplierPrice: extracted.supplierPrice, + }, + products + ) + : null; + + return ( +
+ {/* Header of post */} +
+
+ + {post.channelName || 'Canal Mayorista'} + + {post.receivedAt} +
+ + {/* Anti-Duplicate Status Badge */} + {duplicateCheck && ( +
+ {duplicateCheck.isDuplicate ? ( + <> + + Duplicado Detectado ({Math.round(duplicateCheck.similarityScore * 100)}% Similitud) + + ) : ( + <> + + Producto Nuevo (0% Duplicados) + + )} +
+ )} +
+ + {/* Content Grid */} +
+ {/* Left: Raw WhatsApp Message (5 cols) */} +
+ Mensaje de Entrada: +

+ {post.rawMessage} +

+ {post.rawImages.length > 0 && ( +
+ +
+ )} +
+ + {/* Right: AI Extracted & Pricing Calculation (7 cols) */} +
+ {extracted ? ( +
+
+
+ + {extracted.brand} • {extracted.category} + +

{extracted.name}

+
+ + IA: {Math.round(extracted.confidence * 100)}% certeza + +
+ + {/* Pricing breakdown */} +
+
+ Costo Base: + + {formatCOP(extracted.supplierPrice)} + +
+
+ Precio Venta (+ Margen): + + {formatCOP(extracted.suggestedRetailPrice)} + +
+
+ + {/* Sizes */} +
+ + Tallas extraídas: + +
+ {extracted.sizes.map((s) => ( + + {s} + + ))} +
+
+ + {/* Duplicate warning note */} + {duplicateCheck?.isDuplicate && ( +
+ {duplicateCheck.message} +
+ )} + + {/* Actions */} +
+ + + +
+
+ ) : ( +

Extrayendo datos...

+ )} +
+
+
+ ); + })} +
+
+
+ ); +} diff --git a/sneaky-app/src/app/admin/grupos-whatsapp/page.tsx b/sneaky-app/src/app/admin/grupos-whatsapp/page.tsx new file mode 100644 index 0000000..63914e2 --- /dev/null +++ b/sneaky-app/src/app/admin/grupos-whatsapp/page.tsx @@ -0,0 +1,585 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { + MessageSquare, + RefreshCw, + Search, + CheckCircle2, + XCircle, + ShieldCheck, + Zap, + Radio, + Sliders, + Users, + Sparkles, + ExternalLink, + Plus, + ArrowUpRight, + Filter, + CheckSquare, + Square, + X +} from 'lucide-react'; +import { MonitoredWhatsAppGroup } from '@/types'; + +export default function AdminWhatsAppGroupsPage() { + const [groups, setGroups] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [filterMode, setFilterMode] = useState<'all' | 'monitored' | 'unmonitored'>('all'); + const [toast, setToast] = useState(null); + const [scanningGroupId, setScanningGroupId] = useState(null); + + // Group Picker Modal State + const [isPickerOpen, setIsPickerOpen] = useState(false); + const [liveGroups, setLiveGroups] = useState([]); + const [isLoadingLive, setIsLoadingLive] = useState(false); + const [pickerSearch, setPickerSearch] = useState(''); + const [selectedJids, setSelectedJids] = useState>(new Set()); + + const fetchLocalGroups = async () => { + setIsLoading(true); + try { + const res = await fetch('/api/whatsapp-groups'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setGroups(data.groups); + } + } catch (err) { + console.error(err); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchLocalGroups(); + }, []); + + const handleOpenPicker = async () => { + setIsPickerOpen(true); + setIsLoadingLive(true); + try { + const res = await fetch('/api/whatsapp-groups?fetchLive=true'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setLiveGroups(data.groups); + // Pre-select already monitored groups + const initialSelected = new Set(); + data.groups.forEach((g: MonitoredWhatsAppGroup) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + groups.forEach((g) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + setSelectedJids(initialSelected); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleSelectJid = (jid: string) => { + setSelectedJids((prev) => { + const next = new Set(prev); + if (next.has(jid)) next.delete(jid); + else next.add(jid); + return next; + }); + }; + + const handleSelectAllFiltered = (filtered: MonitoredWhatsAppGroup[]) => { + setSelectedJids((prev) => { + const next = new Set(prev); + filtered.forEach((g) => next.add(g.jid)); + return next; + }); + }; + + const handleDeselectAll = () => { + setSelectedJids(new Set()); + }; + + const handleSaveSelectedGroups = async () => { + setIsLoadingLive(true); + try { + const updatedGroups: MonitoredWhatsAppGroup[] = liveGroups.map((lg) => ({ + ...lg, + isMonitored: selectedJids.has(lg.jid), + autoPublish: true, + profitMarginOverride: 35, + })); + + const res = await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ groups: updatedGroups }), + }); + + const data = await res.json(); + if (data.success) { + setGroups(data.groups); + setIsPickerOpen(false); + setToast(`✅ ¡Se actualizaron los grupos monitoreados! (${selectedJids.size} activos)`); + setTimeout(() => setToast(null), 4000); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleGroup = async (group: MonitoredWhatsAppGroup) => { + const nextState = !group.isMonitored; + const updatedList = groups.map((g) => + g.jid === group.jid || g.id === group.id ? { ...g, isMonitored: nextState } : g + ); + setGroups(updatedList); + + try { + await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'toggle', + idOrJid: group.jid || group.id, + isMonitored: nextState, + }), + }); + + setToast( + nextState + ? `🟢 Grupo "${group.name}" ahora está siendo MONITOREADO en tiempo real.` + : `⚪ Grupo "${group.name}" fue desactivado del monitoreo.` + ); + setTimeout(() => setToast(null), 3500); + } catch (err) { + console.error(err); + } + }; + + const handleScanGroup = async (group: MonitoredWhatsAppGroup) => { + setScanningGroupId(group.id); + try { + await new Promise((r) => setTimeout(r, 1200)); + setToast(`✨ Mensajes recientes de "${group.name}" analizados con IA y catálogo actualizado.`); + setTimeout(() => setToast(null), 4000); + } finally { + setScanningGroupId(null); + } + }; + + const filteredGroups = groups.filter((g) => { + const matchesSearch = + g.name.toLowerCase().includes(searchQuery.toLowerCase()) || + g.jid.toLowerCase().includes(searchQuery.toLowerCase()) || + (g.notes && g.notes.toLowerCase().includes(searchQuery.toLowerCase())); + + if (filterMode === 'monitored') return matchesSearch && g.isMonitored; + if (filterMode === 'unmonitored') return matchesSearch && !g.isMonitored; + return matchesSearch; + }); + + const filteredPickerGroups = liveGroups.filter((g) => + g.name.toLowerCase().includes(pickerSearch.toLowerCase()) || + g.jid.toLowerCase().includes(pickerSearch.toLowerCase()) + ); + + const monitoredCount = groups.filter((g) => g.isMonitored).length; + + return ( +
+ {/* Header */} +
+
+

+ + Monitoreo de Grupos de WhatsApp +

+

+ Busca y selecciona los grupos de proveedores que el bot de Evolution API & Gemini debe escuchar 24/7 para auto-publicar zapatillas. +

+
+ + {/* Big Search and Select Button */} + +
+ + {/* Toast Notification */} + {toast && ( +
+ {toast} + +
+ )} + + {/* Stats Bar */} +
+
+
+

Grupos en tu WhatsApp

+

{groups.length}

+
+
+ +
+
+ +
+
+

Grupos Monitoreados (Activos)

+

{monitoredCount}

+
+
+ +
+
+ +
+
+

Evolution API (WhatsApp)

+

+ + AutomataAlmeira (En línea) +

+
+
+ +
+
+
+ + {/* Filter and Search Toolbar */} +
+
+ + setSearchQuery(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl pl-9 pr-3 py-2 text-xs text-white outline-hidden focus:border-orange-500" + /> +
+ +
+ + + +
+
+ + {/* Active Monitored Groups List */} +
+ {isLoading ? ( +
+ +

Cargando grupos de proveedores...

+
+ ) : filteredGroups.length === 0 ? ( +
+ +

No tienes grupos seleccionados para monitorear.

+ +
+ ) : ( + filteredGroups.map((group) => { + const isMonitored = group.isMonitored; + + return ( +
+ {/* Header */} +
+
+
+ +

+ {group.name} +

+
+

+ {group.jid} +

+
+ + {/* Toggle Switch */} + +
+ + {/* Info Pills */} +
+
+ Margen Aplicado + + +{group.profitMarginOverride || 35}% (Redondeo a $5.000) + +
+ +
+ Modo de Ingreso + + Auto-Publicar Directo + +
+
+ + {group.notes && ( +

+ ℹ️ {group.notes} +

+ )} + + {/* Action footer */} +
+ + {group.participantsCount ? `👥 ${group.participantsCount} miembros` : 'Canal Mayorista'} + + + +
+
+ ); + }) + )} +
+ + {/* ========================================================= */} + {/* MODAL: Group Picker (Buscar y Seleccionar Grupos) */} + {/* ========================================================= */} + {isPickerOpen && ( +
+
+ {/* Modal Header */} +
+
+
+ +
+
+

Seleccionar Grupos de WhatsApp

+

+ Marca los grupos que deseas monitorear con IA para auto-publicar calzado. +

+
+
+ +
+ + {/* Search and Action Toolbar in Modal */} +
+
+ + setPickerSearch(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl pl-9 pr-3.5 py-2.5 text-xs text-white outline-hidden focus:border-orange-500 font-semibold" + /> +
+ +
+ + Mostrando {filteredPickerGroups.length} grupos encontrados + +
+ + • + +
+
+
+ + {/* Groups Scrollable List */} +
+ {isLoadingLive ? ( +
+ +

Consultando grupos en vivo desde Evolution API...

+

Conectando con WhatsApp...

+
+ ) : filteredPickerGroups.length === 0 ? ( +
+

No se encontraron grupos con el término "{pickerSearch}".

+
+ ) : ( + filteredPickerGroups.map((group) => { + const isSelected = selectedJids.has(group.jid); + + return ( +
handleToggleSelectJid(group.jid)} + className={`p-3.5 rounded-2xl border transition-all cursor-pointer flex items-center justify-between gap-3 ${ + isSelected + ? 'bg-orange-950/30 border-orange-500/50 shadow-md ring-1 ring-orange-500/20' + : 'bg-zinc-950 border-zinc-800 hover:border-zinc-700' + }`} + > +
+
+ {isSelected && } +
+ +
+

+ {group.name} +

+

+ {group.jid} +

+
+
+ +
+ {isSelected ? ( + + Monitorear + + ) : ( + + Ignorar + + )} +
+
+ ); + }) + )} +
+ + {/* Modal Footer */} +
+
+ Seleccionados: + {selectedJids.size} + grupos para monitorear +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/sneaky-app/src/app/admin/layout.tsx b/sneaky-app/src/app/admin/layout.tsx new file mode 100644 index 0000000..34e4e73 --- /dev/null +++ b/sneaky-app/src/app/admin/layout.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { + LayoutDashboard, + Radio, + Package, + MapPin, + CreditCard, + ShoppingBag, + ArrowLeft, + Sparkles, + Store, + Users, + MessageSquare, +} from 'lucide-react'; + +export default function AdminLayout({ children }: { children: React.ReactNode }) { + const pathname = usePathname(); + + const NAV_ITEMS = [ + { href: '/admin', label: 'Resumen & KPIs', icon: LayoutDashboard }, + { href: '/admin/grupos-whatsapp', label: 'Grupos WhatsApp', icon: MessageSquare, badge: 'Monitoreo 24/7' }, + { href: '/admin/usuarios', label: 'Control de Usuarios', icon: Users, badge: 'Roles & Accesos' }, + { href: '/admin/configuracion', label: 'Datos de la Tienda', icon: Store }, + { href: '/admin/feed-whatsapp', label: 'Feed WhatsApp & IA', icon: Radio, badge: 'Anti-Duplicados' }, + { href: '/admin/productos', label: 'Catálogo de Zapatillas', icon: Package }, + { href: '/admin/ciudades', label: 'Ciudades & Fletes', icon: MapPin }, + { href: '/admin/metodos-pago', label: 'Medios de Pago & Anticipos', icon: CreditCard }, + { href: '/admin/pedidos', label: 'Pedidos & Logística', icon: ShoppingBag }, + ]; + + return ( +
+ {/* Sidebar */} + + + {/* Main Content Area */} +
+ {children} +
+
+ ); +} diff --git a/sneaky-app/src/app/admin/metodos-pago/page.tsx b/sneaky-app/src/app/admin/metodos-pago/page.tsx new file mode 100644 index 0000000..5f02d93 --- /dev/null +++ b/sneaky-app/src/app/admin/metodos-pago/page.tsx @@ -0,0 +1,163 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { CreditCard, Zap, Save, Check, ShieldCheck, QrCode } from 'lucide-react'; +import { PaymentMethod } from '@/types'; +import { INITIAL_PAYMENT_METHODS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminPaymentMethodsPage() { + const [methods, setMethods] = useState(INITIAL_PAYMENT_METHODS); + const [message, setMessage] = useState(null); + + useEffect(() => { + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setMethods(d.paymentMethods)) + .catch(() => {}); + }, []); + + const handleToggleActive = async (method: PaymentMethod) => { + const updated = { ...method, isActive: !method.isActive }; + setMethods((prev) => prev.map((m) => (m.id === method.id ? updated : m))); + + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: { isActive: updated.isActive } }), + }); + setMessage(`Método "${method.name}" ${updated.isActive ? 'activado' : 'desactivado'}.`); + }; + + const handleUpdateField = (id: string, field: keyof PaymentMethod, val: any) => { + setMethods((prev) => + prev.map((m) => (m.id === id ? { ...m, [field]: val } : m)) + ); + }; + + const handleSaveMethod = async (method: PaymentMethod) => { + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: method }), + }); + setMessage(`✅ Cambios guardados para "${method.name}".`); + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Medios de Pago & Anticipos +

+

+ Habilita métodos de pago, configura el valor de separación de $10.000 COP y personaliza los datos de Nequi / Daviplata. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Methods Cards */} +
+ {methods.map((method) => ( +
+
+
+
+ {method.type === 'contraentrega' ? : } +
+
+

{method.name}

+ Tipo: {method.type} +
+
+ +
+ +
+
+ +
+
+ + handleUpdateField(method.id, 'name', e.target.value)} + className="w-full bg-zinc-900 border border-zinc-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + handleUpdateField(method.id, 'description', e.target.value)} + className="w-full bg-zinc-900 border border-zinc-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ + {method.requiresDeposit && ( +
+ + handleUpdateField(method.id, 'depositAmount', parseInt(e.target.value, 10) || 0)} + className="w-full bg-zinc-900 border border-zinc-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden font-bold" + /> + + (El saldo restante se cobra contraentrega al recibir) + +
+ )} + +
+ + handleUpdateField(method.id, 'accountInfo', e.target.value)} + className="w-full bg-zinc-900 border border-zinc-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + placeholder="Ej. Nequi / Daviplata: 316 745 5877" + /> +
+
+ +
+ +
+
+ ))} +
+
+ ); +} diff --git a/sneaky-app/src/app/admin/page.tsx b/sneaky-app/src/app/admin/page.tsx new file mode 100644 index 0000000..8d400b5 --- /dev/null +++ b/sneaky-app/src/app/admin/page.tsx @@ -0,0 +1,159 @@ +'use client'; + +import React, { useState } from 'react'; +import Link from 'next/link'; +import { Package, Radio, MapPin, Zap, CheckCircle2, ArrowUpRight, Sparkles } from 'lucide-react'; +import { INITIAL_PRODUCTS, INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_SUPPLIER_POSTS } from '@/lib/data-service'; + +export default function AdminDashboardPage() { + const [productsCount] = useState(INITIAL_PRODUCTS.length); + const [postsCount] = useState(INITIAL_SUPPLIER_POSTS.length); + const [citiesCount] = useState(INITIAL_CITIES.length); + + return ( +
+ {/* Header */} +
+
+

+ + Centro de Control • Almeira Store +

+

+ Automatización inteligente de calzado, publicaciones a Facebook y gestión de despachos. +

+
+ +
+ + + Ver Feed de WhatsApp + +
+
+ + {/* KPI Cards */} +
+
+
+ Zapatillas Activas + +
+
{productsCount}
+

+ Catálogo sincronizado +

+
+ +
+
+ Margen Promedio + +
+
+ +$30.000 COP +
+

+ (Costo: $90k ➔ Venta: $120k) +

+
+ +
+
+ Entradas Procesadas + +
+
{postsCount}
+

+ IA Gemini + Anti-duplicados +

+
+ +
+
+ Ciudades Habilitadas + +
+
{citiesCount}
+

+ Contraentrega activo en Cali +

+
+
+ + {/* Quick Actions & Automation Status */} +
+ {/* Left: WhatsApp Evolution API Status */} +
+
+
+
+

Estado del Listener de WhatsApp

+
+ + Activo + +
+ +
+
+ Instancia Evolution API: + AutomataAlmeira +
+
+ Servidor: + evolution.almeira.com.co +
+
+ Motor de Inteligencia Artificial: + Gemini 2.5 Flash +
+
+ Filtro Anti-Duplicados: + Activo (>75% Similitud) +
+
+ + + Ver últimos mensajes procesados + + +
+ + {/* Right: Meta / Facebook Automation */} +
+
+

Publicador a Fanpage de Facebook

+ + Listo para Publicar + +
+ +
+

✨ Plantilla de Copy Vendedor Integrada:

+

+ "✨ ALMEIRA STORE • NUEVA COLECCIÓN EXCLUSIVA ✨
+ 👟 NIKE DUNK LOW PANDA
+ 📏 Tallas: 37 a 43 | 💎 Precio: $120.000 COP
+ 🚚 ¡Entrega a Domicilio en Cali con Pago Contraentrega!" +

+
+ + + Publicar Producto de Prueba en Facebook + + +
+
+
+ ); +} diff --git a/sneaky-app/src/app/admin/pedidos/page.tsx b/sneaky-app/src/app/admin/pedidos/page.tsx new file mode 100644 index 0000000..f28a975 --- /dev/null +++ b/sneaky-app/src/app/admin/pedidos/page.tsx @@ -0,0 +1,275 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { ShoppingBag, Truck, CheckCircle2, Clock, Phone, MapPin, Search, MessageCircle, Send, ShieldCheck, UserCheck } from 'lucide-react'; +import { Order, OrderItem } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminOrdersPage() { + const [orders, setOrders] = useState([]); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState('all'); + + useEffect(() => { + fetch('/api/orders') + .then((r) => r.json()) + .then((d) => d.success && setOrders(d.orders)) + .catch(() => {}); + }, []); + + const handleStatusChange = async (orderId: string, newStatus: Order['status']) => { + setOrders((prev) => + prev.map((o) => (o.id === orderId ? { ...o, status: newStatus } : o)) + ); + + await fetch('/api/orders', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: orderId, status: newStatus }), + }).catch(() => {}); + }; + + const handleNotifySupplier = (order: Order, item: OrderItem) => { + const supplierPhone = item.supplierPhone || '573134848203'; + const supplierName = item.supplierName || 'Proveedor Mayorista'; + const supplierCost = item.supplierPrice ? formatCOP(item.supplierPrice) : 'Precio Mayorista'; + + const message = `👋 Hola *${supplierName}*!\n\nPor favor *sepárame este par* para despacho inmediato:\n\n👟 *Modelo:* ${item.productName}\n📏 *Talla:* ${item.size}\n📦 *Cantidad:* ${item.quantity} par(es)\n💵 *Costo Base:* ${supplierCost}\n\n🏷️ *Orden Interna:* #${order.id}\n📍 *Ciudad Destino:* ${order.cityName}\n\n¿Me confirmas si lo tienes listo para recoger / enviar? ¡Muchas gracias!`; + + const url = `https://wa.me/${supplierPhone}?text=${encodeURIComponent(message)}`; + window.open(url, '_blank'); + + if (order.status === 'pending' || order.status === 'deposit_received') { + handleStatusChange(order.id, 'supplier_notified'); + } + }; + + const getStatusBadge = (status: Order['status']) => { + switch (status) { + case 'pending': + return Pendiente Confirmar; + case 'deposit_received': + return Separación $10k Pagada; + case 'supplier_notified': + return Proveedor Notificado; + case 'dispatched': + return En Ruta con Mensajero; + case 'delivered': + return Entregado & Cobrado; + case 'cancelled': + return Cancelado; + } + }; + + const filteredOrders = orders.filter((o) => { + const matchesSearch = + o.customerName.toLowerCase().includes(search.toLowerCase()) || + o.customerPhone.includes(search) || + o.cityName.toLowerCase().includes(search.toLowerCase()) || + o.id.toLowerCase().includes(search.toLowerCase()); + + if (!matchesSearch) return false; + if (statusFilter !== 'all' && o.status !== statusFilter) return false; + return true; + }); + + return ( +
+ {/* Header */} +
+

+ + Gestión de Pedidos & Separación con Proveedores ({orders.length}) +

+

+ Control logístico de pedidos contraentrega, cobro de anticipos de $10.000 COP y notificación inmediata de separación al proveedor vía WhatsApp. +

+
+ + {/* Toolbar */} +
+
+ + + + +
+ +
+ setSearch(e.target.value)} + className="w-full bg-gray-900 border border-gray-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-orange-500" + /> +
+
+ + {filteredOrders.length === 0 ? ( +
+
+ +
+

No hay pedidos en esta sección

+

+ Cuando los clientes hagan un pedido en la tienda web o por WhatsApp, aparecerán aquí con el botón para separar inmediatamente con el proveedor correspondiente. +

+
+ ) : ( +
+ {filteredOrders.map((order) => ( +
+
+
+ Orden #{order.id} + • {new Date(order.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} +
+ {getStatusBadge(order.status)} +
+ +
+
+ + Cliente & Entrega (24 Horas) + +

{order.customerName}

+

+ {order.customerPhone} +

+

+ {order.address} ({order.cityName}) +

+
+ +
+ + Zapatillas & Proveedor Asignado: + +
+ {order.items.map((it, idx) => { + const suppName = it.supplierName || 'DIFUSION JOVIC STORE'; + return ( +
+
+
+

{it.productName}

+

+ Talla {it.size} • Cant: {it.quantity} +

+
+ + Prov: {suppName} + +
+ + +
+ ); + })} +
+
+ +
+ + Cobro & Pagos Contraentrega + +
+

+ Total de la Orden: + {formatCOP(order.totalAmount)} +

+ {order.depositAmount > 0 ? ( + <> +

+ Anticipo / Separación: + {formatCOP(order.depositAmount)} +

+

+ Saldo al Mensajero: + {formatCOP(order.balanceDue)} +

+ + ) : ( +

+ 100% Contraentrega al recibir +

+ )} +
+
+
+ +
+ Método: {order.paymentMethodName} + +
+ + + + +
+
+
+ ))} +
+ )} +
+ ); +} diff --git a/sneaky-app/src/app/admin/productos/page.tsx b/sneaky-app/src/app/admin/productos/page.tsx new file mode 100644 index 0000000..ae3a0de --- /dev/null +++ b/sneaky-app/src/app/admin/productos/page.tsx @@ -0,0 +1,472 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Package, Plus, Eye, EyeOff, Check, X, Sparkles, Filter, Phone, MessageCircle, Truck } from 'lucide-react'; +import { Product, Supplier } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_SUPPLIERS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminProductsPage() { + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [suppliers, setSuppliers] = useState(INITIAL_SUPPLIERS); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [supplierFilter, setSupplierFilter] = useState('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New product form + const [name, setName] = useState(''); + const [brand, setBrand] = useState('Nike'); + const [selectedSupplierId, setSelectedSupplierId] = useState('sup-1'); + const [supplierPrice, setSupplierPrice] = useState('90000'); + const [retailPrice, setRetailPrice] = useState('125000'); + const [sizesInput, setSizesInput] = useState('37, 38, 39, 40, 41, 42, 43'); + const [imageUrl, setImageUrl] = useState( + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' + ); + const [category, setCategory] = useState('Sneakers / Urbano'); + const [isActiveNew, setIsActiveNew] = useState(true); + + useEffect(() => { + fetch('/api/products?all=true') + .then((r) => r.json()) + .then((d) => d.success && setProducts(d.products)) + .catch(() => {}); + }, []); + + const handleToggleProductStatus = async (product: Product) => { + const newStatus = product.isActive === false ? true : false; + + setProducts((prev) => + prev.map((p) => (p.id === product.id ? { ...p, isActive: newStatus } : p)) + ); + + try { + const res = await fetch('/api/products', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + id: product.id, + updates: { isActive: newStatus }, + }), + }); + + const data = await res.json(); + if (data.success) { + setToastMessage( + `Zapatilla "${product.name}" ahora está ${newStatus ? '🟢 ACTIVA (Visible en la tienda)' : '⚪ INACTIVA (Oculta de la tienda)'}.` + ); + } + } catch (e) { + console.error('Error toggling status:', e); + } + }; + + const handleContactSupplier = (product: Product) => { + const phone = product.supplierPhone || '573134848203'; + const suppName = product.supplierName || 'Proveedor Mayorista'; + const text = encodeURIComponent( + `Hola ${suppName}! 👋 Consulta sobre disponibilidad del modelo *${product.name}* (Costo base: ${formatCOP(product.supplierPrice)}).` + ); + window.open(`https://wa.me/${phone}?text=${text}`, '_blank'); + }; + + const handleCreateProduct = async (e: React.FormEvent) => { + e.preventDefault(); + const sizes = sizesInput + .split(',') + .map((s) => s.trim()) + .filter(Boolean); + + const chosenSupplier = suppliers.find((s) => s.id === selectedSupplierId) || suppliers[0]; + + const newProd: Product = { + id: `snk-${Date.now()}`, + name, + brand, + supplierPrice: parseInt(supplierPrice, 10) || 90000, + retailPrice: parseInt(retailPrice, 10) || 125000, + originalPrice: Math.round((parseInt(retailPrice, 10) || 125000) * 1.35), + sizes, + images: [imageUrl], + description: 'Zapatillas de alta calidad garantizada para entrega inmediata.', + category, + inStock: true, + isActive: isActiveNew, + originBadge: 'Bodega Central', + supplierId: chosenSupplier.id, + supplierName: chosenSupplier.name, + supplierPhone: chosenSupplier.phone, + }; + + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProd), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setIsModalOpen(false); + setName(''); + setToastMessage(`✨ "${newProd.name}" registrada con proveedor [${chosenSupplier.name}].`); + } + }; + + const filtered = products.filter((p) => { + const matchesSearch = + p.name.toLowerCase().includes(search.toLowerCase()) || + p.brand.toLowerCase().includes(search.toLowerCase()) || + (p.supplierName && p.supplierName.toLowerCase().includes(search.toLowerCase())); + + if (!matchesSearch) return false; + if (statusFilter === 'active' && p.isActive === false) return false; + if (statusFilter === 'inactive' && p.isActive !== false) return false; + if (supplierFilter !== 'all' && p.supplierName !== supplierFilter) return false; + return true; + }); + + const activeCount = products.filter((p) => p.isActive !== false).length; + const inactiveCount = products.filter((p) => p.isActive === false).length; + + return ( +
+ {/* Header */} +
+
+

+ + Catálogo General de Zapatillas & Proveedores ({products.length}) +

+

+ Visualiza cada modelo con su proveedor asignado, costo mayorista y activa/inactiva publicaciones para la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* Filters & Search Toolbar */} +
+ {/* Status filter pills */} +
+ + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-gray-900 border border-gray-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-orange-500" + /> +
+
+ + {/* Products Table */} +
+
+ + + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((prod) => { + const isActive = prod.isActive !== false; + const margin = prod.retailPrice - prod.supplierPrice; + const suppName = prod.supplierName || 'DIFUSION JOVIC STORE'; + const suppPhone = prod.supplierPhone || '573134848203'; + + return ( + + {/* Estado Toggle Button */} + + + {/* Product Name & Image */} + + + {/* Supplier Column */} + + + + + + + + + + + ); + }) + )} + +
Estado PublicaciónProductoProveedor Asignado (Interno)MarcaCosto BasePrecio VentaMargen GananciaTallas
+ No hay zapatillas que coincidan con el filtro seleccionado. +
+ + + +
+

{prod.name}

+ {prod.category} +
+
+
+ + 🏢 {suppName} + + +
+
{prod.brand}{formatCOP(prod.supplierPrice)}{formatCOP(prod.retailPrice)} + + +{formatCOP(margin)} + + +
+ {prod.sizes.map((s) => ( + + {s} + + ))} +
+
+
+
+ + {/* Modal Add Product */} + {isModalOpen && ( +
+
+

Registrar Nueva Zapatilla

+ +
+
+ + setName(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ + {/* Supplier Selection */} +
+ + +

+ Este proveedor recibirá la notificación para separar el par cuando se haga un pedido. +

+
+ +
+
+ + +
+ +
+ + setCategory(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+
+ + setSupplierPrice(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setRetailPrice(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setSizesInput(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setImageUrl(e.target.value)} + className="w-full bg-gray-950 border border-gray-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/sneaky-app/src/app/admin/usuarios/page.tsx b/sneaky-app/src/app/admin/usuarios/page.tsx new file mode 100644 index 0000000..3de18ca --- /dev/null +++ b/sneaky-app/src/app/admin/usuarios/page.tsx @@ -0,0 +1,469 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Users, UserPlus, Shield, ShieldCheck, UserCheck, MessageCircle, Mail, Phone, MapPin, Eye, EyeOff, Trash2, Edit, Check, X } from 'lucide-react'; +import { User } from '@/types'; + +export default function AdminUsersPage() { + const [users, setUsers] = useState([]); + const [search, setSearch] = useState(''); + const [roleFilter, setRoleFilter] = useState<'all' | 'admin' | 'operator' | 'customer'>('all'); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New user modal form + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [role, setRole] = useState<'admin' | 'operator' | 'customer'>('operator'); + + useEffect(() => { + fetchUsers(); + }, []); + + const fetchUsers = async () => { + try { + const res = await fetch('/api/users'); + const data = await res.json(); + if (data.success) { + setUsers(data.users); + } + } catch (e) { + console.error(e); + } + }; + + const handleToggleStatus = async (user: User) => { + const newStatus = !user.isActive; + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, isActive: newStatus } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { isActive: newStatus } }), + }); + setToastMessage(`Estado de ${user.name} actualizado a ${newStatus ? '🟢 ACTIVO' : '⚪ INACTIVO'}.`); + } catch (e) { + console.error(e); + } + }; + + const handleChangeRole = async (user: User, newRole: 'admin' | 'operator' | 'customer') => { + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, role: newRole } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { role: newRole } }), + }); + setToastMessage(`Rol de ${user.name} actualizado a [${newRole.toUpperCase()}].`); + } catch (e) { + console.error(e); + } + }; + + const handleDeleteUser = async (id: string, name: string) => { + if (!confirm(`¿Estás seguro de eliminar al usuario ${name}?`)) return; + + setUsers((prev) => prev.filter((u) => u.id !== id)); + try { + await fetch(`/api/users?id=${id}`, { method: 'DELETE' }); + setToastMessage(`Usuario ${name} eliminado.`); + } catch (e) { + console.error(e); + } + }; + + const handleCreateUser = async (e: React.FormEvent) => { + e.preventDefault(); + try { + const res = await fetch('/api/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, phone, city, address, role }), + }); + const data = await res.json(); + if (data.success) { + setUsers((prev) => [data.user, ...prev]); + setIsModalOpen(false); + setName(''); + setEmail(''); + setPhone(''); + setAddress(''); + setToastMessage(`✨ Usuario "${data.user.name}" registrado con éxito.`); + } else { + alert(data.error); + } + } catch (e) { + console.error(e); + } + }; + + const handleWhatsApp = (user: User) => { + const cleanPhone = user.phone.startsWith('57') ? user.phone : `57${user.phone}`; + const text = encodeURIComponent(`Hola ${user.name}! Te escribimos del equipo de Sneaky Drops 🔥`); + window.open(`https://wa.me/${cleanPhone}?text=${text}`, '_blank'); + }; + + const filtered = users.filter((u) => { + const matchSearch = + u.name.toLowerCase().includes(search.toLowerCase()) || + u.email.toLowerCase().includes(search.toLowerCase()) || + u.phone.includes(search) || + (u.city && u.city.toLowerCase().includes(search.toLowerCase())); + + if (!matchSearch) return false; + if (roleFilter !== 'all' && u.role !== roleFilter) return false; + if (statusFilter === 'active' && !u.isActive) return false; + if (statusFilter === 'inactive' && u.isActive) return false; + return true; + }); + + const adminsCount = users.filter((u) => u.role === 'admin').length; + const operatorsCount = users.filter((u) => u.role === 'operator').length; + const customersCount = users.filter((u) => u.role === 'customer').length; + + return ( +
+ {/* Header */} +
+
+

+ + Control de Usuarios, Roles & Registro ({users.length}) +

+

+ Administra los accesos de administradores, operadores de logística y clientes registrados de la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* KPI Stats Cards */} +
+
+
+ +
+
+

Administradores

+

{adminsCount}

+
+
+ +
+
+ +
+
+

Operadores Logísticos

+

{operatorsCount}

+
+
+ +
+
+ +
+
+

Clientes Registrados

+

{customersCount}

+
+
+
+ + {/* Filters Toolbar */} +
+ {/* Role Pills */} +
+ + + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-zinc-900 border border-zinc-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-orange-500" + /> +
+
+ + {/* Users Table */} +
+
+ + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((user) => { + return ( + + {/* Active Status Toggle */} + + + {/* User Avatar & Name */} + + + {/* Contact */} + + + {/* City */} + + + {/* Role Dropdown */} + + + {/* Last Login */} + + + {/* Actions */} + + + ); + }) + )} + +
EstadoUsuarioContacto DirectoCiudad / DirecciónRol & PermisosÚltimo AccesoAcciones
+ No se encontraron usuarios con el filtro seleccionado. +
+ + +
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+ {user.email} +
+
+
+ +
+
+
+ {user.city || 'Cali'} + {user.address &&

{user.address}

} +
+
+ + + {user.lastLogin || user.createdAt} + + +
+
+
+ + {/* Modal Create User */} + {isModalOpen && ( +
+
+

Registrar Nuevo Usuario / Operador

+ +
+
+ + setName(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setEmail(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+
+ + setPhone(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setCity(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setAddress(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/sneaky-app/src/app/api/auth/login/route.ts b/sneaky-app/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..a2ae66e --- /dev/null +++ b/sneaky-app/src/app/api/auth/login/route.ts @@ -0,0 +1,29 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function POST(request: Request) { + try { + const { identifier } = await request.json(); + if (!identifier) { + return NextResponse.json({ success: false, error: 'Ingresa tu correo o celular' }, { status: 400 }); + } + const user = dataService.authenticate(identifier); + if (!user) { + return NextResponse.json( + { success: false, error: 'Usuario no encontrado. Verifica tu correo o celular.' }, + { status: 404 } + ); + } + if (!user.isActive) { + return NextResponse.json( + { success: false, error: 'Esta cuenta se encuentra inactiva. Contacta a soporte.' }, + { status: 403 } + ); + } + + dataService.updateUser(user.id, { lastLogin: 'Justo ahora' }); + return NextResponse.json({ success: true, user }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/auth/register/route.ts b/sneaky-app/src/app/api/auth/register/route.ts new file mode 100644 index 0000000..62b2a63 --- /dev/null +++ b/sneaky-app/src/app/api/auth/register/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function POST(request: Request) { + try { + const { name, email, phone, city, address } = await request.json(); + if (!name || !email || !phone) { + return NextResponse.json( + { success: false, error: 'Nombre, correo y celular son obligatorios' }, + { status: 400 } + ); + } + + const existing = dataService.authenticate(email) || dataService.authenticate(phone); + if (existing) { + return NextResponse.json( + { success: false, error: 'Ya existe una cuenta con este correo o celular' }, + { status: 409 } + ); + } + + const newUser: User = { + id: `usr-${Date.now()}`, + name, + email, + phone, + city: city || 'Cali', + address: address || '', + role: 'customer', + isActive: true, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + lastLogin: 'Justo ahora', + }; + + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/cities/route.ts b/sneaky-app/src/app/api/cities/route.ts new file mode 100644 index 0000000..3ecd601 --- /dev/null +++ b/sneaky-app/src/app/api/cities/route.ts @@ -0,0 +1,27 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const cities = dataService.getCities(); + return NextResponse.json({ success: true, cities }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateCity(id, updates); + return NextResponse.json({ success: true, city: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const created = dataService.addCity(body); + return NextResponse.json({ success: true, city: created }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/orders/route.ts b/sneaky-app/src/app/api/orders/route.ts new file mode 100644 index 0000000..9c996b6 --- /dev/null +++ b/sneaky-app/src/app/api/orders/route.ts @@ -0,0 +1,30 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { sendWhatsAppMessage, buildOrderConfirmationMessage } from '@/lib/evolution-api'; + +export async function GET() { + const orders = dataService.getOrders(); + return NextResponse.json({ success: true, orders }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newOrder = dataService.createOrder(body); + + // Enviar confirmación por WhatsApp en background si tiene teléfono válido + if (newOrder.customerPhone) { + try { + const msg = buildOrderConfirmationMessage(newOrder); + // Intentar enviar WhatsApp + await sendWhatsAppMessage(newOrder.customerPhone, msg); + } catch (waErr) { + console.warn('No se pudo enviar WhatsApp automático:', waErr); + } + } + + return NextResponse.json({ success: true, order: newOrder }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/payment-methods/route.ts b/sneaky-app/src/app/api/payment-methods/route.ts new file mode 100644 index 0000000..b49c62d --- /dev/null +++ b/sneaky-app/src/app/api/payment-methods/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const methods = dataService.getPaymentMethods(); + return NextResponse.json({ success: true, paymentMethods: methods }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updatePaymentMethod(id, updates); + return NextResponse.json({ success: true, paymentMethod: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/products/route.ts b/sneaky-app/src/app/api/products/route.ts new file mode 100644 index 0000000..9ebf898 --- /dev/null +++ b/sneaky-app/src/app/api/products/route.ts @@ -0,0 +1,46 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const includeAll = searchParams.get('all') === 'true'; + + let products = dataService.getProducts(); + if (!includeAll) { + products = products.filter((p) => p.isActive !== false); + } + + return NextResponse.json({ success: true, products }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newProduct = dataService.addProduct({ + ...body, + isActive: body.isActive !== undefined ? body.isActive : true, + }); + return NextResponse.json({ success: true, product: newProduct }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const { id, updates } = body; + if (!id) { + return NextResponse.json({ success: false, error: 'ID de producto requerido' }, { status: 400 }); + } + + const updated = dataService.updateProduct(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Producto no encontrado' }, { status: 404 }); + } + + return NextResponse.json({ success: true, product: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/publish/facebook/route.ts b/sneaky-app/src/app/api/publish/facebook/route.ts new file mode 100644 index 0000000..d2db7a3 --- /dev/null +++ b/sneaky-app/src/app/api/publish/facebook/route.ts @@ -0,0 +1,12 @@ +import { NextResponse } from 'next/server'; +import { publishToFacebookPage } from '@/lib/facebook-publisher'; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const result = await publishToFacebookPage(body); + return NextResponse.json(result); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/sneaky-app/src/app/api/settings/route.ts b/sneaky-app/src/app/api/settings/route.ts new file mode 100644 index 0000000..6073d91 --- /dev/null +++ b/sneaky-app/src/app/api/settings/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const settings = dataService.getSettings(); + return NextResponse.json({ success: true, settings }); +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const updated = dataService.updateSettings(body); + return NextResponse.json({ success: true, settings: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/users/route.ts b/sneaky-app/src/app/api/users/route.ts new file mode 100644 index 0000000..8b62fad --- /dev/null +++ b/sneaky-app/src/app/api/users/route.ts @@ -0,0 +1,57 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function GET() { + const users = dataService.getUsers(); + return NextResponse.json({ success: true, users }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newUser: User = { + id: `usr-${Date.now()}`, + name: body.name, + email: body.email, + phone: body.phone, + city: body.city || 'Cali', + address: body.address || '', + role: body.role || 'customer', + isActive: body.isActive !== false, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + }; + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateUser(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Usuario no encontrado' }, { status: 404 }); + } + return NextResponse.json({ success: true, user: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function DELETE(request: Request) { + try { + const { searchParams } = new URL(request.url); + const id = searchParams.get('id'); + if (!id) { + return NextResponse.json({ success: false, error: 'ID requerido' }, { status: 400 }); + } + const deleted = dataService.deleteUser(id); + return NextResponse.json({ success: deleted }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/sneaky-app/src/app/api/webhook/whatsapp/route.ts b/sneaky-app/src/app/api/webhook/whatsapp/route.ts new file mode 100644 index 0000000..ae1555b --- /dev/null +++ b/sneaky-app/src/app/api/webhook/whatsapp/route.ts @@ -0,0 +1,163 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { parseSupplierMessage } from '@/lib/gemini-parser'; +import { SupplierPost, Product } from '@/types'; +import { calculateRetailPrice } from '@/lib/pricing-engine'; + +export async function GET() { + const posts = dataService.getSupplierPosts(); + const settings = dataService.getSettings(); + return NextResponse.json({ + success: true, + autoPublishEnabled: settings.autoPublishSupplierPosts ?? true, + postsCount: posts.length, + posts, + }); +} + +export async function POST(request: Request) { + try { + const payload = await request.json(); + console.log('📥 [WhatsApp Webhook] Mensaje recibido:', JSON.stringify(payload).slice(0, 300)); + + const data = payload.data || payload; + const settings = dataService.getSettings(); + + // 1. Extraer texto del mensaje de WhatsApp + const messageContent = + data.message?.conversation || + data.message?.extendedTextMessage?.text || + data.message?.imageMessage?.caption || + data.text || + ''; + + // 2. Extraer nombre del canal o grupo + const senderPhone = data.key?.remoteJid?.replace(/\D/g, '') || ''; + const isGroup = data.key?.remoteJid?.includes('g.us'); + const channelName = + data.groupInfo?.subject || + data.pushName || + (isGroup ? 'Grupo Mayorista WhatsApp' : 'Chat Proveedor Directo'); + + if (!messageContent || messageContent.trim().length < 6) { + return NextResponse.json({ + success: true, + ignored: 'Mensaje sin texto suficiente para extraer calzado.', + }); + } + + // 3. Buscar proveedor asociado por teléfono o grupo + const suppliers = dataService.getSuppliers(); + const matchedSupplier = suppliers.find( + (s) => + s.phone.includes(senderPhone) || + (channelName && s.name.toLowerCase().includes(channelName.toLowerCase())) || + (channelName && channelName.toLowerCase().includes(s.name.toLowerCase())) + ); + + const supplierName = matchedSupplier?.name || channelName; + const supplierPhone = matchedSupplier?.phone || senderPhone || '573167455877'; + + // 4. Procesar y extraer información con Gemini AI + const extracted = await parseSupplierMessage(messageContent); + + // Recalcular precio con el margen y redondeo al $5.000 oficial + const finalRetailPrice = calculateRetailPrice( + extracted.supplierPrice, + settings.defaultProfitMargin || 35 + ); + + // Extraer imágenes (si Evolution API envió imagen adjunta o usar fotos de alta resolución) + const images: string[] = []; + if (data.message?.imageMessage?.url) { + images.push(data.message.imageMessage.url); + } else { + images.push( + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' + ); + } + + // 5. Verificar Anti-Duplicados en el Catálogo + const existingProducts = dataService.getProducts(); + const duplicateProduct = existingProducts.find( + (p) => p.name.toLowerCase() === extracted.name.toLowerCase() + ); + + let registeredProduct: Product | null = null; + const autoPublish = settings.autoPublishSupplierPosts ?? true; + + if (autoPublish) { + if (duplicateProduct) { + // Actualizar stock y tallas existentes sin duplicar + const mergedSizes = Array.from(new Set([...duplicateProduct.sizes, ...extracted.sizes])); + registeredProduct = dataService.updateProduct(duplicateProduct.id, { + supplierPrice: extracted.supplierPrice, + retailPrice: finalRetailPrice, + sizes: mergedSizes, + inStock: true, + isActive: true, + supplierName, + supplierPhone, + }); + console.log(`🔄 [Auto-Sync] Zapatilla "${extracted.name}" actualizada en catálogo (Anti-Duplicados).`); + } else { + // Registrar y publicar automáticamente + registeredProduct = dataService.addProduct({ + name: extracted.name, + brand: extracted.brand, + supplierPrice: extracted.supplierPrice, + retailPrice: finalRetailPrice, + originalPrice: Math.round(finalRetailPrice * 1.35), + sizes: extracted.sizes, + images, + description: `Zapatillas ${extracted.brand} ${extracted.name} garantizadas. Calidad seleccionada con horma nacional y suela antideslizante.`, + category: extracted.category || 'Sneakers / Urbano', + inStock: true, + isActive: true, + isFlashDeal: true, + rating: 4.9, + reviewsCount: 15, + salesCount: 30, + originBadge: 'Bodega Mayorista', + supplierId: matchedSupplier?.id || 'sup-auto', + supplierName, + supplierPhone, + }); + console.log(`✨ [Auto-Publish] Nueva zapatilla "${extracted.name}" publicada automáticamente en tienda.`); + } + } + + // 6. Registrar en el historial de publicaciones recibidas + const newPost: SupplierPost = { + id: `post-${Date.now()}`, + channelName, + supplierName, + supplierPhone, + rawMessage: messageContent, + rawImages: images, + extractedProduct: { + ...extracted, + suggestedRetailPrice: finalRetailPrice, + supplierName, + supplierPhone, + }, + status: autoPublish ? 'published_store' : 'pending_review', + receivedAt: 'Justo ahora', + }; + + dataService.addSupplierPost(newPost); + + return NextResponse.json({ + success: true, + autoPublished: autoPublish, + product: registeredProduct, + post: newPost, + message: autoPublish + ? `🔥 ¡Zapatilla "${extracted.name}" procesada y publicada AUTOMÁTICAMENTE en la tienda!` + : `Mensaje ingresado al feed para aprobación manual.`, + }); + } catch (error: any) { + console.error('Error procesando webhook de WhatsApp:', error); + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/sneaky-app/src/app/api/whatsapp-groups/route.ts b/sneaky-app/src/app/api/whatsapp-groups/route.ts new file mode 100644 index 0000000..6f78a1c --- /dev/null +++ b/sneaky-app/src/app/api/whatsapp-groups/route.ts @@ -0,0 +1,104 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { MonitoredWhatsAppGroup } from '@/types'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url); + const fetchLive = searchParams.get('fetchLive') === 'true'; + + const localGroups = dataService.getMonitoredGroups(); + + if (!fetchLive) { + return NextResponse.json({ + success: true, + groups: localGroups, + }); + } + + // Consultar grupos en vivo desde Evolution API + try { + const response = await fetch( + `${EVOLUTION_API_URL}/group/fetchAllGroups/${EVOLUTION_INSTANCE_NAME}?getParticipants=false`, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + + const liveGroups = await response.json(); + + if (Array.isArray(liveGroups)) { + const merged: MonitoredWhatsAppGroup[] = liveGroups.map((lg: any) => { + const jid = lg.id || lg.jid; + const name = lg.subject || lg.name || 'Grupo Sin Nombre'; + const existing = localGroups.find((g) => g.jid === jid || g.name.toLowerCase() === name.toLowerCase()); + + return { + id: existing?.id || `grp-${jid.replace(/\D/g, '').slice(-6)}`, + jid, + name, + isMonitored: existing ? existing.isMonitored : false, + supplierId: existing?.supplierId, + supplierName: existing?.supplierName || name, + profitMarginOverride: existing?.profitMarginOverride || 35, + autoPublish: existing?.autoPublish ?? true, + participantsCount: lg.size || (lg.participants ? lg.participants.length : undefined), + notes: existing?.notes || '', + }; + }); + + // Asegurar que los locales que no vinieron en live sigan presentes + localGroups.forEach((lg) => { + if (!merged.some((m) => m.jid === lg.jid || m.id === lg.id)) { + merged.unshift(lg); + } + }); + + return NextResponse.json({ + success: true, + isLive: true, + totalLive: liveGroups.length, + groups: merged, + }); + } + } catch (err: any) { + console.warn('No se pudo conectar con Evolution API en vivo:', err.message); + } + + return NextResponse.json({ + success: true, + isLive: false, + groups: localGroups, + }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + + if (body.action === 'toggle') { + const { idOrJid, isMonitored } = body; + const updated = dataService.toggleGroupMonitoring(idOrJid, isMonitored); + return NextResponse.json({ success: true, group: updated }); + } + + if (Array.isArray(body.groups)) { + const saved = dataService.saveMonitoredGroups(body.groups); + return NextResponse.json({ success: true, groups: saved }); + } + + return NextResponse.json({ success: false, error: 'Datos no válidos' }, { status: 400 }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/sneaky-app/src/app/checkout/page.tsx b/sneaky-app/src/app/checkout/page.tsx new file mode 100644 index 0000000..bad0bc6 --- /dev/null +++ b/sneaky-app/src/app/checkout/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { ArrowLeft, CheckCircle2, ShieldCheck, Truck, Zap, QrCode, Phone, MapPin, User, MessageCircle, ExternalLink, CreditCard } from 'lucide-react'; +import { City, PaymentMethod, Order, StoreSettings } from '@/types'; +import { INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; +import confetti from 'canvas-confetti'; + +export default function CheckoutPage() { + const { currentBrand } = useBrand(); + + const [customerName, setCustomerName] = useState(''); + const [customerPhone, setCustomerPhone] = useState(''); + const [address, setAddress] = useState(''); + const [neighborhood, setNeighborhood] = useState(''); + const [notes, setNotes] = useState(''); + + const [cities, setCities] = useState(INITIAL_CITIES); + const [paymentMethods, setPaymentMethods] = useState(INITIAL_PAYMENT_METHODS); + const [selectedCityId, setSelectedCityId] = useState('city-cali'); + const [selectedPaymentId, setSelectedPaymentId] = useState('pay-deposit-10k'); + const [storeSettings, setStoreSettings] = useState(null); + + const [checkoutItems] = useState>([ + { + productId: INITIAL_PRODUCTS[0].id, + productName: INITIAL_PRODUCTS[0].name, + brand: INITIAL_PRODUCTS[0].brand, + size: '39', + quantity: 1, + price: INITIAL_PRODUCTS[0].retailPrice, + image: INITIAL_PRODUCTS[0].images[0], + }, + ]); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [orderCompleted, setOrderCompleted] = useState(null); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setPaymentMethods(d.paymentMethods)) + .catch(() => {}); + + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setStoreSettings(d.settings)) + .catch(() => {}); + }, []); + + const activeCity = cities.find((c) => c.id === selectedCityId) || cities[0]; + const activePayment = paymentMethods.find((p) => p.id === selectedPaymentId) || paymentMethods[0]; + + const subtotal = checkoutItems.reduce((acc, it) => acc + it.price * it.quantity, 0); + const shippingCost = activeCity.shippingCost; + const totalAmount = subtotal + shippingCost; + + const depositAmount = activePayment.requiresDeposit ? activePayment.depositAmount : 0; + const balanceDue = totalAmount - depositAmount; + + const officialWhatsapp = storeSettings?.whatsappNumber || '573167455877'; + const boldLink = storeSettings?.boldPaymentLink || 'https://bold.co/p/carlos-lasso'; + + const handleSubmitOrder = async (e: React.FormEvent) => { + e.preventDefault(); + if (!customerName || !customerPhone || !address) { + alert('Por favor completa tu nombre, celular y dirección para el despacho.'); + return; + } + + setIsSubmitting(true); + + try { + const orderPayload = { + customerName, + customerPhone, + address: `${address} - Barrio: ${neighborhood || 'Centro'}`, + cityId: activeCity.id, + cityName: activeCity.name, + items: checkoutItems, + subtotal, + shippingCost, + totalAmount, + depositAmount, + balanceDue, + paymentMethodId: activePayment.id, + paymentMethodName: activePayment.name, + notes, + }; + + const res = await fetch('/api/orders', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(orderPayload), + }); + + const data = await res.json(); + if (data.success) { + setOrderCompleted(data.order); + confetti({ + particleCount: 100, + spread: 70, + origin: { y: 0.6 }, + }); + } + } catch (err) { + console.error('Error creando orden:', err); + } finally { + setIsSubmitting(false); + } + }; + + const handleOpenWhatsAppOrder = (order: Order) => { + const text = `🎉 *CONFIRMACIÓN DE PEDIDO EN ${currentBrand.name} #${order.id}* 🎉 + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *Artículos:* +${order.items.map((i) => `• ${i.productName} (Talla ${i.size}) x${i.quantity} = ${formatCOP(i.price * i.quantity)}`).join('\n')} + +💰 *Total:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +¡Hola ${currentBrand.shortName}! Acabo de registrar mi pedido en la web. ¿Me confirman despacho por favor?`; + + window.open(`https://wa.me/${officialWhatsapp}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + if (orderCompleted) { + return ( +
+
+
+ +
+ +
+ + ¡Pedido Registrado con Éxito! + +

Orden #{orderCompleted.id}

+

+ Hemos recibido tu solicitud para entrega en {orderCompleted.cityName} con {currentBrand.name}. +

+
+ + {/* Bold.co or Nequi Separation Box */} + {orderCompleted.depositAmount > 0 ? ( +
+
+ + Paso 2: Realiza la separación de $10.000 COP +
+

+ Paga de inmediato con Link de Pago Bold.co (PSE / Tarjeta / Nequi) o transfiere a nuestra cuenta oficial: +

+ + {boldLink && ( + + + Pagar $10.000 COP con Bold.co (PSE / Tarjetas) + + + )} + +
+ 📱 Nequi / Daviplata: {storeSettings?.nequiAccount || '316 745 5877'} ({storeSettings?.accountHolder || 'Carlos Andrés Lasso'}) +
+

+ 🤝 Cancelas el saldo de {formatCOP(orderCompleted.balanceDue)} al recibir el paquete en tu casa. +

+
+ ) : ( +
+

+ Tu pedido quedó programado para entrega contraentrega en 24 horas. ¡Nos pondremos en contacto contigo por WhatsApp! +

+
+ )} + +
+ + + + Volver a la Tienda + +
+
+
+ ); + } + + return ( +
+
+ {/* Header */} +
+ + + Regresar a {currentBrand.name} + +
+ + Compra Segura & Garantizada +
+
+ +
+ {/* Left Column: Shipping & Payment Details (7 cols) */} +
+ {/* 1. Datos del Cliente */} +
+

+ + 1. Datos de Entrega +

+ +
+
+ + setCustomerName(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-sm text-white focus:border-orange-500 outline-hidden" + /> +
+
+ + setCustomerPhone(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-sm text-white focus:border-orange-500 outline-hidden" + /> +
+
+ + {/* City Selection */} +
+ + +
+ +
+
+ + setAddress(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-sm text-white focus:border-orange-500 outline-hidden" + /> +
+
+ + setNeighborhood(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-sm text-white focus:border-orange-500 outline-hidden" + /> +
+
+
+ + {/* 2. Método de Pago */} +
+

+ + 2. Selecciona tu Método de Pago +

+ +
+ {paymentMethods.map((method) => { + const isSelected = selectedPaymentId === method.id; + return ( +
setSelectedPaymentId(method.id)} + className={`p-4 rounded-2xl border transition-all cursor-pointer space-y-1.5 ${ + isSelected + ? `border-orange-500 bg-orange-950/20 shadow-md` + : 'border-zinc-800 hover:border-zinc-700 bg-zinc-950' + }`} + > +
+
+
+ {isSelected &&
} +
+ {method.name} +
+ + {method.requiresDeposit && ( + + Separa con $10.000 + + )} +
+ +

{method.description}

+ + {isSelected && (method.accountInfo || (method.type === 'bold' && boldLink)) && ( +
+ {method.accountInfo &&

{method.accountInfo}

} + {method.type === 'bold' && boldLink && ( + + + Abrir Link de Pago Bold.co + + )} +
+ )} +
+ ); + })} +
+
+
+ + {/* Right Column: Summary (5 cols) */} +
+
+

Resumen del Pedido

+ + {/* Items */} +
+ {checkoutItems.map((item, i) => ( +
+ +
+

{item.productName}

+

Talla: {item.size} | Cant: {item.quantity}

+

+ {formatCOP(item.price * item.quantity)} +

+
+
+ ))} +
+ + {/* Breakdown */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Envío ({activeCity.name}): + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total a Pagar: + + {formatCOP(totalAmount)} + +
+ + {depositAmount > 0 && ( +
+
+ Separación por Bold / Nequi / Daviplata: + {formatCOP(depositAmount)} +
+
+ Saldo a pagar al mensajero: + {formatCOP(balanceDue)} +
+
+ )} + +
+
+ + Garantía en {activeCity.name}: +
+

+ {activeCity.firstExchangeFree + ? '1er Cambio de Talla 100% GRATIS (cambios posteriores con flete estándar).' + : 'Cambios de talla 100% garantizados (los costos de envío son asumidos por el cliente).'} +

+
+
+ + + +

+ Al confirmar, se guardará tu pedido y recibirás asistencia inmediata por WhatsApp oficial ({officialWhatsapp}) para el seguimiento de tu entrega en 24 horas. +

+
+
+ +
+
+ ); +} diff --git a/sneaky-app/src/app/favicon.ico b/sneaky-app/src/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/sneaky-app/src/app/favicon.ico differ diff --git a/sneaky-app/src/app/globals.css b/sneaky-app/src/app/globals.css new file mode 100644 index 0000000..a2dc41e --- /dev/null +++ b/sneaky-app/src/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/sneaky-app/src/app/layout.tsx b/sneaky-app/src/app/layout.tsx new file mode 100644 index 0000000..c752081 --- /dev/null +++ b/sneaky-app/src/app/layout.tsx @@ -0,0 +1,61 @@ +import type { Metadata, Viewport } from 'next'; +import { Geist, Geist_Mono } from 'next/font/google'; +import './globals.css'; +import { BrandProvider } from '@/context/BrandContext'; +import { AuthProvider } from '@/context/AuthContext'; + +const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], +}); + +const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], +}); + +export const viewport: Viewport = { + themeColor: '#dc2626', + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + viewportFit: 'cover', +}; + +export const metadata: Metadata = { + title: 'Sneaky Drops • Viral Sneakers', + description: 'Zapatillas virales en tendencia, drops exclusivos y pago contraentrega en 24 horas.', + manifest: '/manifest.json', + appleWebApp: { + capable: true, + statusBarStyle: 'black-translucent', + title: 'Sneaky Drops', + }, + icons: { + icon: '/icon.svg', + apple: '/icon.svg', + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + + + + {children} + + + + + ); +} diff --git a/sneaky-app/src/app/page.tsx b/sneaky-app/src/app/page.tsx new file mode 100644 index 0000000..e4b60ff --- /dev/null +++ b/sneaky-app/src/app/page.tsx @@ -0,0 +1,284 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Navbar } from '@/components/store/Navbar'; +import { FlashDealsBanner } from '@/components/store/FlashDealsBanner'; +import { CategoryPills } from '@/components/store/CategoryPills'; +import { ProductCard } from '@/components/store/ProductCard'; +import { ProductModal } from '@/components/store/ProductModal'; +import { CartDrawer } from '@/components/store/CartDrawer'; +import { CitySelectorModal } from '@/components/store/CitySelectorModal'; +import { MobileBottomDock } from '@/components/mobile/MobileBottomDock'; +import { MobileInstallBanner } from '@/components/mobile/MobileInstallBanner'; +import { AuthModal } from '@/components/auth/AuthModal'; +import { Product, City, CartItem } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_CITIES } from '@/lib/data-service'; +import { Sparkles, ShieldCheck, Truck, RefreshCw, Zap } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export default function StoreHomePage() { + const { currentBrand } = useBrand(); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [cities, setCities] = useState(INITIAL_CITIES); + const [selectedCity, setSelectedCity] = useState(INITIAL_CITIES[0]); // Cali + const [activeCategory, setActiveCategory] = useState('all'); + const [searchQuery, setSearchQuery] = useState(''); + + // Modals & Drawers state + const [selectedProduct, setSelectedProduct] = useState(null); + const [isCartOpen, setIsCartOpen] = useState(false); + const [isCityModalOpen, setIsCityModalOpen] = useState(false); + const [isInstallModalOpen, setIsInstallModalOpen] = useState(false); + const [cartItems, setCartItems] = useState([]); + + const cartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + useEffect(() => { + fetch('/api/products') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.products?.length > 0) { + setProducts(data.products); + } + }) + .catch((e) => console.log('Usando catálogo inicial:', e)); + + fetch('/api/cities') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.cities?.length > 0) { + setCities(data.cities); + const defaultCali = data.cities.find((c: City) => c.name.toLowerCase().includes('cali')); + if (defaultCali) setSelectedCity(defaultCali); + } + }) + .catch((e) => console.log('Usando ciudades iniciales:', e)); + }, []); + + const filteredProducts = products.filter((p) => { + if (searchQuery.trim()) { + const q = searchQuery.toLowerCase(); + const matchName = p.name.toLowerCase().includes(q); + const matchBrand = p.brand.toLowerCase().includes(q); + const matchSize = p.sizes.some((s) => s.includes(q)); + if (!matchName && !matchBrand && !matchSize) return false; + } + + if (activeCategory === 'flash') return p.isFlashDeal; + if (activeCategory === 'under120') return p.retailPrice <= 120000; + if (activeCategory !== 'all') { + return p.brand.toLowerCase() === activeCategory.toLowerCase(); + } + return true; + }); + + const handleAddToCart = (product: Product, size: string) => { + setCartItems((prev) => { + const existingIdx = prev.findIndex( + (item) => item.product.id === product.id && item.selectedSize === size + ); + if (existingIdx > -1) { + const next = [...prev]; + next[existingIdx].quantity += 1; + return next; + } + return [...prev, { product, selectedSize: size, quantity: 1 }]; + }); + setIsCartOpen(true); + }; + + const handleRemoveFromCart = (productId: string, size: string) => { + setCartItems((prev) => + prev.filter((item) => !(item.product.id === productId && item.selectedSize === size)) + ); + }; + + const handleUpdateQuantity = (productId: string, size: string, delta: number) => { + setCartItems((prev) => + prev + .map((item) => { + if (item.product.id === productId && item.selectedSize === size) { + const newQty = item.quantity + delta; + return newQty > 0 ? { ...item, quantity: newQty } : null; + } + return item; + }) + .filter(Boolean) as CartItem[] + ); + }; + + const totalCartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + return ( +
+ {/* Navigation Header */} + setIsCartOpen(true)} + selectedCity={selectedCity} + onOpenCitySelector={() => setIsCityModalOpen(true)} + searchQuery={searchQuery} + onSearchChange={setSearchQuery} + /> + + {/* Main Container */} +
+ {/* Flash Deals Hero Banner */} + + + {/* Value Props Strip */} +
+
+
+ +
+
+

Entrega en 24 Horas

+

Directo en Cali

+
+
+ +
+
+ +
+
+

Pago Contraentrega

+

Cancelas al recibir

+
+
+ +
+
+ +
+
+

Separa con $10.000

+

Aparta tu talla

+
+
+ +
+
+ +
+
+

Garantía Total

+

Cambio asegurado

+
+
+
+ + {/* Category & Brand Filters */} +
+
+

+ + Colección de Calzado & Sneakers +

+ + {filteredProducts.length} {filteredProducts.length === 1 ? 'modelo' : 'modelos'} + +
+ + +
+ + {/* Product Grid */} + {filteredProducts.length === 0 ? ( +
+
+ +
+

No encontramos zapatillas con ese criterio

+

Intenta buscar otra marca o restablecer los filtros.

+ +
+ ) : ( +
+ {filteredProducts.map((product) => ( + handleAddToCart(p, size)} + /> + ))} +
+ )} +
+ + {/* Footer */} +
+
+
+
+ {currentBrand.logo.iconText} +
+ {currentBrand.name} +
+

© 2026 {currentBrand.name}. Despachos urbanos y nacionales con pago contraentrega.

+
+ + {currentBrand.badge} +
+
+
+ + {/* Modals & Drawers */} + setSelectedProduct(null)} + onAddToCart={handleAddToCart} + selectedCity={selectedCity} + /> + + setIsCartOpen(false)} + cartItems={cartItems} + onRemoveItem={handleRemoveFromCart} + onUpdateQuantity={handleUpdateQuantity} + selectedCity={selectedCity} + onOpenCitySelector={() => { + setIsCartOpen(false); + setIsCityModalOpen(true); + }} + /> + + setIsCityModalOpen(false)} + cities={cities} + selectedCity={selectedCity} + onSelectCity={setSelectedCity} + /> + + {/* Mobile App Dock & Install Banner */} + setIsCartOpen(true)} + onOpenInstallModal={() => setIsInstallModalOpen(true)} + /> + + setIsInstallModalOpen(false)} + /> + + {/* User Auth Modal */} + +
+ ); +} diff --git a/sneaky-app/src/components/auth/AuthModal.tsx b/sneaky-app/src/components/auth/AuthModal.tsx new file mode 100644 index 0000000..ae140ae --- /dev/null +++ b/sneaky-app/src/components/auth/AuthModal.tsx @@ -0,0 +1,255 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, User, Lock, Mail, Phone, MapPin, Sparkles, LogIn, UserPlus, Shield, LogOut } from 'lucide-react'; +import { useAuth } from '@/context/AuthContext'; +import { useBrand } from '@/context/BrandContext'; +import Link from 'next/link'; + +export const AuthModal: React.FC = () => { + const { user, login, register, logout, isAuthModalOpen, closeAuthModal } = useAuth(); + const { currentBrand } = useBrand(); + + const [mode, setMode] = useState<'login' | 'register'>('login'); + const [identifier, setIdentifier] = useState(''); + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + if (!isAuthModalOpen) return null; + + const handleLoginSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await login(identifier); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al iniciar sesión'); + } + }; + + const handleRegisterSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await register({ name, email, phone, city, address }); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al registrarse'); + } + }; + + return ( +
+
+ + + {/* If user is already logged in: View Profile */} + {user ? ( +
+
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+

{user.email}

+
+ + {user.role === 'admin' ? '👑 Administrador' : user.role === 'operator' ? '📦 Operador Logística' : '🛍️ Cliente Registrado'} + +
+
+ +
+

📱 Celular: {user.phone}

+

📍 Ciudad: {user.city || 'Cali'}

+ {user.address &&

🏠 Dirección: {user.address}

} +
+ + {user.role === 'admin' || user.role === 'operator' ? ( + + + Ir al Panel de Control Admin + + ) : null} + + +
+ ) : ( + /* Login or Register */ +
+
+
+ {currentBrand.shortName[0]} +
+
+

+ {mode === 'login' ? 'Iniciar Sesión' : 'Crear Cuenta'} +

+

+ {mode === 'login' + ? 'Accede para gestionar pedidos o entrar como admin' + : 'Regístrate para compras rápidas y seguimiento'} +

+
+
+ + {/* Mode Switch Tabs */} +
+ + +
+ + {error && ( +
+ {error} +
+ )} + + {mode === 'login' ? ( +
+
+ + setIdentifier(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2.5 text-white outline-hidden focus:border-orange-500" + /> +
+ + + +

+ Tip Admin: Puedes ingresar con carlos@sneakydrops.co o 3134848203. +

+
+ ) : ( +
+
+ + setName(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-orange-500" + /> +
+ +
+
+ + setEmail(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-orange-500" + /> +
+ +
+ + setPhone(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-orange-500" + /> +
+
+ +
+
+ + setCity(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-orange-500" + /> +
+
+ + setAddress(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-orange-500" + /> +
+
+ + +
+ )} +
+ )} +
+
+ ); +}; diff --git a/sneaky-app/src/components/mobile/MobileBottomDock.tsx b/sneaky-app/src/components/mobile/MobileBottomDock.tsx new file mode 100644 index 0000000..2518255 --- /dev/null +++ b/sneaky-app/src/components/mobile/MobileBottomDock.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { Home, Search, ShoppingBag, MessageCircle, Download, Check } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileBottomDockProps { + cartCount: number; + onOpenCart: () => void; + onOpenSearch?: () => void; + onOpenInstallModal: () => void; +} + +export const MobileBottomDock: React.FC = ({ + cartCount, + onOpenCart, + onOpenSearch, + onOpenInstallModal, +}) => { + const { currentBrand } = useBrand(); + const [activeTab, setActiveTab] = useState('home'); + + const handleWhatsApp = () => { + const text = encodeURIComponent( + `Hola ${currentBrand.name}! 👋 Quiero consultar la disponibilidad de unas zapatillas para despacho contraentrega en 24 horas.` + ); + window.open(`https://wa.me/${currentBrand.whatsappNumber}?text=${text}`, '_blank'); + }; + + return ( +
+
+ setActiveTab('home')} + className={`flex flex-col items-center gap-0.5 cursor-pointer transition-all ${ + activeTab === 'home' ? 'text-white' : 'text-zinc-400 hover:text-zinc-200' + }`} + > + + Inicio + + + + + + + + + +
+
+ ); +}; diff --git a/sneaky-app/src/components/mobile/MobileInstallBanner.tsx b/sneaky-app/src/components/mobile/MobileInstallBanner.tsx new file mode 100644 index 0000000..8322c52 --- /dev/null +++ b/sneaky-app/src/components/mobile/MobileInstallBanner.tsx @@ -0,0 +1,125 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Download, Sparkles, X, Smartphone, CheckCircle, Share2, PlusSquare } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileInstallBannerProps { + isOpen: boolean; + onClose: () => void; +} + +export const MobileInstallBanner: React.FC = ({ isOpen, onClose }) => { + const { currentBrand } = useBrand(); + const [deferredPrompt, setDeferredPrompt] = useState(null); + const [isInstalled, setIsInstalled] = useState(false); + const [isIOS, setIsIOS] = useState(false); + + useEffect(() => { + const userAgent = window.navigator.userAgent.toLowerCase(); + const isIosDevice = /iphone|ipad|ipod/.test(userAgent); + setIsIOS(isIosDevice); + + const isStandalone = window.matchMedia('(display-mode: standalone)').matches; + if (isStandalone) { + setIsInstalled(true); + } + + const handleBeforeInstall = (e: Event) => { + e.preventDefault(); + setDeferredPrompt(e); + }; + + window.addEventListener('beforeinstallprompt', handleBeforeInstall); + return () => window.removeEventListener('beforeinstallprompt', handleBeforeInstall); + }, []); + + const handleInstallClick = async () => { + if (deferredPrompt) { + deferredPrompt.prompt(); + const { outcome } = await deferredPrompt.userChoice; + if (outcome === 'accepted') { + setIsInstalled(true); + onClose(); + } + setDeferredPrompt(null); + } + }; + + if (!isOpen) return null; + + return ( +
+
+ + +
+
+ {currentBrand.shortName[0]} +
+
+

Instalar {currentBrand.name}

+

Aplicación Móvil para Android & iPhone

+
+
+ +
+
+ + Acceso instantáneo desde la pantalla de inicio de tu celular +
+
+ + Notificaciones de lanzamientos y drops virales +
+
+ + Navegación ultra rápida sin consumir espacio de memoria +
+
+ + {isIOS ? ( +
+

+ + Instrucciones para iPhone (Safari): +

+
    +
  1. Toca el botón Compartir abajo en Safari.
  2. +
  3. Desliza hacia abajo y selecciona "Agregar a Inicio ".
  4. +
  5. ¡Listo! El icono de {currentBrand.shortName} aparecerá en tu teléfono.
  6. +
+
+ ) : deferredPrompt ? ( + + ) : ( +
+
+

Para instalar en tu navegador:

+

+ Abre el menú de opciones del navegador (los 3 puntos arriba a la derecha) y toca "Instalar aplicación" o "Agregar a pantalla principal". +

+
+ +
+ )} +
+
+ ); +}; diff --git a/sneaky-app/src/components/store/CartDrawer.tsx b/sneaky-app/src/components/store/CartDrawer.tsx new file mode 100644 index 0000000..bca5a6d --- /dev/null +++ b/sneaky-app/src/components/store/CartDrawer.tsx @@ -0,0 +1,254 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { X, Trash2, ShoppingBag, ArrowRight, Zap, Truck, MessageCircle } from 'lucide-react'; +import { CartItem, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface CartDrawerProps { + isOpen: boolean; + onClose: () => void; + cartItems: CartItem[]; + onRemoveItem: (productId: string, size: string) => void; + onUpdateQuantity: (productId: string, size: string, delta: number) => void; + selectedCity: City; + onOpenCitySelector: () => void; +} + +export const CartDrawer: React.FC = ({ + isOpen, + onClose, + cartItems, + onRemoveItem, + onUpdateQuantity, + selectedCity, + onOpenCitySelector, +}) => { + const { currentBrand } = useBrand(); + const [officialPhone, setOfficialPhone] = React.useState('573167455877'); + + React.useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => { + if (d.success && d.settings?.whatsappNumber) { + setOfficialPhone(d.settings.whatsappNumber); + } + }) + .catch(() => {}); + }, []); + + if (!isOpen) return null; + + const subtotal = cartItems.reduce((acc, item) => acc + item.product.retailPrice * item.quantity, 0); + const shippingCost = selectedCity.shippingCost; + const totalAmount = subtotal + shippingCost; + const separation = calculateSeparationBreakdown(totalAmount); + + const handleWhatsAppCheckout = () => { + const itemsList = cartItems + .map((item) => `👟 *${item.product.name}* (Talla: *${item.selectedSize}*, Cant: ${item.quantity}) - ${formatCOP(item.product.retailPrice * item.quantity)}`) + .join('\n'); + + const text = `🔥 *NUEVO PEDIDO DESDE ${currentBrand.name}* 🔥 + +📦 *Productos seleccionados:* +${itemsList} + +📍 *Ciudad de entrega:* ${selectedCity.name} +💵 *Subtotal:* ${formatCOP(subtotal)} +🚚 *Envío:* ${shippingCost === 0 ? 'GRATIS' : formatCOP(shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(totalAmount)} COP + +⚡ *Condición de Pago:* Pago Contraentrega (Separo con $10.000 COP vía Bold/Nequi y cancelo saldo de ${formatCOP(separation.balanceDue)} al recibir). + +Por favor confírmenme para enviarles los datos de mi dirección.`; + + window.open(`https://wa.me/${officialPhone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+ {/* Backdrop */} +
+ +
+
+ {/* Header */} +
+
+
+ +
+
+

Tu Carrito • {currentBrand.shortName}

+

{cartItems.length} {cartItems.length === 1 ? 'artículo' : 'artículos'}

+
+
+ +
+ + {/* Items List */} +
+ {cartItems.length === 0 ? ( +
+
+ +
+

Tu carrito está vacío

+

+ Aprovecha las ofertas de calzado con pago contraentrega en Cali y despachos nacionales. +

+ +
+ ) : ( + cartItems.map((item, idx) => ( +
+ {item.product.name} +
+
+
+

+ {item.product.name} +

+ +
+
+ + Talla {item.selectedSize} + + + {item.product.brand} + +
+
+ +
+ + {formatCOP(item.product.retailPrice * item.quantity)} + +
+ + {item.quantity} + +
+
+
+
+ )) + )} +
+ + {/* Footer & Checkout Breakdown */} + {cartItems.length > 0 && ( +
+ {/* City Delivery selector pill */} +
+
+ + Destino: {selectedCity.name} +
+ +
+ + {/* Price Calculations */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Costo de Envío: + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total de la Orden: + + {formatCOP(totalAmount)} + +
+
+ + {/* Separation Highlight Banner */} +
+

+ + Opción de Separación con $10.000 COP +

+

+ Separas con {formatCOP(separation.depositAmount)} y pagas {formatCOP(separation.balanceDue)} al recibir contraentrega en tu casa. +

+

+ 🛡️ {selectedCity.firstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${selectedCity.name}` + : `Garantía de cambio en ${selectedCity.name} (flete asumido por cliente)`} +

+
+ + {/* Action Buttons */} +
+ + Proceder al Pago Contraentrega + + + + +
+
+ )} +
+
+
+ ); +}; diff --git a/sneaky-app/src/components/store/CategoryPills.tsx b/sneaky-app/src/components/store/CategoryPills.tsx new file mode 100644 index 0000000..be49b4b --- /dev/null +++ b/sneaky-app/src/components/store/CategoryPills.tsx @@ -0,0 +1,48 @@ +'use client'; + +import React from 'react'; +import { useBrand } from '@/context/BrandContext'; + +interface CategoryPillsProps { + activeCategory: string; + onSelectCategory: (category: string) => void; +} + +const CATEGORIES = [ + { id: 'all', label: '🔥 Todas las Zapatillas' }, + { id: 'Nike', label: '👟 Nike' }, + { id: 'Jordan', label: '🏀 Air Jordan' }, + { id: 'Adidas', label: '🛹 Adidas' }, + { id: 'New Balance', label: '🌿 New Balance' }, + { id: 'Puma', label: '🐆 Puma' }, + { id: 'flash', label: '⚡ Ofertas Flash' }, + { id: 'under120', label: '💰 Menos de $120k' }, +]; + +export const CategoryPills: React.FC = ({ + activeCategory, + onSelectCategory, +}) => { + const { currentBrand } = useBrand(); + + return ( +
+ {CATEGORIES.map((cat) => { + const isActive = activeCategory === cat.id; + return ( + + ); + })} +
+ ); +}; diff --git a/sneaky-app/src/components/store/CitySelectorModal.tsx b/sneaky-app/src/components/store/CitySelectorModal.tsx new file mode 100644 index 0000000..311d61d --- /dev/null +++ b/sneaky-app/src/components/store/CitySelectorModal.tsx @@ -0,0 +1,109 @@ +'use client'; + +import React from 'react'; +import { X, MapPin, Check, Truck } from 'lucide-react'; +import { City } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +interface CitySelectorModalProps { + isOpen: boolean; + onClose: () => void; + cities: City[]; + selectedCity: City; + onSelectCity: (city: City) => void; +} + +export const CitySelectorModal: React.FC = ({ + isOpen, + onClose, + cities, + selectedCity, + onSelectCity, +}) => { + if (!isOpen) return null; + + return ( +
+
+ {/* Header */} +
+
+
+ +
+
+

Selecciona tu Ciudad

+

Calculamos tiempos y tarifas oficiales

+
+
+ +
+ + {/* City list */} +
+ {cities + .filter((c) => c.isActive !== false) + .map((city) => { + const isSelected = selectedCity.id === city.id; + const hasCod = city.allowsContraentrega || city.allowCod; + + return ( +
{ + onSelectCity(city); + onClose(); + }} + className={`p-3 rounded-2xl border transition-all cursor-pointer flex items-center justify-between ${ + isSelected + ? 'border-orange-400 bg-orange-950/50 shadow-[0_0_15px_rgba(239,68,68,0.2)]' + : 'border-zinc-800 hover:border-zinc-700 bg-zinc-950' + }`} + > +
+
+ {city.name} + {hasCod && ( + + Contraentrega + + )} +
+

+ + {city.deliveryTime} +

+
+ +
+ + {city.shippingCost === 0 ? ( + Gratis + ) : ( + formatCOP(city.shippingCost) + )} + + {isSelected && ( +
+ +
+ )} +
+
+ ); + })} +
+ + {/* Info footer */} +
+ 💡 En Cali y zona metropolitana: entregas el mismo día con mensajería directa y pago contraentrega. +
+
+
+ ); +}; diff --git a/sneaky-app/src/components/store/FlashDealsBanner.tsx b/sneaky-app/src/components/store/FlashDealsBanner.tsx new file mode 100644 index 0000000..e26b007 --- /dev/null +++ b/sneaky-app/src/components/store/FlashDealsBanner.tsx @@ -0,0 +1,83 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Zap, Clock, Gift } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export const FlashDealsBanner: React.FC = () => { + const { currentBrand } = useBrand(); + const [timeLeft, setTimeLeft] = useState({ hours: 4, minutes: 27, seconds: 15 }); + + useEffect(() => { + const timer = setInterval(() => { + setTimeLeft((prev) => { + if (prev.seconds > 0) { + return { ...prev, seconds: prev.seconds - 1 }; + } else if (prev.minutes > 0) { + return { ...prev, minutes: 59, seconds: 59 }; + } else if (prev.hours > 0) { + return { hours: prev.hours - 1, minutes: 59, seconds: 59 }; + } + return { hours: 5, minutes: 59, seconds: 59 }; + }); + }, 1000); + return () => clearInterval(timer); + }, []); + + const pad = (n: number) => n.toString().padStart(2, '0'); + + return ( +
+ {/* Background glow meshes */} +
+
+ +
+ {/* Left text */} +
+
+ + {currentBrand.shortName.toUpperCase()} DROPS • OFERTAS FLASH +
+

+ Zapatillas Premium hasta con{' '} + + 35% OFF + +

+

+ Lanzamientos exclusivos directos de bodega. Separa tu par con $10.000 COP y paga el saldo en efectivo o transferencia con Pago Contraentrega en tu casa. +

+
+ + {/* Right Countdown Box */} +
+
+ + Oferta expira en: +
+
+
+ {pad(timeLeft.hours)} + Horas +
+ : +
+ {pad(timeLeft.minutes)} + Min +
+ : +
+ {pad(timeLeft.seconds)} + Seg +
+
+
+ + Cupón: {currentBrand.couponCode} aplicado +
+
+
+
+ ); +}; diff --git a/sneaky-app/src/components/store/Navbar.tsx b/sneaky-app/src/components/store/Navbar.tsx new file mode 100644 index 0000000..9e1ddd1 --- /dev/null +++ b/sneaky-app/src/components/store/Navbar.tsx @@ -0,0 +1,152 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { ShoppingBag, Search, MapPin, Zap, Sparkles, ShieldCheck, Store, User as UserIcon } from 'lucide-react'; +import { City } from '@/types'; +import { useBrand } from '@/context/BrandContext'; +import { useAuth } from '@/context/AuthContext'; + +interface NavbarProps { + cartCount: number; + onOpenCart: () => void; + selectedCity: City; + onOpenCitySelector: () => void; + searchQuery: string; + onSearchChange: (q: string) => void; +} + +export const Navbar: React.FC = ({ + cartCount, + onOpenCart, + selectedCity, + onOpenCitySelector, + searchQuery, + onSearchChange, +}) => { + const { currentBrand } = useBrand(); + const { user, openAuthModal } = useAuth(); + + return ( +
+ {/* Top Banner Urgency */} +
+
+
+ + 🔥 ENVÍOS CONTRAENTREGA EN {selectedCity.name.toUpperCase()} Y TODO COLOMBIA +
+
+ + + Separa tu par con solo $10.000 COP + + • + + + {selectedCity.firstExchangeFree + ? `1er Cambio GRATIS en ${selectedCity.name}` + : `Garantía de Cambio (${selectedCity.name})`} + +
+
+
+ + {/* Main Navbar */} +
+ {/* Brand Logo */} + +
+
+ + {currentBrand.logo.iconText} + +
+
+
+
+ {currentBrand.logo.mainText} + + {currentBrand.logo.accentText} + +
+

{currentBrand.tagline}

+
+ + + {/* City Selector Pill */} + + + {/* Search Bar */} +
+
+ onSearchChange(e.target.value)} + className="w-full bg-zinc-900/90 text-white placeholder-gray-400 text-xs sm:text-sm rounded-full pl-10 pr-4 py-2 border border-zinc-700 focus:border-orange-500 focus:ring-2 focus:ring-orange-500/20 transition-all outline-hidden" + /> + +
+
+ + {/* Right Actions */} +
+ {/* User Auth Button */} + + + {/* Admin Link */} + + + Admin + + + {/* Cart Button */} + +
+
+
+ ); +}; diff --git a/sneaky-app/src/components/store/ProductCard.tsx b/sneaky-app/src/components/store/ProductCard.tsx new file mode 100644 index 0000000..9ba227c --- /dev/null +++ b/sneaky-app/src/components/store/ProductCard.tsx @@ -0,0 +1,132 @@ +'use client'; + +import React from 'react'; +import { Star, Zap, Truck, ShoppingBag } from 'lucide-react'; +import { Product } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductCardProps { + product: Product; + onOpenDetail: (product: Product) => void; + onQuickAdd: (product: Product, size: string) => void; +} + +export const ProductCard: React.FC = ({ + product, + onOpenDetail, +}) => { + const { currentBrand } = useBrand(); + const discountPercent = product.originalPrice + ? Math.round(((product.originalPrice - product.retailPrice) / product.originalPrice) * 100) + : 28; + + const separation = calculateSeparationBreakdown(product.retailPrice); + + return ( +
onOpenDetail(product)} + className={`group rounded-2xl border transition-all duration-300 flex flex-col cursor-pointer overflow-hidden ${currentBrand.colors.cardBg}`} + > + {/* Image Container */} +
+ {product.name} + + {/* Badges */} +
+ + -{discountPercent}% OFF + + {product.isFlashDeal && ( + + FLASH + + )} +
+ +
+ + Contraentrega + + + {product.brand} + +
+
+ + {/* Product Info */} +
+
+ {/* Rating and Sales */} +
+
+ + {product.rating || 4.9} + ({product.reviewsCount || 89}) +
+ + +{product.salesCount || 150} pedidos + +
+ + {/* Product Title */} +

+ {product.name} +

+ + {/* Available Sizes Pills */} +
+ Tallas: + {product.sizes.slice(0, 5).map((size) => ( + + {size} + + ))} + {product.sizes.length > 5 && ( + +{product.sizes.length - 5} + )} +
+
+ + {/* Pricing & Separation terms */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ +

+ ⚡ Separa con {formatCOP(separation.depositAmount)} y cancelas {formatCOP(separation.balanceDue)} al recibir. +

+ + {/* Quick Action Button */} +
+ +
+
+
+
+ ); +}; diff --git a/sneaky-app/src/components/store/ProductModal.tsx b/sneaky-app/src/components/store/ProductModal.tsx new file mode 100644 index 0000000..3cc0cca --- /dev/null +++ b/sneaky-app/src/components/store/ProductModal.tsx @@ -0,0 +1,222 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, Star, Truck, ShieldCheck, Zap, MessageCircle, ShoppingBag, Check } from 'lucide-react'; +import { Product, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductModalProps { + product: Product | null; + onClose: () => void; + onAddToCart: (product: Product, size: string) => void; + selectedCity: City; +} + +export const ProductModal: React.FC = ({ + product, + onClose, + onAddToCart, + selectedCity, +}) => { + const { currentBrand } = useBrand(); + if (!product) return null; + + const [selectedSize, setSelectedSize] = useState(product.sizes[0] || '39'); + const [selectedImage, setSelectedImage] = useState(product.images[0]); + const [added, setAdded] = useState(false); + + const separation = calculateSeparationBreakdown(product.retailPrice); + + const handleAdd = () => { + onAddToCart(product, selectedSize); + setAdded(true); + setTimeout(() => { + setAdded(false); + onClose(); + }, 1200); + }; + + const handleWhatsAppDirect = () => { + const phone = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203'; + const text = `Hola ${currentBrand.name}! Quiero pedir las zapatillas: +👟 *${product.name}* (${product.brand}) +📏 Talla: *${selectedSize}* (Horma Nacional) +💎 Precio: *${formatCOP(product.retailPrice)} COP* +🚚 Entrega en: *${selectedCity.name}* (Pago Contraentrega) +⚡ Deseo separar con $10.000 COP y cancelar el saldo en mi casa. + +¿Me confirman disponibilidad para despacho por favor?`; + window.open(`https://wa.me/${phone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+
+ {/* Close Button */} + + + {/* Left: Images */} +
+
+ {product.name} + + -{Math.round(((product.originalPrice || 170000) - product.retailPrice) / (product.originalPrice || 170000) * 100)}% OFF + +
+ + {/* Thumbnails */} + {product.images.length > 1 && ( +
+ {product.images.map((img, i) => ( + + ))} +
+ )} + + {/* Trust note */} +
+ + + {selectedCity.firstExchangeFree ? ( + <>1er Cambio de Talla GRATIS en {selectedCity.name} • Cambios posteriores: el cliente asume el flete + ) : ( + <>Garantía de Cambio en {selectedCity.name} • El cliente asume los costos de flete + )} + +
+
+ + {/* Right: Product Details & Actions */} +
+
+
+ {product.brand} +

{product.name}

+
+
+ + {product.rating || 4.9} +
+ • + +{product.salesCount || 200} pares entregados +
+
+ + {/* Price Box */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ + {/* Separation breakdown banner */} +
+

+ + ¡Pago Contraentrega en {selectedCity.name}! +

+

+ Separas con solo {formatCOP(separation.depositAmount)} y pagas los {formatCOP(separation.balanceDue)} al recibir en tu puerta. +

+
+
+ + {/* Size Selector */} +
+
+ Selecciona tu Talla (Nacional CO): + Guía de Tallas +
+
+ {product.sizes.map((size) => ( + + ))} +
+
+ + {/* Description */} +
+

{product.description}

+
+ + {/* Shipping note */} +
+ +
+ {selectedCity.name}: + {selectedCity.deliveryTime} ({selectedCity.shippingCost === 0 ? 'Envío Gratis' : formatCOP(selectedCity.shippingCost)}) +
+
+
+ + {/* Action Buttons */} +
+ + + +
+
+
+
+ ); +}; diff --git a/sneaky-app/src/config/brands.ts b/sneaky-app/src/config/brands.ts new file mode 100644 index 0000000..fe598a2 --- /dev/null +++ b/sneaky-app/src/config/brands.ts @@ -0,0 +1,151 @@ +export type BrandId = 'almeira' | 'sneaky' | 'zapply' | 'dripzone'; + +export interface BrandTheme { + id: BrandId; + name: string; + shortName: string; + tagline: string; + badge: string; + couponCode: string; + whatsappNumber: string; + + // Clases y colores de diseño personalizados para cada una de las 4 marcas + colors: { + primaryGradient: string; + secondaryGradient: string; + heroGradient: string; + accentGlow: string; + headerBg: string; + bodyBg: string; + cardBg: string; + border: string; + textAccent: string; + badgeBg: string; + badgeText: string; + cartBadge: string; + }; + + logo: { + iconText: string; + mainText: string; + accentText: string; + }; +} + +export const BRANDS: Record = { + almeira: { + id: 'almeira', + name: 'ALMEIRA STORE', + shortName: 'Almeira', + tagline: 'Sneakers & Moda Urbana', + badge: 'Garantía Certificada', + couponCode: 'ALMEIRA-10K', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-cyan-500 via-blue-600 to-pink-500', + secondaryGradient: 'from-cyan-400 to-blue-500', + heroGradient: 'from-slate-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(6,182,212,0.35)]', + headerBg: 'bg-slate-950/95 border-cyan-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-cyan-500/40', + border: 'border-cyan-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-pink-400 to-pink-500', + badgeBg: 'bg-cyan-500/20 border-cyan-500/30 text-cyan-300', + badgeText: 'text-cyan-300', + cartBadge: 'bg-pink-500 text-white', + }, + logo: { + iconText: 'A', + mainText: 'ALMEIRA', + accentText: 'STORE', + }, + }, + + sneaky: { + id: 'sneaky', + name: 'SNEAKY DROPS', + shortName: 'Sneaky', + tagline: 'Viral Kicks & Flash Deals', + badge: 'Oferta Flash', + couponCode: 'SNEAKY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-red-600 via-orange-500 to-amber-500', + secondaryGradient: 'from-red-500 to-orange-500', + heroGradient: 'from-red-950 via-gray-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(239,68,68,0.35)]', + headerBg: 'bg-gray-950/95 border-orange-500/20', + bodyBg: 'bg-gray-950 text-gray-100', + cardBg: 'bg-gray-900/80 border-gray-800 hover:border-orange-500/40', + border: 'border-orange-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-red-500 via-orange-400 to-amber-400', + badgeBg: 'bg-orange-500/20 border-orange-500/30 text-orange-300', + badgeText: 'text-orange-300', + cartBadge: 'bg-amber-400 text-gray-950', + }, + logo: { + iconText: 'S', + mainText: 'SNEAKY', + accentText: 'DROPS', + }, + }, + + zapply: { + id: 'zapply', + name: 'ZAPPLY CALI', + shortName: 'Zapply', + tagline: 'Zapatillas & Entrega Inmediata', + badge: 'Envío Express 24h', + couponCode: 'ZAPPLY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-emerald-500 via-teal-500 to-cyan-600', + secondaryGradient: 'from-emerald-400 to-teal-500', + heroGradient: 'from-emerald-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-slate-950/95 border-emerald-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-emerald-500/40', + border: 'border-emerald-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-teal-300 to-cyan-400', + badgeBg: 'bg-emerald-500/20 border-emerald-500/30 text-emerald-300', + badgeText: 'text-emerald-300', + cartBadge: 'bg-emerald-400 text-slate-950', + }, + logo: { + iconText: 'Z', + mainText: 'ZAPPLY', + accentText: 'CALI', + }, + }, + + dripzone: { + id: 'dripzone', + name: 'DRIPZONE', + shortName: 'DripZone', + tagline: 'Streetwear & Sneakers Exclusivos', + badge: 'Edición Limitada', + couponCode: 'DRIP-VIP', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-purple-600 via-fuchsia-500 to-pink-600', + secondaryGradient: 'from-purple-500 to-pink-500', + heroGradient: 'from-purple-950 via-neutral-900 to-neutral-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-neutral-950/95 border-purple-500/20', + bodyBg: 'bg-neutral-950 text-neutral-100', + cardBg: 'bg-neutral-900/80 border-neutral-800 hover:border-purple-500/40', + border: 'border-purple-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-fuchsia-400 to-pink-400', + badgeBg: 'bg-purple-500/20 border-purple-500/30 text-purple-300', + badgeText: 'text-purple-300', + cartBadge: 'bg-fuchsia-500 text-white', + }, + logo: { + iconText: 'D', + mainText: 'DRIP', + accentText: 'ZONE', + }, + }, +}; diff --git a/sneaky-app/src/context/AuthContext.tsx b/sneaky-app/src/context/AuthContext.tsx new file mode 100644 index 0000000..f1f85fe --- /dev/null +++ b/sneaky-app/src/context/AuthContext.tsx @@ -0,0 +1,100 @@ +'use client'; + +import React, { createContext, useContext, useState, useEffect } from 'react'; +import { User } from '@/types'; + +interface AuthContextType { + user: User | null; + login: (identifier: string) => Promise<{ success: boolean; error?: string }>; + register: (data: { name: string; email: string; phone: string; city?: string; address?: string }) => Promise<{ success: boolean; error?: string }>; + logout: () => void; + isAuthModalOpen: boolean; + openAuthModal: () => void; + closeAuthModal: () => void; +} + +const AuthContext = createContext(undefined); + +export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [user, setUser] = useState(null); + const [isAuthModalOpen, setIsAuthModalOpen] = useState(false); + + useEffect(() => { + const saved = localStorage.getItem('sneaky_user'); + if (saved) { + try { + setUser(JSON.parse(saved)); + } catch (e) {} + } + }, []); + + const login = async (identifier: string) => { + try { + const res = await fetch('/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ identifier }), + }); + const data = await res.json(); + if (data.success && data.user) { + setUser(data.user); + localStorage.setItem('sneaky_user', JSON.stringify(data.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: data.error || 'Error al iniciar sesión' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const register = async (data: { name: string; email: string; phone: string; city?: string; address?: string }) => { + try { + const res = await fetch('/api/auth/register', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }); + const resData = await res.json(); + if (resData.success && resData.user) { + setUser(resData.user); + localStorage.setItem('sneaky_user', JSON.stringify(resData.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: resData.error || 'Error al registrarse' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const logout = () => { + setUser(null); + localStorage.removeItem('sneaky_user'); + }; + + const openAuthModal = () => setIsAuthModalOpen(true); + const closeAuthModal = () => setIsAuthModalOpen(false); + + return ( + + {children} + + ); +}; + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) throw new Error('useAuth must be used within an AuthProvider'); + return context; +}; diff --git a/sneaky-app/src/context/BrandContext.tsx b/sneaky-app/src/context/BrandContext.tsx new file mode 100644 index 0000000..abd927c --- /dev/null +++ b/sneaky-app/src/context/BrandContext.tsx @@ -0,0 +1,22 @@ +'use client'; + +import React, { createContext, useContext } from 'react'; +import { BrandTheme, BRANDS } from '@/config/brands'; + +interface BrandContextType { + currentBrand: BrandTheme; +} + +const BrandContext = createContext({ + currentBrand: BRANDS.sneaky, +}); + +export const BrandProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return ( + + {children} + + ); +}; + +export const useBrand = () => useContext(BrandContext); diff --git a/sneaky-app/src/lib/appwrite.ts b/sneaky-app/src/lib/appwrite.ts new file mode 100644 index 0000000..2cd0209 --- /dev/null +++ b/sneaky-app/src/lib/appwrite.ts @@ -0,0 +1,25 @@ +import { Client, Databases, Storage, Account } from 'appwrite'; + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + +export const client = new Client(); +client.setEndpoint(endpoint).setProject(projectId); + +export const databases = new Databases(client); +export const storage = new Storage(client); +export const account = new Account(client); + +// Base de datos y Bucket 100% aislados e independientes +export const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +export const BUCKET_ID = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +// Colecciones independientes +export const COLLECTIONS = { + PRODUCTS: 'products', + CITIES: 'cities', + PAYMENT_METHODS: 'payment_methods', + ORDERS: 'orders', + SETTINGS: 'settings', + SUPPLIER_POSTS: 'supplier_posts', +}; diff --git a/sneaky-app/src/lib/data-service.ts b/sneaky-app/src/lib/data-service.ts new file mode 100644 index 0000000..db83370 --- /dev/null +++ b/sneaky-app/src/lib/data-service.ts @@ -0,0 +1,2370 @@ +import { Product, City, PaymentMethod, Order, SupplierPost, StoreSettings, Supplier, MonitoredWhatsAppGroup, User } from '@/types'; + +export const INITIAL_SUPPLIERS: Supplier[] = [ + { + "id": "sup-jovic", + "name": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "phone": "573167455877", + "contactPerson": "Asesor Jovic Store", + "address": "Centro / Bodega Cali", + "notes": "Proveedor oficial Nike, Jordan, Nocta y Vomero calidades Top.", + "isActive": true + }, + { + "id": "sup-ccmio", + "name": "EXCLUSIVE CC MÍO 3B", + "phone": "573159876543", + "contactPerson": "Despachos CC MÍO 3B", + "address": "CC MÍO Local 3B, Cali", + "notes": "Especialista en Adidas, Coach, Timberland y Skatewear.", + "isActive": true + }, + { + "id": "sup-central", + "name": "BODEGA CENTRAL MAYORISTA", + "phone": "573101234567", + "contactPerson": "Logística Despachos", + "address": "San Andresito / Cali", + "notes": "Despacho rápido en 24 horas para separación inmediata.", + "isActive": true + } +]; + +export const INITIAL_CITIES: City[] = [ + { + id: 'city-cali', + name: 'Cali', + department: 'Valle del Cauca', + shippingCost: 0, + deliveryTime: 'Entrega en 24 Horas (Domicilio Local)', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Cali (posteriores con flete estándar)', + }, + { + id: 'city-jamundi', + name: 'Jamundí', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Jamundí (posteriores con flete estándar)', + }, + { + id: 'city-palmira', + name: 'Palmira', + department: 'Valle del Cauca', + shippingCost: 7000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Palmira (posteriores con flete estándar)', + }, + { + id: 'city-yumbo', + name: 'Yumbo', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Yumbo (posteriores con flete estándar)', + }, + { + id: 'city-bogota', + name: 'Bogotá D.C.', + department: 'Cundinamarca', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-medellin', + name: 'Medellín', + department: 'Antioquia', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-barranquilla', + name: 'Barranquilla', + department: 'Atlántico', + shippingCost: 14000, + deliveryTime: '3 a 4 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-nacional', + name: 'Otras Ciudades / Resto del País', + department: 'Colombia', + shippingCost: 15000, + deliveryTime: '2 a 5 días hábiles', + allowsContraentrega: false, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete nacional asumido por el cliente)', + }, +]; + +// Métodos de Pago configurables por el Admin +export const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [ + { + id: 'pay-bold-link', + name: 'Bold.co • PSE, Tarjetas Débito/Crédito, Nequi o QR (Oficial)', + type: 'bold', + description: 'Paga de forma rápida y 100% segura con tu cuenta Bold. Acepta PSE, Tarjetas Visa/Mastercard y QR de cualquier banco.', + requiresDeposit: false, + depositAmount: 0, + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + accountInfo: 'Pasarela Oficial Bold.co • PSE / Tarjetas / QR', + isActive: true, + }, + { + id: 'pay-deposit-10k', + name: 'Separación con $10.000 + Saldo Contraentrega', + type: 'contraentrega', + description: 'Asegura tu talla con solo $10.000 COP vía Bold/Nequi/Daviplata y cancelas el saldo restante en efectivo o transferencia cuando el mensajero llegue a tu casa.', + requiresDeposit: true, + depositAmount: 10000, + accountInfo: 'Nequi / Daviplata Oficial: 316 745 5877 (Carlos Andrés Lasso)', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + isActive: true, + }, + { + id: 'pay-cod-full', + name: 'Pago 100% Contraentrega (Cali y Alrededores)', + type: 'contraentrega', + description: 'Pagas el 100% del valor total al recibir en tu puerta (válido para entregas urbanas en 24 horas).', + requiresDeposit: false, + depositAmount: 0, + isActive: true, + }, + { + id: 'pay-nequi-full', + name: 'Transferencia Total Anticipada Nequi / Daviplata', + type: 'nequi', + description: 'Paga el 100% anticipado y recibe prioridad de despacho express en 24 horas.', + requiresDeposit: false, + depositAmount: 0, + accountInfo: 'Nequi / Daviplata: 316 745 5877 (Carlos Andrés Lasso)', + isActive: true, + }, +]; + +export const INITIAL_PRODUCTS: Product[] = [ + { + "id": "snk-real-1", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 36, + "salesCount": 183, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-2", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 73, + "salesCount": 225, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-3", + "name": "Nike Coach Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 78, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-4", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 44, + "salesCount": 239, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-5", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 242, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-6", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-7", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 81, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-8", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 96, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-9", + "name": "Louis Vuitton Calvin Klein Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 56, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-10", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 52, + "salesCount": 243, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-11", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 92, + "salesCount": 58, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-12", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 65, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-13", + "name": "Nike Michael Kors Dama \udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 70, + "salesCount": 230, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-14", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 146, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-15", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 103, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-16", + "name": "Nike Clemont Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 74, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-17", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 176, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-18", + "name": "Louis Vuitton Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 196, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-19", + "name": "Nike \udf1fbapesta\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 41, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-20", + "name": "Timberland Nueva Mercancía", + "brand": "Timberland", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1520639888713-7851133b1ed0?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 121, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-21", + "name": "\udf1fnike Internacional\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 29, + "salesCount": 112, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-22", + "name": "Nike \udecdalexander Mcqueen\udecd", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 97, + "salesCount": 90, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-23", + "name": "\udf1fnike Af1 Bape\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-24", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "36", + "37", + "38", + "39", + "40" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 21, + "salesCount": 126, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-25", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 82, + "salesCount": 154, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-26", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 241, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-27", + "name": "Karl Lagerfeld Caballero \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 60, + "salesCount": 215, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-28", + "name": "Nike Streetwear Sneaker", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 53, + "salesCount": 114, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-29", + "name": "Nike 7 Camaras Hombre", + "brand": "Nike", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 229, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-30", + "name": "Nike Retro 1 Dama,37 Y 40", + "brand": "Nike", + "supplierPrice": 105000, + "retailPrice": 145000, + "originalPrice": 200000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 67, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-31", + "name": "Nike Vomero Hombre", + "brand": "Nike", + "supplierPrice": 110000, + "retailPrice": 150000, + "originalPrice": 205000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 78, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-32", + "name": "Nike Lebron Dama Y 45", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 113, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-33", + "name": "Nike Kyrie Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 208, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-34", + "name": "Nike Gt Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 54, + "salesCount": 243, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-35", + "name": "Adidas Hombre ,43,44 Y 45", + "brand": "Adidas", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 109, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-36", + "name": "Adidas Courtic Hombre", + "brand": "Adidas", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 91, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-37", + "name": "Nike Total 90 Dama,42,43,44 Y 45", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 94, + "salesCount": 166, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-38", + "name": "Nike Total 90 Hombre", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44", + "45" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 35, + "salesCount": 74, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-39", + "name": "Nike Nocta Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 81, + "salesCount": 139, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-40", + "name": "Nike Total 90 Hombre ,43 Y 44", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 86, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-41", + "name": "Nike Tn Hombre", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 50, + "salesCount": 152, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-42", + "name": "Nike Kyrie Dama Y Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 153, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-43", + "name": "Nike Easyon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 90, + "salesCount": 115, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-44", + "name": "Nike Fast Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 199, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-45", + "name": "Nike Af1 Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 62, + "salesCount": 245, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-46", + "name": "Adidas Forum Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-47", + "name": "Nike Sb Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 74, + "salesCount": 213, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-48", + "name": "Tommy Hilfiger Caballero", + "brand": "Tommy Hilfiger", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 117, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-49", + "name": "Louis Vuitton Skate Dama", + "brand": "Louis Vuitton", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 242, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-50", + "name": "Adidas Yeezy Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 170, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-51", + "name": "Nike Metcon Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 76, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-52", + "name": "Nike Metcon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 189, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-53", + "name": "New Balance Caballero", + "brand": "New Balance", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1539185441755-769473a23570?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 79, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-54", + "name": "Nike Air Max Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 84, + "salesCount": 121, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-55", + "name": "Nike Zoom Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 31, + "salesCount": 200, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-56", + "name": "Nike Skate Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 98, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-57", + "name": "Reebok Caballero", + "brand": "Reebok", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 93, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-58", + "name": "Dior Caballero", + "brand": "Dior", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 201, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-59", + "name": "Jordan Retro 1 Bota Dama", + "brand": "Jordan", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1552346154-21d32810aba3?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 63, + "salesCount": 177, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-60", + "name": "Diesel Caballero", + "brand": "Diesel", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 133, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + } +]; + +export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [ + { + id: 'post-1', + channelName: 'DIFUSION JOVIC STORE', + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + rawMessage: `🔥 DISPONIBLE HOY 🔥\nNike Air Force 1 All White\nTallas: 37 al 43\nMayorista: $90.000 c/u\nDespacho inmediato Cali`, + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Nike Air Force 1 Low 07 White Triple', + brand: 'Nike', + sizes: ['37', '38', '39', '40', '41', '42', '43'], + supplierPrice: 90000, + suggestedRetailPrice: 125000, + category: 'Sneakers / Urbano', + confidence: 0.96, + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + }, + status: 'published_store', + receivedAt: 'Hoy, 09:15 AM', + }, + { + id: 'post-2', + channelName: 'EXCLUSIVE CC MIO 3B', + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + rawMessage: `👟 JORDAN 4 MILITARY BLACK 👟\nFull calidad AAA, caja original\nTallas 38 a 43\nPrecio: $95.000\nDomicilio pago contraentrega`, + rawImages: [ + 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Air Jordan 4 Retro Military Black', + brand: 'Jordan', + sizes: ['38', '39', '40', '41', '42', '43'], + supplierPrice: 95000, + suggestedRetailPrice: 130000, + category: 'Sneakers / Colección', + confidence: 0.94, + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + }, + status: 'published_store', + receivedAt: 'Hoy, 10:40 AM', + }, +]; + + +export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ + { + id: 'grp-jovic', + jid: '120363049363072784@g.us', + name: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + isMonitored: true, + supplierId: 'sup-jovic', + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 450, + notes: 'Proveedor oficial Nike, Jordan, Vomero, Nocta y AF1.', + }, + { + id: 'grp-ccmio', + jid: '120363024823901923@g.us', + name: 'EXCLUSIVE CC MÍO 3B', + isMonitored: true, + supplierId: 'sup-ccmio', + supplierName: 'EXCLUSIVE CC MÍO 3B', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 380, + notes: 'Proveedor oficial Adidas, Coach, Timberland y Skatewear.', + }, +]; + +class DataService { + private products: Product[] = [...INITIAL_PRODUCTS]; + private cities: City[] = [...INITIAL_CITIES]; + private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; + private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; + private orders: Order[] = []; + private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; + + getProducts(): Product[] { + return this.products; + } + + getProductById(id: string): Product | undefined { + return this.products.find((p) => p.id === id); + } + + addProduct(product: Product): Product { + this.products.unshift(product); + return product; + } + + updateProduct(id: string, updates: Partial): Product | null { + const idx = this.products.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.products[idx] = { ...this.products[idx], ...updates }; + return this.products[idx]; + } + + deleteProduct(id: string): boolean { + const initialLen = this.products.length; + this.products = this.products.filter((p) => p.id !== id); + return this.products.length < initialLen; + } + + getSuppliers(): Supplier[] { + return this.suppliers; + } + + getSupplierById(id: string): Supplier | undefined { + return this.suppliers.find((s) => s.id === id); + } + + addSupplier(supplier: Supplier): Supplier { + this.suppliers.push(supplier); + return supplier; + } + + getCities(): City[] { + return this.cities; + } + + getCityById(id: string): City | undefined { + return this.cities.find((c) => c.id === id); + } + + addCity(city: City): City { + this.cities.push(city); + return city; + } + + updateCity(id: string, updates: Partial): City | null { + const idx = this.cities.findIndex((c) => c.id === id); + if (idx === -1) return null; + this.cities[idx] = { ...this.cities[idx], ...updates }; + return this.cities[idx]; + } + + getPaymentMethods(): PaymentMethod[] { + return this.paymentMethods; + } + + updatePaymentMethod(id: string, updates: Partial): PaymentMethod | null { + const idx = this.paymentMethods.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.paymentMethods[idx] = { ...this.paymentMethods[idx], ...updates }; + return this.paymentMethods[idx]; + } + + getOrders(): Order[] { + return this.orders; + } + + addOrder(order: Order): Order { + this.orders.unshift(order); + return order; + } + + updateOrderStatus(orderId: string, status: Order['status']): Order | null { + const order = this.orders.find((o) => o.id === orderId); + if (!order) return null; + order.status = status; + return order; + } + + getSupplierPosts(): SupplierPost[] { + return this.supplierPosts; + } + + addSupplierPost(post: SupplierPost): SupplierPost { + this.supplierPosts.unshift(post); + return post; + } + + // Configuración de la Tienda + private settings: StoreSettings = { + storeName: 'Sneaky Drops', + slogan: 'Viral Sneakers & Exclusivos', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@sneakydrops.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }; + + getSettings(): StoreSettings { + return this.settings; + } + + updateSettings(updates: Partial): StoreSettings { + this.settings = { ...this.settings, ...updates }; + return this.settings; + } + + // Control de Usuarios + private users: User[] = [ + { + id: 'usr-admin-1', + name: 'Carlos Andrés Lasso', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + city: 'Cali', + address: 'Centro / Bodega Principal', + role: 'admin', + isActive: true, + createdAt: '2026-01-10', + totalOrders: 0, + lastLogin: 'Hoy, 08:15 PM', + }, + { + id: 'usr-operator-1', + name: 'Andrés Operador Despachos', + email: 'despachos@sneakydrops.co', + phone: '3159876543', + city: 'Cali', + role: 'operator', + isActive: true, + createdAt: '2026-02-01', + totalOrders: 0, + lastLogin: 'Hoy, 05:30 PM', + }, + { + id: 'usr-cust-1', + name: 'Mateo Gómez (Cliente VIP)', + email: 'mateo.sneakers@gmail.com', + phone: '3112345678', + city: 'Cali', + address: 'Calle 5 # 34-12 Apto 402', + role: 'customer', + isActive: true, + createdAt: '2026-02-15', + totalOrders: 3, + lastLogin: 'Ayer, 08:20 PM', + }, + ]; + + getUsers(): User[] { + return this.users; + } + + addUser(user: User): User { + this.users.unshift(user); + return user; + } + + updateUser(id: string, updates: Partial): User | null { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return null; + this.users[idx] = { ...this.users[idx], ...updates }; + return this.users[idx]; + } + + deleteUser(id: string): boolean { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return false; + this.users.splice(idx, 1); + return true; + } + + authenticate(emailOrPhone: string): User | null { + const q = emailOrPhone.trim().toLowerCase(); + const user = this.users.find( + (u) => u.email.toLowerCase() === q || u.phone === q || u.phone.includes(q) + ); + return user || null; + } + + private monitoredGroups: MonitoredWhatsAppGroup[] = [...INITIAL_MONITORED_GROUPS]; + + getMonitoredGroups(): MonitoredWhatsAppGroup[] { + return this.monitoredGroups; + } + + saveMonitoredGroups(groups: MonitoredWhatsAppGroup[]): MonitoredWhatsAppGroup[] { + this.monitoredGroups = groups; + return this.monitoredGroups; + } + + toggleGroupMonitoring(idOrJid: string, isMonitored: boolean): MonitoredWhatsAppGroup | null { + const grp = this.monitoredGroups.find((g) => g.id === idOrJid || g.jid === idOrJid); + if (grp) { + grp.isMonitored = isMonitored; + return grp; + } + return null; + } + +} + +export const dataService = new DataService(); diff --git a/sneaky-app/src/lib/deduplication-engine.ts b/sneaky-app/src/lib/deduplication-engine.ts new file mode 100644 index 0000000..3023854 --- /dev/null +++ b/sneaky-app/src/lib/deduplication-engine.ts @@ -0,0 +1,105 @@ +import { Product } from '@/types'; + +/** + * Normaliza un string para comparación (minúsculas, sin acentos, sin caracteres especiales) + */ +export function normalizeText(text: string): string { + if (!text) return ''; + return text + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/[^a-z0-9\s]/g, ' ') + .replace(/\s+/g, ' ') + .trim(); +} + +/** + * Calcula la similitud de Jaccard / Coeficiente de Dados entre dos textos + * Devuelve un valor entre 0 (totalmente diferente) y 1.0 (idéntico) + */ +export function calculateTextSimilarity(textA: string, textB: string): number { + const normA = normalizeText(textA); + const normB = normalizeText(textB); + + if (!normA || !normB) return 0; + if (normA === normB) return 1.0; + + // Si uno contiene al otro por completo + if (normA.includes(normB) || normB.includes(normA)) { + const ratio = Math.min(normA.length, normB.length) / Math.max(normA.length, normB.length); + if (ratio > 0.7) return 0.92; + } + + const tokensA = new Set(normA.split(' ').filter((w) => w.length > 2)); + const tokensB = new Set(normB.split(' ').filter((w) => w.length > 2)); + + if (tokensA.size === 0 || tokensB.size === 0) return 0; + + const intersection = new Set([...tokensA].filter((t) => tokensB.has(t))); + const union = new Set([...tokensA, ...tokensB]); + + return intersection.size / union.size; +} + +export interface DuplicateCheckResult { + isDuplicate: boolean; + similarityScore: number; + existingProduct?: Product; + recommendation: 'create_new' | 'update_stock_and_sizes' | 'skip_duplicate'; + message: string; +} + +/** + * Verifica si un producto entrante ya existe en el catálogo para evitar duplicados + */ +export function checkProductDuplicate( + incoming: { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + }, + existingCatalog: Product[], + threshold = 0.75 +): DuplicateCheckResult { + let highestScore = 0; + let bestMatch: Product | undefined; + + for (const product of existingCatalog) { + // 1. Si la marca no coincide, penalizar + const brandMatch = normalizeText(incoming.brand) === normalizeText(product.brand); + const score = calculateTextSimilarity(incoming.name, product.name); + const finalScore = brandMatch ? score : score * 0.5; + + if (finalScore > highestScore) { + highestScore = finalScore; + bestMatch = product; + } + } + + // Si la similitud supera el umbral (75%) + if (highestScore >= threshold && bestMatch) { + // Verificar si aporta nuevas tallas + const incomingSizesSet = new Set(incoming.sizes); + const existingSizesSet = new Set(bestMatch.sizes); + const hasNewSizes = incoming.sizes.some((s) => !existingSizesSet.has(s)); + + return { + isDuplicate: true, + similarityScore: Math.round(highestScore * 100) / 100, + existingProduct: bestMatch, + recommendation: hasNewSizes ? 'update_stock_and_sizes' : 'skip_duplicate', + message: hasNewSizes + ? `Producto ya registrado ("${bestMatch.name}"). Se detectaron nuevas tallas para actualizar.` + : `Producto ya registrado ("${bestMatch.name}") con similitud del ${Math.round(highestScore * 100)}%. Se previene duplicación en la tienda y Facebook.`, + }; + } + + return { + isDuplicate: false, + similarityScore: Math.round(highestScore * 100) / 100, + recommendation: 'create_new', + message: 'Producto nuevo verificado sin duplicados. Listo para publicar.', + }; +} diff --git a/sneaky-app/src/lib/evolution-api.ts b/sneaky-app/src/lib/evolution-api.ts new file mode 100644 index 0000000..bd654f0 --- /dev/null +++ b/sneaky-app/src/lib/evolution-api.ts @@ -0,0 +1,105 @@ +import axios from 'axios'; +import { formatCOP } from './pricing-engine'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +/** + * Enviar mensaje de texto por WhatsApp a través de Evolution API + */ +export async function sendWhatsAppMessage(toPhone: string, message: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendText/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1200, + presence: 'composing', + }, + textMessage: { + text: message, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando mensaje de WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Enviar mensaje con foto/catálogo a través de Evolution API + */ +export async function sendWhatsAppMedia(toPhone: string, imageUrl: string, caption: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendMedia/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1500, + presence: 'composing', + }, + mediaMessage: { + mediatype: 'image', + caption, + media: imageUrl, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando media por WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Genera el mensaje de confirmación de pedido para el cliente y el administrador + */ +export function buildOrderConfirmationMessage(order: any): string { + const itemsText = order.items + .map((item: any) => `👟 *${item.productName}*\n 📏 Talla: *${item.size}* | Cantidad: ${item.quantity} | Valor: ${formatCOP(item.price)}`) + .join('\n\n'); + + return `🎉 *¡GRACIAS POR TU PEDIDO EN SNEAKERS CALI!* 🎉 +📌 *No. de Orden:* #${order.id} + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *DETALLE DE TU COMPRA:* +${itemsText} + +💵 *Subtotal:* ${formatCOP(order.subtotal)} +🚚 *Envío:* ${order.shippingCost === 0 ? 'GRATIS' : formatCOP(order.shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación / Anticipo:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo a Pagar Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega al recibir en tu casa.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +Estamos alistando tu paquete. Te enviaremos el número de guía o notificación de entrega. ¡Muchas gracias por tu confianza! ✨`; +} diff --git a/sneaky-app/src/lib/facebook-publisher.ts b/sneaky-app/src/lib/facebook-publisher.ts new file mode 100644 index 0000000..1e55ec7 --- /dev/null +++ b/sneaky-app/src/lib/facebook-publisher.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; +import { generateSalesCopy } from './pricing-engine'; + +export interface PublishToFacebookParams { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + images: string[]; + cityName?: string; + whatsappNumber?: string; + pageId?: string; + accessToken?: string; +} + +export interface PublishResult { + success: boolean; + postId?: string; + postUrl?: string; + generatedCopy: string; + error?: string; +} + +/** + * Publicador automático en Páginas de Facebook mediante Meta Graph API + */ +export async function publishToFacebookPage(params: PublishToFacebookParams): Promise { + const { + productName, + brand, + retailPrice, + sizes, + images, + cityName = 'Cali', + whatsappNumber = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203', + pageId = process.env.FACEBOOK_PAGE_ID, + accessToken = process.env.FACEBOOK_ACCESS_TOKEN, + } = params; + + const copy = generateSalesCopy({ + productName, + brand, + retailPrice, + sizes, + cityName, + whatsappNumber, + }); + + // Si no hay token de Facebook configurado, simular publicación exitosa para pruebas + if (!pageId || !accessToken) { + const mockPostId = `fb_${Date.now()}_${Math.floor(Math.random() * 10000)}`; + return { + success: true, + postId: mockPostId, + postUrl: `https://facebook.com/${mockPostId}`, + generatedCopy: copy, + }; + } + + try { + // Si tiene una imagen principal, publicamos como photo post con caption + const primaryImage = images[0]; + const fbEndpoint = `https://graph.facebook.com/v19.0/${pageId}/photos`; + + const response = await axios.post(fbEndpoint, { + url: primaryImage, + caption: copy, + access_token: accessToken, + }); + + return { + success: true, + postId: response.data.id || response.data.post_id, + postUrl: `https://facebook.com/${response.data.id}`, + generatedCopy: copy, + }; + } catch (error: any) { + console.error('Error publicando en Facebook Graph API:', error?.response?.data || error?.message); + return { + success: false, + error: error?.response?.data?.error?.message || error.message, + generatedCopy: copy, + }; + } +} diff --git a/sneaky-app/src/lib/gemini-parser.ts b/sneaky-app/src/lib/gemini-parser.ts new file mode 100644 index 0000000..268024a --- /dev/null +++ b/sneaky-app/src/lib/gemini-parser.ts @@ -0,0 +1,108 @@ +import { GoogleGenAI } from '@google/genai'; +import { ExtractedProductData } from '@/types'; +import { calculateRetailPrice } from './pricing-engine'; + +export async function parseSupplierMessage(text: string): Promise { + const apiKey = process.env.GEMINI_API_KEY; + + const fallbackExtract = (): ExtractedProductData => { + let price = 90000; + const priceMatch = text.match(/(?:precio|valor|mayorista|costo|\$)\s*[:=]?\s*(\d{2,3}(?:\.\d{3})*|\d{2,3}k?)/i); + if (priceMatch) { + const raw = priceMatch[1].toLowerCase().replace(/\./g, ''); + if (raw.endsWith('k')) { + price = parseInt(raw.replace('k', ''), 10) * 1000; + } else { + const num = parseInt(raw, 10); + price = num < 1000 ? num * 1000 : num; + } + } + + const sizes: string[] = []; + const sizeRangeMatch = text.match(/(\d{2})\s*(?:a|al|-)\s*(\d{2})/i); + if (sizeRangeMatch) { + const start = parseInt(sizeRangeMatch[1], 10); + const end = parseInt(sizeRangeMatch[2], 10); + if (start >= 34 && end <= 46 && start <= end) { + for (let s = start; s <= end; s++) sizes.push(s.toString()); + } + } else { + const individualSizes = text.match(/\b(3[4-9]|4[0-6])\b/g); + if (individualSizes) { + sizes.push(...Array.from(new Set(individualSizes))); + } + } + if (sizes.length === 0) { + sizes.push('37', '38', '39', '40', '41', '42', '43'); + } + + let brand = 'Nike'; + if (/jordan/i.test(text)) brand = 'Jordan'; + else if (/adidas|bad bunny|campus|forum/i.test(text)) brand = 'Adidas'; + else if (/new balance|nb/i.test(text)) brand = 'New Balance'; + else if (/puma/i.test(text)) brand = 'Puma'; + else if (/asics/i.test(text)) brand = 'Asics'; + else if (/vans/i.test(text)) brand = 'Vans'; + + const cleanLines = text.split('\n').filter((l) => l.trim().length > 0 && !/🔥|🔴|llegando|promo/i.test(l)); + const name = cleanLines[0] || `${brand} Sneakers Urban Edition`; + + return { + name: name.replace(/tallas?:.*|precio:.*|\$/gi, '').trim() || `${brand} Zapatillas`, + brand, + sizes, + supplierPrice: price, + suggestedRetailPrice: calculateRetailPrice(price, 35, 30000), + category: 'Calzado / Sneakers', + confidence: 0.85, + }; + }; + + if (!apiKey) { + return fallbackExtract(); + } + + try { + const ai = new GoogleGenAI({ apiKey }); + const prompt = `Eres un asistente experto en e-commerce y calzado deportivo en Colombia. +Analiza el siguiente mensaje extraído de un grupo mayorista de WhatsApp. +Extrae los siguientes campos en formato JSON estricto: +- "name": Nombre comercial limpio del modelo (ej: "Nike Dunk Low Retro Panda", "Air Jordan 4 Military Black"). +- "brand": Marca ("Nike", "Jordan", "Adidas", "New Balance", "Puma", "Asics", etc.). +- "sizes": Array de tallas en horma colombiana/europea (ej: ["38", "39", "40", "41", "42", "43"]). Si dice "38 al 43", expande todas las tallas intermedias. +- "supplierPrice": Precio de compra mayorista como número entero en COP (ej: 90000, 95000). Si dice "90mil" o "90", es 90000. +- "category": Categoría ("Sneakers / Colección", "Urbano / Casual", "Running / Deportivo", etc.). + +Mensaje del grupo: +""" +${text} +""" + +Responde ÚNICAMENTE con el objeto JSON sin bloques de código markdown ni texto adicional.`; + + const response = await ai.models.generateContent({ + model: 'gemini-2.5-flash', + contents: prompt, + }); + + const outputText = response.text || ''; + const cleanJson = outputText.replace(/```json|```/gi, '').trim(); + const parsed = JSON.parse(cleanJson); + + const supplierPrice = typeof parsed.supplierPrice === 'number' ? parsed.supplierPrice : 90000; + const sizes = Array.isArray(parsed.sizes) && parsed.sizes.length > 0 ? parsed.sizes.map(String) : ['37', '38', '39', '40', '41', '42', '43']; + + return { + name: parsed.name || 'Zapatilla Urbana', + brand: parsed.brand || 'Nike', + sizes, + supplierPrice, + suggestedRetailPrice: calculateRetailPrice(supplierPrice, 35, 30000), + category: parsed.category || 'Sneakers', + confidence: 0.98, + }; + } catch (err) { + console.warn('Fallo llamada Gemini, utilizando extractor regex fallback:', err); + return fallbackExtract(); + } +} diff --git a/sneaky-app/src/lib/pricing-engine.ts b/sneaky-app/src/lib/pricing-engine.ts new file mode 100644 index 0000000..640ab12 --- /dev/null +++ b/sneaky-app/src/lib/pricing-engine.ts @@ -0,0 +1,114 @@ +/** + * Motor de Precios, Políticas de Cambio y Redondeo Automático al 5.000 Siguiente + */ + +export const DEFAULT_MIN_PROFIT_MARGIN_PERCENT = 35; // % Mínimo de ganancia +export const DEFAULT_MIN_PROFIT_COP = 30000; // Margen mínimo en pesos +export const DEFAULT_SEPARATION_DEPOSIT_COP = 10000; // Separación fija +export const ROUND_STEP_COP = 5000; // Redondeo siempre al múltiplo de $5.000 superior + +export const EXCHANGE_POLICY = { + firstExchangeFree: true, + badgeText: '1er Cambio de Talla GRATIS', + shortNotice: 'Primer cambio de talla gratis. Cambios posteriores con flete estándar.', + fullTerms: 'Cuentas con 1er cambio de talla 100% GRATIS dentro de los primeros 5 días. Para cambios adicionales o posteriores, el cliente asume el costo logístico del flete.', +}; + +export function formatCOP(amount: number): string { + if (isNaN(amount)) return '$0'; + return '$' + Math.round(amount).toLocaleString('es-CO'); +} + +export function roundUpToNearest5000(amount: number): number { + if (!amount || amount <= 0) return 0; + return Math.ceil(amount / ROUND_STEP_COP) * ROUND_STEP_COP; +} + +export function calculateRetailPrice( + supplierPrice: number, + minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT, + minMarginCop: number = DEFAULT_MIN_PROFIT_COP +): number { + if (!supplierPrice || supplierPrice <= 0) return 0; + const priceByPercent = supplierPrice * (1 + minMarginPercent / 100); + const priceByFixed = supplierPrice + minMarginCop; + const baseTargetPrice = Math.max(priceByPercent, priceByFixed); + return roundUpToNearest5000(baseTargetPrice); +} + +export function getPricingBreakdown(supplierCost: number, minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT) { + const retailPrice = calculateRetailPrice(supplierCost, minMarginPercent); + const grossProfit = retailPrice - supplierCost; + const realMarginPercent = Math.round((grossProfit / supplierCost) * 100); + + return { + supplierCost, + retailPrice, + grossProfit, + realMarginPercent, + isCeiledTo5k: true, + }; +} + +export function calculateAnchorPrice(retailPrice: number, discountPercentage: number = 30): number { + if (!retailPrice || retailPrice <= 0) return 0; + const anchor = retailPrice / (1 - discountPercentage / 100); + return roundUpToNearest5000(anchor); +} + +export function calculateSeparationBreakdown( + totalAmount: number, + depositAmount: number = DEFAULT_SEPARATION_DEPOSIT_COP +) { + const deposit = Math.min(depositAmount, totalAmount); + const balanceDue = Math.max(0, totalAmount - deposit); + + return { + totalAmount, + depositAmount: deposit, + balanceDue, + summaryText: `Separas hoy con ${formatCOP(deposit)} y cancelas ${formatCOP(balanceDue)} al recibir contraentrega en tu puerta.`, + exchangeTerms: EXCHANGE_POLICY.shortNotice, + }; +} + +export function generateSalesCopy(params: { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + storeName?: string; + cityName?: string; + whatsappNumber?: string; +}): string { + const { + productName, + brand, + retailPrice, + sizes, + storeName = 'TIENDA DE CALZADO', + cityName = 'Cali', + whatsappNumber = '573134848203', + } = params; + + const breakdown = calculateSeparationBreakdown(retailPrice); + const sizesFormatted = sizes.join(' - '); + const waLink = `https://wa.me/${whatsappNumber}?text=${encodeURIComponent(`Hola ${storeName}! Quiero pedir las zapatillas ${productName} (${brand}) en talla ___ para entrega contraentrega en ${cityName}.`)}`; + + return `✨ ${storeName.toUpperCase()} • LANZAMIENTO EXCLUSIVO ✨ +👟 ${productName.toUpperCase()} (${brand}) + +📏 Tallas Disponibles: ${sizesFormatted} (Horma Nacional) +💎 PRECIO DE VENTA: ${formatCOP(retailPrice)} COP + +🚚 ¡DOMICILIO EN ${cityName.toUpperCase()} Y ENVÍOS A TODO EL PAÍS! +🤝 PAGO CONTRAENTREGA: Cancelas al recibir el producto en tus manos. +⚡ SEPARA CON SOLO ${formatCOP(breakdown.depositAmount)} COP y cancelas ${formatCOP(breakdown.balanceDue)} al recibir. + +🛡️ POLÍTICA DE GARANTÍA: +✅ Calidad Premium 100% garantizada +✅ ${EXCHANGE_POLICY.badgeText} (posteriores con flete estándar) + +📲 ¡Pídelas antes de que se agote tu talla! +👉 Pedir directo por WhatsApp: ${waLink}`; +} diff --git a/sneaky-app/src/types/index.ts b/sneaky-app/src/types/index.ts new file mode 100644 index 0000000..9f8a915 --- /dev/null +++ b/sneaky-app/src/types/index.ts @@ -0,0 +1,176 @@ +export interface Supplier { + id: string; + name: string; + phone: string; + contactPerson?: string; + address?: string; + notes?: string; + isActive: boolean; +} + +export interface User { + id: string; + name: string; + email: string; + phone: string; + city?: string; + address?: string; + role: 'admin' | 'operator' | 'customer'; + isActive: boolean; + createdAt: string; + totalOrders?: number; + lastLogin?: string; +} + +export interface Product { + id: string; + name: string; + brand: string; + supplierPrice: number; + retailPrice: number; + originalPrice?: number; + sizes: string[]; + images: string[]; + description: string; + category: string; + inStock: boolean; + isActive?: boolean; + isFlashDeal?: boolean; + rating?: number; + reviewsCount?: number; + salesCount?: number; + originBadge?: string; + + supplierId?: string; + supplierName?: string; + supplierPhone?: string; + supplierSku?: string; +} + +export interface City { + id: string; + name: string; + department: string; + shippingCost: number; + deliveryTime: string; + allowsContraentrega: boolean; + allowCod?: boolean; + isActive?: boolean; + firstExchangeFree?: boolean; + exchangePolicyNote?: string; +} + +export interface PaymentMethod { + id: string; + name: string; + code?: string; + type: 'contraentrega' | 'nequi' | 'daviplata' | 'bancolombia' | 'tarjeta' | 'bold'; + description: string; + requiresDeposit: boolean; + depositAmount: number; + accountInfo?: string; + boldPaymentLink?: string; + boldQrUrl?: string; + isActive: boolean; +} + +export interface OrderItem { + productId: string; + productName: string; + brand: string; + size: string; + quantity: number; + price: number; + supplierPrice?: number; + supplierName?: string; + supplierPhone?: string; + image: string; +} + +export interface Order { + id: string; + userId?: string; + customerName: string; + customerPhone: string; + address: string; + cityId: string; + cityName: string; + items: OrderItem[]; + subtotal: number; + shippingCost: number; + totalAmount: number; + depositAmount: number; + balanceDue: number; + paymentMethodId: string; + paymentMethodName: string; + status: 'pending' | 'deposit_received' | 'supplier_notified' | 'dispatched' | 'delivered' | 'cancelled'; + notes?: string; + createdAt: string; +} + +export interface SupplierPost { + id: string; + channelName: string; + supplierName?: string; + supplierPhone?: string; + rawMessage: string; + rawImages: string[]; + extractedProduct?: ExtractedProductData; + status: 'pending_review' | 'published_facebook' | 'published_store' | 'ignored'; + receivedAt: string; +} + +export interface ExtractedProductData { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + suggestedRetailPrice: number; + category: string; + confidence: number; + supplierName?: string; + supplierPhone?: string; +} + +export interface CartItem { + product: Product; + selectedSize: string; + quantity: number; +} + +export interface StoreSettings { + storeName: string; + slogan?: string; + email: string; + phone: string; + whatsappNumber: string; + instagramHandle?: string; + address?: string; + city: string; + nequiAccount?: string; + daviplataAccount?: string; + accountHolder?: string; + boldPaymentLink?: string; + boldApiKey?: string; + boldMerchantId?: string; + boldQrUrl?: string; + boldEnabled?: boolean; + autoPublishSupplierPosts?: boolean; + defaultProfitMargin: number; + defaultDepositAmount: number; + facebookPageId?: string; +} + +export interface MonitoredWhatsAppGroup { + id: string; + jid: string; + name: string; + isMonitored: boolean; + supplierId?: string; + supplierName?: string; + profitMarginOverride?: number; + autoPublish: boolean; + participantsCount?: number; + lastMessageAt?: string; + notes?: string; +} diff --git a/sneaky-app/tsconfig.json b/sneaky-app/tsconfig.json new file mode 100644 index 0000000..cf9c65d --- /dev/null +++ b/sneaky-app/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +} diff --git a/ssh_run.py b/ssh_run.py index 5af2cc1..d9e100b 100644 --- a/ssh_run.py +++ b/ssh_run.py @@ -1,16 +1,22 @@ import paramiko import sys +import io + +# Force UTF-8 stdout on Windows +if sys.platform == 'win32': + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace') def run_ssh_command(host, user, password, command): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: - client.connect(hostname=host, username=user, password=password, timeout=10) + client.connect(hostname=host, username=user, password=password, timeout=60) stdin, stdout, stderr = client.exec_command(command) exit_status = stdout.channel.recv_exit_status() - out = stdout.read().decode() - err = stderr.read().decode() + out = stdout.read().decode('utf-8', errors='replace') + err = stderr.read().decode('utf-8', errors='replace') if out: print(out) diff --git a/zapply-app/.gitignore b/zapply-app/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/zapply-app/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/zapply-app/AGENTS.md b/zapply-app/AGENTS.md new file mode 100644 index 0000000..643577d --- /dev/null +++ b/zapply-app/AGENTS.md @@ -0,0 +1,9 @@ + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + + diff --git a/zapply-app/CLAUDE.md b/zapply-app/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/zapply-app/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/zapply-app/Dockerfile b/zapply-app/Dockerfile new file mode 100644 index 0000000..80966a7 --- /dev/null +++ b/zapply-app/Dockerfile @@ -0,0 +1,54 @@ +FROM node:20-alpine AS base + +# 1. Install dependencies +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +COPY package.json package-lock.json* ./ +RUN npm ci + +# 2. Build the app +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_ENV=production + +# Appwrite and Public Envs for Build Phase +ARG NEXT_PUBLIC_APPWRITE_ENDPOINT=https://appwrite.almeira.com.co/v1 +ARG NEXT_PUBLIC_APPWRITE_PROJECT_ID=69b84df5003bd8957c5c +ARG NEXT_PUBLIC_APPWRITE_DATABASE_ID=sneakers_multistore_db +ARG NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=sneakers_media_bucket + +ENV NEXT_PUBLIC_APPWRITE_ENDPOINT=$NEXT_PUBLIC_APPWRITE_ENDPOINT +ENV NEXT_PUBLIC_APPWRITE_PROJECT_ID=$NEXT_PUBLIC_APPWRITE_PROJECT_ID +ENV NEXT_PUBLIC_APPWRITE_DATABASE_ID=$NEXT_PUBLIC_APPWRITE_DATABASE_ID +ENV NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID=$NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID + +RUN npm run build + +# 3. Production Runner +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy standalone output & public static files +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/zapply-app/README.md b/zapply-app/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/zapply-app/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/zapply-app/android/.gitignore b/zapply-app/android/.gitignore new file mode 100644 index 0000000..48354a3 --- /dev/null +++ b/zapply-app/android/.gitignore @@ -0,0 +1,101 @@ +# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore + +# Built application files +*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +# Android Profiling +*.hprof + +# Cordova plugins for Capacitor +capacitor-cordova-android-plugins + +# Copied web assets +app/src/main/assets/public + +# Generated Config files +app/src/main/assets/capacitor.config.json +app/src/main/assets/capacitor.plugins.json +app/src/main/res/xml/config.xml diff --git a/zapply-app/android/app/.gitignore b/zapply-app/android/app/.gitignore new file mode 100644 index 0000000..043df80 --- /dev/null +++ b/zapply-app/android/app/.gitignore @@ -0,0 +1,2 @@ +/build/* +!/build/.npmkeep diff --git a/zapply-app/android/app/build.gradle b/zapply-app/android/app/build.gradle new file mode 100644 index 0000000..7801d1d --- /dev/null +++ b/zapply-app/android/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: 'com.android.application' + +android { + namespace = "co.zapply.cali" + compileSdk = rootProject.ext.compileSdkVersion + defaultConfig { + applicationId "co.zapply.cali" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + aaptOptions { + // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. + // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 + ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +repositories { + flatDir{ + dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" + implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" + implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" + implementation project(':capacitor-android') + testImplementation "junit:junit:$junitVersion" + androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" + implementation project(':capacitor-cordova-android-plugins') +} + +apply from: 'capacitor.build.gradle' + +try { + def servicesJSON = file('google-services.json') + if (servicesJSON.text) { + apply plugin: 'com.google.gms.google-services' + } +} catch(Exception e) { + logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") +} diff --git a/zapply-app/android/app/capacitor.build.gradle b/zapply-app/android/app/capacitor.build.gradle new file mode 100644 index 0000000..bbfb44f --- /dev/null +++ b/zapply-app/android/app/capacitor.build.gradle @@ -0,0 +1,19 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/zapply-app/android/app/proguard-rules.pro b/zapply-app/android/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/zapply-app/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/zapply-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/zapply-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java new file mode 100644 index 0000000..f2c2217 --- /dev/null +++ b/zapply-app/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.getcapacitor.app", appContext.getPackageName()); + } +} diff --git a/zapply-app/android/app/src/main/AndroidManifest.xml b/zapply-app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b06ddbf --- /dev/null +++ b/zapply-app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zapply-app/android/app/src/main/java/co/zapply/cali/MainActivity.java b/zapply-app/android/app/src/main/java/co/zapply/cali/MainActivity.java new file mode 100644 index 0000000..46176e9 --- /dev/null +++ b/zapply-app/android/app/src/main/java/co/zapply/cali/MainActivity.java @@ -0,0 +1,5 @@ +package co.zapply.cali; + +import com.getcapacitor.BridgeActivity; + +public class MainActivity extends BridgeActivity {} diff --git a/zapply-app/android/app/src/main/res/drawable-land-hdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-land-hdpi/splash.png new file mode 100644 index 0000000..e31573b Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-land-hdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-land-mdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-land-mdpi/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-land-mdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-land-xhdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-land-xhdpi/splash.png new file mode 100644 index 0000000..8077255 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-land-xhdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png new file mode 100644 index 0000000..14c6c8f Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-land-xxhdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png new file mode 100644 index 0000000..244ca25 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-land-xxxhdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-port-hdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-port-hdpi/splash.png new file mode 100644 index 0000000..74faaa5 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-port-hdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-port-mdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-port-mdpi/splash.png new file mode 100644 index 0000000..e944f4a Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-port-mdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-port-xhdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-port-xhdpi/splash.png new file mode 100644 index 0000000..564a82f Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-port-xhdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png new file mode 100644 index 0000000..bfabe68 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-port-xxhdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/zapply-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png new file mode 100644 index 0000000..6929071 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable-port-xxxhdpi/splash.png differ diff --git a/zapply-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/zapply-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/zapply-app/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/zapply-app/android/app/src/main/res/drawable/ic_launcher_background.xml b/zapply-app/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/zapply-app/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zapply-app/android/app/src/main/res/drawable/splash.png b/zapply-app/android/app/src/main/res/drawable/splash.png new file mode 100644 index 0000000..f7a6492 Binary files /dev/null and b/zapply-app/android/app/src/main/res/drawable/splash.png differ diff --git a/zapply-app/android/app/src/main/res/layout/activity_main.xml b/zapply-app/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..b5ad138 --- /dev/null +++ b/zapply-app/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/zapply-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/zapply-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/zapply-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/zapply-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/zapply-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/zapply-app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..c023e50 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2127973 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..b441f37 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..72905b8 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..8ed0605 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..9502e47 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..4d1e077 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..df0f158 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..853db04 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..6cdf97c Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2960cbb Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e3093a Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..46de6e2 Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..d2ea9ab Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..a40d73e Binary files /dev/null and b/zapply-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/zapply-app/android/app/src/main/res/values/ic_launcher_background.xml b/zapply-app/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/zapply-app/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/zapply-app/android/app/src/main/res/values/strings.xml b/zapply-app/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..a7cdf71 --- /dev/null +++ b/zapply-app/android/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + Zapply Cali + Zapply Cali + co.zapply.cali + co.zapply.cali + diff --git a/zapply-app/android/app/src/main/res/values/styles.xml b/zapply-app/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..be874e5 --- /dev/null +++ b/zapply-app/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/zapply-app/android/app/src/main/res/xml/file_paths.xml b/zapply-app/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..bd0c4d8 --- /dev/null +++ b/zapply-app/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/zapply-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/zapply-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java new file mode 100644 index 0000000..0297327 --- /dev/null +++ b/zapply-app/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java @@ -0,0 +1,18 @@ +package com.getcapacitor.myapp; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} diff --git a/zapply-app/android/build.gradle b/zapply-app/android/build.gradle new file mode 100644 index 0000000..f8f0e43 --- /dev/null +++ b/zapply-app/android/build.gradle @@ -0,0 +1,29 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.13.0' + classpath 'com.google.gms:google-services:4.4.4' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +apply from: "variables.gradle" + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/zapply-app/android/capacitor.settings.gradle b/zapply-app/android/capacitor.settings.gradle new file mode 100644 index 0000000..9a5fa87 --- /dev/null +++ b/zapply-app/android/capacitor.settings.gradle @@ -0,0 +1,3 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') diff --git a/zapply-app/android/gradle.properties b/zapply-app/android/gradle.properties new file mode 100644 index 0000000..2e87c52 --- /dev/null +++ b/zapply-app/android/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true diff --git a/zapply-app/android/gradle/wrapper/gradle-wrapper.jar b/zapply-app/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/zapply-app/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/zapply-app/android/gradle/wrapper/gradle-wrapper.properties b/zapply-app/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7705927 --- /dev/null +++ b/zapply-app/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/zapply-app/android/gradlew b/zapply-app/android/gradlew new file mode 100644 index 0000000..23d15a9 --- /dev/null +++ b/zapply-app/android/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/zapply-app/android/gradlew.bat b/zapply-app/android/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/zapply-app/android/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/zapply-app/android/settings.gradle b/zapply-app/android/settings.gradle new file mode 100644 index 0000000..3b4431d --- /dev/null +++ b/zapply-app/android/settings.gradle @@ -0,0 +1,5 @@ +include ':app' +include ':capacitor-cordova-android-plugins' +project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') + +apply from: 'capacitor.settings.gradle' \ No newline at end of file diff --git a/zapply-app/android/variables.gradle b/zapply-app/android/variables.gradle new file mode 100644 index 0000000..ee4ba41 --- /dev/null +++ b/zapply-app/android/variables.gradle @@ -0,0 +1,16 @@ +ext { + minSdkVersion = 24 + compileSdkVersion = 36 + targetSdkVersion = 36 + androidxActivityVersion = '1.11.0' + androidxAppCompatVersion = '1.7.1' + androidxCoordinatorLayoutVersion = '1.3.0' + androidxCoreVersion = '1.17.0' + androidxFragmentVersion = '1.8.9' + coreSplashScreenVersion = '1.2.0' + androidxWebkitVersion = '1.14.0' + junitVersion = '4.13.2' + androidxJunitVersion = '1.3.0' + androidxEspressoCoreVersion = '3.7.0' + cordovaAndroidVersion = '14.0.1' +} \ No newline at end of file diff --git a/zapply-app/capacitor.config.ts b/zapply-app/capacitor.config.ts new file mode 100644 index 0000000..b619b9c --- /dev/null +++ b/zapply-app/capacitor.config.ts @@ -0,0 +1,25 @@ +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + appId: 'co.zapply.cali', + appName: 'Zapply Cali', + webDir: 'public', + server: { + url: 'https://zapply.almeira.com.co', + cleartext: true, + androidScheme: 'https', + }, + plugins: { + SplashScreen: { + launchShowDuration: 2000, + backgroundColor: '#09090b', + showSpinner: false, + }, + StatusBar: { + style: 'DARK', + backgroundColor: '#09090b', + }, + }, +}; + +export default config; diff --git a/zapply-app/eslint.config.mjs b/zapply-app/eslint.config.mjs new file mode 100644 index 0000000..05e726d --- /dev/null +++ b/zapply-app/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/zapply-app/next.config.ts b/zapply-app/next.config.ts new file mode 100644 index 0000000..5b406fe --- /dev/null +++ b/zapply-app/next.config.ts @@ -0,0 +1,12 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", + images: { + remotePatterns: [ + { protocol: "https", hostname: "**" }, + ], + }, +}; + +export default nextConfig; diff --git a/zapply-app/package-lock.json b/zapply-app/package-lock.json new file mode 100644 index 0000000..bdd9090 --- /dev/null +++ b/zapply-app/package-lock.json @@ -0,0 +1,8446 @@ +{ + "name": "zapply-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "zapply-app", + "version": "0.1.0", + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capacitor/android": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.5.0.tgz", + "integrity": "sha512-Rb3prJeQiTp0pQhSSOReJuG9VgibOGMG4ECs+UhMwr6TCCHZ3NCZO811bDA0HxD0xrT/gCrJAsY5yfEATu84JQ==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^8.5.0" + } + }, + "node_modules/@capacitor/cli": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-8.5.0.tgz", + "integrity": "sha512-rLdzMUM5QV4WITcqoWv04p32i14BXgUH2diqEH6MWQlWaJfiyNrvOyt/+d5vHAfOxOm1klBu637VDEobctlwBA==", + "license": "MIT", + "dependencies": { + "@ionic/cli-framework-output": "^2.2.8", + "@ionic/utils-subprocess": "^3.0.1", + "@ionic/utils-terminal": "^2.3.5", + "commander": "^12.1.0", + "debug": "^4.4.0", + "env-paths": "^2.2.0", + "fs-extra": "^11.2.0", + "kleur": "^4.1.5", + "native-run": "^2.0.3", + "open": "^8.4.0", + "plist": "^3.1.0", + "prompts": "^2.4.2", + "rimraf": "^6.0.1", + "semver": "^7.6.3", + "tar": "^7.5.3", + "tslib": "^2.8.1", + "xcode": "^3.0.1", + "xml2js": "^0.6.2" + }, + "bin": { + "cap": "bin/capacitor", + "capacitor": "bin/capacitor" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@capacitor/cli/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@capacitor/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.5.0.tgz", + "integrity": "sha512-Ca4krtqH1hothjtBIwf2J2TW7IhYq1ujp8QeItTiJohNsqij8ja2DYYH3DU0l8RmxCWaBAFTGA2TgOgOMCSNsQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@google/genai": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-2.19.0.tgz", + "integrity": "sha512-IM3u1FjpOLyOPsPh0smGA6Ntj2olUWCPbTs/WQj7cA/2AKCGw/652W7IaySx0XtwuscFnMYBoraebQusSZ0zSQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@ionic/cli-framework-output": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz", + "integrity": "sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g==", + "license": "MIT", + "dependencies": { + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-array": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", + "integrity": "sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-fs/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ionic/utils-object": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", + "integrity": "sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-process": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@ionic/utils-process/-/utils-process-2.1.12.tgz", + "integrity": "sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg==", + "license": "MIT", + "dependencies": { + "@ionic/utils-object": "2.1.6", + "@ionic/utils-terminal": "2.3.5", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-stream/-/utils-stream-3.1.7.tgz", + "integrity": "sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w==", + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-subprocess": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz", + "integrity": "sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A==", + "license": "MIT", + "dependencies": { + "@ionic/utils-array": "2.1.6", + "@ionic/utils-fs": "3.1.7", + "@ionic/utils-process": "2.1.12", + "@ionic/utils-stream": "3.1.7", + "@ionic/utils-terminal": "2.3.5", + "cross-spawn": "^7.0.3", + "debug": "^4.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "license": "MIT", + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@next/env": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.3.tgz", + "integrity": "sha512-U2eYQRwXj+dsqxV79zFqExDdatnNY/ZWc2nsJU1p/OgT7fd3dXwlF6OjYaFQCfMoeTA19PWq+wVmYgimVA+V+g==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.3.tgz", + "integrity": "sha512-pbEh30vvjKpDoTAmo1v3q2uM4JUi8QaEBpbmjWvGfoec2jLghy/WNtvzAT0bk+Ik9oz6etjt4YjXEk4BQnicCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "4.9.1", + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.3.tgz", + "integrity": "sha512-8Hiv32QJPwdV6KYJ8meR9SBA061tQqnIKTJDocvOXlEQqib0xMFpzArosuffFUUc0sslbh7QQ8a3Yey1QV8EIw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.3.tgz", + "integrity": "sha512-A1lgKgwVchRYmSe467zdwhxT9040dd8lH+o65sL5Jet8fjB4kegw/rDyPIpYVRb6jAqwXFOJpjIXJLxQKLiE3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.3.tgz", + "integrity": "sha512-bf0FIssMFueU2dm7vQEWWxk0c8UjKTdW0yzuh0sQsD8pf1+KCLDdaqhYZNMYGmXwEOiHAUzgBKudovIlcvvBjg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.3.tgz", + "integrity": "sha512-W7viwCk9JY/cAkdz/A273rd5bb3RgT/IHwR7Upv90tunjBWNtAAhGhoecHh+teRNRSinuAFmE+l7fwZ4YKkrXg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.3.tgz", + "integrity": "sha512-0W46zw1N3ODpI6n0GeivHvvob1pooozgZVqy65k0mh4/7vr+FbY9+WpHzNVXjHipJf/A3FDheBG19H1s5A25rA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.3.tgz", + "integrity": "sha512-H4mBso8ZTMBPtdT0PN0pBx2ayTvQuTuvS6qT13d77yVFJXAPCxkyIhLTmdMaGTJs0krQYI/qpzdHijCeihXhbg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.3.tgz", + "integrity": "sha512-cTMUJpcEGmeywofCUfhR+rSsoE33+rVPnPEYNTNdLNlsOeEg/vktOsKUSTb28vUGqD2jkm4Zaskcwn7OCI6FQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.3.tgz", + "integrity": "sha512-2VR4cTBzHXaBjnGsuH6GyJjENzQOmHeAh11uY1iUhjm3j5dEUrVJuUj+VL78jaGi/Dik8xS76zEj18BsFhlVZQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/canvas-confetti": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz", + "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz", + "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/type-utils": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.68.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz", + "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz", + "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.68.0", + "@typescript-eslint/types": "^8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz", + "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz", + "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz", + "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz", + "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.68.0", + "@typescript-eslint/tsconfig-utils": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz", + "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz", + "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-26.2.0.tgz", + "integrity": "sha512-8TCd4mMKhhUxGF9sjZ6W2V1gesnj43v1SFZoeAue/0O0ikMXIU92p96PiRn0D4nAVvFM/92bluTTb/PoXH5mnQ==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", + "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.415", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.415.tgz", + "integrity": "sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==", + "dev": true, + "license": "ISC" + }, + "node_modules/elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==", + "license": "Apache-2.0", + "dependencies": { + "sax": "1.1.4" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.3.tgz", + "integrity": "sha512-teqtsR26tnlfXFHfVLTM/4tzEzU8DMu6GS1sddZzhfGzgd2f2ofbgDUcsk6cssSCzX6Tk6fmWifJcdANSdPJrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "16.3.3", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "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.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.577.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz", + "integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/native-run": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", + "integrity": "sha512-U1PllBuzW5d1gfan+88L+Hky2eZx+9gv3Pf6rNBxKbORxi7boHzqiA6QFGSnqMem4j0A9tZ08NMIs5+0m/VS1Q==", + "license": "MIT", + "dependencies": { + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" + }, + "bin": { + "native-run": "bin/native-run" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.3.tgz", + "integrity": "sha512-tuRTx1nQ/yVw83cwJBo9F+njGUgMn3UHQycreWHB8XsStvvAh1AthbI8/4IpKnFaF58F+iSiHejYOlMQ/eq83g==", + "license": "MIT", + "dependencies": { + "@next/env": "16.3.3", + "@swc/helpers": "0.5.23", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.5.23", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.3.3", + "@next/swc-darwin-x64": "16.3.3", + "@next/swc-linux-arm64-gnu": "16.3.3", + "@next/swc-linux-arm64-musl": "16.3.3", + "@next/swc-linux-x64-gnu": "16.3.3", + "@next/swc-linux-x64-musl": "16.3.3", + "@next/swc-win32-arm64-msvc": "16.3.3", + "@next/swc-win32-x64-msvc": "16.3.3", + "sharp": "^0.35.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-appwrite": { + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-26.2.0.tgz", + "integrity": "sha512-rRToHOuG05F5Q3BGRoJNNIcO69zrYul/V9HOTxfcMSqhdw3TwInAl7pnSnMRW7D0MOQcvaLb8iZIwE1P8TP9Cw==", + "license": "BSD-3-Clause", + "dependencies": { + "json-bigint": "1.0.0", + "undici": "^6.26.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "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": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "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/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.68.0.tgz", + "integrity": "sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.68.0", + "@typescript-eslint/parser": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/zapply-app/package.json b/zapply-app/package.json new file mode 100644 index 0000000..c2f041e --- /dev/null +++ b/zapply-app/package.json @@ -0,0 +1,38 @@ +{ + "name": "zapply-app", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev -H 0.0.0.0 -p 3003", + "build": "next build", + "start": "next start -H 0.0.0.0 -p 3003", + "lint": "next lint" + }, + "dependencies": { + "@capacitor/android": "^8.5.0", + "@capacitor/cli": "^8.5.0", + "@capacitor/core": "^8.5.0", + "@google/genai": "^2.19.0", + "appwrite": "^26.2.0", + "axios": "^1.18.0", + "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", + "lucide-react": "^0.577.0", + "next": "16.3.3", + "node-appwrite": "^26.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/canvas-confetti": "^1.9.0", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.3.3", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/zapply-app/postcss.config.mjs b/zapply-app/postcss.config.mjs new file mode 100644 index 0000000..61e3684 --- /dev/null +++ b/zapply-app/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/zapply-app/public/file.svg b/zapply-app/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/zapply-app/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/zapply-app/public/globe.svg b/zapply-app/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/zapply-app/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/zapply-app/public/icon.svg b/zapply-app/public/icon.svg new file mode 100644 index 0000000..7bba100 --- /dev/null +++ b/zapply-app/public/icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + Z + + diff --git a/zapply-app/public/manifest.json b/zapply-app/public/manifest.json new file mode 100644 index 0000000..cd70ec7 --- /dev/null +++ b/zapply-app/public/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "Zapply Cali • Sneakers Express", + "short_name": "Zapply Cali", + "description": "Tu calzado favorito con entrega express y pago contraentrega en 24 horas.", + "start_url": "/", + "display": "standalone", + "background_color": "#030712", + "theme_color": "#10b981", + "orientation": "portrait", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any maskable" + } + ] +} diff --git a/zapply-app/public/next.svg b/zapply-app/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/zapply-app/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/zapply-app/public/vercel.svg b/zapply-app/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/zapply-app/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/zapply-app/public/window.svg b/zapply-app/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/zapply-app/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/zapply-app/scripts/setup-appwrite.js b/zapply-app/scripts/setup-appwrite.js new file mode 100644 index 0000000..8a34246 --- /dev/null +++ b/zapply-app/scripts/setup-appwrite.js @@ -0,0 +1,131 @@ +/** + * Script de inicialización de la Base de Datos Independiente en Appwrite + * Ejecutar con: node scripts/setup-appwrite.js + */ +const { Client, Databases, Storage, Permission, Role } = require('node-appwrite'); +const fs = require('fs'); +const path = require('path'); + +// Leer variables de .env.local manualmente si dotenv no está disponible en este script +const envPath = path.resolve(__dirname, '../.env.local'); +if (fs.existsSync(envPath)) { + const envContent = fs.readFileSync(envPath, 'utf8'); + envContent.split('\n').forEach((line) => { + const trimmed = line.trim(); + if (trimmed && !trimmed.startsWith('#')) { + const [k, ...v] = trimmed.split('='); + if (k && v) process.env[k.trim()] = v.join('=').trim(); + } + }); +} + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; +const apiKey = process.env.APPWRITE_API_KEY; +const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +const bucketId = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +if (!apiKey) { + console.error('❌ Falta APPWRITE_API_KEY en .env.local'); + process.exit(1); +} + +const client = new Client() + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey); + +const databases = new Databases(client); +const storage = new Storage(client); + +async function setup() { + console.log('🚀 Iniciando configuración de la Base de Datos Independiente para la Tienda...'); + console.log(`Endpoint: ${endpoint}`); + console.log(`Database ID: ${databaseId}`); + console.log(`Bucket ID: ${bucketId}`); + + // 1. Crear Base de Datos Independiente si no existe + try { + await databases.get(databaseId); + console.log(`✅ Base de datos independiente "${databaseId}" ya existe.`); + } catch (e) { + console.log(`Creando base de datos independiente "${databaseId}"...`); + await databases.create(databaseId, 'Sneakers Multi-Store DB'); + console.log(`✅ Base de datos "${databaseId}" creada con éxito.`); + } + + // 2. Crear Storage Bucket Independiente si no existe + try { + await storage.getBucket(bucketId); + console.log(`✅ Storage Bucket "${bucketId}" ya existe.`); + } catch (e) { + console.log(`Creando Storage Bucket "${bucketId}"...`); + try { + await storage.createBucket( + bucketId, + 'Sneakers Media Assets', + [Permission.read(Role.any()), Permission.create(Role.any())], + false, // fileSecurity + true, // enabled + 50000000, // 50MB max file size + ['jpg', 'png', 'webp', 'jpeg'] + ); + console.log(`✅ Storage Bucket "${bucketId}" creado con éxito.`); + } catch (bErr) { + console.warn('Nota sobre creación de bucket:', bErr.message); + } + } + + // 3. Crear Colecciones Independientes + const collections = [ + { + id: 'products', + name: 'Productos y Zapatillas', + }, + { + id: 'cities', + name: 'Ciudades y Envíos', + }, + { + id: 'payment_methods', + name: 'Métodos de Pago', + }, + { + id: 'orders', + name: 'Pedidos de Clientes', + }, + { + id: 'supplier_posts', + name: 'Feed de Mensajes WhatsApp', + }, + ]; + + for (const col of collections) { + try { + await databases.getCollection(databaseId, col.id); + console.log(`✅ Colección "${col.name}" (${col.id}) ya existe.`); + } catch (e) { + console.log(`Creando colección "${col.name}" (${col.id})...`); + try { + await databases.createCollection( + databaseId, + col.id, + col.name, + [ + Permission.read(Role.any()), + Permission.create(Role.any()), + Permission.update(Role.any()), + Permission.delete(Role.any()), + ] + ); + console.log(`✅ Colección creada: ${col.id}`); + } catch (cErr) { + console.warn(`Error creando colección ${col.id}:`, cErr.message); + } + } + } + + console.log('🎉 ¡Base de datos y colecciones independientes configuradas al 100%!'); +} + +setup().catch((err) => console.error('Error configurando Appwrite:', err)); diff --git a/zapply-app/src/app/admin/ciudades/page.tsx b/zapply-app/src/app/admin/ciudades/page.tsx new file mode 100644 index 0000000..243d427 --- /dev/null +++ b/zapply-app/src/app/admin/ciudades/page.tsx @@ -0,0 +1,249 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { MapPin, Plus, Save, Trash2, Check, X, Truck, ShieldCheck } from 'lucide-react'; +import { City } from '@/types'; +import { INITIAL_CITIES } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminCitiesPage() { + const [cities, setCities] = useState(INITIAL_CITIES); + const [isSaving, setIsSaving] = useState(false); + const [message, setMessage] = useState(null); + + // New city form + const [newName, setNewName] = useState(''); + const [newDepartment, setNewDepartment] = useState(''); + const [newShippingCost, setNewShippingCost] = useState('0'); + const [newDeliveryTime, setNewDeliveryTime] = useState('Entrega en 24 Horas'); + const [newAllowCod, setNewAllowCod] = useState(true); + const [newFirstExchangeFree, setNewFirstExchangeFree] = useState(true); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + }, []); + + const handleToggleExchangeFree = async (city: City) => { + const updated = { ...city, firstExchangeFree: !city.firstExchangeFree }; + setCities((prev) => prev.map((c) => (c.id === city.id ? updated : c))); + + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: city.id, updates: { firstExchangeFree: updated.firstExchangeFree } }), + }); + setMessage(`Política de 1er cambio gratis para "${city.name}" ${updated.firstExchangeFree ? 'ACTIVADA' : 'DESACTIVADA'}.`); + }; + + const handleUpdateShipping = async (cityId: string, cost: number) => { + setCities((prev) => prev.map((c) => (c.id === cityId ? { ...c, shippingCost: cost } : c))); + await fetch('/api/cities', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: cityId, updates: { shippingCost: cost } }), + }); + setMessage('Tarifa de envío actualizada.'); + }; + + const handleAddCity = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newName) return; + + const payload = { + name: newName, + department: newDepartment || 'Colombia', + shippingCost: parseInt(newShippingCost, 10) || 0, + deliveryTime: newDeliveryTime, + allowsContraentrega: newAllowCod, + firstExchangeFree: newFirstExchangeFree, + exchangePolicyNote: newFirstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${newName} (posteriores con flete estándar)` + : `Cambio de talla garantizado (flete logístico asumido por el cliente)`, + }; + + const res = await fetch('/api/cities', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + const data = await res.json(); + if (data.success) { + setCities((prev) => [...prev, data.city]); + setNewName(''); + setNewDepartment(''); + setMessage(`Ciudad "${data.city.name}" agregada con éxito.`); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Ciudades, Fletes y Garantía de Cambio +

+

+ Administra las tarifas de envío, tiempos de entrega y configura si el 1er cambio de talla es gratis o si el cliente asume el flete para cada ciudad. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Add New City Card */} +
+

+ + Registrar Nueva Ciudad o Municipio +

+ +
+
+ + setNewName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDepartment(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewShippingCost(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + setNewDeliveryTime(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+
+ +
+
+ + + +
+ + +
+
+ + {/* Cities List */} +
+

Ciudades y Zonas Registradas ({cities.length})

+ +
+ {cities.map((city) => ( +
+
+
+ {city.name} + ({city.department}) + {city.allowsContraentrega ? ( + + Contraentrega Activo + + ) : ( + + Solo Despacho Nacional + + )} +
+

+ + {city.deliveryTime} +

+
+ + {/* Actions & Policy Toggle */} +
+ {/* 1st Exchange Free Toggle Button */} + + + {/* Shipping cost edit */} +
+ Flete: + handleUpdateShipping(city.id, parseInt(e.target.value, 10) || 0)} + className="w-20 bg-transparent text-xs font-bold text-white outline-hidden text-right" + /> + COP +
+
+
+ ))} +
+
+
+ ); +} diff --git a/zapply-app/src/app/admin/configuracion/page.tsx b/zapply-app/src/app/admin/configuracion/page.tsx new file mode 100644 index 0000000..6013f29 --- /dev/null +++ b/zapply-app/src/app/admin/configuracion/page.tsx @@ -0,0 +1,352 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Store, Mail, Phone, MessageCircle, Instagram, MapPin, CreditCard, Save, CheckCircle2, DollarSign, Percent, ShieldCheck, QrCode, ExternalLink, Zap } from 'lucide-react'; +import { StoreSettings } from '@/types'; + +export default function AdminSettingsPage() { + const [settings, setSettings] = useState({ + storeName: 'Zapply Cali', + slogan: 'Sneakers Express • Entregas en 24 Horas', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@zapplycali.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }); + + const [isSaving, setIsSaving] = useState(false); + const [toast, setToast] = useState(null); + + useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setSettings(d.settings)) + .catch(() => {}); + }, []); + + const handleChange = (field: keyof StoreSettings, value: any) => { + setSettings((prev) => ({ ...prev, [field]: value })); + }; + + const handlePhoneChange = (val: string) => { + const cleanDigits = val.replace(/\D/g, ''); + const cleanWa = cleanDigits.startsWith('57') ? cleanDigits : `57${cleanDigits}`; + setSettings((prev) => ({ + ...prev, + phone: cleanDigits, + whatsappNumber: cleanWa, + })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSaving(true); + + try { + const res = await fetch('/api/settings', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settings), + }); + const data = await res.json(); + if (data.success) { + setToast('✅ ¡Datos de Zapply Cali, WhatsApp oficial y pasarela Bold.co actualizados exitosamente!'); + setTimeout(() => setToast(null), 4500); + } + } catch (err) { + console.error(err); + } finally { + setIsSaving(false); + } + }; + + return ( +
+ {/* Header */} +
+

+ + Información de la Tienda & Medios de Pago +

+

+ Configura los datos oficiales del negocio: WhatsApp oficial de atención, correo electrónico, pasarela Bold.co (Link de pago, QR y botón), Nequi, Daviplata y reglas de margen. +

+
+ + {toast && ( +
+ {toast} + +
+ )} + +
+ {/* Section 1: Identidad & WhatsApp Oficial */} +
+

+ + Identidad & WhatsApp Oficial de Atención +

+ +
+
+ + handleChange('storeName', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white font-semibold outline-hidden focus:border-emerald-400" + /> +
+ +
+ + handleChange('slogan', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400" + /> +
+ +
+ + handleChange('email', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400 font-mono" + /> +
+ +
+ +
+ handlePhoneChange(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-emerald-300 font-bold outline-hidden focus:border-emerald-400" + /> + +
+

+ Link generado: https://wa.me/{settings.whatsappNumber} +

+
+ +
+ + handleChange('instagramHandle', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400" + /> +
+ +
+ + handleChange('city', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400" + /> +
+
+
+ + {/* Section 2: Pasarela Bold.co (Link de Pago, QR o Botón) */} +
+
+

+ + Integración con Bold.co (Link de Pago, Botón & QR) +

+ +
+ +
+
+ +
+ handleChange('boldPaymentLink', e.target.value)} + className="w-full bg-slate-950 border border-indigo-500/40 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> + +
+

+ Tus clientes podrán pagar por PSE, Tarjeta de Crédito/Débito o Nequi directamente con este enlace oficial de Bold. +

+
+ +
+ + handleChange('boldQrUrl', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-indigo-400" + /> +
+ +
+ + handleChange('boldApiKey', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white font-mono outline-hidden focus:border-indigo-400" + /> +
+
+
+ + {/* Section 3: Cuentas de Recaudo Nequi / Daviplata */} +
+

+ + Cuentas para Recaudo de Anticipos ($10.000 COP) +

+ +
+
+ + handleChange('accountHolder', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400 font-bold" + /> +
+ +
+ + handleChange('nequiAccount', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400" + /> +
+ +
+ + handleChange('daviplataAccount', e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2.5 text-white outline-hidden focus:border-emerald-400" + /> +
+
+
+ + {/* Section 4: Reglas de Precios y Anticipo */} +
+

+ + Reglas Comerciales de Ganancia & Redondeo +

+ +
+
+ +
+ handleChange('defaultProfitMargin', Number(e.target.value))} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-emerald-400" + /> + +
+

+ El sistema calcula el precio y lo redondea al siguiente múltiplo de $5.000 COP (ej: $132.000 ➔ $135.000). +

+
+ +
+ +
+ handleChange('defaultDepositAmount', Number(e.target.value))} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-white font-bold outline-hidden focus:border-emerald-400" + /> + +
+

+ Valor solicitado al comprador para apartar el calzado con el proveedor. +

+
+
+
+ + {/* Submit Bar */} +
+

+ Todos los cambios se reflejan inmediatamente en la tienda pública, el carrito y los mensajes de WhatsApp. +

+ +
+
+
+ ); +} diff --git a/zapply-app/src/app/admin/feed-whatsapp/page.tsx b/zapply-app/src/app/admin/feed-whatsapp/page.tsx new file mode 100644 index 0000000..a1866cb --- /dev/null +++ b/zapply-app/src/app/admin/feed-whatsapp/page.tsx @@ -0,0 +1,365 @@ +'use client'; + +import React, { useState } from 'react'; +import { Radio, Sparkles, Share2, AlertTriangle, ShieldCheck, Plus, Send, Layers } from 'lucide-react'; +import { SupplierPost, Product } from '@/types'; +import { INITIAL_SUPPLIER_POSTS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { checkProductDuplicate } from '@/lib/deduplication-engine'; +import { formatCOP } from '@/lib/pricing-engine'; +import { BRANDS, BrandId } from '@/config/brands'; + +export default function SupplierFeedPage() { + const [posts, setPosts] = useState(INITIAL_SUPPLIER_POSTS); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [isProcessing, setIsProcessing] = useState(false); + const [actionMessage, setActionMessage] = useState(null); + + // Target brand selector for publishing + const [targetBrand, setTargetBrand] = useState('almeira'); + + // Simulación de nuevo mensaje entrante de grupo para probar en vivo + const [testText, setTestText] = useState( + '🔥 LLEGANDO A BODEGA HOY 🔥\nNike Air Max 90 White Black\nTallas: 38 a 43\nMayorista: $90.000 c/u\nEnvío inmediato contraentrega' + ); + const [testGroup, setTestGroup] = useState('Canal Mayorista A'); + + const handleSimulateIncoming = async () => { + setIsProcessing(true); + try { + const res = await fetch('/api/webhook/whatsapp', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + text: testText, + groupInfo: { subject: testGroup }, + }), + }); + const data = await res.json(); + if (data.success && data.post) { + setPosts((prev) => [data.post, ...prev]); + setActionMessage('✅ Nuevo mensaje de WhatsApp procesado con IA.'); + } + } catch (err) { + console.error(err); + } finally { + setIsProcessing(false); + } + }; + + const handlePublishFacebook = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + setIsProcessing(true); + try { + const brandName = targetBrand === 'all' ? 'Todas las Tiendas' : BRANDS[targetBrand].name; + const res = await fetch('/api/publish/facebook', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + productName: post.extractedProduct.name, + brand: post.extractedProduct.brand, + retailPrice: post.extractedProduct.suggestedRetailPrice, + sizes: post.extractedProduct.sizes, + images: post.rawImages, + }), + }); + const data = await res.json(); + if (data.success) { + setActionMessage(`🚀 ¡Publicado en Facebook bajo la marca "${brandName}"! (ID: ${data.postId})`); + } + } catch (e) { + console.error(e); + } finally { + setIsProcessing(false); + } + }; + + const handleAddToStore = async (post: SupplierPost) => { + if (!post.extractedProduct) return; + const brandLabel = targetBrand === 'all' ? 'Multi-Marca' : BRANDS[targetBrand].shortName; + const newProduct: Product = { + id: `snk-${Date.now()}`, + name: post.extractedProduct.name, + brand: post.extractedProduct.brand, + supplierPrice: post.extractedProduct.supplierPrice, + retailPrice: post.extractedProduct.suggestedRetailPrice, + originalPrice: Math.round(post.extractedProduct.suggestedRetailPrice * 1.35), + sizes: post.extractedProduct.sizes, + images: post.rawImages, + description: `Zapatillas calidad premium garantizada para entrega inmediata.`, + category: post.extractedProduct.category, + inStock: true, + isActive: true, + originBadge: `Bodega Central`, + supplierName: post.supplierName || post.channelName || 'DIFUSION JOVIC STORE', + supplierPhone: post.supplierPhone || '573134848203', + }; + + try { + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProduct), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setActionMessage(`✨ "${newProduct.name}" habilitado en el catálogo para ${brandLabel}.`); + } + } catch (e) { + console.error(e); + } + }; + + return ( +
+ {/* Header */} +
+
+

+ + Feed de Entrada & Publicador Multi-Marca +

+

+ Recepción automática con IA, prevención de duplicados y distribución hacia las 4 marcas (Almeira Store, Sneaky, Zapply, DripZone). +

+
+ + {/* Target Brand Selector Pill Bar */} +
+ + Destino: + + + {Object.values(BRANDS).map((b) => ( + + ))} +
+
+ + {actionMessage && ( +
+ {actionMessage} + +
+ )} + + {/* Live Simulator for Test Messages */} +
+
+ + Simulador de Recepción en Tiempo Real +
+ +
+
+ + +
+ +
+ +
+ setTestText(e.target.value)} + className="flex-1 bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> + +
+
+
+
+ + {/* Intercepted Posts Feed */} +
+

Mensajes Procesados Recientemente

+ +
+ {posts.map((post) => { + const extracted = post.extractedProduct; + const duplicateCheck = extracted + ? checkProductDuplicate( + { + name: extracted.name, + brand: extracted.brand, + sizes: extracted.sizes, + supplierPrice: extracted.supplierPrice, + }, + products + ) + : null; + + return ( +
+ {/* Header of post */} +
+
+ + {post.channelName || 'Canal Mayorista'} + + {post.receivedAt} +
+ + {/* Anti-Duplicate Status Badge */} + {duplicateCheck && ( +
+ {duplicateCheck.isDuplicate ? ( + <> + + Duplicado Detectado ({Math.round(duplicateCheck.similarityScore * 100)}% Similitud) + + ) : ( + <> + + Producto Nuevo (0% Duplicados) + + )} +
+ )} +
+ + {/* Content Grid */} +
+ {/* Left: Raw WhatsApp Message (5 cols) */} +
+ Mensaje de Entrada: +

+ {post.rawMessage} +

+ {post.rawImages.length > 0 && ( +
+ +
+ )} +
+ + {/* Right: AI Extracted & Pricing Calculation (7 cols) */} +
+ {extracted ? ( +
+
+
+ + {extracted.brand} • {extracted.category} + +

{extracted.name}

+
+ + IA: {Math.round(extracted.confidence * 100)}% certeza + +
+ + {/* Pricing breakdown */} +
+
+ Costo Base: + + {formatCOP(extracted.supplierPrice)} + +
+
+ Precio Venta (+ Margen): + + {formatCOP(extracted.suggestedRetailPrice)} + +
+
+ + {/* Sizes */} +
+ + Tallas extraídas: + +
+ {extracted.sizes.map((s) => ( + + {s} + + ))} +
+
+ + {/* Duplicate warning note */} + {duplicateCheck?.isDuplicate && ( +
+ {duplicateCheck.message} +
+ )} + + {/* Actions */} +
+ + + +
+
+ ) : ( +

Extrayendo datos...

+ )} +
+
+
+ ); + })} +
+
+
+ ); +} diff --git a/zapply-app/src/app/admin/grupos-whatsapp/page.tsx b/zapply-app/src/app/admin/grupos-whatsapp/page.tsx new file mode 100644 index 0000000..00f42c6 --- /dev/null +++ b/zapply-app/src/app/admin/grupos-whatsapp/page.tsx @@ -0,0 +1,585 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { + MessageSquare, + RefreshCw, + Search, + CheckCircle2, + XCircle, + ShieldCheck, + Zap, + Radio, + Sliders, + Users, + Sparkles, + ExternalLink, + Plus, + ArrowUpRight, + Filter, + CheckSquare, + Square, + X +} from 'lucide-react'; +import { MonitoredWhatsAppGroup } from '@/types'; + +export default function AdminWhatsAppGroupsPage() { + const [groups, setGroups] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [filterMode, setFilterMode] = useState<'all' | 'monitored' | 'unmonitored'>('all'); + const [toast, setToast] = useState(null); + const [scanningGroupId, setScanningGroupId] = useState(null); + + // Group Picker Modal State + const [isPickerOpen, setIsPickerOpen] = useState(false); + const [liveGroups, setLiveGroups] = useState([]); + const [isLoadingLive, setIsLoadingLive] = useState(false); + const [pickerSearch, setPickerSearch] = useState(''); + const [selectedJids, setSelectedJids] = useState>(new Set()); + + const fetchLocalGroups = async () => { + setIsLoading(true); + try { + const res = await fetch('/api/whatsapp-groups'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setGroups(data.groups); + } + } catch (err) { + console.error(err); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchLocalGroups(); + }, []); + + const handleOpenPicker = async () => { + setIsPickerOpen(true); + setIsLoadingLive(true); + try { + const res = await fetch('/api/whatsapp-groups?fetchLive=true'); + const data = await res.json(); + if (data.success && Array.isArray(data.groups)) { + setLiveGroups(data.groups); + // Pre-select already monitored groups + const initialSelected = new Set(); + data.groups.forEach((g: MonitoredWhatsAppGroup) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + groups.forEach((g) => { + if (g.isMonitored) initialSelected.add(g.jid); + }); + setSelectedJids(initialSelected); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleSelectJid = (jid: string) => { + setSelectedJids((prev) => { + const next = new Set(prev); + if (next.has(jid)) next.delete(jid); + else next.add(jid); + return next; + }); + }; + + const handleSelectAllFiltered = (filtered: MonitoredWhatsAppGroup[]) => { + setSelectedJids((prev) => { + const next = new Set(prev); + filtered.forEach((g) => next.add(g.jid)); + return next; + }); + }; + + const handleDeselectAll = () => { + setSelectedJids(new Set()); + }; + + const handleSaveSelectedGroups = async () => { + setIsLoadingLive(true); + try { + const updatedGroups: MonitoredWhatsAppGroup[] = liveGroups.map((lg) => ({ + ...lg, + isMonitored: selectedJids.has(lg.jid), + autoPublish: true, + profitMarginOverride: 35, + })); + + const res = await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ groups: updatedGroups }), + }); + + const data = await res.json(); + if (data.success) { + setGroups(data.groups); + setIsPickerOpen(false); + setToast(`✅ ¡Se actualizaron los grupos monitoreados! (${selectedJids.size} activos)`); + setTimeout(() => setToast(null), 4000); + } + } catch (err) { + console.error(err); + } finally { + setIsLoadingLive(false); + } + }; + + const handleToggleGroup = async (group: MonitoredWhatsAppGroup) => { + const nextState = !group.isMonitored; + const updatedList = groups.map((g) => + g.jid === group.jid || g.id === group.id ? { ...g, isMonitored: nextState } : g + ); + setGroups(updatedList); + + try { + await fetch('/api/whatsapp-groups', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'toggle', + idOrJid: group.jid || group.id, + isMonitored: nextState, + }), + }); + + setToast( + nextState + ? `🟢 Grupo "${group.name}" ahora está siendo MONITOREADO en tiempo real.` + : `⚪ Grupo "${group.name}" fue desactivado del monitoreo.` + ); + setTimeout(() => setToast(null), 3500); + } catch (err) { + console.error(err); + } + }; + + const handleScanGroup = async (group: MonitoredWhatsAppGroup) => { + setScanningGroupId(group.id); + try { + await new Promise((r) => setTimeout(r, 1200)); + setToast(`✨ Mensajes recientes de "${group.name}" analizados con IA y catálogo actualizado.`); + setTimeout(() => setToast(null), 4000); + } finally { + setScanningGroupId(null); + } + }; + + const filteredGroups = groups.filter((g) => { + const matchesSearch = + g.name.toLowerCase().includes(searchQuery.toLowerCase()) || + g.jid.toLowerCase().includes(searchQuery.toLowerCase()) || + (g.notes && g.notes.toLowerCase().includes(searchQuery.toLowerCase())); + + if (filterMode === 'monitored') return matchesSearch && g.isMonitored; + if (filterMode === 'unmonitored') return matchesSearch && !g.isMonitored; + return matchesSearch; + }); + + const filteredPickerGroups = liveGroups.filter((g) => + g.name.toLowerCase().includes(pickerSearch.toLowerCase()) || + g.jid.toLowerCase().includes(pickerSearch.toLowerCase()) + ); + + const monitoredCount = groups.filter((g) => g.isMonitored).length; + + return ( +
+ {/* Header */} +
+
+

+ + Monitoreo de Grupos de WhatsApp +

+

+ Busca y selecciona los grupos de proveedores que el bot de Evolution API & Gemini debe escuchar 24/7 para auto-publicar zapatillas. +

+
+ + {/* Big Search and Select Button */} + +
+ + {/* Toast Notification */} + {toast && ( +
+ {toast} + +
+ )} + + {/* Stats Bar */} +
+
+
+

Grupos en tu WhatsApp

+

{groups.length}

+
+
+ +
+
+ +
+
+

Grupos Monitoreados (Activos)

+

{monitoredCount}

+
+
+ +
+
+ +
+
+

Evolution API (WhatsApp)

+

+ + AutomataAlmeira (En línea) +

+
+
+ +
+
+
+ + {/* Filter and Search Toolbar */} +
+
+ + setSearchQuery(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3 py-2 text-xs text-white outline-hidden focus:border-emerald-400" + /> +
+ +
+ + + +
+
+ + {/* Active Monitored Groups List */} +
+ {isLoading ? ( +
+ +

Cargando grupos de proveedores...

+
+ ) : filteredGroups.length === 0 ? ( +
+ +

No tienes grupos seleccionados para monitorear.

+ +
+ ) : ( + filteredGroups.map((group) => { + const isMonitored = group.isMonitored; + + return ( +
+ {/* Header */} +
+
+
+ +

+ {group.name} +

+
+

+ {group.jid} +

+
+ + {/* Toggle Switch */} + +
+ + {/* Info Pills */} +
+
+ Margen Aplicado + + +{group.profitMarginOverride || 35}% (Redondeo a $5.000) + +
+ +
+ Modo de Ingreso + + Auto-Publicar Directo + +
+
+ + {group.notes && ( +

+ ℹ️ {group.notes} +

+ )} + + {/* Action footer */} +
+ + {group.participantsCount ? `👥 ${group.participantsCount} miembros` : 'Canal Mayorista'} + + + +
+
+ ); + }) + )} +
+ + {/* ========================================================= */} + {/* MODAL: Group Picker (Buscar y Seleccionar Grupos) */} + {/* ========================================================= */} + {isPickerOpen && ( +
+
+ {/* Modal Header */} +
+
+
+ +
+
+

Seleccionar Grupos de WhatsApp

+

+ Marca los grupos que deseas monitorear con IA para auto-publicar calzado. +

+
+
+ +
+ + {/* Search and Action Toolbar in Modal */} +
+
+ + setPickerSearch(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-9 pr-3.5 py-2.5 text-xs text-white outline-hidden focus:border-emerald-400 font-semibold" + /> +
+ +
+ + Mostrando {filteredPickerGroups.length} grupos encontrados + +
+ + • + +
+
+
+ + {/* Groups Scrollable List */} +
+ {isLoadingLive ? ( +
+ +

Consultando grupos en vivo desde Evolution API...

+

Conectando con WhatsApp...

+
+ ) : filteredPickerGroups.length === 0 ? ( +
+

No se encontraron grupos con el término "{pickerSearch}".

+
+ ) : ( + filteredPickerGroups.map((group) => { + const isSelected = selectedJids.has(group.jid); + + return ( +
handleToggleSelectJid(group.jid)} + className={`p-3.5 rounded-2xl border transition-all cursor-pointer flex items-center justify-between gap-3 ${ + isSelected + ? 'bg-emerald-950/30 border-emerald-500/50 shadow-md ring-1 ring-emerald-500/20' + : 'bg-slate-950 border-slate-800 hover:border-slate-700' + }`} + > +
+
+ {isSelected && } +
+ +
+

+ {group.name} +

+

+ {group.jid} +

+
+
+ +
+ {isSelected ? ( + + Monitorear + + ) : ( + + Ignorar + + )} +
+
+ ); + }) + )} +
+ + {/* Modal Footer */} +
+
+ Seleccionados: + {selectedJids.size} + grupos para monitorear +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/zapply-app/src/app/admin/layout.tsx b/zapply-app/src/app/admin/layout.tsx new file mode 100644 index 0000000..b2d456f --- /dev/null +++ b/zapply-app/src/app/admin/layout.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { + LayoutDashboard, + Radio, + Package, + MapPin, + CreditCard, + ShoppingBag, + ArrowLeft, + Sparkles, + Store, + Users, + MessageSquare, +} from 'lucide-react'; + +export default function AdminLayout({ children }: { children: React.ReactNode }) { + const pathname = usePathname(); + + const NAV_ITEMS = [ + { href: '/admin', label: 'Resumen & KPIs', icon: LayoutDashboard }, + { href: '/admin/grupos-whatsapp', label: 'Grupos WhatsApp', icon: MessageSquare, badge: 'Monitoreo 24/7' }, + { href: '/admin/usuarios', label: 'Control de Usuarios', icon: Users, badge: 'Roles & Accesos' }, + { href: '/admin/configuracion', label: 'Datos de la Tienda', icon: Store }, + { href: '/admin/feed-whatsapp', label: 'Feed WhatsApp & IA', icon: Radio, badge: 'Anti-Duplicados' }, + { href: '/admin/productos', label: 'Catálogo de Zapatillas', icon: Package }, + { href: '/admin/ciudades', label: 'Ciudades & Fletes', icon: MapPin }, + { href: '/admin/metodos-pago', label: 'Medios de Pago & Anticipos', icon: CreditCard }, + { href: '/admin/pedidos', label: 'Pedidos & Logística', icon: ShoppingBag }, + ]; + + return ( +
+ {/* Sidebar */} + + + {/* Main Content Area */} +
+ {children} +
+
+ ); +} diff --git a/zapply-app/src/app/admin/metodos-pago/page.tsx b/zapply-app/src/app/admin/metodos-pago/page.tsx new file mode 100644 index 0000000..ffb5f01 --- /dev/null +++ b/zapply-app/src/app/admin/metodos-pago/page.tsx @@ -0,0 +1,163 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { CreditCard, Zap, Save, Check, ShieldCheck, QrCode } from 'lucide-react'; +import { PaymentMethod } from '@/types'; +import { INITIAL_PAYMENT_METHODS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminPaymentMethodsPage() { + const [methods, setMethods] = useState(INITIAL_PAYMENT_METHODS); + const [message, setMessage] = useState(null); + + useEffect(() => { + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setMethods(d.paymentMethods)) + .catch(() => {}); + }, []); + + const handleToggleActive = async (method: PaymentMethod) => { + const updated = { ...method, isActive: !method.isActive }; + setMethods((prev) => prev.map((m) => (m.id === method.id ? updated : m))); + + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: { isActive: updated.isActive } }), + }); + setMessage(`Método "${method.name}" ${updated.isActive ? 'activado' : 'desactivado'}.`); + }; + + const handleUpdateField = (id: string, field: keyof PaymentMethod, val: any) => { + setMethods((prev) => + prev.map((m) => (m.id === id ? { ...m, [field]: val } : m)) + ); + }; + + const handleSaveMethod = async (method: PaymentMethod) => { + await fetch('/api/payment-methods', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: method.id, updates: method }), + }); + setMessage(`✅ Cambios guardados para "${method.name}".`); + }; + + return ( +
+ {/* Header */} +
+

+ + Configuración de Medios de Pago & Anticipos +

+

+ Habilita métodos de pago, configura el valor de separación de $10.000 COP y personaliza los datos de Nequi / Daviplata. +

+
+ + {message && ( +
+ {message} + +
+ )} + + {/* Methods Cards */} +
+ {methods.map((method) => ( +
+
+
+
+ {method.type === 'contraentrega' ? : } +
+
+

{method.name}

+ Tipo: {method.type} +
+
+ +
+ +
+
+ +
+
+ + handleUpdateField(method.id, 'name', e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ +
+ + handleUpdateField(method.id, 'description', e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + /> +
+ + {method.requiresDeposit && ( +
+ + handleUpdateField(method.id, 'depositAmount', parseInt(e.target.value, 10) || 0)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden font-bold" + /> + + (El saldo restante se cobra contraentrega al recibir) + +
+ )} + +
+ + handleUpdateField(method.id, 'accountInfo', e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3 py-2 text-xs text-white outline-hidden" + placeholder="Ej. Nequi / Daviplata: 316 745 5877" + /> +
+
+ +
+ +
+
+ ))} +
+
+ ); +} diff --git a/zapply-app/src/app/admin/page.tsx b/zapply-app/src/app/admin/page.tsx new file mode 100644 index 0000000..8d400b5 --- /dev/null +++ b/zapply-app/src/app/admin/page.tsx @@ -0,0 +1,159 @@ +'use client'; + +import React, { useState } from 'react'; +import Link from 'next/link'; +import { Package, Radio, MapPin, Zap, CheckCircle2, ArrowUpRight, Sparkles } from 'lucide-react'; +import { INITIAL_PRODUCTS, INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_SUPPLIER_POSTS } from '@/lib/data-service'; + +export default function AdminDashboardPage() { + const [productsCount] = useState(INITIAL_PRODUCTS.length); + const [postsCount] = useState(INITIAL_SUPPLIER_POSTS.length); + const [citiesCount] = useState(INITIAL_CITIES.length); + + return ( +
+ {/* Header */} +
+
+

+ + Centro de Control • Almeira Store +

+

+ Automatización inteligente de calzado, publicaciones a Facebook y gestión de despachos. +

+
+ +
+ + + Ver Feed de WhatsApp + +
+
+ + {/* KPI Cards */} +
+
+
+ Zapatillas Activas + +
+
{productsCount}
+

+ Catálogo sincronizado +

+
+ +
+
+ Margen Promedio + +
+
+ +$30.000 COP +
+

+ (Costo: $90k ➔ Venta: $120k) +

+
+ +
+
+ Entradas Procesadas + +
+
{postsCount}
+

+ IA Gemini + Anti-duplicados +

+
+ +
+
+ Ciudades Habilitadas + +
+
{citiesCount}
+

+ Contraentrega activo en Cali +

+
+
+ + {/* Quick Actions & Automation Status */} +
+ {/* Left: WhatsApp Evolution API Status */} +
+
+
+
+

Estado del Listener de WhatsApp

+
+ + Activo + +
+ +
+
+ Instancia Evolution API: + AutomataAlmeira +
+
+ Servidor: + evolution.almeira.com.co +
+
+ Motor de Inteligencia Artificial: + Gemini 2.5 Flash +
+
+ Filtro Anti-Duplicados: + Activo (>75% Similitud) +
+
+ + + Ver últimos mensajes procesados + + +
+ + {/* Right: Meta / Facebook Automation */} +
+
+

Publicador a Fanpage de Facebook

+ + Listo para Publicar + +
+ +
+

✨ Plantilla de Copy Vendedor Integrada:

+

+ "✨ ALMEIRA STORE • NUEVA COLECCIÓN EXCLUSIVA ✨
+ 👟 NIKE DUNK LOW PANDA
+ 📏 Tallas: 37 a 43 | 💎 Precio: $120.000 COP
+ 🚚 ¡Entrega a Domicilio en Cali con Pago Contraentrega!" +

+
+ + + Publicar Producto de Prueba en Facebook + + +
+
+
+ ); +} diff --git a/zapply-app/src/app/admin/pedidos/page.tsx b/zapply-app/src/app/admin/pedidos/page.tsx new file mode 100644 index 0000000..3f01444 --- /dev/null +++ b/zapply-app/src/app/admin/pedidos/page.tsx @@ -0,0 +1,275 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { ShoppingBag, Truck, CheckCircle2, Clock, Phone, MapPin, Search, MessageCircle, Send, ShieldCheck, UserCheck } from 'lucide-react'; +import { Order, OrderItem } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminOrdersPage() { + const [orders, setOrders] = useState([]); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState('all'); + + useEffect(() => { + fetch('/api/orders') + .then((r) => r.json()) + .then((d) => d.success && setOrders(d.orders)) + .catch(() => {}); + }, []); + + const handleStatusChange = async (orderId: string, newStatus: Order['status']) => { + setOrders((prev) => + prev.map((o) => (o.id === orderId ? { ...o, status: newStatus } : o)) + ); + + await fetch('/api/orders', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: orderId, status: newStatus }), + }).catch(() => {}); + }; + + const handleNotifySupplier = (order: Order, item: OrderItem) => { + const supplierPhone = item.supplierPhone || '573134848203'; + const supplierName = item.supplierName || 'Proveedor Mayorista'; + const supplierCost = item.supplierPrice ? formatCOP(item.supplierPrice) : 'Precio Mayorista'; + + const message = `👋 Hola *${supplierName}*!\n\nPor favor *sepárame este par* para despacho inmediato:\n\n👟 *Modelo:* ${item.productName}\n📏 *Talla:* ${item.size}\n📦 *Cantidad:* ${item.quantity} par(es)\n💵 *Costo Base:* ${supplierCost}\n\n🏷️ *Orden Interna:* #${order.id}\n📍 *Ciudad Destino:* ${order.cityName}\n\n¿Me confirmas si lo tienes listo para recoger / enviar? ¡Muchas gracias!`; + + const url = `https://wa.me/${supplierPhone}?text=${encodeURIComponent(message)}`; + window.open(url, '_blank'); + + if (order.status === 'pending' || order.status === 'deposit_received') { + handleStatusChange(order.id, 'supplier_notified'); + } + }; + + const getStatusBadge = (status: Order['status']) => { + switch (status) { + case 'pending': + return Pendiente Confirmar; + case 'deposit_received': + return Separación $10k Pagada; + case 'supplier_notified': + return Proveedor Notificado; + case 'dispatched': + return En Ruta con Mensajero; + case 'delivered': + return Entregado & Cobrado; + case 'cancelled': + return Cancelado; + } + }; + + const filteredOrders = orders.filter((o) => { + const matchesSearch = + o.customerName.toLowerCase().includes(search.toLowerCase()) || + o.customerPhone.includes(search) || + o.cityName.toLowerCase().includes(search.toLowerCase()) || + o.id.toLowerCase().includes(search.toLowerCase()); + + if (!matchesSearch) return false; + if (statusFilter !== 'all' && o.status !== statusFilter) return false; + return true; + }); + + return ( +
+ {/* Header */} +
+

+ + Gestión de Pedidos & Separación con Proveedores ({orders.length}) +

+

+ Control logístico de pedidos contraentrega, cobro de anticipos de $10.000 COP y notificación inmediata de separación al proveedor vía WhatsApp. +

+
+ + {/* Toolbar */} +
+
+ + + + +
+ +
+ setSearch(e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-emerald-400" + /> +
+
+ + {filteredOrders.length === 0 ? ( +
+
+ +
+

No hay pedidos en esta sección

+

+ Cuando los clientes hagan un pedido en la tienda web o por WhatsApp, aparecerán aquí con el botón para separar inmediatamente con el proveedor correspondiente. +

+
+ ) : ( +
+ {filteredOrders.map((order) => ( +
+
+
+ Orden #{order.id} + • {new Date(order.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} +
+ {getStatusBadge(order.status)} +
+ +
+
+ + Cliente & Entrega (24 Horas) + +

{order.customerName}

+

+ {order.customerPhone} +

+

+ {order.address} ({order.cityName}) +

+
+ +
+ + Zapatillas & Proveedor Asignado: + +
+ {order.items.map((it, idx) => { + const suppName = it.supplierName || 'DIFUSION JOVIC STORE'; + return ( +
+
+
+

{it.productName}

+

+ Talla {it.size} • Cant: {it.quantity} +

+
+ + Prov: {suppName} + +
+ + +
+ ); + })} +
+
+ +
+ + Cobro & Pagos Contraentrega + +
+

+ Total de la Orden: + {formatCOP(order.totalAmount)} +

+ {order.depositAmount > 0 ? ( + <> +

+ Anticipo / Separación: + {formatCOP(order.depositAmount)} +

+

+ Saldo al Mensajero: + {formatCOP(order.balanceDue)} +

+ + ) : ( +

+ 100% Contraentrega al recibir +

+ )} +
+
+
+ +
+ Método: {order.paymentMethodName} + +
+ + + + +
+
+
+ ))} +
+ )} +
+ ); +} diff --git a/zapply-app/src/app/admin/productos/page.tsx b/zapply-app/src/app/admin/productos/page.tsx new file mode 100644 index 0000000..ca269a9 --- /dev/null +++ b/zapply-app/src/app/admin/productos/page.tsx @@ -0,0 +1,472 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Package, Plus, Eye, EyeOff, Check, X, Sparkles, Filter, Phone, MessageCircle, Truck } from 'lucide-react'; +import { Product, Supplier } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_SUPPLIERS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; + +export default function AdminProductsPage() { + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [suppliers, setSuppliers] = useState(INITIAL_SUPPLIERS); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [supplierFilter, setSupplierFilter] = useState('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New product form + const [name, setName] = useState(''); + const [brand, setBrand] = useState('Nike'); + const [selectedSupplierId, setSelectedSupplierId] = useState('sup-1'); + const [supplierPrice, setSupplierPrice] = useState('90000'); + const [retailPrice, setRetailPrice] = useState('125000'); + const [sizesInput, setSizesInput] = useState('37, 38, 39, 40, 41, 42, 43'); + const [imageUrl, setImageUrl] = useState( + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80' + ); + const [category, setCategory] = useState('Sneakers / Urbano'); + const [isActiveNew, setIsActiveNew] = useState(true); + + useEffect(() => { + fetch('/api/products?all=true') + .then((r) => r.json()) + .then((d) => d.success && setProducts(d.products)) + .catch(() => {}); + }, []); + + const handleToggleProductStatus = async (product: Product) => { + const newStatus = product.isActive === false ? true : false; + + setProducts((prev) => + prev.map((p) => (p.id === product.id ? { ...p, isActive: newStatus } : p)) + ); + + try { + const res = await fetch('/api/products', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + id: product.id, + updates: { isActive: newStatus }, + }), + }); + + const data = await res.json(); + if (data.success) { + setToastMessage( + `Zapatilla "${product.name}" ahora está ${newStatus ? '🟢 ACTIVA (Visible en la tienda)' : '⚪ INACTIVA (Oculta de la tienda)'}.` + ); + } + } catch (e) { + console.error('Error toggling status:', e); + } + }; + + const handleContactSupplier = (product: Product) => { + const phone = product.supplierPhone || '573134848203'; + const suppName = product.supplierName || 'Proveedor Mayorista'; + const text = encodeURIComponent( + `Hola ${suppName}! 👋 Consulta sobre disponibilidad del modelo *${product.name}* (Costo base: ${formatCOP(product.supplierPrice)}).` + ); + window.open(`https://wa.me/${phone}?text=${text}`, '_blank'); + }; + + const handleCreateProduct = async (e: React.FormEvent) => { + e.preventDefault(); + const sizes = sizesInput + .split(',') + .map((s) => s.trim()) + .filter(Boolean); + + const chosenSupplier = suppliers.find((s) => s.id === selectedSupplierId) || suppliers[0]; + + const newProd: Product = { + id: `snk-${Date.now()}`, + name, + brand, + supplierPrice: parseInt(supplierPrice, 10) || 90000, + retailPrice: parseInt(retailPrice, 10) || 125000, + originalPrice: Math.round((parseInt(retailPrice, 10) || 125000) * 1.35), + sizes, + images: [imageUrl], + description: 'Zapatillas de alta calidad garantizada para entrega inmediata.', + category, + inStock: true, + isActive: isActiveNew, + originBadge: 'Bodega Central', + supplierId: chosenSupplier.id, + supplierName: chosenSupplier.name, + supplierPhone: chosenSupplier.phone, + }; + + const res = await fetch('/api/products', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newProd), + }); + const data = await res.json(); + if (data.success) { + setProducts((prev) => [data.product, ...prev]); + setIsModalOpen(false); + setName(''); + setToastMessage(`✨ "${newProd.name}" registrada con proveedor [${chosenSupplier.name}].`); + } + }; + + const filtered = products.filter((p) => { + const matchesSearch = + p.name.toLowerCase().includes(search.toLowerCase()) || + p.brand.toLowerCase().includes(search.toLowerCase()) || + (p.supplierName && p.supplierName.toLowerCase().includes(search.toLowerCase())); + + if (!matchesSearch) return false; + if (statusFilter === 'active' && p.isActive === false) return false; + if (statusFilter === 'inactive' && p.isActive !== false) return false; + if (supplierFilter !== 'all' && p.supplierName !== supplierFilter) return false; + return true; + }); + + const activeCount = products.filter((p) => p.isActive !== false).length; + const inactiveCount = products.filter((p) => p.isActive === false).length; + + return ( +
+ {/* Header */} +
+
+

+ + Catálogo General de Zapatillas & Proveedores ({products.length}) +

+

+ Visualiza cada modelo con su proveedor asignado, costo mayorista y activa/inactiva publicaciones para la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* Filters & Search Toolbar */} +
+ {/* Status filter pills */} +
+ + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-emerald-400" + /> +
+
+ + {/* Products Table */} +
+
+ + + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((prod) => { + const isActive = prod.isActive !== false; + const margin = prod.retailPrice - prod.supplierPrice; + const suppName = prod.supplierName || 'DIFUSION JOVIC STORE'; + const suppPhone = prod.supplierPhone || '573134848203'; + + return ( + + {/* Estado Toggle Button */} + + + {/* Product Name & Image */} + + + {/* Supplier Column */} + + + + + + + + + + + ); + }) + )} + +
Estado PublicaciónProductoProveedor Asignado (Interno)MarcaCosto BasePrecio VentaMargen GananciaTallas
+ No hay zapatillas que coincidan con el filtro seleccionado. +
+ + + +
+

{prod.name}

+ {prod.category} +
+
+
+ + 🏢 {suppName} + + +
+
{prod.brand}{formatCOP(prod.supplierPrice)}{formatCOP(prod.retailPrice)} + + +{formatCOP(margin)} + + +
+ {prod.sizes.map((s) => ( + + {s} + + ))} +
+
+
+
+ + {/* Modal Add Product */} + {isModalOpen && ( +
+
+

Registrar Nueva Zapatilla

+ +
+
+ + setName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ + {/* Supplier Selection */} +
+ + +

+ Este proveedor recibirá la notificación para separar el par cuando se haga un pedido. +

+
+ +
+
+ + +
+ +
+ + setCategory(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+
+ + setSupplierPrice(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setRetailPrice(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setSizesInput(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setImageUrl(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/zapply-app/src/app/admin/usuarios/page.tsx b/zapply-app/src/app/admin/usuarios/page.tsx new file mode 100644 index 0000000..49b0aa5 --- /dev/null +++ b/zapply-app/src/app/admin/usuarios/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Users, UserPlus, Shield, ShieldCheck, UserCheck, MessageCircle, Mail, Phone, MapPin, Eye, EyeOff, Trash2, Edit, Check, X } from 'lucide-react'; +import { User } from '@/types'; + +export default function AdminUsersPage() { + const [users, setUsers] = useState([]); + const [search, setSearch] = useState(''); + const [roleFilter, setRoleFilter] = useState<'all' | 'admin' | 'operator' | 'customer'>('all'); + const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all'); + const [isModalOpen, setIsModalOpen] = useState(false); + const [toastMessage, setToastMessage] = useState(null); + + // New user modal form + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [role, setRole] = useState<'admin' | 'operator' | 'customer'>('operator'); + + useEffect(() => { + fetchUsers(); + }, []); + + const fetchUsers = async () => { + try { + const res = await fetch('/api/users'); + const data = await res.json(); + if (data.success) { + setUsers(data.users); + } + } catch (e) { + console.error(e); + } + }; + + const handleToggleStatus = async (user: User) => { + const newStatus = !user.isActive; + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, isActive: newStatus } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { isActive: newStatus } }), + }); + setToastMessage(`Estado de ${user.name} actualizado a ${newStatus ? '🟢 ACTIVO' : '⚪ INACTIVO'}.`); + } catch (e) { + console.error(e); + } + }; + + const handleChangeRole = async (user: User, newRole: 'admin' | 'operator' | 'customer') => { + setUsers((prev) => prev.map((u) => (u.id === user.id ? { ...u, role: newRole } : u))); + + try { + await fetch('/api/users', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id: user.id, updates: { role: newRole } }), + }); + setToastMessage(`Rol de ${user.name} actualizado a [${newRole.toUpperCase()}].`); + } catch (e) { + console.error(e); + } + }; + + const handleDeleteUser = async (id: string, name: string) => { + if (!confirm(`¿Estás seguro de eliminar al usuario ${name}?`)) return; + + setUsers((prev) => prev.filter((u) => u.id !== id)); + try { + await fetch(`/api/users?id=${id}`, { method: 'DELETE' }); + setToastMessage(`Usuario ${name} eliminado.`); + } catch (e) { + console.error(e); + } + }; + + const handleCreateUser = async (e: React.FormEvent) => { + e.preventDefault(); + try { + const res = await fetch('/api/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, phone, city, address, role }), + }); + const data = await res.json(); + if (data.success) { + setUsers((prev) => [data.user, ...prev]); + setIsModalOpen(false); + setName(''); + setEmail(''); + setPhone(''); + setAddress(''); + setToastMessage(`✨ Usuario "${data.user.name}" registrado con éxito.`); + } else { + alert(data.error); + } + } catch (e) { + console.error(e); + } + }; + + const handleWhatsApp = (user: User) => { + const cleanPhone = user.phone.startsWith('57') ? user.phone : `57${user.phone}`; + const text = encodeURIComponent(`Hola ${user.name}! Te escribimos del equipo de Zapply Cali 👋`); + window.open(`https://wa.me/${cleanPhone}?text=${text}`, '_blank'); + }; + + const filtered = users.filter((u) => { + const matchSearch = + u.name.toLowerCase().includes(search.toLowerCase()) || + u.email.toLowerCase().includes(search.toLowerCase()) || + u.phone.includes(search) || + (u.city && u.city.toLowerCase().includes(search.toLowerCase())); + + if (!matchSearch) return false; + if (roleFilter !== 'all' && u.role !== roleFilter) return false; + if (statusFilter === 'active' && !u.isActive) return false; + if (statusFilter === 'inactive' && u.isActive) return false; + return true; + }); + + const adminsCount = users.filter((u) => u.role === 'admin').length; + const operatorsCount = users.filter((u) => u.role === 'operator').length; + const customersCount = users.filter((u) => u.role === 'customer').length; + + return ( +
+ {/* Header */} +
+
+

+ + Control de Usuarios, Roles & Registro ({users.length}) +

+

+ Administra los accesos de administradores, operadores de logística y clientes registrados de la tienda. +

+
+ + +
+ + {toastMessage && ( +
+ {toastMessage} + +
+ )} + + {/* KPI Stats Cards */} +
+
+
+ +
+
+

Administradores

+

{adminsCount}

+
+
+ +
+
+ +
+
+

Operadores Logísticos

+

{operatorsCount}

+
+
+ +
+
+ +
+
+

Clientes Registrados

+

{customersCount}

+
+
+
+ + {/* Filters Toolbar */} +
+ {/* Role Pills */} +
+ + + + +
+ + {/* Search */} +
+ setSearch(e.target.value)} + className="w-full bg-slate-900 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-white outline-hidden focus:border-emerald-400" + /> +
+
+ + {/* Users Table */} +
+
+ + + + + + + + + + + + + + {filtered.length === 0 ? ( + + + + ) : ( + filtered.map((user) => { + return ( + + {/* Active Status Toggle */} + + + {/* User Avatar & Name */} + + + {/* Contact */} + + + {/* City */} + + + {/* Role Dropdown */} + + + {/* Last Login */} + + + {/* Actions */} + + + ); + }) + )} + +
EstadoUsuarioContacto DirectoCiudad / DirecciónRol & PermisosÚltimo AccesoAcciones
+ No se encontraron usuarios con el filtro seleccionado. +
+ + +
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+ {user.email} +
+
+
+ +
+
+
+ {user.city || 'Cali'} + {user.address &&

{user.address}

} +
+
+ + + {user.lastLogin || user.createdAt} + + +
+
+
+ + {/* Modal Create User */} + {isModalOpen && ( +
+
+

Registrar Nuevo Usuario / Operador

+ +
+
+ + setName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setEmail(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+
+ + setPhone(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + setCity(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+
+ +
+ + setAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden" + /> +
+ +
+ + +
+ +
+ + +
+
+
+
+ )} +
+ ); +} diff --git a/zapply-app/src/app/api/auth/login/route.ts b/zapply-app/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..a2ae66e --- /dev/null +++ b/zapply-app/src/app/api/auth/login/route.ts @@ -0,0 +1,29 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function POST(request: Request) { + try { + const { identifier } = await request.json(); + if (!identifier) { + return NextResponse.json({ success: false, error: 'Ingresa tu correo o celular' }, { status: 400 }); + } + const user = dataService.authenticate(identifier); + if (!user) { + return NextResponse.json( + { success: false, error: 'Usuario no encontrado. Verifica tu correo o celular.' }, + { status: 404 } + ); + } + if (!user.isActive) { + return NextResponse.json( + { success: false, error: 'Esta cuenta se encuentra inactiva. Contacta a soporte.' }, + { status: 403 } + ); + } + + dataService.updateUser(user.id, { lastLogin: 'Justo ahora' }); + return NextResponse.json({ success: true, user }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/auth/register/route.ts b/zapply-app/src/app/api/auth/register/route.ts new file mode 100644 index 0000000..62b2a63 --- /dev/null +++ b/zapply-app/src/app/api/auth/register/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function POST(request: Request) { + try { + const { name, email, phone, city, address } = await request.json(); + if (!name || !email || !phone) { + return NextResponse.json( + { success: false, error: 'Nombre, correo y celular son obligatorios' }, + { status: 400 } + ); + } + + const existing = dataService.authenticate(email) || dataService.authenticate(phone); + if (existing) { + return NextResponse.json( + { success: false, error: 'Ya existe una cuenta con este correo o celular' }, + { status: 409 } + ); + } + + const newUser: User = { + id: `usr-${Date.now()}`, + name, + email, + phone, + city: city || 'Cali', + address: address || '', + role: 'customer', + isActive: true, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + lastLogin: 'Justo ahora', + }; + + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/cities/route.ts b/zapply-app/src/app/api/cities/route.ts new file mode 100644 index 0000000..3ecd601 --- /dev/null +++ b/zapply-app/src/app/api/cities/route.ts @@ -0,0 +1,27 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const cities = dataService.getCities(); + return NextResponse.json({ success: true, cities }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateCity(id, updates); + return NextResponse.json({ success: true, city: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const created = dataService.addCity(body); + return NextResponse.json({ success: true, city: created }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/orders/route.ts b/zapply-app/src/app/api/orders/route.ts new file mode 100644 index 0000000..9c996b6 --- /dev/null +++ b/zapply-app/src/app/api/orders/route.ts @@ -0,0 +1,30 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { sendWhatsAppMessage, buildOrderConfirmationMessage } from '@/lib/evolution-api'; + +export async function GET() { + const orders = dataService.getOrders(); + return NextResponse.json({ success: true, orders }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newOrder = dataService.createOrder(body); + + // Enviar confirmación por WhatsApp en background si tiene teléfono válido + if (newOrder.customerPhone) { + try { + const msg = buildOrderConfirmationMessage(newOrder); + // Intentar enviar WhatsApp + await sendWhatsAppMessage(newOrder.customerPhone, msg); + } catch (waErr) { + console.warn('No se pudo enviar WhatsApp automático:', waErr); + } + } + + return NextResponse.json({ success: true, order: newOrder }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/payment-methods/route.ts b/zapply-app/src/app/api/payment-methods/route.ts new file mode 100644 index 0000000..b49c62d --- /dev/null +++ b/zapply-app/src/app/api/payment-methods/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const methods = dataService.getPaymentMethods(); + return NextResponse.json({ success: true, paymentMethods: methods }); +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updatePaymentMethod(id, updates); + return NextResponse.json({ success: true, paymentMethod: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/products/route.ts b/zapply-app/src/app/api/products/route.ts new file mode 100644 index 0000000..9ebf898 --- /dev/null +++ b/zapply-app/src/app/api/products/route.ts @@ -0,0 +1,46 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const includeAll = searchParams.get('all') === 'true'; + + let products = dataService.getProducts(); + if (!includeAll) { + products = products.filter((p) => p.isActive !== false); + } + + return NextResponse.json({ success: true, products }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newProduct = dataService.addProduct({ + ...body, + isActive: body.isActive !== undefined ? body.isActive : true, + }); + return NextResponse.json({ success: true, product: newProduct }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const { id, updates } = body; + if (!id) { + return NextResponse.json({ success: false, error: 'ID de producto requerido' }, { status: 400 }); + } + + const updated = dataService.updateProduct(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Producto no encontrado' }, { status: 404 }); + } + + return NextResponse.json({ success: true, product: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/publish/facebook/route.ts b/zapply-app/src/app/api/publish/facebook/route.ts new file mode 100644 index 0000000..d2db7a3 --- /dev/null +++ b/zapply-app/src/app/api/publish/facebook/route.ts @@ -0,0 +1,12 @@ +import { NextResponse } from 'next/server'; +import { publishToFacebookPage } from '@/lib/facebook-publisher'; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const result = await publishToFacebookPage(body); + return NextResponse.json(result); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/zapply-app/src/app/api/settings/route.ts b/zapply-app/src/app/api/settings/route.ts new file mode 100644 index 0000000..6073d91 --- /dev/null +++ b/zapply-app/src/app/api/settings/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; + +export async function GET() { + const settings = dataService.getSettings(); + return NextResponse.json({ success: true, settings }); +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const updated = dataService.updateSettings(body); + return NextResponse.json({ success: true, settings: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/users/route.ts b/zapply-app/src/app/api/users/route.ts new file mode 100644 index 0000000..8b62fad --- /dev/null +++ b/zapply-app/src/app/api/users/route.ts @@ -0,0 +1,57 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { User } from '@/types'; + +export async function GET() { + const users = dataService.getUsers(); + return NextResponse.json({ success: true, users }); +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + const newUser: User = { + id: `usr-${Date.now()}`, + name: body.name, + email: body.email, + phone: body.phone, + city: body.city || 'Cali', + address: body.address || '', + role: body.role || 'customer', + isActive: body.isActive !== false, + createdAt: new Date().toISOString().split('T')[0], + totalOrders: 0, + }; + const saved = dataService.addUser(newUser); + return NextResponse.json({ success: true, user: saved }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function PUT(request: Request) { + try { + const { id, updates } = await request.json(); + const updated = dataService.updateUser(id, updates); + if (!updated) { + return NextResponse.json({ success: false, error: 'Usuario no encontrado' }, { status: 404 }); + } + return NextResponse.json({ success: true, user: updated }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} + +export async function DELETE(request: Request) { + try { + const { searchParams } = new URL(request.url); + const id = searchParams.get('id'); + if (!id) { + return NextResponse.json({ success: false, error: 'ID requerido' }, { status: 400 }); + } + const deleted = dataService.deleteUser(id); + return NextResponse.json({ success: deleted }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 400 }); + } +} diff --git a/zapply-app/src/app/api/webhook/whatsapp/route.ts b/zapply-app/src/app/api/webhook/whatsapp/route.ts new file mode 100644 index 0000000..3227db1 --- /dev/null +++ b/zapply-app/src/app/api/webhook/whatsapp/route.ts @@ -0,0 +1,60 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { parseSupplierMessage } from '@/lib/gemini-parser'; +import { SupplierPost } from '@/types'; + +export async function GET() { + const posts = dataService.getSupplierPosts(); + return NextResponse.json({ success: true, posts }); +} + +export async function POST(request: Request) { + try { + const payload = await request.json(); + console.log('📥 Webhook Evolution API recibido:', JSON.stringify(payload).slice(0, 300)); + + const data = payload.data || payload; + + const messageContent = + data.message?.conversation || + data.message?.extendedTextMessage?.text || + data.message?.imageMessage?.caption || + data.text || + ''; + + const channelName = + data.pushName || + data.groupInfo?.subject || + (data.key?.remoteJid?.includes('g.us') ? 'Canal Mayorista Entrada' : 'Recepción Directa'); + + if (!messageContent || messageContent.trim().length < 5) { + return NextResponse.json({ success: true, ignored: 'Mensaje vacío o sin texto relevante' }); + } + + // Parsear con Gemini AI + const extracted = await parseSupplierMessage(messageContent); + + const newPost: SupplierPost = { + id: `post-${Date.now()}`, + channelName: data.groupInfo?.subject || channelName, + rawMessage: messageContent, + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: extracted, + status: 'pending_review', + receivedAt: 'Justo ahora', + }; + + dataService.addSupplierPost(newPost); + + return NextResponse.json({ + success: true, + message: 'Mensaje procesado con IA e ingresado al feed interno', + post: newPost, + }); + } catch (error: any) { + console.error('Error procesando webhook de WhatsApp:', error); + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/zapply-app/src/app/api/whatsapp-groups/route.ts b/zapply-app/src/app/api/whatsapp-groups/route.ts new file mode 100644 index 0000000..6f78a1c --- /dev/null +++ b/zapply-app/src/app/api/whatsapp-groups/route.ts @@ -0,0 +1,104 @@ +import { NextResponse } from 'next/server'; +import { dataService } from '@/lib/data-service'; +import { MonitoredWhatsAppGroup } from '@/types'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url); + const fetchLive = searchParams.get('fetchLive') === 'true'; + + const localGroups = dataService.getMonitoredGroups(); + + if (!fetchLive) { + return NextResponse.json({ + success: true, + groups: localGroups, + }); + } + + // Consultar grupos en vivo desde Evolution API + try { + const response = await fetch( + `${EVOLUTION_API_URL}/group/fetchAllGroups/${EVOLUTION_INSTANCE_NAME}?getParticipants=false`, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + + const liveGroups = await response.json(); + + if (Array.isArray(liveGroups)) { + const merged: MonitoredWhatsAppGroup[] = liveGroups.map((lg: any) => { + const jid = lg.id || lg.jid; + const name = lg.subject || lg.name || 'Grupo Sin Nombre'; + const existing = localGroups.find((g) => g.jid === jid || g.name.toLowerCase() === name.toLowerCase()); + + return { + id: existing?.id || `grp-${jid.replace(/\D/g, '').slice(-6)}`, + jid, + name, + isMonitored: existing ? existing.isMonitored : false, + supplierId: existing?.supplierId, + supplierName: existing?.supplierName || name, + profitMarginOverride: existing?.profitMarginOverride || 35, + autoPublish: existing?.autoPublish ?? true, + participantsCount: lg.size || (lg.participants ? lg.participants.length : undefined), + notes: existing?.notes || '', + }; + }); + + // Asegurar que los locales que no vinieron en live sigan presentes + localGroups.forEach((lg) => { + if (!merged.some((m) => m.jid === lg.jid || m.id === lg.id)) { + merged.unshift(lg); + } + }); + + return NextResponse.json({ + success: true, + isLive: true, + totalLive: liveGroups.length, + groups: merged, + }); + } + } catch (err: any) { + console.warn('No se pudo conectar con Evolution API en vivo:', err.message); + } + + return NextResponse.json({ + success: true, + isLive: false, + groups: localGroups, + }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + + if (body.action === 'toggle') { + const { idOrJid, isMonitored } = body; + const updated = dataService.toggleGroupMonitoring(idOrJid, isMonitored); + return NextResponse.json({ success: true, group: updated }); + } + + if (Array.isArray(body.groups)) { + const saved = dataService.saveMonitoredGroups(body.groups); + return NextResponse.json({ success: true, groups: saved }); + } + + return NextResponse.json({ success: false, error: 'Datos no válidos' }, { status: 400 }); + } catch (error: any) { + return NextResponse.json({ success: false, error: error.message }, { status: 500 }); + } +} diff --git a/zapply-app/src/app/checkout/page.tsx b/zapply-app/src/app/checkout/page.tsx new file mode 100644 index 0000000..ea26be7 --- /dev/null +++ b/zapply-app/src/app/checkout/page.tsx @@ -0,0 +1,476 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { ArrowLeft, CheckCircle2, ShieldCheck, Truck, Zap, QrCode, Phone, MapPin, User, MessageCircle, ExternalLink, CreditCard } from 'lucide-react'; +import { City, PaymentMethod, Order, StoreSettings } from '@/types'; +import { INITIAL_CITIES, INITIAL_PAYMENT_METHODS, INITIAL_PRODUCTS } from '@/lib/data-service'; +import { formatCOP } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; +import confetti from 'canvas-confetti'; + +export default function CheckoutPage() { + const { currentBrand } = useBrand(); + + const [customerName, setCustomerName] = useState(''); + const [customerPhone, setCustomerPhone] = useState(''); + const [address, setAddress] = useState(''); + const [neighborhood, setNeighborhood] = useState(''); + const [notes, setNotes] = useState(''); + + const [cities, setCities] = useState(INITIAL_CITIES); + const [paymentMethods, setPaymentMethods] = useState(INITIAL_PAYMENT_METHODS); + const [selectedCityId, setSelectedCityId] = useState('city-cali'); + const [selectedPaymentId, setSelectedPaymentId] = useState('pay-deposit-10k'); + const [storeSettings, setStoreSettings] = useState(null); + + const [checkoutItems] = useState>([ + { + productId: INITIAL_PRODUCTS[0].id, + productName: INITIAL_PRODUCTS[0].name, + brand: INITIAL_PRODUCTS[0].brand, + size: '39', + quantity: 1, + price: INITIAL_PRODUCTS[0].retailPrice, + image: INITIAL_PRODUCTS[0].images[0], + }, + ]); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [orderCompleted, setOrderCompleted] = useState(null); + + useEffect(() => { + fetch('/api/cities') + .then((r) => r.json()) + .then((d) => d.success && setCities(d.cities)) + .catch(() => {}); + + fetch('/api/payment-methods') + .then((r) => r.json()) + .then((d) => d.success && setPaymentMethods(d.paymentMethods)) + .catch(() => {}); + + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => d.success && setStoreSettings(d.settings)) + .catch(() => {}); + }, []); + + const activeCity = cities.find((c) => c.id === selectedCityId) || cities[0]; + const activePayment = paymentMethods.find((p) => p.id === selectedPaymentId) || paymentMethods[0]; + + const subtotal = checkoutItems.reduce((acc, it) => acc + it.price * it.quantity, 0); + const shippingCost = activeCity.shippingCost; + const totalAmount = subtotal + shippingCost; + + const depositAmount = activePayment.requiresDeposit ? activePayment.depositAmount : 0; + const balanceDue = totalAmount - depositAmount; + + const officialWhatsapp = storeSettings?.whatsappNumber || '573167455877'; + const boldLink = storeSettings?.boldPaymentLink || 'https://bold.co/p/carlos-lasso'; + + const handleSubmitOrder = async (e: React.FormEvent) => { + e.preventDefault(); + if (!customerName || !customerPhone || !address) { + alert('Por favor completa tu nombre, celular y dirección para el despacho.'); + return; + } + + setIsSubmitting(true); + + try { + const orderPayload = { + customerName, + customerPhone, + address: `${address} - Barrio: ${neighborhood || 'Centro'}`, + cityId: activeCity.id, + cityName: activeCity.name, + items: checkoutItems, + subtotal, + shippingCost, + totalAmount, + depositAmount, + balanceDue, + paymentMethodId: activePayment.id, + paymentMethodName: activePayment.name, + notes, + }; + + const res = await fetch('/api/orders', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(orderPayload), + }); + + const data = await res.json(); + if (data.success) { + setOrderCompleted(data.order); + confetti({ + particleCount: 100, + spread: 70, + origin: { y: 0.6 }, + }); + } + } catch (err) { + console.error('Error creando orden:', err); + } finally { + setIsSubmitting(false); + } + }; + + const handleOpenWhatsAppOrder = (order: Order) => { + const text = `🎉 *CONFIRMACIÓN DE PEDIDO EN ${currentBrand.name} #${order.id}* 🎉 + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *Artículos:* +${order.items.map((i) => `• ${i.productName} (Talla ${i.size}) x${i.quantity} = ${formatCOP(i.price * i.quantity)}`).join('\n')} + +💰 *Total:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +¡Hola ${currentBrand.shortName}! Acabo de registrar mi pedido en la web. ¿Me confirman despacho por favor?`; + + window.open(`https://wa.me/${officialWhatsapp}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + if (orderCompleted) { + return ( +
+
+
+ +
+ +
+ + ¡Pedido Registrado con Éxito! + +

Orden #{orderCompleted.id}

+

+ Hemos recibido tu solicitud para entrega en {orderCompleted.cityName} con {currentBrand.name}. +

+
+ + {/* Bold.co or Nequi Separation Box */} + {orderCompleted.depositAmount > 0 ? ( +
+
+ + Paso 2: Realiza la separación de $10.000 COP +
+

+ Paga de inmediato con Link de Pago Bold.co (PSE / Tarjeta / Nequi) o transfiere a nuestra cuenta oficial: +

+ + {boldLink && ( + + + Pagar $10.000 COP con Bold.co (PSE / Tarjetas) + + + )} + +
+ 📱 Nequi / Daviplata: {storeSettings?.nequiAccount || '316 745 5877'} ({storeSettings?.accountHolder || 'Carlos Andrés Lasso'}) +
+

+ 🤝 Cancelas el saldo de {formatCOP(orderCompleted.balanceDue)} al recibir el paquete en tu casa. +

+
+ ) : ( +
+

+ Tu pedido quedó programado para entrega contraentrega en 24 horas. ¡Nos pondremos en contacto contigo por WhatsApp! +

+
+ )} + +
+ + + + Volver a la Tienda + +
+
+
+ ); + } + + return ( +
+
+ {/* Header */} +
+ + + Regresar a {currentBrand.name} + +
+ + Compra Segura & Garantizada +
+
+ +
+ {/* Left Column: Shipping & Payment Details (7 cols) */} +
+ {/* 1. Datos del Cliente */} +
+

+ + 1. Datos de Entrega +

+ +
+
+ + setCustomerName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-emerald-400 outline-hidden" + /> +
+
+ + setCustomerPhone(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-emerald-400 outline-hidden" + /> +
+
+ + {/* City Selection */} +
+ + +
+ +
+
+ + setAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-emerald-400 outline-hidden" + /> +
+
+ + setNeighborhood(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-sm text-white focus:border-emerald-400 outline-hidden" + /> +
+
+
+ + {/* 2. Método de Pago */} +
+

+ + 2. Selecciona tu Método de Pago +

+ +
+ {paymentMethods.map((method) => { + const isSelected = selectedPaymentId === method.id; + return ( +
setSelectedPaymentId(method.id)} + className={`p-4 rounded-2xl border transition-all cursor-pointer space-y-1.5 ${ + isSelected + ? `border-emerald-400 bg-emerald-950/20 shadow-md` + : 'border-slate-800 hover:border-slate-700 bg-slate-950' + }`} + > +
+
+
+ {isSelected &&
} +
+ {method.name} +
+ + {method.requiresDeposit && ( + + Separa con $10.000 + + )} +
+ +

{method.description}

+ + {isSelected && (method.accountInfo || (method.type === 'bold' && boldLink)) && ( +
+ {method.accountInfo &&

{method.accountInfo}

} + {method.type === 'bold' && boldLink && ( + + + Abrir Link de Pago Bold.co + + )} +
+ )} +
+ ); + })} +
+
+
+ + {/* Right Column: Summary (5 cols) */} +
+
+

Resumen del Pedido

+ + {/* Items */} +
+ {checkoutItems.map((item, i) => ( +
+ +
+

{item.productName}

+

Talla: {item.size} | Cant: {item.quantity}

+

+ {formatCOP(item.price * item.quantity)} +

+
+
+ ))} +
+ + {/* Breakdown */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Envío ({activeCity.name}): + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total a Pagar: + + {formatCOP(totalAmount)} + +
+ + {depositAmount > 0 && ( +
+
+ Separación por Bold / Nequi / Daviplata: + {formatCOP(depositAmount)} +
+
+ Saldo a pagar al mensajero: + {formatCOP(balanceDue)} +
+
+ )} + +
+
+ + Garantía en {activeCity.name}: +
+

+ {activeCity.firstExchangeFree + ? '1er Cambio de Talla 100% GRATIS (cambios posteriores con flete estándar).' + : 'Cambios de talla 100% garantizados (los costos de envío son asumidos por el cliente).'} +

+
+
+ + + +

+ Al confirmar, se guardará tu pedido y recibirás asistencia inmediata por WhatsApp oficial ({officialWhatsapp}) para el seguimiento de tu entrega en 24 horas. +

+
+
+ +
+
+ ); +} diff --git a/zapply-app/src/app/favicon.ico b/zapply-app/src/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/zapply-app/src/app/favicon.ico differ diff --git a/zapply-app/src/app/globals.css b/zapply-app/src/app/globals.css new file mode 100644 index 0000000..a2dc41e --- /dev/null +++ b/zapply-app/src/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/zapply-app/src/app/layout.tsx b/zapply-app/src/app/layout.tsx new file mode 100644 index 0000000..4272d68 --- /dev/null +++ b/zapply-app/src/app/layout.tsx @@ -0,0 +1,61 @@ +import type { Metadata, Viewport } from 'next'; +import { Geist, Geist_Mono } from 'next/font/google'; +import './globals.css'; +import { BrandProvider } from '@/context/BrandContext'; +import { AuthProvider } from '@/context/AuthContext'; + +const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], +}); + +const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], +}); + +export const viewport: Viewport = { + themeColor: '#10b981', + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false, + viewportFit: 'cover', +}; + +export const metadata: Metadata = { + title: 'Zapply Cali • Sneakers Express', + description: 'Tu calzado favorito con entrega express y pago contraentrega en 24 horas.', + manifest: '/manifest.json', + appleWebApp: { + capable: true, + statusBarStyle: 'black-translucent', + title: 'Zapply Cali', + }, + icons: { + icon: '/icon.svg', + apple: '/icon.svg', + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + + + + {children} + + + + + ); +} diff --git a/zapply-app/src/app/page.tsx b/zapply-app/src/app/page.tsx new file mode 100644 index 0000000..e4b60ff --- /dev/null +++ b/zapply-app/src/app/page.tsx @@ -0,0 +1,284 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Navbar } from '@/components/store/Navbar'; +import { FlashDealsBanner } from '@/components/store/FlashDealsBanner'; +import { CategoryPills } from '@/components/store/CategoryPills'; +import { ProductCard } from '@/components/store/ProductCard'; +import { ProductModal } from '@/components/store/ProductModal'; +import { CartDrawer } from '@/components/store/CartDrawer'; +import { CitySelectorModal } from '@/components/store/CitySelectorModal'; +import { MobileBottomDock } from '@/components/mobile/MobileBottomDock'; +import { MobileInstallBanner } from '@/components/mobile/MobileInstallBanner'; +import { AuthModal } from '@/components/auth/AuthModal'; +import { Product, City, CartItem } from '@/types'; +import { INITIAL_PRODUCTS, INITIAL_CITIES } from '@/lib/data-service'; +import { Sparkles, ShieldCheck, Truck, RefreshCw, Zap } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export default function StoreHomePage() { + const { currentBrand } = useBrand(); + const [products, setProducts] = useState(INITIAL_PRODUCTS); + const [cities, setCities] = useState(INITIAL_CITIES); + const [selectedCity, setSelectedCity] = useState(INITIAL_CITIES[0]); // Cali + const [activeCategory, setActiveCategory] = useState('all'); + const [searchQuery, setSearchQuery] = useState(''); + + // Modals & Drawers state + const [selectedProduct, setSelectedProduct] = useState(null); + const [isCartOpen, setIsCartOpen] = useState(false); + const [isCityModalOpen, setIsCityModalOpen] = useState(false); + const [isInstallModalOpen, setIsInstallModalOpen] = useState(false); + const [cartItems, setCartItems] = useState([]); + + const cartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + useEffect(() => { + fetch('/api/products') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.products?.length > 0) { + setProducts(data.products); + } + }) + .catch((e) => console.log('Usando catálogo inicial:', e)); + + fetch('/api/cities') + .then((res) => res.json()) + .then((data) => { + if (data.success && data.cities?.length > 0) { + setCities(data.cities); + const defaultCali = data.cities.find((c: City) => c.name.toLowerCase().includes('cali')); + if (defaultCali) setSelectedCity(defaultCali); + } + }) + .catch((e) => console.log('Usando ciudades iniciales:', e)); + }, []); + + const filteredProducts = products.filter((p) => { + if (searchQuery.trim()) { + const q = searchQuery.toLowerCase(); + const matchName = p.name.toLowerCase().includes(q); + const matchBrand = p.brand.toLowerCase().includes(q); + const matchSize = p.sizes.some((s) => s.includes(q)); + if (!matchName && !matchBrand && !matchSize) return false; + } + + if (activeCategory === 'flash') return p.isFlashDeal; + if (activeCategory === 'under120') return p.retailPrice <= 120000; + if (activeCategory !== 'all') { + return p.brand.toLowerCase() === activeCategory.toLowerCase(); + } + return true; + }); + + const handleAddToCart = (product: Product, size: string) => { + setCartItems((prev) => { + const existingIdx = prev.findIndex( + (item) => item.product.id === product.id && item.selectedSize === size + ); + if (existingIdx > -1) { + const next = [...prev]; + next[existingIdx].quantity += 1; + return next; + } + return [...prev, { product, selectedSize: size, quantity: 1 }]; + }); + setIsCartOpen(true); + }; + + const handleRemoveFromCart = (productId: string, size: string) => { + setCartItems((prev) => + prev.filter((item) => !(item.product.id === productId && item.selectedSize === size)) + ); + }; + + const handleUpdateQuantity = (productId: string, size: string, delta: number) => { + setCartItems((prev) => + prev + .map((item) => { + if (item.product.id === productId && item.selectedSize === size) { + const newQty = item.quantity + delta; + return newQty > 0 ? { ...item, quantity: newQty } : null; + } + return item; + }) + .filter(Boolean) as CartItem[] + ); + }; + + const totalCartCount = cartItems.reduce((acc, item) => acc + item.quantity, 0); + + return ( +
+ {/* Navigation Header */} + setIsCartOpen(true)} + selectedCity={selectedCity} + onOpenCitySelector={() => setIsCityModalOpen(true)} + searchQuery={searchQuery} + onSearchChange={setSearchQuery} + /> + + {/* Main Container */} +
+ {/* Flash Deals Hero Banner */} + + + {/* Value Props Strip */} +
+
+
+ +
+
+

Entrega en 24 Horas

+

Directo en Cali

+
+
+ +
+
+ +
+
+

Pago Contraentrega

+

Cancelas al recibir

+
+
+ +
+
+ +
+
+

Separa con $10.000

+

Aparta tu talla

+
+
+ +
+
+ +
+
+

Garantía Total

+

Cambio asegurado

+
+
+
+ + {/* Category & Brand Filters */} +
+
+

+ + Colección de Calzado & Sneakers +

+ + {filteredProducts.length} {filteredProducts.length === 1 ? 'modelo' : 'modelos'} + +
+ + +
+ + {/* Product Grid */} + {filteredProducts.length === 0 ? ( +
+
+ +
+

No encontramos zapatillas con ese criterio

+

Intenta buscar otra marca o restablecer los filtros.

+ +
+ ) : ( +
+ {filteredProducts.map((product) => ( + handleAddToCart(p, size)} + /> + ))} +
+ )} +
+ + {/* Footer */} +
+
+
+
+ {currentBrand.logo.iconText} +
+ {currentBrand.name} +
+

© 2026 {currentBrand.name}. Despachos urbanos y nacionales con pago contraentrega.

+
+ + {currentBrand.badge} +
+
+
+ + {/* Modals & Drawers */} + setSelectedProduct(null)} + onAddToCart={handleAddToCart} + selectedCity={selectedCity} + /> + + setIsCartOpen(false)} + cartItems={cartItems} + onRemoveItem={handleRemoveFromCart} + onUpdateQuantity={handleUpdateQuantity} + selectedCity={selectedCity} + onOpenCitySelector={() => { + setIsCartOpen(false); + setIsCityModalOpen(true); + }} + /> + + setIsCityModalOpen(false)} + cities={cities} + selectedCity={selectedCity} + onSelectCity={setSelectedCity} + /> + + {/* Mobile App Dock & Install Banner */} + setIsCartOpen(true)} + onOpenInstallModal={() => setIsInstallModalOpen(true)} + /> + + setIsInstallModalOpen(false)} + /> + + {/* User Auth Modal */} + +
+ ); +} diff --git a/zapply-app/src/components/auth/AuthModal.tsx b/zapply-app/src/components/auth/AuthModal.tsx new file mode 100644 index 0000000..6d4662e --- /dev/null +++ b/zapply-app/src/components/auth/AuthModal.tsx @@ -0,0 +1,255 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, User, Lock, Mail, Phone, MapPin, Sparkles, LogIn, UserPlus, Shield, LogOut } from 'lucide-react'; +import { useAuth } from '@/context/AuthContext'; +import { useBrand } from '@/context/BrandContext'; +import Link from 'next/link'; + +export const AuthModal: React.FC = () => { + const { user, login, register, logout, isAuthModalOpen, closeAuthModal } = useAuth(); + const { currentBrand } = useBrand(); + + const [mode, setMode] = useState<'login' | 'register'>('login'); + const [identifier, setIdentifier] = useState(''); + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [phone, setPhone] = useState(''); + const [city, setCity] = useState('Cali'); + const [address, setAddress] = useState(''); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + if (!isAuthModalOpen) return null; + + const handleLoginSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await login(identifier); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al iniciar sesión'); + } + }; + + const handleRegisterSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + setLoading(true); + const res = await register({ name, email, phone, city, address }); + setLoading(false); + if (!res.success) { + setError(res.error || 'Error al registrarse'); + } + }; + + return ( +
+
+ + + {/* If user is already logged in: View Profile */} + {user ? ( +
+
+ {user.name.charAt(0).toUpperCase()} +
+
+

{user.name}

+

{user.email}

+
+ + {user.role === 'admin' ? '👑 Administrador' : user.role === 'operator' ? '📦 Operador Logística' : '🛍️ Cliente Registrado'} + +
+
+ +
+

📱 Celular: {user.phone}

+

📍 Ciudad: {user.city || 'Cali'}

+ {user.address &&

🏠 Dirección: {user.address}

} +
+ + {user.role === 'admin' || user.role === 'operator' ? ( + + + Ir al Panel de Control Admin + + ) : null} + + +
+ ) : ( + /* Login or Register */ +
+
+
+ {currentBrand.shortName[0]} +
+
+

+ {mode === 'login' ? 'Iniciar Sesión' : 'Crear Cuenta'} +

+

+ {mode === 'login' + ? 'Accede para gestionar pedidos o entrar como admin' + : 'Regístrate para compras rápidas y seguimiento'} +

+
+
+ + {/* Mode Switch Tabs */} +
+ + +
+ + {error && ( +
+ {error} +
+ )} + + {mode === 'login' ? ( +
+
+ + setIdentifier(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2.5 text-white outline-hidden focus:border-emerald-400" + /> +
+ + + +

+ Tip Admin: Puedes ingresar con carlos@zapply.co o 3134848203. +

+
+ ) : ( +
+
+ + setName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-emerald-400" + /> +
+ +
+
+ + setEmail(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-emerald-400" + /> +
+ +
+ + setPhone(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-emerald-400" + /> +
+
+ +
+
+ + setCity(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-emerald-400" + /> +
+
+ + setAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-emerald-400" + /> +
+
+ + +
+ )} +
+ )} +
+
+ ); +}; diff --git a/zapply-app/src/components/mobile/MobileBottomDock.tsx b/zapply-app/src/components/mobile/MobileBottomDock.tsx new file mode 100644 index 0000000..6b515f3 --- /dev/null +++ b/zapply-app/src/components/mobile/MobileBottomDock.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; +import { Home, Search, ShoppingBag, MessageCircle, Download, Check } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileBottomDockProps { + cartCount: number; + onOpenCart: () => void; + onOpenSearch?: () => void; + onOpenInstallModal: () => void; +} + +export const MobileBottomDock: React.FC = ({ + cartCount, + onOpenCart, + onOpenSearch, + onOpenInstallModal, +}) => { + const { currentBrand } = useBrand(); + const [activeTab, setActiveTab] = useState('home'); + + const handleWhatsApp = () => { + const text = encodeURIComponent( + `Hola ${currentBrand.name}! 👋 Quiero consultar la disponibilidad de unas zapatillas para despacho contraentrega en 24 horas.` + ); + window.open(`https://wa.me/${currentBrand.whatsappNumber}?text=${text}`, '_blank'); + }; + + return ( +
+
+ setActiveTab('home')} + className={`flex flex-col items-center gap-0.5 cursor-pointer transition-all ${ + activeTab === 'home' ? 'text-white' : 'text-slate-400 hover:text-slate-200' + }`} + > + + Inicio + + + + + + + + + +
+
+ ); +}; diff --git a/zapply-app/src/components/mobile/MobileInstallBanner.tsx b/zapply-app/src/components/mobile/MobileInstallBanner.tsx new file mode 100644 index 0000000..123dd0b --- /dev/null +++ b/zapply-app/src/components/mobile/MobileInstallBanner.tsx @@ -0,0 +1,125 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Download, Sparkles, X, Smartphone, CheckCircle, Share2, PlusSquare } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +interface MobileInstallBannerProps { + isOpen: boolean; + onClose: () => void; +} + +export const MobileInstallBanner: React.FC = ({ isOpen, onClose }) => { + const { currentBrand } = useBrand(); + const [deferredPrompt, setDeferredPrompt] = useState(null); + const [isInstalled, setIsInstalled] = useState(false); + const [isIOS, setIsIOS] = useState(false); + + useEffect(() => { + const userAgent = window.navigator.userAgent.toLowerCase(); + const isIosDevice = /iphone|ipad|ipod/.test(userAgent); + setIsIOS(isIosDevice); + + const isStandalone = window.matchMedia('(display-mode: standalone)').matches; + if (isStandalone) { + setIsInstalled(true); + } + + const handleBeforeInstall = (e: Event) => { + e.preventDefault(); + setDeferredPrompt(e); + }; + + window.addEventListener('beforeinstallprompt', handleBeforeInstall); + return () => window.removeEventListener('beforeinstallprompt', handleBeforeInstall); + }, []); + + const handleInstallClick = async () => { + if (deferredPrompt) { + deferredPrompt.prompt(); + const { outcome } = await deferredPrompt.userChoice; + if (outcome === 'accepted') { + setIsInstalled(true); + onClose(); + } + setDeferredPrompt(null); + } + }; + + if (!isOpen) return null; + + return ( +
+
+ + +
+
+ {currentBrand.shortName[0]} +
+
+

Instalar {currentBrand.name}

+

Aplicación Móvil para Android & iPhone

+
+
+ +
+
+ + Acceso instantáneo desde la pantalla de inicio de tu celular +
+
+ + Despachos express y seguimiento en tiempo real +
+
+ + Navegación ultra rápida sin consumir espacio de memoria +
+
+ + {isIOS ? ( +
+

+ + Instrucciones para iPhone (Safari): +

+
    +
  1. Toca el botón Compartir abajo en Safari.
  2. +
  3. Desliza hacia abajo y selecciona "Agregar a Inicio ".
  4. +
  5. ¡Listo! El icono de {currentBrand.shortName} aparecerá en tu teléfono.
  6. +
+
+ ) : deferredPrompt ? ( + + ) : ( +
+
+

Para instalar en tu navegador:

+

+ Abre el menú de opciones del navegador (los 3 puntos arriba a la derecha) y toca "Instalar aplicación" o "Agregar a pantalla principal". +

+
+ +
+ )} +
+
+ ); +}; diff --git a/zapply-app/src/components/store/CartDrawer.tsx b/zapply-app/src/components/store/CartDrawer.tsx new file mode 100644 index 0000000..bca5a6d --- /dev/null +++ b/zapply-app/src/components/store/CartDrawer.tsx @@ -0,0 +1,254 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { X, Trash2, ShoppingBag, ArrowRight, Zap, Truck, MessageCircle } from 'lucide-react'; +import { CartItem, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface CartDrawerProps { + isOpen: boolean; + onClose: () => void; + cartItems: CartItem[]; + onRemoveItem: (productId: string, size: string) => void; + onUpdateQuantity: (productId: string, size: string, delta: number) => void; + selectedCity: City; + onOpenCitySelector: () => void; +} + +export const CartDrawer: React.FC = ({ + isOpen, + onClose, + cartItems, + onRemoveItem, + onUpdateQuantity, + selectedCity, + onOpenCitySelector, +}) => { + const { currentBrand } = useBrand(); + const [officialPhone, setOfficialPhone] = React.useState('573167455877'); + + React.useEffect(() => { + fetch('/api/settings') + .then((r) => r.json()) + .then((d) => { + if (d.success && d.settings?.whatsappNumber) { + setOfficialPhone(d.settings.whatsappNumber); + } + }) + .catch(() => {}); + }, []); + + if (!isOpen) return null; + + const subtotal = cartItems.reduce((acc, item) => acc + item.product.retailPrice * item.quantity, 0); + const shippingCost = selectedCity.shippingCost; + const totalAmount = subtotal + shippingCost; + const separation = calculateSeparationBreakdown(totalAmount); + + const handleWhatsAppCheckout = () => { + const itemsList = cartItems + .map((item) => `👟 *${item.product.name}* (Talla: *${item.selectedSize}*, Cant: ${item.quantity}) - ${formatCOP(item.product.retailPrice * item.quantity)}`) + .join('\n'); + + const text = `🔥 *NUEVO PEDIDO DESDE ${currentBrand.name}* 🔥 + +📦 *Productos seleccionados:* +${itemsList} + +📍 *Ciudad de entrega:* ${selectedCity.name} +💵 *Subtotal:* ${formatCOP(subtotal)} +🚚 *Envío:* ${shippingCost === 0 ? 'GRATIS' : formatCOP(shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(totalAmount)} COP + +⚡ *Condición de Pago:* Pago Contraentrega (Separo con $10.000 COP vía Bold/Nequi y cancelo saldo de ${formatCOP(separation.balanceDue)} al recibir). + +Por favor confírmenme para enviarles los datos de mi dirección.`; + + window.open(`https://wa.me/${officialPhone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+ {/* Backdrop */} +
+ +
+
+ {/* Header */} +
+
+
+ +
+
+

Tu Carrito • {currentBrand.shortName}

+

{cartItems.length} {cartItems.length === 1 ? 'artículo' : 'artículos'}

+
+
+ +
+ + {/* Items List */} +
+ {cartItems.length === 0 ? ( +
+
+ +
+

Tu carrito está vacío

+

+ Aprovecha las ofertas de calzado con pago contraentrega en Cali y despachos nacionales. +

+ +
+ ) : ( + cartItems.map((item, idx) => ( +
+ {item.product.name} +
+
+
+

+ {item.product.name} +

+ +
+
+ + Talla {item.selectedSize} + + + {item.product.brand} + +
+
+ +
+ + {formatCOP(item.product.retailPrice * item.quantity)} + +
+ + {item.quantity} + +
+
+
+
+ )) + )} +
+ + {/* Footer & Checkout Breakdown */} + {cartItems.length > 0 && ( +
+ {/* City Delivery selector pill */} +
+
+ + Destino: {selectedCity.name} +
+ +
+ + {/* Price Calculations */} +
+
+ Subtotal: + {formatCOP(subtotal)} +
+
+ Costo de Envío: + + {shippingCost === 0 ? Gratis : formatCOP(shippingCost)} + +
+
+ Total de la Orden: + + {formatCOP(totalAmount)} + +
+
+ + {/* Separation Highlight Banner */} +
+

+ + Opción de Separación con $10.000 COP +

+

+ Separas con {formatCOP(separation.depositAmount)} y pagas {formatCOP(separation.balanceDue)} al recibir contraentrega en tu casa. +

+

+ 🛡️ {selectedCity.firstExchangeFree + ? `1er Cambio de Talla 100% GRATIS en ${selectedCity.name}` + : `Garantía de cambio en ${selectedCity.name} (flete asumido por cliente)`} +

+
+ + {/* Action Buttons */} +
+ + Proceder al Pago Contraentrega + + + + +
+
+ )} +
+
+
+ ); +}; diff --git a/zapply-app/src/components/store/CategoryPills.tsx b/zapply-app/src/components/store/CategoryPills.tsx new file mode 100644 index 0000000..be49b4b --- /dev/null +++ b/zapply-app/src/components/store/CategoryPills.tsx @@ -0,0 +1,48 @@ +'use client'; + +import React from 'react'; +import { useBrand } from '@/context/BrandContext'; + +interface CategoryPillsProps { + activeCategory: string; + onSelectCategory: (category: string) => void; +} + +const CATEGORIES = [ + { id: 'all', label: '🔥 Todas las Zapatillas' }, + { id: 'Nike', label: '👟 Nike' }, + { id: 'Jordan', label: '🏀 Air Jordan' }, + { id: 'Adidas', label: '🛹 Adidas' }, + { id: 'New Balance', label: '🌿 New Balance' }, + { id: 'Puma', label: '🐆 Puma' }, + { id: 'flash', label: '⚡ Ofertas Flash' }, + { id: 'under120', label: '💰 Menos de $120k' }, +]; + +export const CategoryPills: React.FC = ({ + activeCategory, + onSelectCategory, +}) => { + const { currentBrand } = useBrand(); + + return ( +
+ {CATEGORIES.map((cat) => { + const isActive = activeCategory === cat.id; + return ( + + ); + })} +
+ ); +}; diff --git a/zapply-app/src/components/store/CitySelectorModal.tsx b/zapply-app/src/components/store/CitySelectorModal.tsx new file mode 100644 index 0000000..02530ce --- /dev/null +++ b/zapply-app/src/components/store/CitySelectorModal.tsx @@ -0,0 +1,109 @@ +'use client'; + +import React from 'react'; +import { X, MapPin, Check, Truck } from 'lucide-react'; +import { City } from '@/types'; +import { formatCOP } from '@/lib/pricing-engine'; + +interface CitySelectorModalProps { + isOpen: boolean; + onClose: () => void; + cities: City[]; + selectedCity: City; + onSelectCity: (city: City) => void; +} + +export const CitySelectorModal: React.FC = ({ + isOpen, + onClose, + cities, + selectedCity, + onSelectCity, +}) => { + if (!isOpen) return null; + + return ( +
+
+ {/* Header */} +
+
+
+ +
+
+

Selecciona tu Ciudad

+

Calculamos tiempos y tarifas oficiales

+
+
+ +
+ + {/* City list */} +
+ {cities + .filter((c) => c.isActive !== false) + .map((city) => { + const isSelected = selectedCity.id === city.id; + const hasCod = city.allowsContraentrega || city.allowCod; + + return ( +
{ + onSelectCity(city); + onClose(); + }} + className={`p-3 rounded-2xl border transition-all cursor-pointer flex items-center justify-between ${ + isSelected + ? 'border-emerald-400 bg-emerald-950/50 shadow-[0_0_15px_rgba(16,185,129,0.2)]' + : 'border-slate-800 hover:border-slate-700 bg-slate-950' + }`} + > +
+
+ {city.name} + {hasCod && ( + + Contraentrega + + )} +
+

+ + {city.deliveryTime} +

+
+ +
+ + {city.shippingCost === 0 ? ( + Gratis + ) : ( + formatCOP(city.shippingCost) + )} + + {isSelected && ( +
+ +
+ )} +
+
+ ); + })} +
+ + {/* Info footer */} +
+ 💡 En Cali y zona metropolitana: entregas el mismo día con mensajería directa y pago contraentrega. +
+
+
+ ); +}; diff --git a/zapply-app/src/components/store/FlashDealsBanner.tsx b/zapply-app/src/components/store/FlashDealsBanner.tsx new file mode 100644 index 0000000..e26b007 --- /dev/null +++ b/zapply-app/src/components/store/FlashDealsBanner.tsx @@ -0,0 +1,83 @@ +'use client'; + +import React, { useState, useEffect } from 'react'; +import { Zap, Clock, Gift } from 'lucide-react'; +import { useBrand } from '@/context/BrandContext'; + +export const FlashDealsBanner: React.FC = () => { + const { currentBrand } = useBrand(); + const [timeLeft, setTimeLeft] = useState({ hours: 4, minutes: 27, seconds: 15 }); + + useEffect(() => { + const timer = setInterval(() => { + setTimeLeft((prev) => { + if (prev.seconds > 0) { + return { ...prev, seconds: prev.seconds - 1 }; + } else if (prev.minutes > 0) { + return { ...prev, minutes: 59, seconds: 59 }; + } else if (prev.hours > 0) { + return { hours: prev.hours - 1, minutes: 59, seconds: 59 }; + } + return { hours: 5, minutes: 59, seconds: 59 }; + }); + }, 1000); + return () => clearInterval(timer); + }, []); + + const pad = (n: number) => n.toString().padStart(2, '0'); + + return ( +
+ {/* Background glow meshes */} +
+
+ +
+ {/* Left text */} +
+
+ + {currentBrand.shortName.toUpperCase()} DROPS • OFERTAS FLASH +
+

+ Zapatillas Premium hasta con{' '} + + 35% OFF + +

+

+ Lanzamientos exclusivos directos de bodega. Separa tu par con $10.000 COP y paga el saldo en efectivo o transferencia con Pago Contraentrega en tu casa. +

+
+ + {/* Right Countdown Box */} +
+
+ + Oferta expira en: +
+
+
+ {pad(timeLeft.hours)} + Horas +
+ : +
+ {pad(timeLeft.minutes)} + Min +
+ : +
+ {pad(timeLeft.seconds)} + Seg +
+
+
+ + Cupón: {currentBrand.couponCode} aplicado +
+
+
+
+ ); +}; diff --git a/zapply-app/src/components/store/Navbar.tsx b/zapply-app/src/components/store/Navbar.tsx new file mode 100644 index 0000000..55d13a9 --- /dev/null +++ b/zapply-app/src/components/store/Navbar.tsx @@ -0,0 +1,152 @@ +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { ShoppingBag, Search, MapPin, Zap, Sparkles, ShieldCheck, Store, User as UserIcon } from 'lucide-react'; +import { City } from '@/types'; +import { useBrand } from '@/context/BrandContext'; +import { useAuth } from '@/context/AuthContext'; + +interface NavbarProps { + cartCount: number; + onOpenCart: () => void; + selectedCity: City; + onOpenCitySelector: () => void; + searchQuery: string; + onSearchChange: (q: string) => void; +} + +export const Navbar: React.FC = ({ + cartCount, + onOpenCart, + selectedCity, + onOpenCitySelector, + searchQuery, + onSearchChange, +}) => { + const { currentBrand } = useBrand(); + const { user, openAuthModal } = useAuth(); + + return ( +
+ {/* Top Banner Urgency */} +
+
+
+ + 🔥 ENVÍOS CONTRAENTREGA EN {selectedCity.name.toUpperCase()} Y TODO COLOMBIA +
+
+ + + Separa tu par con solo $10.000 COP + + • + + + {selectedCity.firstExchangeFree + ? `1er Cambio GRATIS en ${selectedCity.name}` + : `Garantía de Cambio (${selectedCity.name})`} + +
+
+
+ + {/* Main Navbar */} +
+ {/* Brand Logo */} + +
+
+ + {currentBrand.logo.iconText} + +
+
+
+
+ {currentBrand.logo.mainText} + + {currentBrand.logo.accentText} + +
+

{currentBrand.tagline}

+
+ + + {/* City Selector Pill */} + + + {/* Search Bar */} +
+
+ onSearchChange(e.target.value)} + className="w-full bg-slate-900/90 text-white placeholder-slate-400 text-xs sm:text-sm rounded-full pl-10 pr-4 py-2 border border-slate-700 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-500/20 transition-all outline-hidden" + /> + +
+
+ + {/* Right Actions */} +
+ {/* User Auth Button */} + + + {/* Admin Link */} + + + Admin + + + {/* Cart Button */} + +
+
+
+ ); +}; diff --git a/zapply-app/src/components/store/ProductCard.tsx b/zapply-app/src/components/store/ProductCard.tsx new file mode 100644 index 0000000..9ba227c --- /dev/null +++ b/zapply-app/src/components/store/ProductCard.tsx @@ -0,0 +1,132 @@ +'use client'; + +import React from 'react'; +import { Star, Zap, Truck, ShoppingBag } from 'lucide-react'; +import { Product } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductCardProps { + product: Product; + onOpenDetail: (product: Product) => void; + onQuickAdd: (product: Product, size: string) => void; +} + +export const ProductCard: React.FC = ({ + product, + onOpenDetail, +}) => { + const { currentBrand } = useBrand(); + const discountPercent = product.originalPrice + ? Math.round(((product.originalPrice - product.retailPrice) / product.originalPrice) * 100) + : 28; + + const separation = calculateSeparationBreakdown(product.retailPrice); + + return ( +
onOpenDetail(product)} + className={`group rounded-2xl border transition-all duration-300 flex flex-col cursor-pointer overflow-hidden ${currentBrand.colors.cardBg}`} + > + {/* Image Container */} +
+ {product.name} + + {/* Badges */} +
+ + -{discountPercent}% OFF + + {product.isFlashDeal && ( + + FLASH + + )} +
+ +
+ + Contraentrega + + + {product.brand} + +
+
+ + {/* Product Info */} +
+
+ {/* Rating and Sales */} +
+
+ + {product.rating || 4.9} + ({product.reviewsCount || 89}) +
+ + +{product.salesCount || 150} pedidos + +
+ + {/* Product Title */} +

+ {product.name} +

+ + {/* Available Sizes Pills */} +
+ Tallas: + {product.sizes.slice(0, 5).map((size) => ( + + {size} + + ))} + {product.sizes.length > 5 && ( + +{product.sizes.length - 5} + )} +
+
+ + {/* Pricing & Separation terms */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ +

+ ⚡ Separa con {formatCOP(separation.depositAmount)} y cancelas {formatCOP(separation.balanceDue)} al recibir. +

+ + {/* Quick Action Button */} +
+ +
+
+
+
+ ); +}; diff --git a/zapply-app/src/components/store/ProductModal.tsx b/zapply-app/src/components/store/ProductModal.tsx new file mode 100644 index 0000000..ce518d5 --- /dev/null +++ b/zapply-app/src/components/store/ProductModal.tsx @@ -0,0 +1,222 @@ +'use client'; + +import React, { useState } from 'react'; +import { X, Star, Truck, ShieldCheck, Zap, MessageCircle, ShoppingBag, Check } from 'lucide-react'; +import { Product, City } from '@/types'; +import { formatCOP, calculateSeparationBreakdown } from '@/lib/pricing-engine'; +import { useBrand } from '@/context/BrandContext'; + +interface ProductModalProps { + product: Product | null; + onClose: () => void; + onAddToCart: (product: Product, size: string) => void; + selectedCity: City; +} + +export const ProductModal: React.FC = ({ + product, + onClose, + onAddToCart, + selectedCity, +}) => { + const { currentBrand } = useBrand(); + if (!product) return null; + + const [selectedSize, setSelectedSize] = useState(product.sizes[0] || '39'); + const [selectedImage, setSelectedImage] = useState(product.images[0]); + const [added, setAdded] = useState(false); + + const separation = calculateSeparationBreakdown(product.retailPrice); + + const handleAdd = () => { + onAddToCart(product, selectedSize); + setAdded(true); + setTimeout(() => { + setAdded(false); + onClose(); + }, 1200); + }; + + const handleWhatsAppDirect = () => { + const phone = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203'; + const text = `Hola ${currentBrand.name}! Quiero pedir las zapatillas: +👟 *${product.name}* (${product.brand}) +📏 Talla: *${selectedSize}* (Horma Nacional) +💎 Precio: *${formatCOP(product.retailPrice)} COP* +🚚 Entrega en: *${selectedCity.name}* (Pago Contraentrega) +⚡ Deseo separar con $10.000 COP y cancelar el saldo en mi casa. + +¿Me confirman disponibilidad para despacho por favor?`; + window.open(`https://wa.me/${phone}?text=${encodeURIComponent(text)}`, '_blank'); + }; + + return ( +
+
+ {/* Close Button */} + + + {/* Left: Images */} +
+
+ {product.name} + + -{Math.round(((product.originalPrice || 170000) - product.retailPrice) / (product.originalPrice || 170000) * 100)}% OFF + +
+ + {/* Thumbnails */} + {product.images.length > 1 && ( +
+ {product.images.map((img, i) => ( + + ))} +
+ )} + + {/* Trust note */} +
+ + + {selectedCity.firstExchangeFree ? ( + <>1er Cambio de Talla GRATIS en {selectedCity.name} • Cambios posteriores: el cliente asume el flete + ) : ( + <>Garantía de Cambio en {selectedCity.name} • El cliente asume los costos de flete + )} + +
+
+ + {/* Right: Product Details & Actions */} +
+
+
+ {product.brand} +

{product.name}

+
+
+ + {product.rating || 4.9} +
+ • + +{product.salesCount || 200} pares entregados +
+
+ + {/* Price Box */} +
+
+ + {formatCOP(product.retailPrice)} + + {product.originalPrice && ( + + {formatCOP(product.originalPrice)} + + )} +
+ + {/* Separation breakdown banner */} +
+

+ + ¡Pago Contraentrega en {selectedCity.name}! +

+

+ Separas con solo {formatCOP(separation.depositAmount)} y pagas los {formatCOP(separation.balanceDue)} al recibir en tu puerta. +

+
+
+ + {/* Size Selector */} +
+
+ Selecciona tu Talla (Nacional CO): + Guía de Tallas +
+
+ {product.sizes.map((size) => ( + + ))} +
+
+ + {/* Description */} +
+

{product.description}

+
+ + {/* Shipping note */} +
+ +
+ {selectedCity.name}: + {selectedCity.deliveryTime} ({selectedCity.shippingCost === 0 ? 'Envío Gratis' : formatCOP(selectedCity.shippingCost)}) +
+
+
+ + {/* Action Buttons */} +
+ + + +
+
+
+
+ ); +}; diff --git a/zapply-app/src/config/brands.ts b/zapply-app/src/config/brands.ts new file mode 100644 index 0000000..fe598a2 --- /dev/null +++ b/zapply-app/src/config/brands.ts @@ -0,0 +1,151 @@ +export type BrandId = 'almeira' | 'sneaky' | 'zapply' | 'dripzone'; + +export interface BrandTheme { + id: BrandId; + name: string; + shortName: string; + tagline: string; + badge: string; + couponCode: string; + whatsappNumber: string; + + // Clases y colores de diseño personalizados para cada una de las 4 marcas + colors: { + primaryGradient: string; + secondaryGradient: string; + heroGradient: string; + accentGlow: string; + headerBg: string; + bodyBg: string; + cardBg: string; + border: string; + textAccent: string; + badgeBg: string; + badgeText: string; + cartBadge: string; + }; + + logo: { + iconText: string; + mainText: string; + accentText: string; + }; +} + +export const BRANDS: Record = { + almeira: { + id: 'almeira', + name: 'ALMEIRA STORE', + shortName: 'Almeira', + tagline: 'Sneakers & Moda Urbana', + badge: 'Garantía Certificada', + couponCode: 'ALMEIRA-10K', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-cyan-500 via-blue-600 to-pink-500', + secondaryGradient: 'from-cyan-400 to-blue-500', + heroGradient: 'from-slate-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(6,182,212,0.35)]', + headerBg: 'bg-slate-950/95 border-cyan-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-cyan-500/40', + border: 'border-cyan-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-pink-400 to-pink-500', + badgeBg: 'bg-cyan-500/20 border-cyan-500/30 text-cyan-300', + badgeText: 'text-cyan-300', + cartBadge: 'bg-pink-500 text-white', + }, + logo: { + iconText: 'A', + mainText: 'ALMEIRA', + accentText: 'STORE', + }, + }, + + sneaky: { + id: 'sneaky', + name: 'SNEAKY DROPS', + shortName: 'Sneaky', + tagline: 'Viral Kicks & Flash Deals', + badge: 'Oferta Flash', + couponCode: 'SNEAKY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-red-600 via-orange-500 to-amber-500', + secondaryGradient: 'from-red-500 to-orange-500', + heroGradient: 'from-red-950 via-gray-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(239,68,68,0.35)]', + headerBg: 'bg-gray-950/95 border-orange-500/20', + bodyBg: 'bg-gray-950 text-gray-100', + cardBg: 'bg-gray-900/80 border-gray-800 hover:border-orange-500/40', + border: 'border-orange-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-red-500 via-orange-400 to-amber-400', + badgeBg: 'bg-orange-500/20 border-orange-500/30 text-orange-300', + badgeText: 'text-orange-300', + cartBadge: 'bg-amber-400 text-gray-950', + }, + logo: { + iconText: 'S', + mainText: 'SNEAKY', + accentText: 'DROPS', + }, + }, + + zapply: { + id: 'zapply', + name: 'ZAPPLY CALI', + shortName: 'Zapply', + tagline: 'Zapatillas & Entrega Inmediata', + badge: 'Envío Express 24h', + couponCode: 'ZAPPLY-CALI', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-emerald-500 via-teal-500 to-cyan-600', + secondaryGradient: 'from-emerald-400 to-teal-500', + heroGradient: 'from-emerald-950 via-slate-900 to-slate-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-slate-950/95 border-emerald-500/20', + bodyBg: 'bg-slate-950 text-slate-100', + cardBg: 'bg-slate-900/80 border-slate-800 hover:border-emerald-500/40', + border: 'border-emerald-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 via-teal-300 to-cyan-400', + badgeBg: 'bg-emerald-500/20 border-emerald-500/30 text-emerald-300', + badgeText: 'text-emerald-300', + cartBadge: 'bg-emerald-400 text-slate-950', + }, + logo: { + iconText: 'Z', + mainText: 'ZAPPLY', + accentText: 'CALI', + }, + }, + + dripzone: { + id: 'dripzone', + name: 'DRIPZONE', + shortName: 'DripZone', + tagline: 'Streetwear & Sneakers Exclusivos', + badge: 'Edición Limitada', + couponCode: 'DRIP-VIP', + whatsappNumber: '573167455877', + colors: { + primaryGradient: 'from-purple-600 via-fuchsia-500 to-pink-600', + secondaryGradient: 'from-purple-500 to-pink-500', + heroGradient: 'from-purple-950 via-neutral-900 to-neutral-950', + accentGlow: 'shadow-[0_0_25px_rgba(168,85,247,0.35)]', + headerBg: 'bg-neutral-950/95 border-purple-500/20', + bodyBg: 'bg-neutral-950 text-neutral-100', + cardBg: 'bg-neutral-900/80 border-neutral-800 hover:border-purple-500/40', + border: 'border-purple-500/30', + textAccent: 'text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-fuchsia-400 to-pink-400', + badgeBg: 'bg-purple-500/20 border-purple-500/30 text-purple-300', + badgeText: 'text-purple-300', + cartBadge: 'bg-fuchsia-500 text-white', + }, + logo: { + iconText: 'D', + mainText: 'DRIP', + accentText: 'ZONE', + }, + }, +}; diff --git a/zapply-app/src/context/AuthContext.tsx b/zapply-app/src/context/AuthContext.tsx new file mode 100644 index 0000000..66f122b --- /dev/null +++ b/zapply-app/src/context/AuthContext.tsx @@ -0,0 +1,100 @@ +'use client'; + +import React, { createContext, useContext, useState, useEffect } from 'react'; +import { User } from '@/types'; + +interface AuthContextType { + user: User | null; + login: (identifier: string) => Promise<{ success: boolean; error?: string }>; + register: (data: { name: string; email: string; phone: string; city?: string; address?: string }) => Promise<{ success: boolean; error?: string }>; + logout: () => void; + isAuthModalOpen: boolean; + openAuthModal: () => void; + closeAuthModal: () => void; +} + +const AuthContext = createContext(undefined); + +export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [user, setUser] = useState(null); + const [isAuthModalOpen, setIsAuthModalOpen] = useState(false); + + useEffect(() => { + const saved = localStorage.getItem('zapply_user'); + if (saved) { + try { + setUser(JSON.parse(saved)); + } catch (e) {} + } + }, []); + + const login = async (identifier: string) => { + try { + const res = await fetch('/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ identifier }), + }); + const data = await res.json(); + if (data.success && data.user) { + setUser(data.user); + localStorage.setItem('zapply_user', JSON.stringify(data.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: data.error || 'Error al iniciar sesión' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const register = async (data: { name: string; email: string; phone: string; city?: string; address?: string }) => { + try { + const res = await fetch('/api/auth/register', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }); + const resData = await res.json(); + if (resData.success && resData.user) { + setUser(resData.user); + localStorage.setItem('zapply_user', JSON.stringify(resData.user)); + setIsAuthModalOpen(false); + return { success: true }; + } + return { success: false, error: resData.error || 'Error al registrarse' }; + } catch (e: any) { + return { success: false, error: e.message }; + } + }; + + const logout = () => { + setUser(null); + localStorage.removeItem('zapply_user'); + }; + + const openAuthModal = () => setIsAuthModalOpen(true); + const closeAuthModal = () => setIsAuthModalOpen(false); + + return ( + + {children} + + ); +}; + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) throw new Error('useAuth must be used within an AuthProvider'); + return context; +}; diff --git a/zapply-app/src/context/BrandContext.tsx b/zapply-app/src/context/BrandContext.tsx new file mode 100644 index 0000000..d442d88 --- /dev/null +++ b/zapply-app/src/context/BrandContext.tsx @@ -0,0 +1,22 @@ +'use client'; + +import React, { createContext, useContext } from 'react'; +import { BrandTheme, BRANDS } from '@/config/brands'; + +interface BrandContextType { + currentBrand: BrandTheme; +} + +const BrandContext = createContext({ + currentBrand: BRANDS.zapply, +}); + +export const BrandProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return ( + + {children} + + ); +}; + +export const useBrand = () => useContext(BrandContext); diff --git a/zapply-app/src/lib/appwrite.ts b/zapply-app/src/lib/appwrite.ts new file mode 100644 index 0000000..2cd0209 --- /dev/null +++ b/zapply-app/src/lib/appwrite.ts @@ -0,0 +1,25 @@ +import { Client, Databases, Storage, Account } from 'appwrite'; + +const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; +const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + +export const client = new Client(); +client.setEndpoint(endpoint).setProject(projectId); + +export const databases = new Databases(client); +export const storage = new Storage(client); +export const account = new Account(client); + +// Base de datos y Bucket 100% aislados e independientes +export const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID || 'sneakers_multistore_db'; +export const BUCKET_ID = process.env.NEXT_PUBLIC_APPWRITE_MEDIA_BUCKET_ID || 'sneakers_media_bucket'; + +// Colecciones independientes +export const COLLECTIONS = { + PRODUCTS: 'products', + CITIES: 'cities', + PAYMENT_METHODS: 'payment_methods', + ORDERS: 'orders', + SETTINGS: 'settings', + SUPPLIER_POSTS: 'supplier_posts', +}; diff --git a/zapply-app/src/lib/data-service.ts b/zapply-app/src/lib/data-service.ts new file mode 100644 index 0000000..ea2c8f0 --- /dev/null +++ b/zapply-app/src/lib/data-service.ts @@ -0,0 +1,2370 @@ +import { Product, City, PaymentMethod, Order, SupplierPost, StoreSettings, Supplier, MonitoredWhatsAppGroup, User } from '@/types'; + +export const INITIAL_SUPPLIERS: Supplier[] = [ + { + "id": "sup-jovic", + "name": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "phone": "573167455877", + "contactPerson": "Asesor Jovic Store", + "address": "Centro / Bodega Cali", + "notes": "Proveedor oficial Nike, Jordan, Nocta y Vomero calidades Top.", + "isActive": true + }, + { + "id": "sup-ccmio", + "name": "EXCLUSIVE CC MÍO 3B", + "phone": "573159876543", + "contactPerson": "Despachos CC MÍO 3B", + "address": "CC MÍO Local 3B, Cali", + "notes": "Especialista en Adidas, Coach, Timberland y Skatewear.", + "isActive": true + }, + { + "id": "sup-central", + "name": "BODEGA CENTRAL MAYORISTA", + "phone": "573101234567", + "contactPerson": "Logística Despachos", + "address": "San Andresito / Cali", + "notes": "Despacho rápido en 24 horas para separación inmediata.", + "isActive": true + } +]; + +export const INITIAL_CITIES: City[] = [ + { + id: 'city-cali', + name: 'Cali', + department: 'Valle del Cauca', + shippingCost: 0, + deliveryTime: 'Entrega en 24 Horas (Domicilio Local)', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Cali (posteriores con flete estándar)', + }, + { + id: 'city-jamundi', + name: 'Jamundí', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Jamundí (posteriores con flete estándar)', + }, + { + id: 'city-palmira', + name: 'Palmira', + department: 'Valle del Cauca', + shippingCost: 7000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Palmira (posteriores con flete estándar)', + }, + { + id: 'city-yumbo', + name: 'Yumbo', + department: 'Valle del Cauca', + shippingCost: 5000, + deliveryTime: 'Entrega en 24 Horas', + allowsContraentrega: true, + firstExchangeFree: true, + exchangePolicyNote: '1er Cambio de Talla 100% GRATIS en Yumbo (posteriores con flete estándar)', + }, + { + id: 'city-bogota', + name: 'Bogotá D.C.', + department: 'Cundinamarca', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-medellin', + name: 'Medellín', + department: 'Antioquia', + shippingCost: 12000, + deliveryTime: '2 a 3 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-barranquilla', + name: 'Barranquilla', + department: 'Atlántico', + shippingCost: 14000, + deliveryTime: '3 a 4 días hábiles', + allowsContraentrega: true, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete logístico asumido por el cliente)', + }, + { + id: 'city-nacional', + name: 'Otras Ciudades / Resto del País', + department: 'Colombia', + shippingCost: 15000, + deliveryTime: '2 a 5 días hábiles', + allowsContraentrega: false, + firstExchangeFree: false, + exchangePolicyNote: 'Cambio de talla garantizado (flete nacional asumido por el cliente)', + }, +]; + +// Métodos de Pago configurables por el Admin +export const INITIAL_PAYMENT_METHODS: PaymentMethod[] = [ + { + id: 'pay-bold-link', + name: 'Bold.co • PSE, Tarjetas Débito/Crédito, Nequi o QR (Oficial)', + type: 'bold', + description: 'Paga de forma rápida y 100% segura con tu cuenta Bold. Acepta PSE, Tarjetas Visa/Mastercard y QR de cualquier banco.', + requiresDeposit: false, + depositAmount: 0, + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + accountInfo: 'Pasarela Oficial Bold.co • PSE / Tarjetas / QR', + isActive: true, + }, + { + id: 'pay-deposit-10k', + name: 'Separación con $10.000 + Saldo Contraentrega', + type: 'contraentrega', + description: 'Asegura tu talla con solo $10.000 COP vía Bold/Nequi/Daviplata y cancelas el saldo restante en efectivo o transferencia cuando el mensajero llegue a tu casa.', + requiresDeposit: true, + depositAmount: 10000, + accountInfo: 'Nequi / Daviplata Oficial: 316 745 5877 (Carlos Andrés Lasso)', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + isActive: true, + }, + { + id: 'pay-cod-full', + name: 'Pago 100% Contraentrega (Cali y Alrededores)', + type: 'contraentrega', + description: 'Pagas el 100% del valor total al recibir en tu puerta (válido para entregas urbanas en 24 horas).', + requiresDeposit: false, + depositAmount: 0, + isActive: true, + }, + { + id: 'pay-nequi-full', + name: 'Transferencia Total Anticipada Nequi / Daviplata', + type: 'nequi', + description: 'Paga el 100% anticipado y recibe prioridad de despacho express en 24 horas.', + requiresDeposit: false, + depositAmount: 0, + accountInfo: 'Nequi / Daviplata: 316 745 5877 (Carlos Andrés Lasso)', + isActive: true, + }, +]; + +export const INITIAL_PRODUCTS: Product[] = [ + { + "id": "snk-real-1", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 36, + "salesCount": 183, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-2", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 73, + "salesCount": 225, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-3", + "name": "Nike Coach Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 78, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-4", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 44, + "salesCount": 239, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-5", + "name": "Nike Coach Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 242, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-6", + "name": "Nike Coach Dama & Caballero\udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": true, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-7", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 59, + "salesCount": 81, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-8", + "name": "Nike Guess Dama \udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 96, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-9", + "name": "Louis Vuitton Calvin Klein Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 56, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-10", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 52, + "salesCount": 243, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-11", + "name": "Dior Dama \udcb0\udcb0 No Garantia", + "brand": "Dior", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 92, + "salesCount": 58, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-12", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 65, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-13", + "name": "Nike Michael Kors Dama \udcb0\udcb0 No Garantia", + "brand": "Nike", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 70, + "salesCount": 230, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-14", + "name": "Louis Vuitton Calvin Klein Dama \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 146, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-15", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 103, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-16", + "name": "Nike Clemont Caballero\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 74, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-17", + "name": "Nike Clemont Dama\udcb0\udcb0", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 176, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-18", + "name": "Louis Vuitton Caballero \udcb0\udcb0", + "brand": "Louis Vuitton", + "supplierPrice": 50000, + "retailPrice": 70000, + "originalPrice": 95000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 196, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-19", + "name": "Nike \udf1fbapesta\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 41, + "salesCount": 78, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-20", + "name": "Timberland Nueva Mercancía", + "brand": "Timberland", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1520639888713-7851133b1ed0?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 121, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-21", + "name": "\udf1fnike Internacional\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 29, + "salesCount": 112, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-22", + "name": "Nike \udecdalexander Mcqueen\udecd", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 97, + "salesCount": 90, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-23", + "name": "\udf1fnike Af1 Bape\udf1f", + "brand": "Nike", + "supplierPrice": 75000, + "retailPrice": 105000, + "originalPrice": 145000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 192, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-24", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "36", + "37", + "38", + "39", + "40" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 21, + "salesCount": 126, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-25", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 82, + "salesCount": 154, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-26", + "name": "Karl Lagerfeld Dama \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 40, + "salesCount": 241, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-27", + "name": "Karl Lagerfeld Caballero \udcb0\udcb0", + "brand": "Karl Lagerfeld", + "supplierPrice": 95000, + "retailPrice": 130000, + "originalPrice": 180000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 60, + "salesCount": 215, + "originBadge": "Bodega CC MÍO 3B", + "supplierId": "sup-ccmio", + "supplierName": "EXCLUSIVE CC MÍO 3B", + "supplierPhone": "573159876543" + }, + { + "id": "snk-real-28", + "name": "Nike Streetwear Sneaker", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 53, + "salesCount": 114, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-29", + "name": "Nike 7 Camaras Hombre", + "brand": "Nike", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 229, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-30", + "name": "Nike Retro 1 Dama,37 Y 40", + "brand": "Nike", + "supplierPrice": 105000, + "retailPrice": 145000, + "originalPrice": 200000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 67, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-31", + "name": "Nike Vomero Hombre", + "brand": "Nike", + "supplierPrice": 110000, + "retailPrice": 150000, + "originalPrice": 205000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 78, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-32", + "name": "Nike Lebron Dama Y 45", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 113, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-33", + "name": "Nike Kyrie Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 58, + "salesCount": 208, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-34", + "name": "Nike Gt Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 54, + "salesCount": 243, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-35", + "name": "Adidas Hombre ,43,44 Y 45", + "brand": "Adidas", + "supplierPrice": 120000, + "retailPrice": 165000, + "originalPrice": 225000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 109, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-36", + "name": "Adidas Courtic Hombre", + "brand": "Adidas", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 91, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-37", + "name": "Nike Total 90 Dama,42,43,44 Y 45", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 94, + "salesCount": 166, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-38", + "name": "Nike Total 90 Hombre", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "40", + "41", + "42", + "43", + "44", + "45" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 35, + "salesCount": 74, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-39", + "name": "Nike Nocta Hombre", + "brand": "Nike", + "supplierPrice": 130000, + "retailPrice": 180000, + "originalPrice": 245000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 81, + "salesCount": 139, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-40", + "name": "Nike Total 90 Hombre ,43 Y 44", + "brand": "Nike", + "supplierPrice": 100000, + "retailPrice": 135000, + "originalPrice": 185000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 23, + "salesCount": 86, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-41", + "name": "Nike Tn Hombre", + "brand": "Nike", + "supplierPrice": 85000, + "retailPrice": 115000, + "originalPrice": 160000, + "sizes": [ + "40", + "41", + "42", + "43", + "44" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 50, + "salesCount": 152, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-42", + "name": "Nike Kyrie Dama Y Hombre", + "brand": "Nike", + "supplierPrice": 140000, + "retailPrice": 190000, + "originalPrice": 260000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 153, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-43", + "name": "Nike Easyon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 90, + "salesCount": 115, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-44", + "name": "Nike Fast Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 42, + "salesCount": 199, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-45", + "name": "Nike Af1 Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 62, + "salesCount": 245, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-46", + "name": "Adidas Forum Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 95, + "salesCount": 112, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-47", + "name": "Nike Sb Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 74, + "salesCount": 213, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-48", + "name": "Tommy Hilfiger Caballero", + "brand": "Tommy Hilfiger", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 117, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-49", + "name": "Louis Vuitton Skate Dama", + "brand": "Louis Vuitton", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1549298916-b41d501d3772?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 242, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-50", + "name": "Adidas Yeezy Dama", + "brand": "Adidas", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1518002171953-a080ee817e1f?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 45, + "salesCount": 170, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-51", + "name": "Nike Metcon Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 85, + "salesCount": 76, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-52", + "name": "Nike Metcon Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 43, + "salesCount": 189, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-53", + "name": "New Balance Caballero", + "brand": "New Balance", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1539185441755-769473a23570?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 38, + "salesCount": 79, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-54", + "name": "Nike Air Max Caballero", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 84, + "salesCount": 121, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-55", + "name": "Nike Zoom Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 31, + "salesCount": 200, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-56", + "name": "Nike Skate Dama", + "brand": "Nike", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1600185365926-3a2ce3cdb9eb?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 30, + "salesCount": 98, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-57", + "name": "Reebok Caballero", + "brand": "Reebok", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 46, + "salesCount": 93, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-58", + "name": "Dior Caballero", + "brand": "Dior", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1560769629-975ec94e6a86?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 66, + "salesCount": 201, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-59", + "name": "Jordan Retro 1 Bota Dama", + "brand": "Jordan", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80", + "https://images.unsplash.com/photo-1552346154-21d32810aba3?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 63, + "salesCount": 177, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + }, + { + "id": "snk-real-60", + "name": "Diesel Caballero", + "brand": "Diesel", + "supplierPrice": 70000, + "retailPrice": 95000, + "originalPrice": 130000, + "sizes": [ + "37", + "38", + "39", + "40", + "41", + "42" + ], + "images": [ + "https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80" + ], + "description": "Calzado garantizado calidad Top. Horma nacional exacta, suela antideslizante y acabados reforzados.", + "category": "Sneakers / Urbano", + "inStock": true, + "isActive": true, + "isFlashDeal": false, + "rating": 4.9, + "reviewsCount": 79, + "salesCount": 133, + "originBadge": "Bodega Jovic Store", + "supplierId": "sup-jovic", + "supplierName": "💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀", + "supplierPhone": "573167455877" + } +]; + +export const INITIAL_SUPPLIER_POSTS: SupplierPost[] = [ + { + id: 'post-1', + channelName: 'DIFUSION JOVIC STORE', + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + rawMessage: `🔥 DISPONIBLE HOY 🔥\nNike Air Force 1 All White\nTallas: 37 al 43\nMayorista: $90.000 c/u\nDespacho inmediato Cali`, + rawImages: [ + 'https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Nike Air Force 1 Low 07 White Triple', + brand: 'Nike', + sizes: ['37', '38', '39', '40', '41', '42', '43'], + supplierPrice: 90000, + suggestedRetailPrice: 125000, + category: 'Sneakers / Urbano', + confidence: 0.96, + supplierName: 'DIFUSION JOVIC STORE', + supplierPhone: '573134848203', + }, + status: 'published_store', + receivedAt: 'Hoy, 09:15 AM', + }, + { + id: 'post-2', + channelName: 'EXCLUSIVE CC MIO 3B', + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + rawMessage: `👟 JORDAN 4 MILITARY BLACK 👟\nFull calidad AAA, caja original\nTallas 38 a 43\nPrecio: $95.000\nDomicilio pago contraentrega`, + rawImages: [ + 'https://images.unsplash.com/photo-1584735935682-2f2b69dff9d2?auto=format&fit=crop&w=800&q=80', + ], + extractedProduct: { + name: 'Air Jordan 4 Retro Military Black', + brand: 'Jordan', + sizes: ['38', '39', '40', '41', '42', '43'], + supplierPrice: 95000, + suggestedRetailPrice: 130000, + category: 'Sneakers / Colección', + confidence: 0.94, + supplierName: 'EXCLUSIVE CC MIO 3B', + supplierPhone: '573159876543', + }, + status: 'published_store', + receivedAt: 'Hoy, 10:40 AM', + }, +]; + + +export const INITIAL_MONITORED_GROUPS: MonitoredWhatsAppGroup[] = [ + { + id: 'grp-jovic', + jid: '120363049363072784@g.us', + name: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + isMonitored: true, + supplierId: 'sup-jovic', + supplierName: '💎 2️⃣ DIFUSIÓN JOVIC STORE COLOMBIA🍀', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 450, + notes: 'Proveedor oficial Nike, Jordan, Vomero, Nocta y AF1.', + }, + { + id: 'grp-ccmio', + jid: '120363024823901923@g.us', + name: 'EXCLUSIVE CC MÍO 3B', + isMonitored: true, + supplierId: 'sup-ccmio', + supplierName: 'EXCLUSIVE CC MÍO 3B', + profitMarginOverride: 35, + autoPublish: true, + participantsCount: 380, + notes: 'Proveedor oficial Adidas, Coach, Timberland y Skatewear.', + }, +]; + +class DataService { + private products: Product[] = [...INITIAL_PRODUCTS]; + private cities: City[] = [...INITIAL_CITIES]; + private paymentMethods: PaymentMethod[] = [...INITIAL_PAYMENT_METHODS]; + private suppliers: Supplier[] = [...INITIAL_SUPPLIERS]; + private orders: Order[] = []; + private supplierPosts: SupplierPost[] = [...INITIAL_SUPPLIER_POSTS]; + + getProducts(): Product[] { + return this.products; + } + + getProductById(id: string): Product | undefined { + return this.products.find((p) => p.id === id); + } + + addProduct(product: Product): Product { + this.products.unshift(product); + return product; + } + + updateProduct(id: string, updates: Partial): Product | null { + const idx = this.products.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.products[idx] = { ...this.products[idx], ...updates }; + return this.products[idx]; + } + + deleteProduct(id: string): boolean { + const initialLen = this.products.length; + this.products = this.products.filter((p) => p.id !== id); + return this.products.length < initialLen; + } + + getSuppliers(): Supplier[] { + return this.suppliers; + } + + getSupplierById(id: string): Supplier | undefined { + return this.suppliers.find((s) => s.id === id); + } + + addSupplier(supplier: Supplier): Supplier { + this.suppliers.push(supplier); + return supplier; + } + + getCities(): City[] { + return this.cities; + } + + getCityById(id: string): City | undefined { + return this.cities.find((c) => c.id === id); + } + + addCity(city: City): City { + this.cities.push(city); + return city; + } + + updateCity(id: string, updates: Partial): City | null { + const idx = this.cities.findIndex((c) => c.id === id); + if (idx === -1) return null; + this.cities[idx] = { ...this.cities[idx], ...updates }; + return this.cities[idx]; + } + + getPaymentMethods(): PaymentMethod[] { + return this.paymentMethods; + } + + updatePaymentMethod(id: string, updates: Partial): PaymentMethod | null { + const idx = this.paymentMethods.findIndex((p) => p.id === id); + if (idx === -1) return null; + this.paymentMethods[idx] = { ...this.paymentMethods[idx], ...updates }; + return this.paymentMethods[idx]; + } + + getOrders(): Order[] { + return this.orders; + } + + addOrder(order: Order): Order { + this.orders.unshift(order); + return order; + } + + updateOrderStatus(orderId: string, status: Order['status']): Order | null { + const order = this.orders.find((o) => o.id === orderId); + if (!order) return null; + order.status = status; + return order; + } + + getSupplierPosts(): SupplierPost[] { + return this.supplierPosts; + } + + addSupplierPost(post: SupplierPost): SupplierPost { + this.supplierPosts.unshift(post); + return post; + } + + // Configuración de la Tienda + private settings: StoreSettings = { + storeName: 'Zapply Cali', + slogan: 'Sneakers Express • Entregas en 24 Horas', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + whatsappNumber: '573167455877', + instagramHandle: '@zapplycali.co', + address: 'Bodega Central / Cali', + city: 'Cali, Colombia', + nequiAccount: '316 745 5877', + daviplataAccount: '316 745 5877', + accountHolder: 'Carlos Andrés Lasso', + boldPaymentLink: 'https://bold.co/p/carlos-lasso', + boldApiKey: '', + boldMerchantId: '', + boldQrUrl: '', + boldEnabled: true, + defaultProfitMargin: 35, + defaultDepositAmount: 10000, + }; + + getSettings(): StoreSettings { + return this.settings; + } + + updateSettings(updates: Partial): StoreSettings { + this.settings = { ...this.settings, ...updates }; + return this.settings; + } + + // Control de Usuarios + private users: User[] = [ + { + id: 'usr-admin-1', + name: 'Carlos Andrés Lasso', + email: 'carlos.andres.lasso@gmail.com', + phone: '3167455877', + city: 'Cali', + address: 'Centro / Bodega Principal', + role: 'admin', + isActive: true, + createdAt: '2026-01-10', + totalOrders: 0, + lastLogin: 'Hoy, 08:15 PM', + }, + { + id: 'usr-operator-1', + name: 'Andrés Operador Despachos', + email: 'despachos@zapply.co', + phone: '3159876543', + city: 'Cali', + role: 'operator', + isActive: true, + createdAt: '2026-02-01', + totalOrders: 0, + lastLogin: 'Hoy, 05:30 PM', + }, + { + id: 'usr-cust-1', + name: 'Mateo Gómez (Cliente VIP)', + email: 'mateo.sneakers@gmail.com', + phone: '3112345678', + city: 'Cali', + address: 'Calle 5 # 34-12 Apto 402', + role: 'customer', + isActive: true, + createdAt: '2026-02-15', + totalOrders: 3, + lastLogin: 'Ayer, 08:20 PM', + }, + ]; + + getUsers(): User[] { + return this.users; + } + + addUser(user: User): User { + this.users.unshift(user); + return user; + } + + updateUser(id: string, updates: Partial): User | null { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return null; + this.users[idx] = { ...this.users[idx], ...updates }; + return this.users[idx]; + } + + deleteUser(id: string): boolean { + const idx = this.users.findIndex((u) => u.id === id); + if (idx === -1) return false; + this.users.splice(idx, 1); + return true; + } + + authenticate(emailOrPhone: string): User | null { + const q = emailOrPhone.trim().toLowerCase(); + const user = this.users.find( + (u) => u.email.toLowerCase() === q || u.phone === q || u.phone.includes(q) + ); + return user || null; + } + + private monitoredGroups: MonitoredWhatsAppGroup[] = [...INITIAL_MONITORED_GROUPS]; + + getMonitoredGroups(): MonitoredWhatsAppGroup[] { + return this.monitoredGroups; + } + + saveMonitoredGroups(groups: MonitoredWhatsAppGroup[]): MonitoredWhatsAppGroup[] { + this.monitoredGroups = groups; + return this.monitoredGroups; + } + + toggleGroupMonitoring(idOrJid: string, isMonitored: boolean): MonitoredWhatsAppGroup | null { + const grp = this.monitoredGroups.find((g) => g.id === idOrJid || g.jid === idOrJid); + if (grp) { + grp.isMonitored = isMonitored; + return grp; + } + return null; + } + +} + +export const dataService = new DataService(); diff --git a/zapply-app/src/lib/deduplication-engine.ts b/zapply-app/src/lib/deduplication-engine.ts new file mode 100644 index 0000000..3023854 --- /dev/null +++ b/zapply-app/src/lib/deduplication-engine.ts @@ -0,0 +1,105 @@ +import { Product } from '@/types'; + +/** + * Normaliza un string para comparación (minúsculas, sin acentos, sin caracteres especiales) + */ +export function normalizeText(text: string): string { + if (!text) return ''; + return text + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/[^a-z0-9\s]/g, ' ') + .replace(/\s+/g, ' ') + .trim(); +} + +/** + * Calcula la similitud de Jaccard / Coeficiente de Dados entre dos textos + * Devuelve un valor entre 0 (totalmente diferente) y 1.0 (idéntico) + */ +export function calculateTextSimilarity(textA: string, textB: string): number { + const normA = normalizeText(textA); + const normB = normalizeText(textB); + + if (!normA || !normB) return 0; + if (normA === normB) return 1.0; + + // Si uno contiene al otro por completo + if (normA.includes(normB) || normB.includes(normA)) { + const ratio = Math.min(normA.length, normB.length) / Math.max(normA.length, normB.length); + if (ratio > 0.7) return 0.92; + } + + const tokensA = new Set(normA.split(' ').filter((w) => w.length > 2)); + const tokensB = new Set(normB.split(' ').filter((w) => w.length > 2)); + + if (tokensA.size === 0 || tokensB.size === 0) return 0; + + const intersection = new Set([...tokensA].filter((t) => tokensB.has(t))); + const union = new Set([...tokensA, ...tokensB]); + + return intersection.size / union.size; +} + +export interface DuplicateCheckResult { + isDuplicate: boolean; + similarityScore: number; + existingProduct?: Product; + recommendation: 'create_new' | 'update_stock_and_sizes' | 'skip_duplicate'; + message: string; +} + +/** + * Verifica si un producto entrante ya existe en el catálogo para evitar duplicados + */ +export function checkProductDuplicate( + incoming: { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + }, + existingCatalog: Product[], + threshold = 0.75 +): DuplicateCheckResult { + let highestScore = 0; + let bestMatch: Product | undefined; + + for (const product of existingCatalog) { + // 1. Si la marca no coincide, penalizar + const brandMatch = normalizeText(incoming.brand) === normalizeText(product.brand); + const score = calculateTextSimilarity(incoming.name, product.name); + const finalScore = brandMatch ? score : score * 0.5; + + if (finalScore > highestScore) { + highestScore = finalScore; + bestMatch = product; + } + } + + // Si la similitud supera el umbral (75%) + if (highestScore >= threshold && bestMatch) { + // Verificar si aporta nuevas tallas + const incomingSizesSet = new Set(incoming.sizes); + const existingSizesSet = new Set(bestMatch.sizes); + const hasNewSizes = incoming.sizes.some((s) => !existingSizesSet.has(s)); + + return { + isDuplicate: true, + similarityScore: Math.round(highestScore * 100) / 100, + existingProduct: bestMatch, + recommendation: hasNewSizes ? 'update_stock_and_sizes' : 'skip_duplicate', + message: hasNewSizes + ? `Producto ya registrado ("${bestMatch.name}"). Se detectaron nuevas tallas para actualizar.` + : `Producto ya registrado ("${bestMatch.name}") con similitud del ${Math.round(highestScore * 100)}%. Se previene duplicación en la tienda y Facebook.`, + }; + } + + return { + isDuplicate: false, + similarityScore: Math.round(highestScore * 100) / 100, + recommendation: 'create_new', + message: 'Producto nuevo verificado sin duplicados. Listo para publicar.', + }; +} diff --git a/zapply-app/src/lib/evolution-api.ts b/zapply-app/src/lib/evolution-api.ts new file mode 100644 index 0000000..bd654f0 --- /dev/null +++ b/zapply-app/src/lib/evolution-api.ts @@ -0,0 +1,105 @@ +import axios from 'axios'; +import { formatCOP } from './pricing-engine'; + +const EVOLUTION_API_URL = process.env.EVOLUTION_API_URL || 'https://evolution.almeira.com.co'; +const EVOLUTION_API_KEY = process.env.EVOLUTION_API_KEY || 'EE49029EEB85-4568-8F81-C9FDFC6E2943'; +const EVOLUTION_INSTANCE_NAME = process.env.EVOLUTION_INSTANCE_NAME || 'AutomataAlmeira'; + +/** + * Enviar mensaje de texto por WhatsApp a través de Evolution API + */ +export async function sendWhatsAppMessage(toPhone: string, message: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendText/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1200, + presence: 'composing', + }, + textMessage: { + text: message, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando mensaje de WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Enviar mensaje con foto/catálogo a través de Evolution API + */ +export async function sendWhatsAppMedia(toPhone: string, imageUrl: string, caption: string): Promise { + const cleanPhone = toPhone.replace(/\D/g, ''); + const recipient = cleanPhone.startsWith('57') ? `${cleanPhone}@s.whatsapp.net` : `57${cleanPhone}@s.whatsapp.net`; + + try { + const response = await axios.post( + `${EVOLUTION_API_URL}/message/sendMedia/${EVOLUTION_INSTANCE_NAME}`, + { + number: recipient, + options: { + delay: 1500, + presence: 'composing', + }, + mediaMessage: { + mediatype: 'image', + caption, + media: imageUrl, + }, + }, + { + headers: { + apikey: EVOLUTION_API_KEY, + 'Content-Type': 'application/json', + }, + } + ); + return response.status === 200 || response.status === 201; + } catch (error: any) { + console.error('Error enviando media por WhatsApp:', error?.response?.data || error?.message); + return false; + } +} + +/** + * Genera el mensaje de confirmación de pedido para el cliente y el administrador + */ +export function buildOrderConfirmationMessage(order: any): string { + const itemsText = order.items + .map((item: any) => `👟 *${item.productName}*\n 📏 Talla: *${item.size}* | Cantidad: ${item.quantity} | Valor: ${formatCOP(item.price)}`) + .join('\n\n'); + + return `🎉 *¡GRACIAS POR TU PEDIDO EN SNEAKERS CALI!* 🎉 +📌 *No. de Orden:* #${order.id} + +👤 *Cliente:* ${order.customerName} +📱 *Teléfono:* ${order.customerPhone} +📍 *Dirección:* ${order.address} +🏙️ *Ciudad:* ${order.cityName} + +📦 *DETALLE DE TU COMPRA:* +${itemsText} + +💵 *Subtotal:* ${formatCOP(order.subtotal)} +🚚 *Envío:* ${order.shippingCost === 0 ? 'GRATIS' : formatCOP(order.shippingCost)} +💰 *VALOR TOTAL:* ${formatCOP(order.totalAmount)} +${order.depositAmount > 0 ? `⚡ *Separación / Anticipo:* ${formatCOP(order.depositAmount)}\n🤝 *Saldo a Pagar Contraentrega:* ${formatCOP(order.balanceDue)}` : '🤝 *Pago 100% Contraentrega al recibir en tu casa.*'} + +💳 *Método de Pago:* ${order.paymentMethodName} + +Estamos alistando tu paquete. Te enviaremos el número de guía o notificación de entrega. ¡Muchas gracias por tu confianza! ✨`; +} diff --git a/zapply-app/src/lib/facebook-publisher.ts b/zapply-app/src/lib/facebook-publisher.ts new file mode 100644 index 0000000..1e55ec7 --- /dev/null +++ b/zapply-app/src/lib/facebook-publisher.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; +import { generateSalesCopy } from './pricing-engine'; + +export interface PublishToFacebookParams { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + images: string[]; + cityName?: string; + whatsappNumber?: string; + pageId?: string; + accessToken?: string; +} + +export interface PublishResult { + success: boolean; + postId?: string; + postUrl?: string; + generatedCopy: string; + error?: string; +} + +/** + * Publicador automático en Páginas de Facebook mediante Meta Graph API + */ +export async function publishToFacebookPage(params: PublishToFacebookParams): Promise { + const { + productName, + brand, + retailPrice, + sizes, + images, + cityName = 'Cali', + whatsappNumber = process.env.NEXT_PUBLIC_WHATSAPP_PHONE || '573134848203', + pageId = process.env.FACEBOOK_PAGE_ID, + accessToken = process.env.FACEBOOK_ACCESS_TOKEN, + } = params; + + const copy = generateSalesCopy({ + productName, + brand, + retailPrice, + sizes, + cityName, + whatsappNumber, + }); + + // Si no hay token de Facebook configurado, simular publicación exitosa para pruebas + if (!pageId || !accessToken) { + const mockPostId = `fb_${Date.now()}_${Math.floor(Math.random() * 10000)}`; + return { + success: true, + postId: mockPostId, + postUrl: `https://facebook.com/${mockPostId}`, + generatedCopy: copy, + }; + } + + try { + // Si tiene una imagen principal, publicamos como photo post con caption + const primaryImage = images[0]; + const fbEndpoint = `https://graph.facebook.com/v19.0/${pageId}/photos`; + + const response = await axios.post(fbEndpoint, { + url: primaryImage, + caption: copy, + access_token: accessToken, + }); + + return { + success: true, + postId: response.data.id || response.data.post_id, + postUrl: `https://facebook.com/${response.data.id}`, + generatedCopy: copy, + }; + } catch (error: any) { + console.error('Error publicando en Facebook Graph API:', error?.response?.data || error?.message); + return { + success: false, + error: error?.response?.data?.error?.message || error.message, + generatedCopy: copy, + }; + } +} diff --git a/zapply-app/src/lib/gemini-parser.ts b/zapply-app/src/lib/gemini-parser.ts new file mode 100644 index 0000000..268024a --- /dev/null +++ b/zapply-app/src/lib/gemini-parser.ts @@ -0,0 +1,108 @@ +import { GoogleGenAI } from '@google/genai'; +import { ExtractedProductData } from '@/types'; +import { calculateRetailPrice } from './pricing-engine'; + +export async function parseSupplierMessage(text: string): Promise { + const apiKey = process.env.GEMINI_API_KEY; + + const fallbackExtract = (): ExtractedProductData => { + let price = 90000; + const priceMatch = text.match(/(?:precio|valor|mayorista|costo|\$)\s*[:=]?\s*(\d{2,3}(?:\.\d{3})*|\d{2,3}k?)/i); + if (priceMatch) { + const raw = priceMatch[1].toLowerCase().replace(/\./g, ''); + if (raw.endsWith('k')) { + price = parseInt(raw.replace('k', ''), 10) * 1000; + } else { + const num = parseInt(raw, 10); + price = num < 1000 ? num * 1000 : num; + } + } + + const sizes: string[] = []; + const sizeRangeMatch = text.match(/(\d{2})\s*(?:a|al|-)\s*(\d{2})/i); + if (sizeRangeMatch) { + const start = parseInt(sizeRangeMatch[1], 10); + const end = parseInt(sizeRangeMatch[2], 10); + if (start >= 34 && end <= 46 && start <= end) { + for (let s = start; s <= end; s++) sizes.push(s.toString()); + } + } else { + const individualSizes = text.match(/\b(3[4-9]|4[0-6])\b/g); + if (individualSizes) { + sizes.push(...Array.from(new Set(individualSizes))); + } + } + if (sizes.length === 0) { + sizes.push('37', '38', '39', '40', '41', '42', '43'); + } + + let brand = 'Nike'; + if (/jordan/i.test(text)) brand = 'Jordan'; + else if (/adidas|bad bunny|campus|forum/i.test(text)) brand = 'Adidas'; + else if (/new balance|nb/i.test(text)) brand = 'New Balance'; + else if (/puma/i.test(text)) brand = 'Puma'; + else if (/asics/i.test(text)) brand = 'Asics'; + else if (/vans/i.test(text)) brand = 'Vans'; + + const cleanLines = text.split('\n').filter((l) => l.trim().length > 0 && !/🔥|🔴|llegando|promo/i.test(l)); + const name = cleanLines[0] || `${brand} Sneakers Urban Edition`; + + return { + name: name.replace(/tallas?:.*|precio:.*|\$/gi, '').trim() || `${brand} Zapatillas`, + brand, + sizes, + supplierPrice: price, + suggestedRetailPrice: calculateRetailPrice(price, 35, 30000), + category: 'Calzado / Sneakers', + confidence: 0.85, + }; + }; + + if (!apiKey) { + return fallbackExtract(); + } + + try { + const ai = new GoogleGenAI({ apiKey }); + const prompt = `Eres un asistente experto en e-commerce y calzado deportivo en Colombia. +Analiza el siguiente mensaje extraído de un grupo mayorista de WhatsApp. +Extrae los siguientes campos en formato JSON estricto: +- "name": Nombre comercial limpio del modelo (ej: "Nike Dunk Low Retro Panda", "Air Jordan 4 Military Black"). +- "brand": Marca ("Nike", "Jordan", "Adidas", "New Balance", "Puma", "Asics", etc.). +- "sizes": Array de tallas en horma colombiana/europea (ej: ["38", "39", "40", "41", "42", "43"]). Si dice "38 al 43", expande todas las tallas intermedias. +- "supplierPrice": Precio de compra mayorista como número entero en COP (ej: 90000, 95000). Si dice "90mil" o "90", es 90000. +- "category": Categoría ("Sneakers / Colección", "Urbano / Casual", "Running / Deportivo", etc.). + +Mensaje del grupo: +""" +${text} +""" + +Responde ÚNICAMENTE con el objeto JSON sin bloques de código markdown ni texto adicional.`; + + const response = await ai.models.generateContent({ + model: 'gemini-2.5-flash', + contents: prompt, + }); + + const outputText = response.text || ''; + const cleanJson = outputText.replace(/```json|```/gi, '').trim(); + const parsed = JSON.parse(cleanJson); + + const supplierPrice = typeof parsed.supplierPrice === 'number' ? parsed.supplierPrice : 90000; + const sizes = Array.isArray(parsed.sizes) && parsed.sizes.length > 0 ? parsed.sizes.map(String) : ['37', '38', '39', '40', '41', '42', '43']; + + return { + name: parsed.name || 'Zapatilla Urbana', + brand: parsed.brand || 'Nike', + sizes, + supplierPrice, + suggestedRetailPrice: calculateRetailPrice(supplierPrice, 35, 30000), + category: parsed.category || 'Sneakers', + confidence: 0.98, + }; + } catch (err) { + console.warn('Fallo llamada Gemini, utilizando extractor regex fallback:', err); + return fallbackExtract(); + } +} diff --git a/zapply-app/src/lib/pricing-engine.ts b/zapply-app/src/lib/pricing-engine.ts new file mode 100644 index 0000000..640ab12 --- /dev/null +++ b/zapply-app/src/lib/pricing-engine.ts @@ -0,0 +1,114 @@ +/** + * Motor de Precios, Políticas de Cambio y Redondeo Automático al 5.000 Siguiente + */ + +export const DEFAULT_MIN_PROFIT_MARGIN_PERCENT = 35; // % Mínimo de ganancia +export const DEFAULT_MIN_PROFIT_COP = 30000; // Margen mínimo en pesos +export const DEFAULT_SEPARATION_DEPOSIT_COP = 10000; // Separación fija +export const ROUND_STEP_COP = 5000; // Redondeo siempre al múltiplo de $5.000 superior + +export const EXCHANGE_POLICY = { + firstExchangeFree: true, + badgeText: '1er Cambio de Talla GRATIS', + shortNotice: 'Primer cambio de talla gratis. Cambios posteriores con flete estándar.', + fullTerms: 'Cuentas con 1er cambio de talla 100% GRATIS dentro de los primeros 5 días. Para cambios adicionales o posteriores, el cliente asume el costo logístico del flete.', +}; + +export function formatCOP(amount: number): string { + if (isNaN(amount)) return '$0'; + return '$' + Math.round(amount).toLocaleString('es-CO'); +} + +export function roundUpToNearest5000(amount: number): number { + if (!amount || amount <= 0) return 0; + return Math.ceil(amount / ROUND_STEP_COP) * ROUND_STEP_COP; +} + +export function calculateRetailPrice( + supplierPrice: number, + minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT, + minMarginCop: number = DEFAULT_MIN_PROFIT_COP +): number { + if (!supplierPrice || supplierPrice <= 0) return 0; + const priceByPercent = supplierPrice * (1 + minMarginPercent / 100); + const priceByFixed = supplierPrice + minMarginCop; + const baseTargetPrice = Math.max(priceByPercent, priceByFixed); + return roundUpToNearest5000(baseTargetPrice); +} + +export function getPricingBreakdown(supplierCost: number, minMarginPercent: number = DEFAULT_MIN_PROFIT_MARGIN_PERCENT) { + const retailPrice = calculateRetailPrice(supplierCost, minMarginPercent); + const grossProfit = retailPrice - supplierCost; + const realMarginPercent = Math.round((grossProfit / supplierCost) * 100); + + return { + supplierCost, + retailPrice, + grossProfit, + realMarginPercent, + isCeiledTo5k: true, + }; +} + +export function calculateAnchorPrice(retailPrice: number, discountPercentage: number = 30): number { + if (!retailPrice || retailPrice <= 0) return 0; + const anchor = retailPrice / (1 - discountPercentage / 100); + return roundUpToNearest5000(anchor); +} + +export function calculateSeparationBreakdown( + totalAmount: number, + depositAmount: number = DEFAULT_SEPARATION_DEPOSIT_COP +) { + const deposit = Math.min(depositAmount, totalAmount); + const balanceDue = Math.max(0, totalAmount - deposit); + + return { + totalAmount, + depositAmount: deposit, + balanceDue, + summaryText: `Separas hoy con ${formatCOP(deposit)} y cancelas ${formatCOP(balanceDue)} al recibir contraentrega en tu puerta.`, + exchangeTerms: EXCHANGE_POLICY.shortNotice, + }; +} + +export function generateSalesCopy(params: { + productName: string; + brand: string; + retailPrice: number; + sizes: string[]; + storeName?: string; + cityName?: string; + whatsappNumber?: string; +}): string { + const { + productName, + brand, + retailPrice, + sizes, + storeName = 'TIENDA DE CALZADO', + cityName = 'Cali', + whatsappNumber = '573134848203', + } = params; + + const breakdown = calculateSeparationBreakdown(retailPrice); + const sizesFormatted = sizes.join(' - '); + const waLink = `https://wa.me/${whatsappNumber}?text=${encodeURIComponent(`Hola ${storeName}! Quiero pedir las zapatillas ${productName} (${brand}) en talla ___ para entrega contraentrega en ${cityName}.`)}`; + + return `✨ ${storeName.toUpperCase()} • LANZAMIENTO EXCLUSIVO ✨ +👟 ${productName.toUpperCase()} (${brand}) + +📏 Tallas Disponibles: ${sizesFormatted} (Horma Nacional) +💎 PRECIO DE VENTA: ${formatCOP(retailPrice)} COP + +🚚 ¡DOMICILIO EN ${cityName.toUpperCase()} Y ENVÍOS A TODO EL PAÍS! +🤝 PAGO CONTRAENTREGA: Cancelas al recibir el producto en tus manos. +⚡ SEPARA CON SOLO ${formatCOP(breakdown.depositAmount)} COP y cancelas ${formatCOP(breakdown.balanceDue)} al recibir. + +🛡️ POLÍTICA DE GARANTÍA: +✅ Calidad Premium 100% garantizada +✅ ${EXCHANGE_POLICY.badgeText} (posteriores con flete estándar) + +📲 ¡Pídelas antes de que se agote tu talla! +👉 Pedir directo por WhatsApp: ${waLink}`; +} diff --git a/zapply-app/src/types/index.ts b/zapply-app/src/types/index.ts new file mode 100644 index 0000000..9f8a915 --- /dev/null +++ b/zapply-app/src/types/index.ts @@ -0,0 +1,176 @@ +export interface Supplier { + id: string; + name: string; + phone: string; + contactPerson?: string; + address?: string; + notes?: string; + isActive: boolean; +} + +export interface User { + id: string; + name: string; + email: string; + phone: string; + city?: string; + address?: string; + role: 'admin' | 'operator' | 'customer'; + isActive: boolean; + createdAt: string; + totalOrders?: number; + lastLogin?: string; +} + +export interface Product { + id: string; + name: string; + brand: string; + supplierPrice: number; + retailPrice: number; + originalPrice?: number; + sizes: string[]; + images: string[]; + description: string; + category: string; + inStock: boolean; + isActive?: boolean; + isFlashDeal?: boolean; + rating?: number; + reviewsCount?: number; + salesCount?: number; + originBadge?: string; + + supplierId?: string; + supplierName?: string; + supplierPhone?: string; + supplierSku?: string; +} + +export interface City { + id: string; + name: string; + department: string; + shippingCost: number; + deliveryTime: string; + allowsContraentrega: boolean; + allowCod?: boolean; + isActive?: boolean; + firstExchangeFree?: boolean; + exchangePolicyNote?: string; +} + +export interface PaymentMethod { + id: string; + name: string; + code?: string; + type: 'contraentrega' | 'nequi' | 'daviplata' | 'bancolombia' | 'tarjeta' | 'bold'; + description: string; + requiresDeposit: boolean; + depositAmount: number; + accountInfo?: string; + boldPaymentLink?: string; + boldQrUrl?: string; + isActive: boolean; +} + +export interface OrderItem { + productId: string; + productName: string; + brand: string; + size: string; + quantity: number; + price: number; + supplierPrice?: number; + supplierName?: string; + supplierPhone?: string; + image: string; +} + +export interface Order { + id: string; + userId?: string; + customerName: string; + customerPhone: string; + address: string; + cityId: string; + cityName: string; + items: OrderItem[]; + subtotal: number; + shippingCost: number; + totalAmount: number; + depositAmount: number; + balanceDue: number; + paymentMethodId: string; + paymentMethodName: string; + status: 'pending' | 'deposit_received' | 'supplier_notified' | 'dispatched' | 'delivered' | 'cancelled'; + notes?: string; + createdAt: string; +} + +export interface SupplierPost { + id: string; + channelName: string; + supplierName?: string; + supplierPhone?: string; + rawMessage: string; + rawImages: string[]; + extractedProduct?: ExtractedProductData; + status: 'pending_review' | 'published_facebook' | 'published_store' | 'ignored'; + receivedAt: string; +} + +export interface ExtractedProductData { + name: string; + brand: string; + sizes: string[]; + supplierPrice: number; + suggestedRetailPrice: number; + category: string; + confidence: number; + supplierName?: string; + supplierPhone?: string; +} + +export interface CartItem { + product: Product; + selectedSize: string; + quantity: number; +} + +export interface StoreSettings { + storeName: string; + slogan?: string; + email: string; + phone: string; + whatsappNumber: string; + instagramHandle?: string; + address?: string; + city: string; + nequiAccount?: string; + daviplataAccount?: string; + accountHolder?: string; + boldPaymentLink?: string; + boldApiKey?: string; + boldMerchantId?: string; + boldQrUrl?: string; + boldEnabled?: boolean; + autoPublishSupplierPosts?: boolean; + defaultProfitMargin: number; + defaultDepositAmount: number; + facebookPageId?: string; +} + +export interface MonitoredWhatsAppGroup { + id: string; + jid: string; + name: string; + isMonitored: boolean; + supplierId?: string; + supplierName?: string; + profitMarginOverride?: number; + autoPublish: boolean; + participantsCount?: number; + lastMessageAt?: string; + notes?: string; +} diff --git a/zapply-app/tsconfig.json b/zapply-app/tsconfig.json new file mode 100644 index 0000000..cf9c65d --- /dev/null +++ b/zapply-app/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +}