holy shit

This commit is contained in:
Omer Sabic 2024-05-29 19:19:45 +02:00
parent d520ed620c
commit f2dc32a88b
27 changed files with 782 additions and 103 deletions

395
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "front-end",
"version": "0.0.1",
"dependencies": {
"aws-sdk": "^2.1628.0",
"bits-ui": "^0.21.7",
"clsx": "^2.1.1",
"formsnap": "^1.0.0",
@ -1150,6 +1151,41 @@
"postcss": "^8.1.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==",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/aws-sdk": {
"version": "2.1628.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1628.0.tgz",
"integrity": "sha512-mUjvITHmV46JbCTQR8TovWzJEHZtbC9cTRySXyuIuuYQNjA2RrbfqLXXKR/xru+vPFKnfTLw+QQ/BC2l1/Ln5g==",
"hasInstallScript": true,
"dependencies": {
"buffer": "4.9.2",
"events": "1.1.1",
"ieee754": "1.1.13",
"jmespath": "0.16.0",
"querystring": "0.2.0",
"sax": "1.2.1",
"url": "0.10.3",
"util": "^0.12.4",
"uuid": "8.0.0",
"xml2js": "0.6.2"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/axobject-query": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz",
@ -1163,6 +1199,25 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"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"
}
]
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@ -1260,6 +1315,16 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/buffer": {
"version": "4.9.2",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
"dependencies": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4",
"isarray": "^1.0.0"
}
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
@ -1276,6 +1341,24 @@
"optional": true,
"peer": true
},
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
},
"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",
@ -1493,6 +1576,22 @@
"node": ">=0.10.0"
}
},
"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==",
"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/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@ -1541,6 +1640,25 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
"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==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es6-promise": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
@ -1630,6 +1748,14 @@
"@types/estree": "^1.0.0"
}
},
"node_modules/events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==",
"engines": {
"node": ">=0.4.x"
}
},
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@ -1672,6 +1798,14 @@
"tabbable": "^6.2.0"
}
},
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"dependencies": {
"is-callable": "^1.1.3"
}
},
"node_modules/foreground-child": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
@ -1769,6 +1903,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@ -1810,12 +1962,70 @@
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"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==",
"dev": true
},
"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==",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"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==",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@ -1832,6 +2042,11 @@
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="
},
"node_modules/ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -1870,8 +2085,22 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
@ -1884,6 +2113,17 @@
"node": ">=8"
}
},
"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==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-core-module": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
@ -1911,6 +2151,20 @@
"node": ">=8"
}
},
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"dependencies": {
"has-tostringtag": "^1.0.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",
@ -1938,6 +2192,25 @@
"@types/estree": "*"
}
},
"node_modules/is-typed-array": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
"integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
"dependencies": {
"which-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -1968,6 +2241,14 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/jmespath": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
"integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/joi": {
"version": "17.13.0",
"resolved": "https://registry.npmjs.org/joi/-/joi-17.13.0.tgz",
@ -2354,6 +2635,14 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
},
"node_modules/possible-typed-array-names": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
"integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
@ -2605,6 +2894,20 @@
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
"optional": true
},
"node_modules/punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
},
"node_modules/querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
"engines": {
"node": ">=0.4.x"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -2773,11 +3076,32 @@
"rimraf": "^2.5.2"
}
},
"node_modules/sax": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
"integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="
},
"node_modules/set-cookie-parser": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
"integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ=="
},
"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==",
"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/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -3612,11 +3936,40 @@
"browserslist": ">= 4.21.0"
}
},
"node_modules/url": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
"integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==",
"dependencies": {
"punycode": "1.3.2",
"querystring": "0.2.0"
}
},
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"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=="
},
"node_modules/uuid": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/valibot": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-0.30.0.tgz",
@ -3713,6 +4066,24 @@
"node": ">= 8"
}
},
"node_modules/which-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
"integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.7",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
@ -3803,6 +4174,26 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
"node_modules/xml2js": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
"integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
"dependencies": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
"engines": {
"node": ">=4.0"
}
},
"node_modules/yaml": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",

View File

@ -33,6 +33,7 @@
},
"type": "module",
"dependencies": {
"aws-sdk": "^2.1628.0",
"bits-ui": "^0.21.7",
"clsx": "^2.1.1",
"formsnap": "^1.0.0",

View File

@ -1,4 +1,5 @@
import { config } from '$lib/index.js';
import { redirect } from '@sveltejs/kit';
/** @type {import('@sveltejs/kit').HandleFetch} */
export async function handleFetch({ event, request, fetch }) {
@ -7,4 +8,20 @@ export async function handleFetch({ event, request, fetch }) {
request.headers.set('cookie', event.request.headers.get('cookie'));
}
return fetch(request);
}
}
// /** @type {import('@sveltejs/kit').Handle} */
// export async function handle({ event, resolve }) {
// if (event.request.headers.get('host') !== config.frontend_url && !event.request.url.includes("/site/")) {
// console.log("external")
// // event.url.pathname = "/site/f622fdc1-c16e-41b3-a95b-8ebd03883912";
// const res = await fetch(config.frontend_url + "/site/f622fdc1-c16e-41b3-a95b-8ebd0388391" + (event.url.pathname ? `${event.url.pathname}` : "" )).then(x=>x.text());
// // const ress = new Response(event.request.headers.get('host'), res);
// // console.log(ress.url)
// return new Response(res, event.request);
// }
// return resolve(event);
// }

View File

@ -1,3 +1,5 @@
export const config = {
api_url: "http://localhost:3000"
api_url: "http://localhost:3000",
frontend_url: "localhost:3002",
sites_url: "127.0.0.1.nip.io:3001"
}

View File

@ -66,7 +66,7 @@
{/if}
</div>
<div class="text-center text-7xl text-white">
<h2 class="fading mt-48 snap-center">i fucking made you</h2>
<h2 class="fading mt-48 snap-center">example</h2>
<FadingText class="fading my-64 snap-center" {winHeight} {scrollY}>Convert Your Videos To Blogs</FadingText>
<FadingText class="fading mt-48 snap-center" {winHeight} {scrollY}>Get More Subscribers</FadingText>
<FadingText class="fading my-64 snap-center" {winHeight} {scrollY}>Engage Your Existing Viewerbase</FadingText>
@ -76,3 +76,9 @@
<FadingText class="fading my-64 snap-center" {winHeight} {scrollY}>Profit</FadingText>
</div>
</div>
<svelte:head>
<script async src="https://js.stripe.com/v3/pricing-table.js"></script>
</svelte:head>
<stripe-pricing-table pricing-table-id="prctbl_1PIRmXFrdGTeTMwdIiQBQFKj"
publishable-key="pk_test_51MRcs0FrdGTeTMwduNYA1NKcMhCIjlxxh5CAr6QhMkqJhxprTpkUFCWfaYHUGnnQMDa9PQqDbJoeGThZ7YMCC90700edsLwqgw">
</stripe-pricing-table>

View File

@ -0,0 +1,55 @@
// src/routes/api/upload/+server.js
import { json } from '@sveltejs/kit';
import S3 from 'aws-sdk/clients/s3.js';
const s3 = new S3({
accessKeyId: 'c39c1d310e9f6afd16840b81c7870c16',
secretAccessKey: '0d336803615f0a35026624237fedf5b62e3d5ada60287067f98e11cdcfc48aa9',
region: 'auto',
endpoint: 'https://f79c2f6c3ee16c813cbc853bc7e16166.r2.cloudflarestorage.com'
});
const BUCKET_NAME = 'youpage';
/** @type {import("@sveltejs/kit").RequestHandler} */
export async function POST({ request }) {
const data = await request.formData();
/** @type {Blob} */
const file = data.get('file');
const oldFilePath = data.get('oldFilePath'); // Path of the old file to delete if it exists
const blog_id = data.get('id');
if (!file) {
return json({ error: 'No file uploaded' }, { status: 400 });
}
const filePath = `uploads/${blog_id}-${file.name.slice(0,16)}`;
try {
// Upload the new file
const uploadParams = {
Bucket: BUCKET_NAME,
Key: filePath,
Body: new Uint8Array(await file.arrayBuffer()),
ContentType: file.type
};
await s3.upload(uploadParams).promise();
// Delete the old file if it exists
if (oldFilePath && oldFilePath !== "undefined") {
console.log("old file: ", oldFilePath)
const deleteParams = {
Bucket: BUCKET_NAME,
Key: oldFilePath
};
await s3.deleteObject(deleteParams).promise();
}
return json({ filePath: `https://pub-ccf2d12acd4047ab951129d9788c75d7.r2.dev/${filePath.replace("/", "%2F")}` });
} catch (error) {
console.error('File upload failed:', error);
return json({ error: 'File upload failed' }, { status: 500 });
}
}

View File

@ -4,16 +4,15 @@ import { redirect } from "@sveltejs/kit";
/** @type {import("./$types").LayoutServerLoad} */
export const load = async ({fetch, cookies}) => {
if(!cookies.get("token")) {
console.log("ruh roh no token")
return redirect(302, "/auth")
return redirect(302, "/app/auth");
}
const res = await fetch(config.api_url+"/me")
const res = await fetch(config.api_url+"/me");
if(res.status > 399 && res.status < 499) {
cookies.delete("token", {
path: "/"
});
redirect(302, "/auth");
redirect(302, "/app/auth");
}
const data = await res.json();

View File

@ -15,6 +15,7 @@
import { ModeWatcher, toggleMode } from 'mode-watcher';
import { Toaster } from '$lib/components/ui/sonner';
import { config } from '$lib';
/** @type {import('./$types').LayoutServerData} */
export let data;
@ -24,7 +25,7 @@
{ name: 'Articles', redirect: '/app/articles' },
{ name: 'Emails', redirect: '/app/emails' },
{ name: 'Website', redirect: '/app/website' },
{ name: 'Analytics', redirect: '##' },
// { name: 'Analytics', redirect: '##' },
];
async function logout() {
@ -60,7 +61,7 @@
<nav class="grid gap-6 text-lg font-medium">
<a href="##" class="flex items-center gap-2 text-lg font-semibold">
<Package2 class="h-6 w-6" />
<span class="sr-only">{data.me.user.name}</span>
<span class="sr-only">{data.me.name}</span>
</a>
{#each navs as nav}
<a href="{nav.redirect}" class="hover:text-foreground">{nav.name}</a>
@ -92,7 +93,7 @@
<span class="sr-only">Toggle theme</span>
</Button>
</div>
<form class="flex-1 sm:flex-initial">
<!-- <form class="flex-1 sm:flex-initial">
<div class="relative">
<Search class="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
@ -101,7 +102,10 @@
class="pl-8 sm:w-[300px] md:w-[200px] lg:w-[300px]"
/>
</div>
</form>
</form> -->
<div class="md:ml-0 ml-auto">
Tokens: <span>{data.me.tokens}</span>
</div>
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button builders={[builder]} variant="secondary" size="icon" class="rounded-full">
@ -112,7 +116,7 @@
<DropdownMenu.Content align="end">
<DropdownMenu.Label>My Account</DropdownMenu.Label>
<DropdownMenu.Separator />
<DropdownMenu.Item>Settings</DropdownMenu.Item>
<DropdownMenu.Item href={config.api_url + "/me/billing"}>Billing</DropdownMenu.Item>
<DropdownMenu.Item>Support</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item on:click={logout}>Logout</DropdownMenu.Item>

View File

@ -9,7 +9,7 @@ export const load = async ({fetch, cookies}) => {
// path: "/"
// });
redirect(302, "/auth");
redirect(302, "/app/auth");
}
const data = await res.json();

View File

@ -15,18 +15,18 @@
export let data;
</script>
<div class="grid gap-4 md:grid-cols-2 md:gap-8 lg:grid-cols-4">
<div class="grid gap-4 md:grid-cols-2 md:gap-8 lg:grid-cols-3">
<Card.Root>
<Card.Header class="flex flex-row items-center justify-between space-y-0 pb-2">
<Card.Title class="text-sm font-medium">Total Articles</Card.Title>
<DollarSign class="h-4 w-4 text-muted-foreground" />
</Card.Header>
<Card.Content>
<div class="text-2xl font-bold">48</div>
<div class="text-2xl font-bold">{data.dashboard_info.totalArticles}</div>
<p class="text-xs text-muted-foreground">7 remaining this month</p>
</Card.Content>
</Card.Root>
<Card.Root>
<!-- <Card.Root>
<Card.Header class="flex flex-row items-center justify-between space-y-0 pb-2">
<Card.Title class="text-sm font-medium">Subscriptions</Card.Title>
<Users class="h-4 w-4 text-muted-foreground" />
@ -35,15 +35,15 @@
<div class="text-2xl font-bold">+2350</div>
<p class="text-xs text-muted-foreground">+180.1% from last month</p>
</Card.Content>
</Card.Root>
</Card.Root> -->
<Card.Root>
<Card.Header class="flex flex-row items-center justify-between space-y-0 pb-2">
<Card.Title class="text-sm font-medium">Emails collected</Card.Title>
<CreditCard class="h-4 w-4 text-muted-foreground" />
</Card.Header>
<Card.Content>
<div class="text-2xl font-bold">+573</div>
<p class="text-xs text-muted-foreground">+19% from last month</p>
<div class="text-2xl font-bold">{data.dashboard_info.totalEmails}</div>
<!-- <p class="text-xs text-muted-foreground">+19% from last month</p> -->
</Card.Content>
</Card.Root>
<Card.Root>
@ -52,8 +52,8 @@
<Activity class="h-4 w-4 text-muted-foreground" />
</Card.Header>
<Card.Content>
<div class="text-2xl font-bold">+12,234</div>
<p class="text-xs text-muted-foreground">+201 since last hour</p>
<div class="text-2xl font-bold">{data.dashboard_info.totalViews}</div>
<!-- <p class="text-xs text-muted-foreground">+201 since last hour</p> -->
</Card.Content>
</Card.Root>
</div>

View File

@ -85,7 +85,7 @@
{/if}
</Table.Cell>
<Table.Cell class="max-w-[300px] overflow-hidden overflow-ellipsis text-nowrap"
>{article.id}</Table.Cell
>{article.title}</Table.Cell
>
<Table.Cell class="text-end">{'Youtube'}</Table.Cell>
<Table.Cell class="text-end">{article.views}</Table.Cell>
@ -118,12 +118,12 @@
<Pagination.Root count={data.total_articles} perPage={10} let:pages currentPage={currentPage}>
<Pagination.Content>
<Pagination.Item>
<!-- <Pagination.Item>
<Pagination.PrevButton>
<ChevronLeft class="h-4 w-4" />
<span class="hidden sm:block">Previous</span>
</Pagination.PrevButton>
</Pagination.Item>
</Pagination.Item> -->
{#each pages as page (page.key)}
{#if page.type === 'ellipsis'}
<Pagination.Item>
@ -145,12 +145,12 @@
</Pagination.Item>
{/if}
{/each}
<Pagination.Item>
<!-- <Pagination.Item>
<Pagination.NextButton>
<span class="hidden sm:block">Next</span>
<ChevronRight class="h-4 w-4" />
</Pagination.NextButton>
</Pagination.Item>
</Pagination.Item> -->
</Pagination.Content>
</Pagination.Root>
{:else}

View File

@ -65,7 +65,7 @@
>
<Form.Field {form} name="video_id">
<Form.Control let:attrs>
<div class="grid gap-4 py-4">
<div class="grid gap-4 mb-4">
<div class="grid grid-cols-4 items-center gap-4">
<Form.Label class="text-right">Youtube video*</Form.Label>
<!-- <Input
@ -97,7 +97,7 @@
</Form.Field>
<Form.Field {form} name="length">
<Form.Control let:attrs>
<div class="grid gap-4 py-4">
<div class="grid gap-4 mb-4">
<div class="grid grid-cols-4 items-center gap-4">
<Form.Label class="text-right">Article length</Form.Label>
<Select.Root portal={null} name="length">
@ -112,14 +112,16 @@
<Select.Item
value="1500"
label="Medium (~1500 words)"
disabled={['free', 'basic'].includes(tier)}
>Medium (~1500 words)<ProBadge /></Select.Item
>
>Medium (~1500 words)
<!-- <ProBadge /> -->
</Select.Item>
<!-- disabled={['free', 'basic'].includes(tier)} -->
<Select.Item
value="2500"
label="Long (~2500 words)"
disabled={['free', 'basic'].includes(tier)}
>Long (~2500 words)<ProBadge /></Select.Item
>Long (~2500 words)
<!-- <ProBadge /> -->
</Select.Item
>
</Select.Group>
</Select.Content>
@ -131,7 +133,7 @@
</Form.Field>
<Form.Field {form} name="format">
<Form.Control let:attrs>
<div class="grid gap-4 py-4">
<div class="grid gap-4 mb-4">
<div class="grid grid-cols-4 items-center gap-4">
<Form.Label class="text-right">Format</Form.Label>
<Select.Root portal={null} name="format">
@ -160,8 +162,9 @@
<div class="grid grid-cols-4 items-center gap-4">
<Form.Label class="text-right">Include FAQ</Form.Label>
<div class="flex items-center justify-start">
<Switch disabled={['free', 'basic'].includes(tier)} {...attrs} />
<ProBadge class="ml-[10px]" />
<!-- <Switch disabled={['free', 'basic'].includes(tier)} {...attrs} /> -->
<Switch {...attrs} />
<!-- <ProBadge class="ml-[10px]" /> -->
</div>
</div>
</Form.Control>

View File

@ -1,5 +1,5 @@
import { config } from "$lib";
import { fail, message, superValidate } from "sveltekit-superforms";
import { fail, message, superValidate, withFiles } from "sveltekit-superforms";
import { schema } from "./schema";
import { zod } from "sveltekit-superforms/adapters";
@ -9,10 +9,12 @@ export const load = async ({ fetch }) => {
credentials: 'include'
});
const {site} = await blogRes.json();
const { site } = await blogRes.json();
site.primary_color_hex = "#" + site.primary_color_hex
site.secondary_color_hex = "#" + site.secondary_color_hex
site.text_color_hex = "#" + site.text_color_hex
// console.log("getting back", site)
return {
blog_info: site,
form: await superValidate(site, zod(schema))
@ -25,7 +27,7 @@ export const actions = {
const form = await superValidate(event, zod(schema));
if (!form.valid) {
return fail(400, {
form,
form
});
}
@ -48,7 +50,7 @@ export const actions = {
});
return {
form,
form: form,
};
},
}

View File

@ -1,77 +1,237 @@
<script>
import * as Form from '$lib/components/ui/form';
import { Input } from '$lib/components/ui/input';
// @ts-ignore
import { Switch } from '$lib/components/ui/switch';
import { superForm } from 'sveltekit-superforms';
import { zodClient } from 'sveltekit-superforms/adapters';
import { schema } from './schema';
import ColorPicker from 'svelte-awesome-color-picker';
import { toast } from 'svelte-sonner';
import { Textarea } from '$lib/components/ui/textarea';
import { config } from '$lib';
/** @type {import("./$types").PageServerData} */
export let data;
const form = superForm(data.form, {
validators: zodClient(schema),
resetForm: false,
onResult: (e) => {
if(e.result.type == "success") {
toast.success("Website configuration successfully updated!");
}
else {
toast.error("Error when updating website.");
}
}
resetForm: false,
onResult: (e) => {
if (e.result.type == 'success') {
toast.success('Website configuration successfully updated!');
} else {
console.log(e.result)
toast.error('Error when updating website.');
}
}
});
const { form: formData, enhance } = form;
$formData.id = data.blog_info.id
console.log(data.blog_info)
$: {
console.log($formData.primary_color_hex)
}
const { form: formData, enhance, tainted, isTainted } = form;
$formData.id = data.blog_info.id;
/**
* @param {Event} event
* @param {string} oldValue
*/
async function handleFileChange(event, oldValue) {
if (!event.target) return;
// @ts-ignore
let file = event.target.files[0];
return await uploadFile(file, oldValue);
}
/**
* @param {Blob} file
* @param {string} oldValue
*/
async function uploadFile(file, oldValue) {
const formData = new FormData();
formData.append('file', file);
formData.append('oldFilePath', oldValue);
formData.append('id', data.blog_info.id);
const response = await fetch('/api/upload-asset', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.filePath) {
return result.filePath;
} else {
console.error('File upload failed:', result.error);
}
}
let disable_freebies = !$formData.use_freebie;
$: disable_freebies = !$formData.use_freebie;
</script>
<div class="max-w-2xl w-full">
<form method="post" use:enhance>
<input type="text" value="{data.blog_info.id}" name="id" readonly class="hidden">
<Form.Field {form} name="name">
<Form.Control let:attrs>
<Form.Label>Blog name</Form.Label>
<Input {...attrs} bind:value={$formData.name} />
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="primary_color_hex">
<Form.Control let:attrs>
<Form.Label>Primary color</Form.Label>
<ColorPicker on:input={e=> {
if(e.detail.hex) $formData.primary_color_hex = e.detail.hex
}} hex={data.blog_info.primary_color_hex} {...attrs}/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="secondary_color_hex">
<Form.Control let:attrs>
<Form.Label>Secondary color</Form.Label>
<ColorPicker on:input={e=> {
if(e.detail.hex) $formData.secondary_color_hex = e.detail.hex
}} hex={data.blog_info.secondary_color_hex} {...attrs}/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="text_color_hex">
<Form.Control let:attrs>
<Form.Label>Text color</Form.Label>
<ColorPicker on:input={e=> {
if(e.detail.hex) $formData.text_color_hex = e.detail.hex
}} hex={data.blog_info.text_color_hex} {...attrs}/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Button>Submit</Form.Button>
<div class="w-full max-w-7xl">
<form method="post" use:enhance enctype="multipart/form-data">
<input type="text" value={data.blog_info.id} name="id" readonly class="hidden" />
<div class="grid grid-cols-2 gap-16">
<div>
<h2 class="font-bold text-2xl mb-4">Basics</h2>
<Form.Field {form} name="name">
<Form.Control let:attrs>
<Form.Label>Blog name</Form.Label>
<Input {...attrs} bind:value={$formData.name} />
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="title">
<Form.Control let:attrs>
<Form.Label>Blog title</Form.Label>
<Input {...attrs} bind:value={$formData.title} />
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="subtitle">
<Form.Control let:attrs>
<Form.Label>Blog subtitle</Form.Label>
<Input {...attrs} bind:value={$formData.subtitle} />
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="primary_color_hex">
<Form.Control let:attrs>
<Form.Label>Primary color</Form.Label>
<ColorPicker
on:input={(e) => {
if (e.detail.hex) $formData.primary_color_hex = e.detail.hex;
}}
hex={data.blog_info.primary_color_hex}
{...attrs}
/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="secondary_color_hex">
<Form.Control let:attrs>
<Form.Label>Secondary color</Form.Label>
<ColorPicker
on:input={(e) => {
if (e.detail.hex) $formData.secondary_color_hex = e.detail.hex;
}}
hex={data.blog_info.secondary_color_hex}
{...attrs}
/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="text_color_hex">
<Form.Control let:attrs>
<Form.Label>Text color</Form.Label>
<ColorPicker
on:input={(e) => {
if (e.detail.hex) $formData.text_color_hex = e.detail.hex;
}}
hex={data.blog_info.text_color_hex}
{...attrs}
/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="domain">
<Form.Control let:attrs>
<Form.Label>Custom domain</Form.Label>
<Input {...attrs} bind:value={$formData.domain} />
</Form.Control>
{#if data.blog_info.subdomain_slug}
<Form.Description>You can also access your website at <a href="http://{data.blog_info.subdomain_slug}.{config.sites_url}" class="underline font-semibold">{data.blog_info.subdomain_slug}.{config.sites_url}</a></Form.Description>
{/if}
<Form.FieldErrors />
</Form.Field>
</div>
<div>
<h2 class="font-bold text-2xl mb-4">Freebies</h2>
<Form.Field {form} name="use_freebie">
<Form.Control let:attrs>
<Form.Label class="text-right">Send freebie</Form.Label>
<div class="flex items-center justify-start">
<!-- <Switch disabled={['free', 'basic'].includes(tier)} {...attrs} /> -->
<Switch {...attrs} bind:checked={$formData.use_freebie} />
<!-- <ProBadge class="ml-[10px]" /> -->
</div>
<Form.Description
>Whether to send a freebie when a new person enters their email on your website.</Form.Description
>
</Form.Control>
</Form.Field>
<Form.Field {form} name="freebie_name">
<Form.Control let:attrs>
<Form.Label class="text-right">Freebie Name</Form.Label>
<div class="flex items-center justify-start">
<Input
{...attrs}
bind:value={$formData.freebie_name}
bind:readonly={disable_freebies}
/>
</div>
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="freebie_url">
<Form.Control let:attrs>
<Form.Label class="text-right">Freebie file</Form.Label>
<div class="flex items-center justify-start">
<Input
type="file"
on:input={(e) =>
handleFileChange(e, $formData.freebie_url).then((x) => {
$formData.freebie_url = x;
})}
bind:disabled={disable_freebies}
/>
<Input {...attrs} class="hidden" bind:value={$formData.freebie_url} readonly />
</div>
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="freebie_image_url">
<Form.Control let:attrs>
<Form.Label class="text-right">Freebie image</Form.Label>
<div class="flex items-center justify-start">
<Input
type="file"
accept="png,jpg,webp,jpeg"
on:input={(e) =>
handleFileChange(e, $formData.freebie_image_url).then(
(x) => ($formData.freebie_image_url = x)
)}
bind:disabled={disable_freebies}
/>
<Input {...attrs} class="hidden" bind:value={$formData.freebie_image_url} readonly />
</div>
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="freebie_text">
<Form.Control let:attrs>
<Form.Label class="text-right">Freebie text</Form.Label>
<div class="flex items-center justify-start">
<Textarea
{...attrs}
bind:value={$formData.freebie_text}
/>
</div>
</Form.Control>
<Form.FieldErrors />
<Form.Description>The text displayed next to the signup form on your blog.</Form.Description>
</Form.Field>
</div>
</div>
<Form.Button disabled={!isTainted($tainted)}>Submit</Form.Button>
</form>
</div>

View File

@ -6,4 +6,37 @@ export const schema = z.object({
primary_color_hex: z.string().length(7),
secondary_color_hex: z.string().length(7),
text_color_hex: z.string().length(7),
domain: z.string(),
use_freebie: z.boolean(),
freebie_name: z.string(),
freebie_url: z.string(),
freebie_image_url: z.string(),
freebie_text: z.string(),
title: z.string(),
subtitle: z.string(),
}).superRefine((data, ctx) => {
console.log(data);
if (data.use_freebie) {
if (!data.freebie_name || data.freebie_name.length === 0) {
ctx.addIssue({
path: ['freebie_name'],
message: "A freebie name' is required when 'Use freebie' is true.",
code: "custom"
});
}
if (!data.freebie_url) {
ctx.addIssue({
path: ['freebie_url'],
message: "A freebie file is required when 'Use freebie' is true.",
code: "custom"
});
}
if (!data.freebie_image_url) {
ctx.addIssue({
path: ['freebie_image'],
message: "'freebie_image' is required when 'use_freebie' is true.",
code: "custom"
});
}
}
});

View File

@ -25,7 +25,7 @@ export const load = async ({ request, cookies }) => {
} catch (e) {
console.log(e);
}
redirect(302, "/");
redirect(302, "/app");
}
return {

View File

@ -8,7 +8,7 @@
<ModeWatcher />
<div class="mx-auto flex h-full w-full max-w-64 items-center justify-center">
<div class="mx-auto flex h-screen w-screen max-w-64 items-center justify-center">
<!-- <Button href="{config.api_url}/auth/google"><GoogleIcon class="h-4 w-4 mr-2" /> Log in with google</Button> -->
<a
href="{config.api_url}/auth/google"

View File

@ -0,0 +1,6 @@
/** @type {import('./$types').RequestHandler} */
export function GET(event) {
console.log(event.request.referrer);
return new Response("success");
}

View File

@ -1,7 +1,7 @@
<script>
import { browser } from '$app/environment';
import { enhance } from '$app/forms';
import '../../../../app.pcss';
import '../../../app.pcss';
let currentPath = '';