diff --git a/README.md b/README.md index 061277f0..95cf9704 100644 --- a/README.md +++ b/README.md @@ -1 +1,98 @@ -# seb44_main_005 +# ๐Ÿ‹ ์•กํ‹ฐ์˜จ(ActiOn) +

+แ„†แ…ฎแ„Œแ…ฆ + +

+ + +### ๐Ÿ–๏ธ ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„: [![Since](https://img.shields.io/badge/since-2023.07.06-D1B6E1.svg?&edge_flat=false)](https://github.com/codestates-seb/seb44_main_005) ~ [![End](https://img.shields.io/badge/end-2023.07.24-D1B6E1.svg?&edge_flat=false)](https://github.com/codestates-seb/seb44_main_005) + +### ๐Ÿ๏ธ ๋ฐฐํฌ ๋งํฌ : [Acti-On](http://ac-ti-on.s3-website.ap-northeast-2.amazonaws.com/) + + +
+ +## ๐Ÿ‘ฅ ํŒ€์› ์†Œ๊ฐœ +|![๊น€ํƒœ์šฐ](https://github.com/TaeWooKim-SCH.png)|![๊น€๋ฏผ์ง€](https://github.com/kminvita.png)|![ํ˜„์ฑ„์€](https://github.com/chen4023.png)|![๊ฐ•๋™์šฐ](https://github.com/developer-DongWoo.png)|![์‹ ์ด์ˆ˜](https://github.com/isu-nice.png)| +|---|---|---|---|---| +|[๊น€ํƒœ์šฐ](https://github.com/TaeWooKim-SCH)|[๊น€๋ฏผ์ง€](https://github.com/kminvita)|[ํ˜„์ฑ„์€](https://github.com/chen4023)|[๊ฐ•๋™์šฐ](https://github.com/developer-DongWoo)|[์‹ ์ด์ˆ˜](https://github.com/isu-nice)| +|FE ํŒ€์žฅ|FE ํŒ€์›|FE ํŒ€์›|BE ๋ถ€ํŒ€์žฅ|BE ํŒ€์›| + +
+
+ +## ๐Ÿ‹ ์•กํ‹ฐ์˜จ(ActiOn)์—์„œ๋Š” ์–ด๋–ค ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‚˜์š” ? + + ### ์ œ์ฃผ๋„์—์„œ ํŠน๋ณ„ํ•œ ๊ฒฝํ—˜์„ ๋งŒ๋“ค๊ณ  ์‹ถ์œผ์‹  ๋ถ„๋“ค์—๊ฒŒ ๋‹ค์–‘ํ•œ ๋ ˆ์ € ์˜ˆ์•ฝ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ด๋“œ๋ฆฝ๋‹ˆ๋‹ค +
+ +

+ +

+ +
+
+ + + |![๊ธฐ๋Šฅ1](https://github.com/codestates-seb/seb44_main_005/assets/106866926/d95f4411-b1ba-4bea-9f8b-d5667eba1c30)|![๊ธฐ๋Šฅ2](https://github.com/codestates-seb/seb44_main_005/assets/106866926/c54ff1bf-ea0a-467c-8d4e-a4ce2fbcbce0)| + |---|---| + |![๊ธฐ๋Šฅ3](https://github.com/codestates-seb/seb44_main_005/assets/106866926/c6e377af-f7b8-49cc-bd4f-b680512ce913)|![๊ธฐ๋Šฅ4](https://github.com/codestates-seb/seb44_main_005/assets/106866926/6d5a652d-d54c-4743-9e25-96e2f7156f96)| + +
+
+
+ + +## ๐Ÿ› ๏ธ Stack + +

+ + + +

+ +
+
+
+ + ## โš™๏ธ ๋‹ด๋‹น ํŒŒํŠธ + + |ํ”„๋ก ํŠธ ๋‹ด๋‹นํŒŒํŠธ|๋ฐฑ์—”๋“œ ๋‹ด๋‹นํŒŒํŠธ| + |---|---| + |![ํ”„๋ก ํŠธ](https://github.com/codestates-seb/seb44_main_005/assets/106866926/ec1d30c8-a5d0-403a-aa13-0cea83c96701)|![๋ฐฑ์—”๋“œ](https://github.com/codestates-seb/seb44_main_005/assets/106866926/232f70d0-e3dd-4260-8563-45dc75fcb710)| + +
+
+
+ + + +## ๐Ÿ“‚ Documents +### [โœ๏ธ ์‚ฌ์šฉ์ž ์š”๊ตฌ์‚ฌํ•ญ ์ •์˜์„œ](https://www.notion.so/codestates/db6bf9c5921a4e3ca9ac1c50ada9b733?v=7cf202032177497ab5ca9f8a40470389&pvs=4) +### [โœ๏ธ API ๋ช…์„ธ์„œ](https://www.notion.so/codestates/API-19b0436b7f1347bfbc37113fe4abcfdf?pvs=4) +### [โœ๏ธ ERD]() +
+ +
+
+ +### [โœ๏ธ ํ™”๋ฉด ์ •์˜์„œ](https://www.figma.com/embed?embed_host=notion&url=https%3A%2F%2Fwww.figma.com%2Ffile%2F1vjGhkjq29PfthTwTSINtA%2FActiOn---Design%3Ftype%3Ddesign%26node-id%3D0%3A1%26mode%3Ddesign%26t%3DhTD356WXL3mu34Nz-1) +
+แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-07-24 แ„‹แ…ฉแ„’แ…ฎ 1 43 52 + +
+
+
+ + +## โœจGit Commit & PR Message + +| ํƒœ๊ทธ์ด๋ฆ„ | ์„ค๋ช… | +| -------- | ----------------------------------------------------- | +| feat | ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€ | +| fix | ๋ฒ„๊ทธ ์ˆ˜์ • | +| design | CSS ๋“ฑ UI ์ˆ˜์ • | +| style | ์ฝ”๋“œ ํฌ๋งท ๋ณ€๊ฒฝ, ์„ธ๋ฏธ ์ฝœ๋ก  ๋ˆ„๋ฝ, ์ฝ”๋“œ ์ˆ˜์ •์ด ์—†๋Š” ๊ฒฝ์šฐ | +| refactor | ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง | +| docs | ๋ฌธ์„œ ์ˆ˜์ • | +| test | ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ • ํ•˜๋Š” ๊ฒฝ์šฐ | diff --git a/client/.env b/client/.env index 980e0936..d4b0db16 100644 --- a/client/.env +++ b/client/.env @@ -1,5 +1,4 @@ - -VITE_APP_API_URL=https://85b2-121-176-132-24.ngrok-free.app +VITE_APP_API_URL=http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080 VITE_APP_CLIENT_ID=810037556553-l3tm2nq6j7en13fb0fgrppafm1e7mhvu.apps.googleusercontent.com VITE_APP_REDIRECT_URI =http://localhost:5173/login/oauth2/code/google diff --git a/client/dist/_redirects b/client/dist/_redirects new file mode 100644 index 00000000..f8243379 --- /dev/null +++ b/client/dist/_redirects @@ -0,0 +1 @@ +/* /index.html 200 \ No newline at end of file diff --git a/client/dist/assets/NanumSquareNeo-aLt-1b9af8b2.ttf b/client/dist/assets/NanumSquareNeo-aLt-1b9af8b2.ttf new file mode 100644 index 00000000..59461879 Binary files /dev/null and b/client/dist/assets/NanumSquareNeo-aLt-1b9af8b2.ttf differ diff --git a/client/dist/assets/NanumSquareNeo-bRg-864de849.ttf b/client/dist/assets/NanumSquareNeo-bRg-864de849.ttf new file mode 100644 index 00000000..8680fb38 Binary files /dev/null and b/client/dist/assets/NanumSquareNeo-bRg-864de849.ttf differ diff --git a/client/dist/assets/NanumSquareNeo-cBd-4749fa56.ttf b/client/dist/assets/NanumSquareNeo-cBd-4749fa56.ttf new file mode 100644 index 00000000..ccde7f70 Binary files /dev/null and b/client/dist/assets/NanumSquareNeo-cBd-4749fa56.ttf differ diff --git a/client/dist/assets/NanumSquareNeo-dEb-3cedb3ee.ttf b/client/dist/assets/NanumSquareNeo-dEb-3cedb3ee.ttf new file mode 100644 index 00000000..0f3b2a81 Binary files /dev/null and b/client/dist/assets/NanumSquareNeo-dEb-3cedb3ee.ttf differ diff --git a/client/dist/assets/NanumSquareNeo-eHv-a2850a33.ttf b/client/dist/assets/NanumSquareNeo-eHv-a2850a33.ttf new file mode 100644 index 00000000..51a02abf Binary files /dev/null and b/client/dist/assets/NanumSquareNeo-eHv-a2850a33.ttf differ diff --git a/client/dist/assets/activity-224a3acc.svg b/client/dist/assets/activity-224a3acc.svg new file mode 100644 index 00000000..36335df4 --- /dev/null +++ b/client/dist/assets/activity-224a3acc.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/all-234340ae.svg b/client/dist/assets/all-234340ae.svg new file mode 100644 index 00000000..a1bcd9f9 --- /dev/null +++ b/client/dist/assets/all-234340ae.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/atv-768e6dd8.svg b/client/dist/assets/atv-768e6dd8.svg new file mode 100644 index 00000000..fc6eccf3 --- /dev/null +++ b/client/dist/assets/atv-768e6dd8.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/bg3-1869f4c7.svg b/client/dist/assets/bg3-1869f4c7.svg new file mode 100644 index 00000000..748a396e --- /dev/null +++ b/client/dist/assets/bg3-1869f4c7.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/dist/assets/bottom-890eee8a.svg b/client/dist/assets/bottom-890eee8a.svg new file mode 100644 index 00000000..c9324bf0 --- /dev/null +++ b/client/dist/assets/bottom-890eee8a.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/dist/assets/close-8ae4dc29.svg b/client/dist/assets/close-8ae4dc29.svg new file mode 100644 index 00000000..ac64b72e --- /dev/null +++ b/client/dist/assets/close-8ae4dc29.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/diving-783d9b05.svg b/client/dist/assets/diving-783d9b05.svg new file mode 100644 index 00000000..13f08ee8 --- /dev/null +++ b/client/dist/assets/diving-783d9b05.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/emptyStar-c709dc52.svg b/client/dist/assets/emptyStar-c709dc52.svg new file mode 100644 index 00000000..3bcf7dc3 --- /dev/null +++ b/client/dist/assets/emptyStar-c709dc52.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/favicon-2b274266.svg b/client/dist/assets/favicon-2b274266.svg new file mode 100644 index 00000000..99d28511 --- /dev/null +++ b/client/dist/assets/favicon-2b274266.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/fillStar-ef57f9e5.svg b/client/dist/assets/fillStar-ef57f9e5.svg new file mode 100644 index 00000000..4aea33ac --- /dev/null +++ b/client/dist/assets/fillStar-ef57f9e5.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/google-60b8f21d.svg b/client/dist/assets/google-60b8f21d.svg new file mode 100644 index 00000000..12a55ef0 --- /dev/null +++ b/client/dist/assets/google-60b8f21d.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/client/dist/assets/headerlogo-2a4f0716.svg b/client/dist/assets/headerlogo-2a4f0716.svg new file mode 100644 index 00000000..ed3bcd6e --- /dev/null +++ b/client/dist/assets/headerlogo-2a4f0716.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/index-79531179.js b/client/dist/assets/index-79531179.js new file mode 100644 index 00000000..a6327cd9 --- /dev/null +++ b/client/dist/assets/index-79531179.js @@ -0,0 +1,1286 @@ +var DS=Object.defineProperty;var OS=(e,t,n)=>t in e?DS(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var _i=(e,t,n)=>(OS(e,typeof t!="symbol"?t+"":t,n),n);function BS(e,t){for(var n=0;nr[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const s of o)if(s.type==="childList")for(const i of s.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function n(o){const s={};return o.integrity&&(s.integrity=o.integrity),o.referrerPolicy&&(s.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?s.credentials="include":o.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(o){if(o.ep)return;o.ep=!0;const s=n(o);fetch(o.href,s)}})();function ci(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function VS(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var n=function r(){if(this instanceof r){var o=[null];o.push.apply(o,arguments);var s=Function.bind.apply(t,o);return new s}return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}),n}var xv={exports:{}},xl={},wv={exports:{}},fe={};/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var ui=Symbol.for("react.element"),zS=Symbol.for("react.portal"),FS=Symbol.for("react.fragment"),US=Symbol.for("react.strict_mode"),$S=Symbol.for("react.profiler"),WS=Symbol.for("react.provider"),HS=Symbol.for("react.context"),GS=Symbol.for("react.forward_ref"),KS=Symbol.for("react.suspense"),JS=Symbol.for("react.memo"),YS=Symbol.for("react.lazy"),qp=Symbol.iterator;function ZS(e){return e===null||typeof e!="object"?null:(e=qp&&e[qp]||e["@@iterator"],typeof e=="function"?e:null)}var Sv={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Cv=Object.assign,bv={};function zo(e,t,n){this.props=e,this.context=t,this.refs=bv,this.updater=n||Sv}zo.prototype.isReactComponent={};zo.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};zo.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function Av(){}Av.prototype=zo.prototype;function qd(e,t,n){this.props=e,this.context=t,this.refs=bv,this.updater=n||Sv}var ef=qd.prototype=new Av;ef.constructor=qd;Cv(ef,zo.prototype);ef.isPureReactComponent=!0;var eh=Array.isArray,kv=Object.prototype.hasOwnProperty,tf={current:null},Ev={key:!0,ref:!0,__self:!0,__source:!0};function Rv(e,t,n){var r,o={},s=null,i=null;if(t!=null)for(r in t.ref!==void 0&&(i=t.ref),t.key!==void 0&&(s=""+t.key),t)kv.call(t,r)&&!Ev.hasOwnProperty(r)&&(o[r]=t[r]);var a=arguments.length-2;if(a===1)o.children=n;else if(1>>1,R=z[X];if(0>>1;Xo(J,q))$o(te,J)?(z[X]=te,z[$]=q,X=$):(z[X]=J,z[B]=q,X=B);else if($o(te,q))z[X]=te,z[$]=q,X=$;else break e}}return W}function o(z,W){var q=z.sortIndex-W.sortIndex;return q!==0?q:z.id-W.id}if(typeof performance=="object"&&typeof performance.now=="function"){var s=performance;e.unstable_now=function(){return s.now()}}else{var i=Date,a=i.now();e.unstable_now=function(){return i.now()-a}}var l=[],c=[],d=1,f=null,p=3,h=!1,v=!1,x=!1,C=typeof setTimeout=="function"?setTimeout:null,g=typeof clearTimeout=="function"?clearTimeout:null,m=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function y(z){for(var W=n(c);W!==null;){if(W.callback===null)r(c);else if(W.startTime<=z)r(c),W.sortIndex=W.expirationTime,t(l,W);else break;W=n(c)}}function S(z){if(x=!1,y(z),!v)if(n(l)!==null)v=!0,Z(A);else{var W=n(c);W!==null&&ne(S,W.startTime-z)}}function A(z,W){v=!1,x&&(x=!1,g(k),k=-1),h=!0;var q=p;try{for(y(W),f=n(l);f!==null&&(!(f.expirationTime>W)||z&&!T());){var X=f.callback;if(typeof X=="function"){f.callback=null,p=f.priorityLevel;var R=X(f.expirationTime<=W);W=e.unstable_now(),typeof R=="function"?f.callback=R:f===n(l)&&r(l),y(W)}else r(l);f=n(l)}if(f!==null)var j=!0;else{var B=n(c);B!==null&&ne(S,B.startTime-W),j=!1}return j}finally{f=null,p=q,h=!1}}var L=!1,_=null,k=-1,M=5,I=-1;function T(){return!(e.unstable_now()-Iz||125X?(z.sortIndex=q,t(c,z),n(l)===null&&z===n(c)&&(x?(g(k),k=-1):x=!0,ne(S,q-X))):(z.sortIndex=R,t(l,z),v||h||(v=!0,Z(A))),z},e.unstable_shouldYield=T,e.unstable_wrapCallback=function(z){var W=p;return function(){var q=p;p=W;try{return z.apply(this,arguments)}finally{p=q}}}})(Nv);Pv.exports=Nv;var l2=Pv.exports;/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Lv=w,Nt=l2;function U(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Nu=Object.prototype.hasOwnProperty,c2=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,nh={},rh={};function u2(e){return Nu.call(rh,e)?!0:Nu.call(nh,e)?!1:c2.test(e)?rh[e]=!0:(nh[e]=!0,!1)}function d2(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function f2(e,t,n,r){if(t===null||typeof t>"u"||d2(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function gt(e,t,n,r,o,s,i){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=s,this.removeEmptyString=i}var rt={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){rt[e]=new gt(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];rt[t]=new gt(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){rt[e]=new gt(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){rt[e]=new gt(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){rt[e]=new gt(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){rt[e]=new gt(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){rt[e]=new gt(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){rt[e]=new gt(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){rt[e]=new gt(e,5,!1,e.toLowerCase(),null,!1,!1)});var rf=/[\-:]([a-z])/g;function of(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(rf,of);rt[t]=new gt(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(rf,of);rt[t]=new gt(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(rf,of);rt[t]=new gt(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){rt[e]=new gt(e,1,!1,e.toLowerCase(),null,!1,!1)});rt.xlinkHref=new gt("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){rt[e]=new gt(e,1,!1,e.toLowerCase(),null,!0,!0)});function sf(e,t,n,r){var o=rt.hasOwnProperty(t)?rt[t]:null;(o!==null?o.type!==0:r||!(2a||o[i]!==s[a]){var l=` +`+o[i].replace(" at new "," at ");return e.displayName&&l.includes("")&&(l=l.replace("",e.displayName)),l}while(1<=i&&0<=a);break}}}finally{Ac=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?gs(e):""}function p2(e){switch(e.tag){case 5:return gs(e.type);case 16:return gs("Lazy");case 13:return gs("Suspense");case 19:return gs("SuspenseList");case 0:case 2:case 15:return e=kc(e.type,!1),e;case 11:return e=kc(e.type.render,!1),e;case 1:return e=kc(e.type,!0),e;default:return""}}function Mu(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case to:return"Fragment";case eo:return"Portal";case Lu:return"Profiler";case af:return"StrictMode";case _u:return"Suspense";case Iu:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Mv:return(e.displayName||"Context")+".Consumer";case Iv:return(e._context.displayName||"Context")+".Provider";case lf:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case cf:return t=e.displayName||null,t!==null?t:Mu(e.type)||"Memo";case Mn:t=e._payload,e=e._init;try{return Mu(e(t))}catch{}}return null}function h2(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Mu(t);case 8:return t===af?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function rr(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function Ov(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function m2(e){var t=Ov(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var o=n.get,s=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(i){r=""+i,s.call(this,i)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(i){r=""+i},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Di(e){e._valueTracker||(e._valueTracker=m2(e))}function Bv(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Ov(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function Ta(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Du(e,t){var n=t.checked;return Oe({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function sh(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=rr(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function Vv(e,t){t=t.checked,t!=null&&sf(e,"checked",t,!1)}function Ou(e,t){Vv(e,t);var n=rr(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Bu(e,t.type,n):t.hasOwnProperty("defaultValue")&&Bu(e,t.type,rr(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function ih(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Bu(e,t,n){(t!=="number"||Ta(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var vs=Array.isArray;function vo(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o"+t.valueOf().toString()+"",t=Oi.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Us(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var bs={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},g2=["Webkit","ms","Moz","O"];Object.keys(bs).forEach(function(e){g2.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),bs[t]=bs[e]})});function $v(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||bs.hasOwnProperty(e)&&bs[e]?(""+t).trim():t+"px"}function Wv(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,o=$v(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}var v2=Oe({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Fu(e,t){if(t){if(v2[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(U(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(U(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(U(61))}if(t.style!=null&&typeof t.style!="object")throw Error(U(62))}}function Uu(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var $u=null;function uf(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Wu=null,yo=null,xo=null;function ch(e){if(e=pi(e)){if(typeof Wu!="function")throw Error(U(280));var t=e.stateNode;t&&(t=Al(t),Wu(e.stateNode,e.type,t))}}function Hv(e){yo?xo?xo.push(e):xo=[e]:yo=e}function Gv(){if(yo){var e=yo,t=xo;if(xo=yo=null,ch(e),t)for(e=0;e>>=0,e===0?32:31-(T2(e)/j2|0)|0}var Bi=64,Vi=4194304;function ys(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function La(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,o=e.suspendedLanes,s=e.pingedLanes,i=n&268435455;if(i!==0){var a=i&~o;a!==0?r=ys(a):(s&=i,s!==0&&(r=ys(s)))}else i=n&~o,i!==0?r=ys(i):s!==0&&(r=ys(s));if(r===0)return 0;if(t!==0&&t!==r&&!(t&o)&&(o=r&-r,s=t&-t,o>=s||o===16&&(s&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function di(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Xt(t),e[t]=n}function _2(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=ks),yh=String.fromCharCode(32),xh=!1;function f0(e,t){switch(e){case"keyup":return aC.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function p0(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var no=!1;function cC(e,t){switch(e){case"compositionend":return p0(t);case"keypress":return t.which!==32?null:(xh=!0,yh);case"textInput":return e=t.data,e===yh&&xh?null:e;default:return null}}function uC(e,t){if(no)return e==="compositionend"||!yf&&f0(e,t)?(e=u0(),ma=mf=Fn=null,no=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=bh(n)}}function v0(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?v0(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function y0(){for(var e=window,t=Ta();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Ta(e.document)}return t}function xf(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function xC(e){var t=y0(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&v0(n.ownerDocument.documentElement,n)){if(r!==null&&xf(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var o=n.textContent.length,s=Math.min(r.start,o);r=r.end===void 0?s:Math.min(r.end,o),!e.extend&&s>r&&(o=r,r=s,s=o),o=Ah(n,s);var i=Ah(n,r);o&&i&&(e.rangeCount!==1||e.anchorNode!==o.node||e.anchorOffset!==o.offset||e.focusNode!==i.node||e.focusOffset!==i.offset)&&(t=t.createRange(),t.setStart(o.node,o.offset),e.removeAllRanges(),s>r?(e.addRange(t),e.extend(i.node,i.offset)):(t.setEnd(i.node,i.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,ro=null,Zu=null,Rs=null,Qu=!1;function kh(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Qu||ro==null||ro!==Ta(r)||(r=ro,"selectionStart"in r&&xf(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Rs&&Js(Rs,r)||(Rs=r,r=Ma(Zu,"onSelect"),0io||(e.current=rd[io],rd[io]=null,io--)}function Ce(e,t){io++,rd[io]=e.current,e.current=t}var or={},ct=lr(or),St=lr(!1),Lr=or;function ko(e,t){var n=e.type.contextTypes;if(!n)return or;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o={},s;for(s in n)o[s]=t[s];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function Ct(e){return e=e.childContextTypes,e!=null}function Oa(){Ee(St),Ee(ct)}function Lh(e,t,n){if(ct.current!==or)throw Error(U(168));Ce(ct,t),Ce(St,n)}function R0(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var o in r)if(!(o in t))throw Error(U(108,h2(e)||"Unknown",o));return Oe({},n,r)}function Ba(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||or,Lr=ct.current,Ce(ct,e),Ce(St,St.current),!0}function _h(e,t,n){var r=e.stateNode;if(!r)throw Error(U(169));n?(e=R0(e,t,Lr),r.__reactInternalMemoizedMergedChildContext=e,Ee(St),Ee(ct),Ce(ct,e)):Ee(St),Ce(St,n)}var mn=null,kl=!1,Vc=!1;function T0(e){mn===null?mn=[e]:mn.push(e)}function NC(e){kl=!0,T0(e)}function cr(){if(!Vc&&mn!==null){Vc=!0;var e=0,t=ve;try{var n=mn;for(ve=1;e>=i,o-=i,gn=1<<32-Xt(t)+o|n<k?(M=_,_=null):M=_.sibling;var I=p(g,_,y[k],S);if(I===null){_===null&&(_=M);break}e&&_&&I.alternate===null&&t(g,_),m=s(I,m,k),L===null?A=I:L.sibling=I,L=I,_=M}if(k===y.length)return n(g,_),Pe&&yr(g,k),A;if(_===null){for(;kk?(M=_,_=null):M=_.sibling;var T=p(g,_,I.value,S);if(T===null){_===null&&(_=M);break}e&&_&&T.alternate===null&&t(g,_),m=s(T,m,k),L===null?A=T:L.sibling=T,L=T,_=M}if(I.done)return n(g,_),Pe&&yr(g,k),A;if(_===null){for(;!I.done;k++,I=y.next())I=f(g,I.value,S),I!==null&&(m=s(I,m,k),L===null?A=I:L.sibling=I,L=I);return Pe&&yr(g,k),A}for(_=r(g,_);!I.done;k++,I=y.next())I=h(_,g,k,I.value,S),I!==null&&(e&&I.alternate!==null&&_.delete(I.key===null?k:I.key),m=s(I,m,k),L===null?A=I:L.sibling=I,L=I);return e&&_.forEach(function(O){return t(g,O)}),Pe&&yr(g,k),A}function C(g,m,y,S){if(typeof y=="object"&&y!==null&&y.type===to&&y.key===null&&(y=y.props.children),typeof y=="object"&&y!==null){switch(y.$$typeof){case Mi:e:{for(var A=y.key,L=m;L!==null;){if(L.key===A){if(A=y.type,A===to){if(L.tag===7){n(g,L.sibling),m=o(L,y.props.children),m.return=g,g=m;break e}}else if(L.elementType===A||typeof A=="object"&&A!==null&&A.$$typeof===Mn&&zh(A)===L.type){n(g,L.sibling),m=o(L,y.props),m.ref=qo(g,L,y),m.return=g,g=m;break e}n(g,L);break}else t(g,L);L=L.sibling}y.type===to?(m=Pr(y.props.children,g.mode,S,y.key),m.return=g,g=m):(S=ba(y.type,y.key,y.props,null,g.mode,S),S.ref=qo(g,m,y),S.return=g,g=S)}return i(g);case eo:e:{for(L=y.key;m!==null;){if(m.key===L)if(m.tag===4&&m.stateNode.containerInfo===y.containerInfo&&m.stateNode.implementation===y.implementation){n(g,m.sibling),m=o(m,y.children||[]),m.return=g,g=m;break e}else{n(g,m);break}else t(g,m);m=m.sibling}m=Kc(y,g.mode,S),m.return=g,g=m}return i(g);case Mn:return L=y._init,C(g,m,L(y._payload),S)}if(vs(y))return v(g,m,y,S);if(Jo(y))return x(g,m,y,S);Gi(g,y)}return typeof y=="string"&&y!==""||typeof y=="number"?(y=""+y,m!==null&&m.tag===6?(n(g,m.sibling),m=o(m,y),m.return=g,g=m):(n(g,m),m=Gc(y,g.mode,S),m.return=g,g=m),i(g)):n(g,m)}return C}var Ro=D0(!0),O0=D0(!1),hi={},ln=lr(hi),Xs=lr(hi),qs=lr(hi);function Er(e){if(e===hi)throw Error(U(174));return e}function Tf(e,t){switch(Ce(qs,t),Ce(Xs,e),Ce(ln,hi),e=t.nodeType,e){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:zu(null,"");break;default:e=e===8?t.parentNode:t,t=e.namespaceURI||null,e=e.tagName,t=zu(t,e)}Ee(ln),Ce(ln,t)}function To(){Ee(ln),Ee(Xs),Ee(qs)}function B0(e){Er(qs.current);var t=Er(ln.current),n=zu(t,e.type);t!==n&&(Ce(Xs,e),Ce(ln,n))}function jf(e){Xs.current===e&&(Ee(ln),Ee(Xs))}var _e=lr(0);function Wa(e){for(var t=e;t!==null;){if(t.tag===13){var n=t.memoizedState;if(n!==null&&(n=n.dehydrated,n===null||n.data==="$?"||n.data==="$!"))return t}else if(t.tag===19&&t.memoizedProps.revealOrder!==void 0){if(t.flags&128)return t}else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var zc=[];function Pf(){for(var e=0;en?n:4,e(!0);var r=Fc.transition;Fc.transition={};try{e(!1),t()}finally{ve=n,Fc.transition=r}}function ey(){return Wt().memoizedState}function MC(e,t,n){var r=Qn(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},ty(e))ny(t,n);else if(n=L0(e,t,n,r),n!==null){var o=ht();qt(n,e,r,o),ry(n,t,r)}}function DC(e,t,n){var r=Qn(e),o={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(ty(e))ny(t,o);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var i=t.lastRenderedState,a=s(i,n);if(o.hasEagerState=!0,o.eagerState=a,en(a,i)){var l=t.interleaved;l===null?(o.next=o,Ef(t)):(o.next=l.next,l.next=o),t.interleaved=o;return}}catch{}finally{}n=L0(e,t,o,r),n!==null&&(o=ht(),qt(n,e,r,o),ry(n,t,r))}}function ty(e){var t=e.alternate;return e===De||t!==null&&t===De}function ny(e,t){Ts=Ha=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function ry(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ff(e,n)}}var Ga={readContext:$t,useCallback:st,useContext:st,useEffect:st,useImperativeHandle:st,useInsertionEffect:st,useLayoutEffect:st,useMemo:st,useReducer:st,useRef:st,useState:st,useDebugValue:st,useDeferredValue:st,useTransition:st,useMutableSource:st,useSyncExternalStore:st,useId:st,unstable_isNewReconciler:!1},OC={readContext:$t,useCallback:function(e,t){return rn().memoizedState=[e,t===void 0?null:t],e},useContext:$t,useEffect:Uh,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,xa(4194308,4,Y0.bind(null,t,e),n)},useLayoutEffect:function(e,t){return xa(4194308,4,e,t)},useInsertionEffect:function(e,t){return xa(4,2,e,t)},useMemo:function(e,t){var n=rn();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=rn();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=MC.bind(null,De,e),[r.memoizedState,e]},useRef:function(e){var t=rn();return e={current:e},t.memoizedState=e},useState:Fh,useDebugValue:Mf,useDeferredValue:function(e){return rn().memoizedState=e},useTransition:function(){var e=Fh(!1),t=e[0];return e=IC.bind(null,e[1]),rn().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=De,o=rn();if(Pe){if(n===void 0)throw Error(U(407));n=n()}else{if(n=t(),Qe===null)throw Error(U(349));Ir&30||F0(r,t,n)}o.memoizedState=n;var s={value:n,getSnapshot:t};return o.queue=s,Uh($0.bind(null,r,s,e),[e]),r.flags|=2048,ni(9,U0.bind(null,r,s,n,t),void 0,null),n},useId:function(){var e=rn(),t=Qe.identifierPrefix;if(Pe){var n=vn,r=gn;n=(r&~(1<<32-Xt(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=ei++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=i.createElement(n,{is:r.is}):(e=i.createElement(n),n==="select"&&(i=e,r.multiple?i.multiple=!0:r.size&&(i.size=r.size))):e=i.createElementNS(e,n),e[sn]=t,e[Qs]=r,fy(e,t,!1,!1),t.stateNode=e;e:{switch(i=Uu(n,r),n){case"dialog":Ae("cancel",e),Ae("close",e),o=r;break;case"iframe":case"object":case"embed":Ae("load",e),o=r;break;case"video":case"audio":for(o=0;oPo&&(t.flags|=128,r=!0,es(s,!1),t.lanes=4194304)}else{if(!r)if(e=Wa(i),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),es(s,!0),s.tail===null&&s.tailMode==="hidden"&&!i.alternate&&!Pe)return it(t),null}else 2*Ue()-s.renderingStartTime>Po&&n!==1073741824&&(t.flags|=128,r=!0,es(s,!1),t.lanes=4194304);s.isBackwards?(i.sibling=t.child,t.child=i):(n=s.last,n!==null?n.sibling=i:t.child=i,s.last=i)}return s.tail!==null?(t=s.tail,s.rendering=t,s.tail=t.sibling,s.renderingStartTime=Ue(),t.sibling=null,n=_e.current,Ce(_e,r?n&1|2:n&1),t):(it(t),null);case 22:case 23:return Ff(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?Tt&1073741824&&(it(t),t.subtreeFlags&6&&(t.flags|=8192)):it(t),null;case 24:return null;case 25:return null}throw Error(U(156,t.tag))}function HC(e,t){switch(Sf(t),t.tag){case 1:return Ct(t.type)&&Oa(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return To(),Ee(St),Ee(ct),Pf(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return jf(t),null;case 13:if(Ee(_e),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(U(340));Eo()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Ee(_e),null;case 4:return To(),null;case 10:return kf(t.type._context),null;case 22:case 23:return Ff(),null;case 24:return null;default:return null}}var Ji=!1,lt=!1,GC=typeof WeakSet=="function"?WeakSet:Set,Y=null;function uo(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){Ve(e,t,r)}else n.current=null}function md(e,t,n){try{n()}catch(r){Ve(e,t,r)}}var Qh=!1;function KC(e,t){if(Xu=_a,e=y0(),xf(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var o=r.anchorOffset,s=r.focusNode;r=r.focusOffset;try{n.nodeType,s.nodeType}catch{n=null;break e}var i=0,a=-1,l=-1,c=0,d=0,f=e,p=null;t:for(;;){for(var h;f!==n||o!==0&&f.nodeType!==3||(a=i+o),f!==s||r!==0&&f.nodeType!==3||(l=i+r),f.nodeType===3&&(i+=f.nodeValue.length),(h=f.firstChild)!==null;)p=f,f=h;for(;;){if(f===e)break t;if(p===n&&++c===o&&(a=i),p===s&&++d===r&&(l=i),(h=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=h}n=a===-1||l===-1?null:{start:a,end:l}}else n=null}n=n||{start:0,end:0}}else n=null;for(qu={focusedElem:e,selectionRange:n},_a=!1,Y=t;Y!==null;)if(t=Y,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Y=e;else for(;Y!==null;){t=Y;try{var v=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(v!==null){var x=v.memoizedProps,C=v.memoizedState,g=t.stateNode,m=g.getSnapshotBeforeUpdate(t.elementType===t.type?x:Yt(t.type,x),C);g.__reactInternalSnapshotBeforeUpdate=m}break;case 3:var y=t.stateNode.containerInfo;y.nodeType===1?y.textContent="":y.nodeType===9&&y.documentElement&&y.removeChild(y.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(U(163))}}catch(S){Ve(t,t.return,S)}if(e=t.sibling,e!==null){e.return=t.return,Y=e;break}Y=t.return}return v=Qh,Qh=!1,v}function js(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var o=r=r.next;do{if((o.tag&e)===e){var s=o.destroy;o.destroy=void 0,s!==void 0&&md(t,n,s)}o=o.next}while(o!==r)}}function Tl(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function gd(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function my(e){var t=e.alternate;t!==null&&(e.alternate=null,my(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[sn],delete t[Qs],delete t[nd],delete t[jC],delete t[PC])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function gy(e){return e.tag===5||e.tag===3||e.tag===4}function Xh(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||gy(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function vd(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Da));else if(r!==4&&(e=e.child,e!==null))for(vd(e,t,n),e=e.sibling;e!==null;)vd(e,t,n),e=e.sibling}function yd(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(yd(e,t,n),e=e.sibling;e!==null;)yd(e,t,n),e=e.sibling}var tt=null,Zt=!1;function Pn(e,t,n){for(n=n.child;n!==null;)vy(e,t,n),n=n.sibling}function vy(e,t,n){if(an&&typeof an.onCommitFiberUnmount=="function")try{an.onCommitFiberUnmount(wl,n)}catch{}switch(n.tag){case 5:lt||uo(n,t);case 6:var r=tt,o=Zt;tt=null,Pn(e,t,n),tt=r,Zt=o,tt!==null&&(Zt?(e=tt,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):tt.removeChild(n.stateNode));break;case 18:tt!==null&&(Zt?(e=tt,n=n.stateNode,e.nodeType===8?Bc(e.parentNode,n):e.nodeType===1&&Bc(e,n),Gs(e)):Bc(tt,n.stateNode));break;case 4:r=tt,o=Zt,tt=n.stateNode.containerInfo,Zt=!0,Pn(e,t,n),tt=r,Zt=o;break;case 0:case 11:case 14:case 15:if(!lt&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){o=r=r.next;do{var s=o,i=s.destroy;s=s.tag,i!==void 0&&(s&2||s&4)&&md(n,t,i),o=o.next}while(o!==r)}Pn(e,t,n);break;case 1:if(!lt&&(uo(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(a){Ve(n,t,a)}Pn(e,t,n);break;case 21:Pn(e,t,n);break;case 22:n.mode&1?(lt=(r=lt)||n.memoizedState!==null,Pn(e,t,n),lt=r):Pn(e,t,n);break;default:Pn(e,t,n)}}function qh(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new GC),t.forEach(function(r){var o=nb.bind(null,e,r);n.has(r)||(n.add(r),r.then(o,o))})}}function Gt(e,t){var n=t.deletions;if(n!==null)for(var r=0;ro&&(o=i),r&=~s}if(r=o,r=Ue()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*YC(r/1960))-r,10e?16:e,Un===null)var r=!1;else{if(e=Un,Un=null,Ya=0,he&6)throw Error(U(331));var o=he;for(he|=4,Y=e.current;Y!==null;){var s=Y,i=s.child;if(Y.flags&16){var a=s.deletions;if(a!==null){for(var l=0;lUe()-Vf?jr(e,0):Bf|=n),bt(e,t)}function ky(e,t){t===0&&(e.mode&1?(t=Vi,Vi<<=1,!(Vi&130023424)&&(Vi=4194304)):t=1);var n=ht();e=kn(e,t),e!==null&&(di(e,t,n),bt(e,n))}function tb(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),ky(e,n)}function nb(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,o=e.memoizedState;o!==null&&(n=o.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(U(314))}r!==null&&r.delete(t),ky(e,n)}var Ey;Ey=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||St.current)xt=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return xt=!1,$C(e,t,n);xt=!!(e.flags&131072)}else xt=!1,Pe&&t.flags&1048576&&j0(t,za,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;wa(e,t),e=t.pendingProps;var o=ko(t,ct.current);So(t,n),o=Lf(null,t,r,e,o,n);var s=_f();return t.flags|=1,typeof o=="object"&&o!==null&&typeof o.render=="function"&&o.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Ct(r)?(s=!0,Ba(t)):s=!1,t.memoizedState=o.state!==null&&o.state!==void 0?o.state:null,Rf(t),o.updater=El,t.stateNode=o,o._reactInternals=t,ld(t,r,e,n),t=dd(null,t,r,!0,s,n)):(t.tag=0,Pe&&s&&wf(t),pt(null,t,o,n),t=t.child),t;case 16:r=t.elementType;e:{switch(wa(e,t),e=t.pendingProps,o=r._init,r=o(r._payload),t.type=r,o=t.tag=ob(r),e=Yt(r,e),o){case 0:t=ud(null,t,r,e,n);break e;case 1:t=Jh(null,t,r,e,n);break e;case 11:t=Gh(null,t,r,e,n);break e;case 14:t=Kh(null,t,r,Yt(r.type,e),n);break e}throw Error(U(306,r,""))}return t;case 0:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Yt(r,o),ud(e,t,r,o,n);case 1:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Yt(r,o),Jh(e,t,r,o,n);case 3:e:{if(cy(t),e===null)throw Error(U(387));r=t.pendingProps,s=t.memoizedState,o=s.element,_0(e,t),$a(t,r,null,n);var i=t.memoizedState;if(r=i.element,s.isDehydrated)if(s={element:r,isDehydrated:!1,cache:i.cache,pendingSuspenseBoundaries:i.pendingSuspenseBoundaries,transitions:i.transitions},t.updateQueue.baseState=s,t.memoizedState=s,t.flags&256){o=jo(Error(U(423)),t),t=Yh(e,t,r,n,o);break e}else if(r!==o){o=jo(Error(U(424)),t),t=Yh(e,t,r,n,o);break e}else for(jt=Jn(t.stateNode.containerInfo.firstChild),Pt=t,Pe=!0,Qt=null,n=O0(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(Eo(),r===o){t=En(e,t,n);break e}pt(e,t,r,n)}t=t.child}return t;case 5:return B0(t),e===null&&sd(t),r=t.type,o=t.pendingProps,s=e!==null?e.memoizedProps:null,i=o.children,ed(r,o)?i=null:s!==null&&ed(r,s)&&(t.flags|=32),ly(e,t),pt(e,t,i,n),t.child;case 6:return e===null&&sd(t),null;case 13:return uy(e,t,n);case 4:return Tf(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Ro(t,null,r,n):pt(e,t,r,n),t.child;case 11:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Yt(r,o),Gh(e,t,r,o,n);case 7:return pt(e,t,t.pendingProps,n),t.child;case 8:return pt(e,t,t.pendingProps.children,n),t.child;case 12:return pt(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,o=t.pendingProps,s=t.memoizedProps,i=o.value,Ce(Fa,r._currentValue),r._currentValue=i,s!==null)if(en(s.value,i)){if(s.children===o.children&&!St.current){t=En(e,t,n);break e}}else for(s=t.child,s!==null&&(s.return=t);s!==null;){var a=s.dependencies;if(a!==null){i=s.child;for(var l=a.firstContext;l!==null;){if(l.context===r){if(s.tag===1){l=wn(-1,n&-n),l.tag=2;var c=s.updateQueue;if(c!==null){c=c.shared;var d=c.pending;d===null?l.next=l:(l.next=d.next,d.next=l),c.pending=l}}s.lanes|=n,l=s.alternate,l!==null&&(l.lanes|=n),id(s.return,n,t),a.lanes|=n;break}l=l.next}}else if(s.tag===10)i=s.type===t.type?null:s.child;else if(s.tag===18){if(i=s.return,i===null)throw Error(U(341));i.lanes|=n,a=i.alternate,a!==null&&(a.lanes|=n),id(i,n,t),i=s.sibling}else i=s.child;if(i!==null)i.return=s;else for(i=s;i!==null;){if(i===t){i=null;break}if(s=i.sibling,s!==null){s.return=i.return,i=s;break}i=i.return}s=i}pt(e,t,o.children,n),t=t.child}return t;case 9:return o=t.type,r=t.pendingProps.children,So(t,n),o=$t(o),r=r(o),t.flags|=1,pt(e,t,r,n),t.child;case 14:return r=t.type,o=Yt(r,t.pendingProps),o=Yt(r.type,o),Kh(e,t,r,o,n);case 15:return iy(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Yt(r,o),wa(e,t),t.tag=1,Ct(r)?(e=!0,Ba(t)):e=!1,So(t,n),M0(t,r,o),ld(t,r,o,n),dd(null,t,r,!0,e,n);case 19:return dy(e,t,n);case 22:return ay(e,t,n)}throw Error(U(156,t.tag))};function Ry(e,t){return qv(e,t)}function rb(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Ft(e,t,n,r){return new rb(e,t,n,r)}function $f(e){return e=e.prototype,!(!e||!e.isReactComponent)}function ob(e){if(typeof e=="function")return $f(e)?1:0;if(e!=null){if(e=e.$$typeof,e===lf)return 11;if(e===cf)return 14}return 2}function Xn(e,t){var n=e.alternate;return n===null?(n=Ft(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function ba(e,t,n,r,o,s){var i=2;if(r=e,typeof e=="function")$f(e)&&(i=1);else if(typeof e=="string")i=5;else e:switch(e){case to:return Pr(n.children,o,s,t);case af:i=8,o|=8;break;case Lu:return e=Ft(12,n,t,o|2),e.elementType=Lu,e.lanes=s,e;case _u:return e=Ft(13,n,t,o),e.elementType=_u,e.lanes=s,e;case Iu:return e=Ft(19,n,t,o),e.elementType=Iu,e.lanes=s,e;case Dv:return Pl(n,o,s,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Iv:i=10;break e;case Mv:i=9;break e;case lf:i=11;break e;case cf:i=14;break e;case Mn:i=16,r=null;break e}throw Error(U(130,e==null?e:typeof e,""))}return t=Ft(i,n,t,o),t.elementType=e,t.type=r,t.lanes=s,t}function Pr(e,t,n,r){return e=Ft(7,e,r,t),e.lanes=n,e}function Pl(e,t,n,r){return e=Ft(22,e,r,t),e.elementType=Dv,e.lanes=n,e.stateNode={isHidden:!1},e}function Gc(e,t,n){return e=Ft(6,e,null,t),e.lanes=n,e}function Kc(e,t,n){return t=Ft(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function sb(e,t,n,r,o){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Rc(0),this.expirationTimes=Rc(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Rc(0),this.identifierPrefix=r,this.onRecoverableError=o,this.mutableSourceEagerHydrationData=null}function Wf(e,t,n,r,o,s,i,a,l){return e=new sb(e,t,n,a,l),t===1?(t=1,s===!0&&(t|=8)):t=0,s=Ft(3,null,null,t),e.current=s,s.stateNode=e,s.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Rf(s),e}function ib(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(Ny)}catch(e){console.error(e)}}Ny(),jv.exports=_t;var Ly=jv.exports;const Ml=ci(Ly);var am=Ly;Pu.createRoot=am.createRoot,Pu.hydrateRoot=am.hydrateRoot;/** + * @remix-run/router v1.7.1 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */function oi(){return oi=Object.assign?Object.assign.bind():function(e){for(var t=1;t"u")throw new Error(t)}function Jf(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function fb(){return Math.random().toString(36).substr(2,8)}function cm(e,t){return{usr:e.state,key:e.key,idx:t}}function bd(e,t,n,r){return n===void 0&&(n=null),oi({pathname:typeof e=="string"?e:e.pathname,search:"",hash:""},typeof t=="string"?$o(t):t,{state:n,key:t&&t.key||r||fb()})}function Xa(e){let{pathname:t="/",search:n="",hash:r=""}=e;return n&&n!=="?"&&(t+=n.charAt(0)==="?"?n:"?"+n),r&&r!=="#"&&(t+=r.charAt(0)==="#"?r:"#"+r),t}function $o(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substr(n),e=e.substr(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substr(r),e=e.substr(0,r)),e&&(t.pathname=e)}return t}function pb(e,t,n,r){r===void 0&&(r={});let{window:o=document.defaultView,v5Compat:s=!1}=r,i=o.history,a=$n.Pop,l=null,c=d();c==null&&(c=0,i.replaceState(oi({},i.state,{idx:c}),""));function d(){return(i.state||{idx:null}).idx}function f(){a=$n.Pop;let C=d(),g=C==null?null:C-c;c=C,l&&l({action:a,location:x.location,delta:g})}function p(C,g){a=$n.Push;let m=bd(x.location,C,g);n&&n(m,C),c=d()+1;let y=cm(m,c),S=x.createHref(m);try{i.pushState(y,"",S)}catch(A){if(A instanceof DOMException&&A.name==="DataCloneError")throw A;o.location.assign(S)}s&&l&&l({action:a,location:x.location,delta:1})}function h(C,g){a=$n.Replace;let m=bd(x.location,C,g);n&&n(m,C),c=d();let y=cm(m,c),S=x.createHref(m);i.replaceState(y,"",S),s&&l&&l({action:a,location:x.location,delta:0})}function v(C){let g=o.location.origin!=="null"?o.location.origin:o.location.href,m=typeof C=="string"?C:Xa(C);return Ge(g,"No window.location.(origin|href) available to create URL for href: "+m),new URL(m,g)}let x={get action(){return a},get location(){return e(o,i)},listen(C){if(l)throw new Error("A history only accepts one active listener");return o.addEventListener(lm,f),l=C,()=>{o.removeEventListener(lm,f),l=null}},createHref(C){return t(o,C)},createURL:v,encodeLocation(C){let g=v(C);return{pathname:g.pathname,search:g.search,hash:g.hash}},push:p,replace:h,go(C){return i.go(C)}};return x}var um;(function(e){e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error"})(um||(um={}));function hb(e,t,n){n===void 0&&(n="/");let r=typeof t=="string"?$o(t):t,o=Yf(r.pathname||"/",n);if(o==null)return null;let s=_y(e);mb(s);let i=null;for(let a=0;i==null&&a{let l={relativePath:a===void 0?s.path||"":a,caseSensitive:s.caseSensitive===!0,childrenIndex:i,route:s};l.relativePath.startsWith("/")&&(Ge(l.relativePath.startsWith(r),'Absolute route path "'+l.relativePath+'" nested under path '+('"'+r+'" is not valid. An absolute child route path ')+"must start with the combined path of all its parent routes."),l.relativePath=l.relativePath.slice(r.length));let c=qn([r,l.relativePath]),d=n.concat(l);s.children&&s.children.length>0&&(Ge(s.index!==!0,"Index routes must not have child routes. Please remove "+('all child routes from route path "'+c+'".')),_y(s.children,t,d,c)),!(s.path==null&&!s.index)&&t.push({path:c,score:Cb(c,s.index),routesMeta:d})};return e.forEach((s,i)=>{var a;if(s.path===""||!((a=s.path)!=null&&a.includes("?")))o(s,i);else for(let l of Iy(s.path))o(s,i,l)}),t}function Iy(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,o=n.endsWith("?"),s=n.replace(/\?$/,"");if(r.length===0)return o?[s,""]:[s];let i=Iy(r.join("/")),a=[];return a.push(...i.map(l=>l===""?s:[s,l].join("/"))),o&&a.push(...i),a.map(l=>e.startsWith("/")&&l===""?"/":l)}function mb(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:bb(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}const gb=/^:\w+$/,vb=3,yb=2,xb=1,wb=10,Sb=-2,dm=e=>e==="*";function Cb(e,t){let n=e.split("/"),r=n.length;return n.some(dm)&&(r+=Sb),t&&(r+=yb),n.filter(o=>!dm(o)).reduce((o,s)=>o+(gb.test(s)?vb:s===""?xb:wb),r)}function bb(e,t){return e.length===t.length&&e.slice(0,-1).every((r,o)=>r===t[o])?e[e.length-1]-t[t.length-1]:0}function Ab(e,t){let{routesMeta:n}=e,r={},o="/",s=[];for(let i=0;i{if(d==="*"){let p=a[f]||"";i=s.slice(0,s.length-p.length).replace(/(.)\/+$/,"$1")}return c[d]=Tb(a[f]||"",d),c},{}),pathname:s,pathnameBase:i,pattern:e}}function Eb(e,t,n){t===void 0&&(t=!1),n===void 0&&(n=!0),Jf(e==="*"||!e.endsWith("*")||e.endsWith("/*"),'Route path "'+e+'" will be treated as if it were '+('"'+e.replace(/\*$/,"/*")+'" because the `*` character must ')+"always follow a `/` in the pattern. To get rid of this warning, "+('please change the route path to "'+e.replace(/\*$/,"/*")+'".'));let r=[],o="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^$?{}|()[\]]/g,"\\$&").replace(/\/:(\w+)/g,(i,a)=>(r.push(a),"/([^\\/]+)"));return e.endsWith("*")?(r.push("*"),o+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?o+="\\/*$":e!==""&&e!=="/"&&(o+="(?:(?=\\/|$))"),[new RegExp(o,t?void 0:"i"),r]}function Rb(e){try{return decodeURI(e)}catch(t){return Jf(!1,'The URL path "'+e+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent '+("encoding ("+t+").")),e}}function Tb(e,t){try{return decodeURIComponent(e)}catch(n){return Jf(!1,'The value for the URL param "'+t+'" will not be decoded because'+(' the string "'+e+'" is a malformed URL segment. This is probably')+(" due to a bad percent encoding ("+n+").")),e}}function Yf(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}function jb(e,t){t===void 0&&(t="/");let{pathname:n,search:r="",hash:o=""}=typeof e=="string"?$o(e):e;return{pathname:n?n.startsWith("/")?n:Pb(n,t):t,search:Lb(r),hash:_b(o)}}function Pb(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(o=>{o===".."?n.length>1&&n.pop():o!=="."&&n.push(o)}),n.length>1?n.join("/"):"/"}function Jc(e,t,n,r){return"Cannot include a '"+e+"' character in a manually specified "+("`to."+t+"` field ["+JSON.stringify(r)+"]. Please separate it out to the ")+("`to."+n+"` field. Alternatively you may provide the full path as ")+'a string in and the router will parse it for you.'}function My(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Dy(e,t,n,r){r===void 0&&(r=!1);let o;typeof e=="string"?o=$o(e):(o=oi({},e),Ge(!o.pathname||!o.pathname.includes("?"),Jc("?","pathname","search",o)),Ge(!o.pathname||!o.pathname.includes("#"),Jc("#","pathname","hash",o)),Ge(!o.search||!o.search.includes("#"),Jc("#","search","hash",o)));let s=e===""||o.pathname==="",i=s?"/":o.pathname,a;if(r||i==null)a=n;else{let f=t.length-1;if(i.startsWith("..")){let p=i.split("/");for(;p[0]==="..";)p.shift(),f-=1;o.pathname=p.join("/")}a=f>=0?t[f]:"/"}let l=jb(o,a),c=i&&i!=="/"&&i.endsWith("/"),d=(s||i===".")&&n.endsWith("/");return!l.pathname.endsWith("/")&&(c||d)&&(l.pathname+="/"),l}const qn=e=>e.join("/").replace(/\/\/+/g,"/"),Nb=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Lb=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,_b=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e;function Ib(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}const Oy=["post","put","patch","delete"];new Set(Oy);const Mb=["get",...Oy];new Set(Mb);/** + * React Router v6.14.1 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */function qa(){return qa=Object.assign?Object.assign.bind():function(e){for(var t=1;tl.pathnameBase)),i=w.useRef(!1);return zy(()=>{i.current=!0}),w.useCallback(function(l,c){if(c===void 0&&(c={}),!i.current)return;if(typeof l=="number"){n.go(l);return}let d=Dy(l,JSON.parse(s),o,c.relative==="path");e==null&&t!=="/"&&(d.pathname=d.pathname==="/"?t:qn([t,d.pathname])),(c.replace?n.replace:n.push)(d,c.state,c)},[t,n,s,o,e])}const Bb=w.createContext(null);function Vb(e){let t=w.useContext(ur).outlet;return t&&w.createElement(Bb.Provider,{value:e},t)}function Qf(e,t){let{relative:n}=t===void 0?{}:t,{matches:r}=w.useContext(ur),{pathname:o}=tn(),s=JSON.stringify(My(r).map(i=>i.pathnameBase));return w.useMemo(()=>Dy(e,JSON.parse(s),o,n==="path"),[e,s,o,n])}function zb(e,t){return Fb(e,t)}function Fb(e,t,n){mi()||Ge(!1);let{navigator:r}=w.useContext($r),{matches:o}=w.useContext(ur),s=o[o.length-1],i=s?s.params:{};s&&s.pathname;let a=s?s.pathnameBase:"/";s&&s.route;let l=tn(),c;if(t){var d;let x=typeof t=="string"?$o(t):t;a==="/"||(d=x.pathname)!=null&&d.startsWith(a)||Ge(!1),c=x}else c=l;let f=c.pathname||"/",p=a==="/"?f:f.slice(a.length)||"/",h=hb(e,{pathname:p}),v=Gb(h&&h.map(x=>Object.assign({},x,{params:Object.assign({},i,x.params),pathname:qn([a,r.encodeLocation?r.encodeLocation(x.pathname).pathname:x.pathname]),pathnameBase:x.pathnameBase==="/"?a:qn([a,r.encodeLocation?r.encodeLocation(x.pathnameBase).pathname:x.pathnameBase])})),o,n);return t&&v?w.createElement(Dl.Provider,{value:{location:qa({pathname:"/",search:"",hash:"",state:null,key:"default"},c),navigationType:$n.Pop}},v):v}function Ub(){let e=Zb(),t=Ib(e)?e.status+" "+e.statusText:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,o={padding:"0.5rem",backgroundColor:"rgba(200,200,200, 0.5)"},s=null;return w.createElement(w.Fragment,null,w.createElement("h2",null,"Unexpected Application Error!"),w.createElement("h3",{style:{fontStyle:"italic"}},t),n?w.createElement("pre",{style:o},n):null,s)}const $b=w.createElement(Ub,null);class Wb extends w.Component{constructor(t){super(t),this.state={location:t.location,revalidation:t.revalidation,error:t.error}}static getDerivedStateFromError(t){return{error:t}}static getDerivedStateFromProps(t,n){return n.location!==t.location||n.revalidation!=="idle"&&t.revalidation==="idle"?{error:t.error,location:t.location,revalidation:t.revalidation}:{error:t.error||n.error,location:n.location,revalidation:t.revalidation||n.revalidation}}componentDidCatch(t,n){console.error("React Router caught the following error during render",t,n)}render(){return this.state.error?w.createElement(ur.Provider,{value:this.props.routeContext},w.createElement(Vy.Provider,{value:this.state.error,children:this.props.component})):this.props.children}}function Hb(e){let{routeContext:t,match:n,children:r}=e,o=w.useContext(Zf);return o&&o.static&&o.staticContext&&(n.route.errorElement||n.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=n.route.id),w.createElement(ur.Provider,{value:t},r)}function Gb(e,t,n){var r;if(t===void 0&&(t=[]),n===void 0&&(n=null),e==null){var o;if((o=n)!=null&&o.errors)e=n.matches;else return null}let s=e,i=(r=n)==null?void 0:r.errors;if(i!=null){let a=s.findIndex(l=>l.route.id&&(i==null?void 0:i[l.route.id]));a>=0||Ge(!1),s=s.slice(0,Math.min(s.length,a+1))}return s.reduceRight((a,l,c)=>{let d=l.route.id?i==null?void 0:i[l.route.id]:null,f=null;n&&(f=l.route.errorElement||$b);let p=t.concat(s.slice(0,c+1)),h=()=>{let v;return d?v=f:l.route.Component?v=w.createElement(l.route.Component,null):l.route.element?v=l.route.element:v=a,w.createElement(Hb,{match:l,routeContext:{outlet:a,matches:p,isDataRoute:n!=null},children:v})};return n&&(l.route.ErrorBoundary||l.route.errorElement||c===0)?w.createElement(Wb,{location:n.location,revalidation:n.revalidation,component:f,error:d,children:h(),routeContext:{outlet:null,matches:p,isDataRoute:!0}}):h()},null)}var Ad;(function(e){e.UseBlocker="useBlocker",e.UseRevalidator="useRevalidator",e.UseNavigateStable="useNavigate"})(Ad||(Ad={}));var si;(function(e){e.UseBlocker="useBlocker",e.UseLoaderData="useLoaderData",e.UseActionData="useActionData",e.UseRouteError="useRouteError",e.UseNavigation="useNavigation",e.UseRouteLoaderData="useRouteLoaderData",e.UseMatches="useMatches",e.UseRevalidator="useRevalidator",e.UseNavigateStable="useNavigate",e.UseRouteId="useRouteId"})(si||(si={}));function Kb(e){let t=w.useContext(Zf);return t||Ge(!1),t}function Jb(e){let t=w.useContext(By);return t||Ge(!1),t}function Yb(e){let t=w.useContext(ur);return t||Ge(!1),t}function Fy(e){let t=Yb(),n=t.matches[t.matches.length-1];return n.route.id||Ge(!1),n.route.id}function Zb(){var e;let t=w.useContext(Vy),n=Jb(si.UseRouteError),r=Fy(si.UseRouteError);return t||((e=n.errors)==null?void 0:e[r])}function Qb(){let{router:e}=Kb(Ad.UseNavigateStable),t=Fy(si.UseNavigateStable),n=w.useRef(!1);return zy(()=>{n.current=!0}),w.useCallback(function(o,s){s===void 0&&(s={}),n.current&&(typeof o=="number"?e.navigate(o):e.navigate(o,qa({fromRouteId:t},s)))},[e,t])}function Ol(e){return Vb(e.context)}function xe(e){Ge(!1)}function Xb(e){let{basename:t="/",children:n=null,location:r,navigationType:o=$n.Pop,navigator:s,static:i=!1}=e;mi()&&Ge(!1);let a=t.replace(/^\/*/,"/"),l=w.useMemo(()=>({basename:a,navigator:s,static:i}),[a,s,i]);typeof r=="string"&&(r=$o(r));let{pathname:c="/",search:d="",hash:f="",state:p=null,key:h="default"}=r,v=w.useMemo(()=>{let x=Yf(c,a);return x==null?null:{location:{pathname:x,search:d,hash:f,state:p,key:h},navigationType:o}},[a,c,d,f,p,h,o]);return v==null?null:w.createElement($r.Provider,{value:l},w.createElement(Dl.Provider,{children:n,value:v}))}function Xf(e){let{children:t,location:n}=e;return zb(kd(t),n)}var fm;(function(e){e[e.pending=0]="pending",e[e.success=1]="success",e[e.error=2]="error"})(fm||(fm={}));new Promise(()=>{});function kd(e,t){t===void 0&&(t=[]);let n=[];return w.Children.forEach(e,(r,o)=>{if(!w.isValidElement(r))return;let s=[...t,o];if(r.type===w.Fragment){n.push.apply(n,kd(r.props.children,s));return}r.type!==xe&&Ge(!1),!r.props.index||!r.props.children||Ge(!1);let i={id:r.props.id||s.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,loader:r.props.loader,action:r.props.action,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(i.children=kd(r.props.children,s)),n.push(i)}),n}/** + * React Router DOM v6.14.1 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */function el(){return el=Object.assign?Object.assign.bind():function(e){for(var t=1;t=0)&&(n[o]=e[o]);return n}function qb(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function eA(e,t){return e.button===0&&(!t||t==="_self")&&!qb(e)}function Ed(e){return e===void 0&&(e=""),new URLSearchParams(typeof e=="string"||Array.isArray(e)||e instanceof URLSearchParams?e:Object.keys(e).reduce((t,n)=>{let r=e[n];return t.concat(Array.isArray(r)?r.map(o=>[n,o]):[[n,r]])},[]))}function tA(e,t){let n=Ed(e);if(t)for(let r of t.keys())n.has(r)||t.getAll(r).forEach(o=>{n.append(r,o)});return n}const nA=["onClick","relative","reloadDocument","replace","state","target","to","preventScrollReset"],rA=["aria-current","caseSensitive","className","end","style","to","children"],oA="startTransition",pm=t2[oA];function sA(e){let{basename:t,children:n,future:r,window:o}=e,s=w.useRef();s.current==null&&(s.current=db({window:o,v5Compat:!0}));let i=s.current,[a,l]=w.useState({action:i.action,location:i.location}),{v7_startTransition:c}=r||{},d=w.useCallback(f=>{c&&pm?pm(()=>l(f)):l(f)},[l,c]);return w.useLayoutEffect(()=>i.listen(d),[i,d]),w.createElement(Xb,{basename:t,children:n,location:a.location,navigationType:a.action,navigator:i})}const iA=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u",aA=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Ie=w.forwardRef(function(t,n){let{onClick:r,relative:o,reloadDocument:s,replace:i,state:a,target:l,to:c,preventScrollReset:d}=t,f=Uy(t,nA),{basename:p}=w.useContext($r),h,v=!1;if(typeof c=="string"&&aA.test(c)&&(h=c,iA))try{let m=new URL(window.location.href),y=c.startsWith("//")?new URL(m.protocol+c):new URL(c),S=Yf(y.pathname,p);y.origin===m.origin&&S!=null?c=S+y.search+y.hash:v=!0}catch{}let x=Db(c,{relative:o}),C=lA(c,{replace:i,state:a,target:l,preventScrollReset:d,relative:o});function g(m){r&&r(m),m.defaultPrevented||C(m)}return w.createElement("a",el({},f,{href:h||x,onClick:v||s?r:g,ref:n,target:l}))}),ns=w.forwardRef(function(t,n){let{"aria-current":r="page",caseSensitive:o=!1,className:s="",end:i=!1,style:a,to:l,children:c}=t,d=Uy(t,rA),f=Qf(l,{relative:d.relative}),p=tn(),h=w.useContext(By),{navigator:v}=w.useContext($r),x=v.encodeLocation?v.encodeLocation(f).pathname:f.pathname,C=p.pathname,g=h&&h.navigation&&h.navigation.location?h.navigation.location.pathname:null;o||(C=C.toLowerCase(),g=g?g.toLowerCase():null,x=x.toLowerCase());let m=C===x||!i&&C.startsWith(x)&&C.charAt(x.length)==="/",y=g!=null&&(g===x||!i&&g.startsWith(x)&&g.charAt(x.length)==="/"),S=m?r:void 0,A;typeof s=="function"?A=s({isActive:m,isPending:y}):A=[s,m?"active":null,y?"pending":null].filter(Boolean).join(" ");let L=typeof a=="function"?a({isActive:m,isPending:y}):a;return w.createElement(Ie,el({},d,{"aria-current":S,className:A,ref:n,style:L,to:l}),typeof c=="function"?c({isActive:m,isPending:y}):c)});var hm;(function(e){e.UseScrollRestoration="useScrollRestoration",e.UseSubmit="useSubmit",e.UseSubmitFetcher="useSubmitFetcher",e.UseFetcher="useFetcher"})(hm||(hm={}));var mm;(function(e){e.UseFetchers="useFetchers",e.UseScrollRestoration="useScrollRestoration"})(mm||(mm={}));function lA(e,t){let{target:n,replace:r,state:o,preventScrollReset:s,relative:i}=t===void 0?{}:t,a=qe(),l=tn(),c=Qf(e,{relative:i});return w.useCallback(d=>{if(eA(d,n)){d.preventDefault();let f=r!==void 0?r:Xa(l)===Xa(c);a(e,{replace:f,state:o,preventScrollReset:s,relative:i})}},[l,a,c,r,o,n,e,s,i])}function dr(e){let t=w.useRef(Ed(e)),n=w.useRef(!1),r=tn(),o=w.useMemo(()=>tA(r.search,n.current?null:t.current),[r.search]),s=qe(),i=w.useCallback((a,l)=>{const c=Ed(typeof a=="function"?a(o):a);n.current=!0,s("?"+c,l)},[s,o]);return[o,i]}function cA(e){const t=new Error(e);if(t.stack===void 0)try{throw t}catch{}return t}var uA=cA,ue=uA;function dA(e){return!!e&&typeof e.then=="function"}var ke=dA;function fA(e,t){if(e!=null)return e;throw ue(t??"Got unexpected null or undefined")}var Ne=fA;function ce(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class Bl{getValue(){throw ue("BaseLoadable")}toPromise(){throw ue("BaseLoadable")}valueMaybe(){throw ue("BaseLoadable")}valueOrThrow(){throw ue(`Loadable expected value, but in "${this.state}" state`)}promiseMaybe(){throw ue("BaseLoadable")}promiseOrThrow(){throw ue(`Loadable expected promise, but in "${this.state}" state`)}errorMaybe(){throw ue("BaseLoadable")}errorOrThrow(){throw ue(`Loadable expected error, but in "${this.state}" state`)}is(t){return t.state===this.state&&t.contents===this.contents}map(t){throw ue("BaseLoadable")}}class pA extends Bl{constructor(t){super(),ce(this,"state","hasValue"),ce(this,"contents",void 0),this.contents=t}getValue(){return this.contents}toPromise(){return Promise.resolve(this.contents)}valueMaybe(){return this.contents}valueOrThrow(){return this.contents}promiseMaybe(){}errorMaybe(){}map(t){try{const n=t(this.contents);return ke(n)?Or(n):No(n)?n:gi(n)}catch(n){return ke(n)?Or(n.next(()=>this.map(t))):Vl(n)}}}class hA extends Bl{constructor(t){super(),ce(this,"state","hasError"),ce(this,"contents",void 0),this.contents=t}getValue(){throw this.contents}toPromise(){return Promise.reject(this.contents)}valueMaybe(){}promiseMaybe(){}errorMaybe(){return this.contents}errorOrThrow(){return this.contents}map(t){return this}}class $y extends Bl{constructor(t){super(),ce(this,"state","loading"),ce(this,"contents",void 0),this.contents=t}getValue(){throw this.contents}toPromise(){return this.contents}valueMaybe(){}promiseMaybe(){return this.contents}promiseOrThrow(){return this.contents}errorMaybe(){}map(t){return Or(this.contents.then(n=>{const r=t(n);if(No(r)){const o=r;switch(o.state){case"hasValue":return o.contents;case"hasError":throw o.contents;case"loading":return o.contents}}return r}).catch(n=>{if(ke(n))return n.then(()=>this.map(t).contents);throw n}))}}function gi(e){return Object.freeze(new pA(e))}function Vl(e){return Object.freeze(new hA(e))}function Or(e){return Object.freeze(new $y(e))}function Wy(){return Object.freeze(new $y(new Promise(()=>{})))}function mA(e){return e.every(t=>t.state==="hasValue")?gi(e.map(t=>t.contents)):e.some(t=>t.state==="hasError")?Vl(Ne(e.find(t=>t.state==="hasError"),"Invalid loadable passed to loadableAll").contents):Or(Promise.all(e.map(t=>t.contents)))}function Hy(e){const n=(Array.isArray(e)?e:Object.getOwnPropertyNames(e).map(o=>e[o])).map(o=>No(o)?o:ke(o)?Or(o):gi(o)),r=mA(n);return Array.isArray(e)?r:r.map(o=>Object.getOwnPropertyNames(e).reduce((s,i,a)=>({...s,[i]:o[a]}),{}))}function No(e){return e instanceof Bl}const gA={of:e=>ke(e)?Or(e):No(e)?e:gi(e),error:e=>Vl(e),loading:()=>Wy(),all:Hy,isLoadable:No};var Wr={loadableWithValue:gi,loadableWithError:Vl,loadableWithPromise:Or,loadableLoading:Wy,loadableAll:Hy,isLoadable:No,RecoilLoadable:gA},vA=Wr.loadableWithValue,yA=Wr.loadableWithError,xA=Wr.loadableWithPromise,wA=Wr.loadableLoading,SA=Wr.loadableAll,CA=Wr.isLoadable,bA=Wr.RecoilLoadable,vi=Object.freeze({__proto__:null,loadableWithValue:vA,loadableWithError:yA,loadableWithPromise:xA,loadableLoading:wA,loadableAll:SA,isLoadable:CA,RecoilLoadable:bA});const Rd={RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED:!0,RECOIL_GKS_ENABLED:new Set(["recoil_hamt_2020","recoil_sync_external_store","recoil_suppress_rerender_in_callback","recoil_memory_managament_2020"])};function AA(e,t){var n,r;const o=(n=process.env[e])===null||n===void 0||(r=n.toLowerCase())===null||r===void 0?void 0:r.trim();if(o==null||o==="")return;if(!["true","false"].includes(o))throw ue(`({}).${e} value must be 'true', 'false', or empty: ${o}`);t(o==="true")}function kA(e,t){var n;const r=(n=process.env[e])===null||n===void 0?void 0:n.trim();r==null||r===""||t(r.split(/\s*,\s*|\s+/))}function EA(){var e;typeof process>"u"||((e=process)===null||e===void 0?void 0:e.env)!=null&&(AA("RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED",t=>{Rd.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED=t}),kA("RECOIL_GKS_ENABLED",t=>{t.forEach(n=>{Rd.RECOIL_GKS_ENABLED.add(n)})}))}EA();var Wo=Rd;function zl(e){return Wo.RECOIL_GKS_ENABLED.has(e)}zl.setPass=e=>{Wo.RECOIL_GKS_ENABLED.add(e)};zl.setFail=e=>{Wo.RECOIL_GKS_ENABLED.delete(e)};zl.clear=()=>{Wo.RECOIL_GKS_ENABLED.clear()};var we=zl;function RA(e,t,{error:n}={}){return null}var TA=RA,qf=TA,Yc,Zc,Qc;const jA=(Yc=V.createMutableSource)!==null&&Yc!==void 0?Yc:V.unstable_createMutableSource,Gy=(Zc=V.useMutableSource)!==null&&Zc!==void 0?Zc:V.unstable_useMutableSource,Ky=(Qc=V.useSyncExternalStore)!==null&&Qc!==void 0?Qc:V.unstable_useSyncExternalStore;function PA(){var e;const{ReactCurrentDispatcher:t,ReactCurrentOwner:n}=V.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;return((e=t==null?void 0:t.current)!==null&&e!==void 0?e:n.currentDispatcher).useSyncExternalStore!=null}function NA(){return we("recoil_transition_support")?{mode:"TRANSITION_SUPPORT",early:!0,concurrent:!0}:we("recoil_sync_external_store")&&Ky!=null?{mode:"SYNC_EXTERNAL_STORE",early:!0,concurrent:!1}:we("recoil_mutable_source")&&Gy!=null&&typeof window<"u"&&!window.$disableRecoilValueMutableSource_TEMP_HACK_DO_NOT_USE?we("recoil_suppress_rerender_in_callback")?{mode:"MUTABLE_SOURCE",early:!0,concurrent:!0}:{mode:"MUTABLE_SOURCE",early:!1,concurrent:!1}:we("recoil_suppress_rerender_in_callback")?{mode:"LEGACY",early:!0,concurrent:!1}:{mode:"LEGACY",early:!1,concurrent:!1}}function LA(){return!1}var yi={createMutableSource:jA,useMutableSource:Gy,useSyncExternalStore:Ky,currentRendererSupportsUseSyncExternalStore:PA,reactMode:NA,isFastRefreshEnabled:LA};class ep{constructor(t){ce(this,"key",void 0),this.key=t}toJSON(){return{key:this.key}}}class Jy extends ep{}class Yy extends ep{}function _A(e){return e instanceof Jy||e instanceof Yy}var Fl={AbstractRecoilValue:ep,RecoilState:Jy,RecoilValueReadOnly:Yy,isRecoilValue:_A},IA=Fl.AbstractRecoilValue,MA=Fl.RecoilState,DA=Fl.RecoilValueReadOnly,OA=Fl.isRecoilValue,Lo=Object.freeze({__proto__:null,AbstractRecoilValue:IA,RecoilState:MA,RecoilValueReadOnly:DA,isRecoilValue:OA});function BA(e,t){return function*(){let n=0;for(const r of e)yield t(r,n++)}()}var Ul=BA;class Zy{}const VA=new Zy,Br=new Map,tp=new Map;function zA(e){return Ul(e,t=>Ne(tp.get(t)))}function FA(e){if(Br.has(e)){const t=`Duplicate atom key "${e}". This is a FATAL ERROR in + production. But it is safe to ignore this warning if it occurred because of + hot module replacement.`;console.warn(t)}}function UA(e){Wo.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED&&FA(e.key),Br.set(e.key,e);const t=e.set==null?new Lo.RecoilValueReadOnly(e.key):new Lo.RecoilState(e.key);return tp.set(e.key,t),t}class Qy extends Error{}function $A(e){const t=Br.get(e);if(t==null)throw new Qy(`Missing definition for RecoilValue: "${e}""`);return t}function WA(e){return Br.get(e)}const tl=new Map;function HA(e){var t;if(!we("recoil_memory_managament_2020"))return;const n=Br.get(e);if(n!=null&&(t=n.shouldDeleteConfigOnRelease)!==null&&t!==void 0&&t.call(n)){var r;Br.delete(e),(r=Xy(e))===null||r===void 0||r(),tl.delete(e)}}function GA(e,t){we("recoil_memory_managament_2020")&&(t===void 0?tl.delete(e):tl.set(e,t))}function Xy(e){return tl.get(e)}var Et={nodes:Br,recoilValues:tp,registerNode:UA,getNode:$A,getNodeMaybe:WA,deleteNodeConfigIfPossible:HA,setConfigDeletionHandler:GA,getConfigDeletionHandler:Xy,recoilValuesForKeys:zA,NodeMissingError:Qy,DefaultValue:Zy,DEFAULT_VALUE:VA};function KA(e,t){t()}var JA={enqueueExecution:KA};function YA(e,t){return t={exports:{}},e(t,t.exports),t.exports}var ZA=YA(function(e){var t=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(P){return typeof P}:function(P){return P&&typeof Symbol=="function"&&P.constructor===Symbol&&P!==Symbol.prototype?"symbol":typeof P},n={},r=5,o=Math.pow(2,r),s=o-1,i=o/2,a=o/4,l={},c=function(E){return function(){return E}},d=n.hash=function(P){var E=typeof P>"u"?"undefined":t(P);if(E==="number")return P;E!=="string"&&(P+="");for(var F=0,G=0,K=P.length;G>1&1431655765,E=(E&858993459)+(E>>2&858993459),E=E+(E>>4)&252645135,E+=E>>8,E+=E>>16,E&127},p=function(E,F){return F>>>E&s},h=function(E){return 1<=F;)K[ae--]=K[ae];return K[F]=G,K}for(var se=0,ie=0,de=new Array(Q+1);se>>=1;return ae[F]=G,T(E,ie+1,ae)},D=function(E,F,G,K){for(var Q=new Array(F-1),ae=0,se=0,ie=0,de=K.length;ie1?M(E,this.hash,de):de[0]}var Te=K();return Te===l?this:(++se.value,H(E,G,this.hash,this,Q,k(E,Q,ae,Te)))},q=function(E,F,G,K,Q,ae,se){var ie=this.mask,de=this.children,Te=p(G,Q),vt=h(Te),Ye=v(ie,vt),Dt=ie&vt,Ht=Dt?de[Ye]:L,Yr=Ht._modify(E,F,G+r,K,Q,ae,se);if(Ht===Yr)return this;var Li=ne(E,this),Go=ie,Ko=void 0;if(Dt&&_(Yr)){if(Go&=~vt,!Go)return L;if(de.length<=2&&O(de[Ye^1]))return de[Ye^1];Ko=C(Li,Ye,de)}else if(!Dt&&!_(Yr)){if(de.length>=i)return N(E,Te,Yr,ie,de);Go|=vt,Ko=g(Li,Ye,Yr,de)}else Ko=x(Li,Ye,Yr,de);return Li?(this.mask=Go,this.children=Ko,this):I(E,Go,Ko)},X=function(E,F,G,K,Q,ae,se){var ie=this.size,de=this.children,Te=p(G,Q),vt=de[Te],Ye=(vt||L)._modify(E,F,G+r,K,Q,ae,se);if(vt===Ye)return this;var Dt=ne(E,this),Ht=void 0;if(_(vt)&&!_(Ye))++ie,Ht=x(Dt,Te,Ye,de);else if(!_(vt)&&_(Ye)){if(--ie,ie<=a)return D(E,ie,Te,de);Ht=x(Dt,Te,L,de)}else Ht=x(Dt,Te,Ye,de);return Dt?(this.size=ie,this.children=Ht,this):T(E,ie,Ht)};L._modify=function(P,E,F,G,K,Q,ae){var se=G();return se===l?L:(++ae.value,k(P,K,Q,se))};function R(P,E,F,G,K){this._editable=P,this._edit=E,this._config=F,this._root=G,this._size=K}R.prototype.setTree=function(P,E){return this._editable?(this._root=P,this._size=E,this):P===this._root?this:new R(this._editable,this._edit,this._config,P,E)};var j=n.tryGetHash=function(P,E,F,G){for(var K=G._root,Q=0,ae=G._config.keyEq;;)switch(K.type){case m:return ae(F,K.key)?K.value:P;case y:{if(E===K.hash)for(var se=K.children,ie=0,de=se.length;ie{n.set(o,t(r,o))}),n}var nl=nk;function rk(){return{nodeDeps:new Map,nodeToNodeSubscriptions:new Map}}function ok(e){return{nodeDeps:nl(e.nodeDeps,t=>new Set(t)),nodeToNodeSubscriptions:nl(e.nodeToNodeSubscriptions,t=>new Set(t))}}function Xc(e,t,n,r){const{nodeDeps:o,nodeToNodeSubscriptions:s}=n,i=o.get(e);if(i&&r&&i!==r.nodeDeps.get(e))return;o.set(e,t);const a=i==null?t:Ls(t,i);for(const l of a)s.has(l)||s.set(l,new Set),Ne(s.get(l)).add(e);if(i){const l=Ls(i,t);for(const c of l){if(!s.has(c))return;const d=Ne(s.get(c));d.delete(e),d.size===0&&s.delete(c)}}}function sk(e,t,n,r){var o,s,i,a;const l=n.getState();r===l.currentTree.version||r===((o=l.nextTree)===null||o===void 0?void 0:o.version)||((s=l.previousTree)===null||s===void 0||s.version);const c=n.getGraph(r);if(Xc(e,t,c),r===((i=l.previousTree)===null||i===void 0?void 0:i.version)){const f=n.getGraph(l.currentTree.version);Xc(e,t,f,c)}if(r===((a=l.previousTree)===null||a===void 0?void 0:a.version)||r===l.currentTree.version){var d;const f=(d=l.nextTree)===null||d===void 0?void 0:d.version;if(f!==void 0){const p=n.getGraph(f);Xc(e,t,p,c)}}}var xi={cloneGraph:ok,graph:rk,saveDepsToStore:sk};let ik=0;const ak=()=>ik++;let lk=0;const ck=()=>lk++;let uk=0;const dk=()=>uk++;var $l={getNextTreeStateVersion:ak,getNextStoreID:ck,getNextComponentID:dk};const{persistentMap:gm}=ek,{graph:fk}=xi,{getNextTreeStateVersion:qy}=$l;function ex(){const e=qy();return{version:e,stateID:e,transactionMetadata:{},dirtyAtoms:new Set,atomValues:gm(),nonvalidatedAtoms:gm()}}function pk(){const e=ex();return{currentTree:e,nextTree:null,previousTree:null,commitDepth:0,knownAtoms:new Set,knownSelectors:new Set,transactionSubscriptions:new Map,nodeTransactionSubscriptions:new Map,nodeToComponentSubscriptions:new Map,queuedComponentCallbacks_DEPRECATED:[],suspendedComponentResolvers:new Set,graphsByVersion:new Map().set(e.version,fk()),retention:{referenceCounts:new Map,nodesRetainedByZone:new Map,retainablesToCheckForRelease:new Set},nodeCleanupFunctions:new Map}}var tx={makeEmptyTreeState:ex,makeEmptyStoreState:pk,getNextTreeStateVersion:qy};class nx{}function hk(){return new nx}var Wl={RetentionZone:nx,retentionZone:hk};function mk(e,t){const n=new Set(e);return n.add(t),n}function gk(e,t){const n=new Set(e);return n.delete(t),n}function vk(e,t,n){const r=new Map(e);return r.set(t,n),r}function yk(e,t,n){const r=new Map(e);return r.set(t,n(r.get(t))),r}function xk(e,t){const n=new Map(e);return n.delete(t),n}function wk(e,t){const n=new Map(e);return t.forEach(r=>n.delete(r)),n}var rx={setByAddingToSet:mk,setByDeletingFromSet:gk,mapBySettingInMap:vk,mapByUpdatingInMap:yk,mapByDeletingFromMap:xk,mapByDeletingMultipleFromMap:wk};function*Sk(e,t){let n=0;for(const r of e)t(r,n++)&&(yield r)}var op=Sk;function Ck(e,t){return new Proxy(e,{get:(r,o)=>(!(o in r)&&o in t&&(r[o]=t[o]()),r[o]),ownKeys:r=>Object.keys(r)})}var ox=Ck;const{getNode:wi,getNodeMaybe:bk,recoilValuesForKeys:vm}=Et,{RetentionZone:ym}=Wl,{setByAddingToSet:Ak}=rx,kk=Object.freeze(new Set);class Ek extends Error{}function Rk(e,t,n){if(!we("recoil_memory_managament_2020"))return()=>{};const{nodesRetainedByZone:r}=e.getState().retention;function o(s){let i=r.get(s);i||r.set(s,i=new Set),i.add(t)}if(n instanceof ym)o(n);else if(Array.isArray(n))for(const s of n)o(s);return()=>{if(!we("recoil_memory_managament_2020"))return;const{retention:s}=e.getState();function i(a){const l=s.nodesRetainedByZone.get(a);l==null||l.delete(t),l&&l.size===0&&s.nodesRetainedByZone.delete(a)}if(n instanceof ym)i(n);else if(Array.isArray(n))for(const a of n)i(a)}}function sp(e,t,n,r){const o=e.getState();if(o.nodeCleanupFunctions.has(n))return;const s=wi(n),i=Rk(e,n,s.retainedBy),a=s.init(e,t,r);o.nodeCleanupFunctions.set(n,()=>{a(),i()})}function Tk(e,t,n){sp(e,e.getState().currentTree,t,n)}function jk(e,t){var n;const r=e.getState();(n=r.nodeCleanupFunctions.get(t))===null||n===void 0||n(),r.nodeCleanupFunctions.delete(t)}function Pk(e,t,n){return sp(e,t,n,"get"),wi(n).get(e,t)}function sx(e,t,n){return wi(n).peek(e,t)}function Nk(e,t,n){var r;const o=bk(t);return o==null||(r=o.invalidate)===null||r===void 0||r.call(o,e),{...e,atomValues:e.atomValues.clone().delete(t),nonvalidatedAtoms:e.nonvalidatedAtoms.clone().set(t,n),dirtyAtoms:Ak(e.dirtyAtoms,t)}}function Lk(e,t,n,r){const o=wi(n);if(o.set==null)throw new Ek(`Attempt to set read-only RecoilValue: ${n}`);const s=o.set;return sp(e,t,n,"set"),s(e,t,r)}function _k(e,t,n){const r=e.getState(),o=e.getGraph(t.version),s=wi(n).nodeType;return ox({type:s},{loadable:()=>sx(e,t,n),isActive:()=>r.knownAtoms.has(n)||r.knownSelectors.has(n),isSet:()=>s==="selector"?!1:t.atomValues.has(n),isModified:()=>t.dirtyAtoms.has(n),deps:()=>{var i;return vm((i=o.nodeDeps.get(n))!==null&&i!==void 0?i:[])},subscribers:()=>{var i,a;return{nodes:vm(op(ix(e,t,new Set([n])),l=>l!==n)),components:Ul((i=(a=r.nodeToComponentSubscriptions.get(n))===null||a===void 0?void 0:a.values())!==null&&i!==void 0?i:[],([l])=>({name:l}))}}})}function ix(e,t,n){const r=new Set,o=Array.from(n),s=e.getGraph(t.version);for(let a=o.pop();a;a=o.pop()){var i;r.add(a);const l=(i=s.nodeToNodeSubscriptions.get(a))!==null&&i!==void 0?i:kk;for(const c of l)r.has(c)||o.push(c)}return r}var fr={getNodeLoadable:Pk,peekNodeLoadable:sx,setNodeValue:Lk,initializeNode:Tk,cleanUpNode:jk,setUnvalidatedAtomValue_DEPRECATED:Nk,peekNodeInfo:_k,getDownstreamNodes:ix};let ax=null;function Ik(e){ax=e}function Mk(){var e;(e=ax)===null||e===void 0||e()}var lx={setInvalidateMemoizedSnapshot:Ik,invalidateMemoizedSnapshot:Mk};const{getDownstreamNodes:Dk,getNodeLoadable:cx,setNodeValue:Ok}=fr,{getNextComponentID:Bk}=$l,{getNode:Vk,getNodeMaybe:ux}=Et,{DefaultValue:ip}=Et,{reactMode:zk}=yi,{AbstractRecoilValue:Fk,RecoilState:Uk,RecoilValueReadOnly:$k,isRecoilValue:Wk}=Lo,{invalidateMemoizedSnapshot:Hk}=lx;function Gk(e,{key:t},n=e.getState().currentTree){var r,o;const s=e.getState();n.version===s.currentTree.version||n.version===((r=s.nextTree)===null||r===void 0?void 0:r.version)||(n.version,(o=s.previousTree)===null||o===void 0||o.version);const i=cx(e,n,t);return i.state==="loading"&&i.contents.catch(()=>{}),i}function Kk(e,t){const n=e.clone();return t.forEach((r,o)=>{r.state==="hasValue"&&r.contents instanceof ip?n.delete(o):n.set(o,r)}),n}function Jk(e,t,{key:n},r){if(typeof r=="function"){const o=cx(e,t,n);if(o.state==="loading"){const s=`Tried to set atom or selector "${n}" using an updater function while the current state is pending, this is not currently supported.`;throw ue(s)}else if(o.state==="hasError")throw o.contents;return r(o.contents)}else return r}function Yk(e,t,n){if(n.type==="set"){const{recoilValue:o,valueOrUpdater:s}=n,i=Jk(e,t,o,s),a=Ok(e,t,o.key,i);for(const[l,c]of a.entries())Td(t,l,c)}else if(n.type==="setLoadable"){const{recoilValue:{key:o},loadable:s}=n;Td(t,o,s)}else if(n.type==="markModified"){const{recoilValue:{key:o}}=n;t.dirtyAtoms.add(o)}else if(n.type==="setUnvalidated"){var r;const{recoilValue:{key:o},unvalidatedValue:s}=n,i=ux(o);i==null||(r=i.invalidate)===null||r===void 0||r.call(i,t),t.atomValues.delete(o),t.nonvalidatedAtoms.set(o,s),t.dirtyAtoms.add(o)}else qf(`Unknown action ${n.type}`)}function Td(e,t,n){n.state==="hasValue"&&n.contents instanceof ip?e.atomValues.delete(t):e.atomValues.set(t,n),e.dirtyAtoms.add(t),e.nonvalidatedAtoms.delete(t)}function dx(e,t){e.replaceState(n=>{const r=fx(n);for(const o of t)Yk(e,r,o);return px(e,r),Hk(),r})}function Hl(e,t){if(_s.length){const n=_s[_s.length-1];let r=n.get(e);r||n.set(e,r=[]),r.push(t)}else dx(e,[t])}const _s=[];function Zk(){const e=new Map;return _s.push(e),()=>{for(const[t,n]of e)dx(t,n);_s.pop()}}function fx(e){return{...e,atomValues:e.atomValues.clone(),nonvalidatedAtoms:e.nonvalidatedAtoms.clone(),dirtyAtoms:new Set(e.dirtyAtoms)}}function px(e,t){const n=Dk(e,t,t.dirtyAtoms);for(const s of n){var r,o;(r=ux(s))===null||r===void 0||(o=r.invalidate)===null||o===void 0||o.call(r,t)}}function hx(e,t,n){Hl(e,{type:"set",recoilValue:t,valueOrUpdater:n})}function Qk(e,t,n){if(n instanceof ip)return hx(e,t,n);Hl(e,{type:"setLoadable",recoilValue:t,loadable:n})}function Xk(e,t){Hl(e,{type:"markModified",recoilValue:t})}function qk(e,t,n){Hl(e,{type:"setUnvalidated",recoilValue:t,unvalidatedValue:n})}function eE(e,{key:t},n,r=null){const o=Bk(),s=e.getState();s.nodeToComponentSubscriptions.has(t)||s.nodeToComponentSubscriptions.set(t,new Map),Ne(s.nodeToComponentSubscriptions.get(t)).set(o,[r??"",n]);const i=zk();if(i.early&&(i.mode==="LEGACY"||i.mode==="MUTABLE_SOURCE")){const a=e.getState().nextTree;a&&a.dirtyAtoms.has(t)&&n(a)}return{release:()=>{const a=e.getState(),l=a.nodeToComponentSubscriptions.get(t);l===void 0||!l.has(o)||(l.delete(o),l.size===0&&a.nodeToComponentSubscriptions.delete(t))}}}function tE(e,t){var n;const{currentTree:r}=e.getState(),o=Vk(t.key);(n=o.clearCache)===null||n===void 0||n.call(o,e,r)}var un={RecoilValueReadOnly:$k,AbstractRecoilValue:Fk,RecoilState:Uk,getRecoilValueAsLoadable:Gk,setRecoilValue:hx,setRecoilValueLoadable:Qk,markRecoilValueModified:Xk,setUnvalidatedRecoilValue:qk,subscribeToRecoilValue:eE,isRecoilValue:Wk,applyAtomValueWrites:Kk,batchStart:Zk,writeLoadableToTreeState:Td,invalidateDownstreams:px,copyTreeState:fx,refreshRecoilValue:tE};function nE(e,t,n){const r=e.entries();let o=r.next();for(;!o.done;){const s=o.value;if(t.call(n,s[1],s[0],e))return!0;o=r.next()}return!1}var rE=nE;const{cleanUpNode:oE}=fr,{deleteNodeConfigIfPossible:sE,getNode:mx}=Et,{RetentionZone:gx}=Wl,iE=12e4,vx=new Set;function yx(e,t){const n=e.getState(),r=n.currentTree;if(n.nextTree)return;const o=new Set;for(const i of t)if(i instanceof gx)for(const a of uE(n,i))o.add(a);else o.add(i);const s=aE(e,o);for(const i of s)cE(e,r,i)}function aE(e,t){const n=e.getState(),r=n.currentTree,o=e.getGraph(r.version),s=new Set,i=new Set;return a(t),s;function a(l){const c=new Set,d=lE(e,r,l,s,i);for(const v of d){var f;if(mx(v).retainedBy==="recoilRoot"){i.add(v);continue}if(((f=n.retention.referenceCounts.get(v))!==null&&f!==void 0?f:0)>0){i.add(v);continue}if(xx(v).some(C=>n.retention.referenceCounts.get(C))){i.add(v);continue}const x=o.nodeToNodeSubscriptions.get(v);if(x&&rE(x,C=>i.has(C))){i.add(v);continue}s.add(v),c.add(v)}const p=new Set;for(const v of c)for(const x of(h=o.nodeDeps.get(v))!==null&&h!==void 0?h:vx){var h;s.has(x)||p.add(x)}p.size&&a(p)}}function lE(e,t,n,r,o){const s=e.getGraph(t.version),i=[],a=new Set;for(;n.size>0;)l(Ne(n.values().next().value));return i;function l(c){if(r.has(c)||o.has(c)){n.delete(c);return}if(a.has(c))return;const d=s.nodeToNodeSubscriptions.get(c);if(d)for(const f of d)l(f);a.add(c),n.delete(c),i.push(c)}}function cE(e,t,n){if(!we("recoil_memory_managament_2020"))return;oE(e,n);const r=e.getState();r.knownAtoms.delete(n),r.knownSelectors.delete(n),r.nodeTransactionSubscriptions.delete(n),r.retention.referenceCounts.delete(n);const o=xx(n);for(const l of o){var s;(s=r.retention.nodesRetainedByZone.get(l))===null||s===void 0||s.delete(n)}t.atomValues.delete(n),t.dirtyAtoms.delete(n),t.nonvalidatedAtoms.delete(n);const i=r.graphsByVersion.get(t.version);if(i){const l=i.nodeDeps.get(n);if(l!==void 0){i.nodeDeps.delete(n);for(const c of l){var a;(a=i.nodeToNodeSubscriptions.get(c))===null||a===void 0||a.delete(n)}}i.nodeToNodeSubscriptions.delete(n)}sE(n)}function uE(e,t){var n;return(n=e.retention.nodesRetainedByZone.get(t))!==null&&n!==void 0?n:vx}function xx(e){const t=mx(e).retainedBy;return t===void 0||t==="components"||t==="recoilRoot"?[]:t instanceof gx?[t]:t}function dE(e,t){const n=e.getState();n.nextTree?n.retention.retainablesToCheckForRelease.add(t):yx(e,new Set([t]))}function fE(e,t,n){var r;if(!we("recoil_memory_managament_2020"))return;const o=e.getState().retention.referenceCounts,s=((r=o.get(t))!==null&&r!==void 0?r:0)+n;s===0?wx(e,t):o.set(t,s)}function wx(e,t){if(!we("recoil_memory_managament_2020"))return;e.getState().retention.referenceCounts.delete(t),dE(e,t)}function pE(e){if(!we("recoil_memory_managament_2020"))return;const t=e.getState();yx(e,t.retention.retainablesToCheckForRelease),t.retention.retainablesToCheckForRelease.clear()}function hE(e){return e===void 0?"recoilRoot":e}var Hr={SUSPENSE_TIMEOUT_MS:iE,updateRetainCount:fE,updateRetainCountToZero:wx,releaseScheduledRetainablesNow:pE,retainedByOptionWithDefault:hE};const{unstable_batchedUpdates:mE}=Ml;var gE={unstable_batchedUpdates:mE};const{unstable_batchedUpdates:vE}=gE;var yE={unstable_batchedUpdates:vE};const{batchStart:xE}=un,{unstable_batchedUpdates:wE}=yE;let ap=wE||(e=>e());const SE=e=>{ap=e},CE=()=>ap,bE=e=>{ap(()=>{let t=()=>{};try{t=xE(),e()}finally{t()}})};var Gl={getBatcher:CE,setBatcher:SE,batchUpdates:bE};function*AE(e){for(const t of e)for(const n of t)yield n}var Sx=AE;const Cx=typeof Window>"u"||typeof window>"u",kE=e=>!Cx&&(e===window||e instanceof Window),EE=typeof navigator<"u"&&navigator.product==="ReactNative";var Kl={isSSR:Cx,isReactNative:EE,isWindow:kE};function RE(e,t){let n;return(...r)=>{n||(n={});const o=t(...r);return Object.hasOwnProperty.call(n,o)||(n[o]=e(...r)),n[o]}}function TE(e,t){let n,r;return(...o)=>{const s=t(...o);return n===s||(n=s,r=e(...o)),r}}function jE(e,t){let n,r;return[(...i)=>{const a=t(...i);return n===a||(n=a,r=e(...i)),r},()=>{n=null}]}var PE={memoizeWithArgsHash:RE,memoizeOneWithArgsHash:TE,memoizeOneWithArgsHashAndInvalidation:jE};const{batchUpdates:jd}=Gl,{initializeNode:NE,peekNodeInfo:LE}=fr,{graph:_E}=xi,{getNextStoreID:IE}=$l,{DEFAULT_VALUE:ME,recoilValues:xm,recoilValuesForKeys:wm}=Et,{AbstractRecoilValue:DE,getRecoilValueAsLoadable:OE,setRecoilValue:Sm,setUnvalidatedRecoilValue:BE}=un,{updateRetainCount:Aa}=Hr,{setInvalidateMemoizedSnapshot:VE}=lx,{getNextTreeStateVersion:zE,makeEmptyStoreState:FE}=tx,{isSSR:UE}=Kl,{memoizeOneWithArgsHashAndInvalidation:$E}=PE;class Jl{constructor(t,n){ce(this,"_store",void 0),ce(this,"_refCount",1),ce(this,"getLoadable",r=>(this.checkRefCount_INTERNAL(),OE(this._store,r))),ce(this,"getPromise",r=>(this.checkRefCount_INTERNAL(),this.getLoadable(r).toPromise())),ce(this,"getNodes_UNSTABLE",r=>{if(this.checkRefCount_INTERNAL(),(r==null?void 0:r.isModified)===!0){if((r==null?void 0:r.isInitialized)===!1)return[];const i=this._store.getState().currentTree;return wm(i.dirtyAtoms)}const o=this._store.getState().knownAtoms,s=this._store.getState().knownSelectors;return(r==null?void 0:r.isInitialized)==null?xm.values():r.isInitialized===!0?wm(Sx([o,s])):op(xm.values(),({key:i})=>!o.has(i)&&!s.has(i))}),ce(this,"getInfo_UNSTABLE",({key:r})=>(this.checkRefCount_INTERNAL(),LE(this._store,this._store.getState().currentTree,r))),ce(this,"map",r=>{this.checkRefCount_INTERNAL();const o=new Pd(this,jd);return r(o),o}),ce(this,"asyncMap",async r=>{this.checkRefCount_INTERNAL();const o=new Pd(this,jd);return o.retain(),await r(o),o.autoRelease_INTERNAL(),o}),this._store={storeID:IE(),parentStoreID:n,getState:()=>t,replaceState:r=>{t.currentTree=r(t.currentTree)},getGraph:r=>{const o=t.graphsByVersion;if(o.has(r))return Ne(o.get(r));const s=_E();return o.set(r,s),s},subscribeToTransactions:()=>({release:()=>{}}),addTransactionMetadata:()=>{throw ue("Cannot subscribe to Snapshots")}};for(const r of this._store.getState().knownAtoms)NE(this._store,r,"get"),Aa(this._store,r,1);this.autoRelease_INTERNAL()}retain(){this._refCount<=0,this._refCount++;let t=!1;return()=>{t||(t=!0,this._release())}}autoRelease_INTERNAL(){UE||window.setTimeout(()=>this._release(),10)}_release(){if(this._refCount--,this._refCount===0){if(this._store.getState().nodeCleanupFunctions.forEach(t=>t()),this._store.getState().nodeCleanupFunctions.clear(),!we("recoil_memory_managament_2020"))return}else this._refCount<0}isRetained(){return this._refCount>0}checkRefCount_INTERNAL(){we("recoil_memory_managament_2020")&&this._refCount<=0}getStore_INTERNAL(){return this.checkRefCount_INTERNAL(),this._store}getID(){return this.checkRefCount_INTERNAL(),this._store.getState().currentTree.stateID}getStoreID(){return this.checkRefCount_INTERNAL(),this._store.storeID}}function bx(e,t,n=!1){const r=e.getState(),o=n?zE():t.version;return{currentTree:{version:n?o:t.version,stateID:n?o:t.stateID,transactionMetadata:{...t.transactionMetadata},dirtyAtoms:new Set(t.dirtyAtoms),atomValues:t.atomValues.clone(),nonvalidatedAtoms:t.nonvalidatedAtoms.clone()},commitDepth:0,nextTree:null,previousTree:null,knownAtoms:new Set(r.knownAtoms),knownSelectors:new Set(r.knownSelectors),transactionSubscriptions:new Map,nodeTransactionSubscriptions:new Map,nodeToComponentSubscriptions:new Map,queuedComponentCallbacks_DEPRECATED:[],suspendedComponentResolvers:new Set,graphsByVersion:new Map().set(o,e.getGraph(t.version)),retention:{referenceCounts:new Map,nodesRetainedByZone:new Map,retainablesToCheckForRelease:new Set},nodeCleanupFunctions:new Map(Ul(r.nodeCleanupFunctions.entries(),([s])=>[s,()=>{}]))}}function WE(e){const t=new Jl(FE());return e!=null?t.map(e):t}const[Cm,Ax]=$E((e,t)=>{var n;const r=e.getState(),o=t==="latest"?(n=r.nextTree)!==null&&n!==void 0?n:r.currentTree:Ne(r.previousTree);return new Jl(bx(e,o),e.storeID)},(e,t)=>{var n,r;return String(t)+String(e.storeID)+String((n=e.getState().nextTree)===null||n===void 0?void 0:n.version)+String(e.getState().currentTree.version)+String((r=e.getState().previousTree)===null||r===void 0?void 0:r.version)});VE(Ax);function HE(e,t="latest"){const n=Cm(e,t);return n.isRetained()?n:(Ax(),Cm(e,t))}class Pd extends Jl{constructor(t,n){super(bx(t.getStore_INTERNAL(),t.getStore_INTERNAL().getState().currentTree,!0),t.getStoreID()),ce(this,"_batch",void 0),ce(this,"set",(r,o)=>{this.checkRefCount_INTERNAL();const s=this.getStore_INTERNAL();this._batch(()=>{Aa(s,r.key,1),Sm(this.getStore_INTERNAL(),r,o)})}),ce(this,"reset",r=>{this.checkRefCount_INTERNAL();const o=this.getStore_INTERNAL();this._batch(()=>{Aa(o,r.key,1),Sm(this.getStore_INTERNAL(),r,ME)})}),ce(this,"setUnvalidatedAtomValues_DEPRECATED",r=>{this.checkRefCount_INTERNAL();const o=this.getStore_INTERNAL();jd(()=>{for(const[s,i]of r.entries())Aa(o,s,1),BE(o,new DE(s),i)})}),this._batch=n}}var Yl={Snapshot:Jl,MutableSnapshot:Pd,freshSnapshot:WE,cloneSnapshot:HE},GE=Yl.Snapshot,KE=Yl.MutableSnapshot,JE=Yl.freshSnapshot,YE=Yl.cloneSnapshot,Zl=Object.freeze({__proto__:null,Snapshot:GE,MutableSnapshot:KE,freshSnapshot:JE,cloneSnapshot:YE});function ZE(...e){const t=new Set;for(const n of e)for(const r of n)t.add(r);return t}var QE=ZE;const{useRef:XE}=V;function qE(e){const t=XE(e);return t.current===e&&typeof e=="function"&&(t.current=e()),t}var bm=qE;const{getNextTreeStateVersion:eR,makeEmptyStoreState:kx}=tx,{cleanUpNode:tR,getDownstreamNodes:nR,initializeNode:rR,setNodeValue:oR,setUnvalidatedAtomValue_DEPRECATED:sR}=fr,{graph:iR}=xi,{cloneGraph:aR}=xi,{getNextStoreID:Ex}=$l,{createMutableSource:qc,reactMode:Rx}=yi,{applyAtomValueWrites:lR}=un,{releaseScheduledRetainablesNow:Tx}=Hr,{freshSnapshot:cR}=Zl,{useCallback:uR,useContext:jx,useEffect:Nd,useMemo:dR,useRef:fR,useState:pR}=V;function rs(){throw ue("This component must be used inside a component.")}const Px=Object.freeze({storeID:Ex(),getState:rs,replaceState:rs,getGraph:rs,subscribeToTransactions:rs,addTransactionMetadata:rs});let Ld=!1;function Am(e){if(Ld)throw ue("An atom update was triggered within the execution of a state updater function. State updater functions provided to Recoil must be pure functions.");const t=e.getState();if(t.nextTree===null){we("recoil_memory_managament_2020")&&we("recoil_release_on_cascading_update_killswitch_2021")&&t.commitDepth>0&&Tx(e);const n=t.currentTree.version,r=eR();t.nextTree={...t.currentTree,version:r,stateID:r,dirtyAtoms:new Set,transactionMetadata:{}},t.graphsByVersion.set(r,aR(Ne(t.graphsByVersion.get(n))))}}const Nx=V.createContext({current:Px}),Ql=()=>jx(Nx),Lx=V.createContext(null);function hR(){return jx(Lx)}function lp(e,t,n){const r=nR(e,n,n.dirtyAtoms);for(const o of r){const s=t.nodeToComponentSubscriptions.get(o);if(s)for(const[i,[a,l]]of s)l(n)}}function _x(e){const t=e.getState(),n=t.currentTree,r=n.dirtyAtoms;if(r.size){for(const[o,s]of t.nodeTransactionSubscriptions)if(r.has(o))for(const[i,a]of s)a(e);for(const[o,s]of t.transactionSubscriptions)s(e);(!Rx().early||t.suspendedComponentResolvers.size>0)&&(lp(e,t,n),t.suspendedComponentResolvers.forEach(o=>o()),t.suspendedComponentResolvers.clear())}t.queuedComponentCallbacks_DEPRECATED.forEach(o=>o(n)),t.queuedComponentCallbacks_DEPRECATED.splice(0,t.queuedComponentCallbacks_DEPRECATED.length)}function mR(e){const t=e.getState();t.commitDepth++;try{const{nextTree:n}=t;if(n==null)return;t.previousTree=t.currentTree,t.currentTree=n,t.nextTree=null,_x(e),t.previousTree!=null?t.graphsByVersion.delete(t.previousTree.version):qf("Ended batch with no previous state, which is unexpected","recoil"),t.previousTree=null,we("recoil_memory_managament_2020")&&n==null&&Tx(e)}finally{t.commitDepth--}}function gR({setNotifyBatcherOfChange:e}){const t=Ql(),[,n]=pR([]);return e(()=>n({})),Nd(()=>(e(()=>n({})),()=>{e(()=>{})}),[e]),Nd(()=>{JA.enqueueExecution("Batcher",()=>{mR(t.current)})}),null}function vR(e,t){const n=kx();return t({set:(r,o)=>{const s=n.currentTree,i=oR(e,s,r.key,o),a=new Set(i.keys()),l=s.nonvalidatedAtoms.clone();for(const c of a)l.delete(c);n.currentTree={...s,dirtyAtoms:QE(s.dirtyAtoms,a),atomValues:lR(s.atomValues,i),nonvalidatedAtoms:l}},setUnvalidatedAtomValues:r=>{r.forEach((o,s)=>{n.currentTree=sR(n.currentTree,s,o)})}}),n}function yR(e){const t=cR(e),n=t.getStore_INTERNAL().getState();return t.retain(),n.nodeCleanupFunctions.forEach(r=>r()),n.nodeCleanupFunctions.clear(),n}let km=0;function xR({initializeState_DEPRECATED:e,initializeState:t,store_INTERNAL:n,children:r}){let o;const s=h=>{const v=o.current.graphsByVersion;if(v.has(h))return Ne(v.get(h));const x=iR();return v.set(h,x),x},i=(h,v)=>{if(v==null){const{transactionSubscriptions:x}=f.current.getState(),C=km++;return x.set(C,h),{release:()=>{x.delete(C)}}}else{const{nodeTransactionSubscriptions:x}=f.current.getState();x.has(v)||x.set(v,new Map);const C=km++;return Ne(x.get(v)).set(C,h),{release:()=>{const g=x.get(v);g&&(g.delete(C),g.size===0&&x.delete(v))}}}},a=h=>{Am(f.current);for(const v of Object.keys(h))Ne(f.current.getState().nextTree).transactionMetadata[v]=h[v]},l=h=>{Am(f.current);const v=Ne(o.current.nextTree);let x;try{Ld=!0,x=h(v)}finally{Ld=!1}x!==v&&(o.current.nextTree=x,Rx().early&&lp(f.current,o.current,x),Ne(c.current)())},c=fR(null),d=uR(h=>{c.current=h},[c]),f=bm(()=>n??{storeID:Ex(),getState:()=>o.current,replaceState:l,getGraph:s,subscribeToTransactions:i,addTransactionMetadata:a});n!=null&&(f.current=n),o=bm(()=>e!=null?vR(f.current,e):t!=null?yR(t):kx());const p=dR(()=>qc==null?void 0:qc(o,()=>o.current.currentTree.version),[o]);return Nd(()=>{const h=f.current;for(const v of new Set(h.getState().knownAtoms))rR(h,v,"get");return()=>{for(const v of h.getState().knownAtoms)tR(h,v)}},[f]),V.createElement(Nx.Provider,{value:f},V.createElement(Lx.Provider,{value:p},V.createElement(gR,{setNotifyBatcherOfChange:d}),r))}function wR(e){const{override:t,...n}=e,r=Ql();return t===!1&&r.current!==Px?e.children:V.createElement(xR,n)}function SR(){return Ql().current.storeID}var jn={RecoilRoot:wR,useStoreRef:Ql,useRecoilMutableSource:hR,useRecoilStoreID:SR,notifyComponents_FOR_TESTING:lp,sendEndOfBatchNotifications_FOR_TESTING:_x};function CR(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(let n=0,r=e.length;n{t.current=e}),t.current}var Ix=ER;const{useStoreRef:RR}=jn,{SUSPENSE_TIMEOUT_MS:TR}=Hr,{updateRetainCount:os}=Hr,{RetentionZone:jR}=Wl,{useEffect:PR,useRef:NR}=V,{isSSR:Em}=Kl;function LR(e){if(we("recoil_memory_managament_2020"))return _R(e)}function _R(e){const n=(Array.isArray(e)?e:[e]).map(i=>i instanceof jR?i:i.key),r=RR();PR(()=>{if(!we("recoil_memory_managament_2020"))return;const i=r.current;if(o.current&&!Em)window.clearTimeout(o.current),o.current=null;else for(const a of n)os(i,a,1);return()=>{for(const a of n)os(i,a,-1)}},[r,...n]);const o=NR(),s=Ix(n);if(!Em&&(s===void 0||!bR(s,n))){const i=r.current;for(const a of n)os(i,a,1);if(s)for(const a of s)os(i,a,-1);o.current&&window.clearTimeout(o.current),o.current=window.setTimeout(()=>{o.current=null;for(const a of n)os(i,a,-1)},TR)}}var cp=LR;function IR(){return""}var Si=IR;const{batchUpdates:MR}=Gl,{DEFAULT_VALUE:Mx}=Et,{currentRendererSupportsUseSyncExternalStore:DR,reactMode:Ho,useMutableSource:OR,useSyncExternalStore:BR}=yi,{useRecoilMutableSource:VR,useStoreRef:dn}=jn,{AbstractRecoilValue:_d,getRecoilValueAsLoadable:Ci,setRecoilValue:rl,setUnvalidatedRecoilValue:zR,subscribeToRecoilValue:_o}=un,{useCallback:At,useEffect:Io,useMemo:Dx,useRef:Is,useState:up}=V,{setByAddingToSet:FR}=rx,{isSSR:UR}=Kl;function dp(e,t,n){if(e.state==="hasValue")return e.contents;throw e.state==="loading"?new Promise(o=>{const s=n.current.getState().suspendedComponentResolvers;s.add(o),UR&&ke(e.contents)&&e.contents.finally(()=>{s.delete(o)})}):e.state==="hasError"?e.contents:ue(`Invalid value of loadable atom "${t.key}"`)}function $R(){const e=Si(),t=dn(),[,n]=up([]),r=Is(new Set);r.current=new Set;const o=Is(new Set),s=Is(new Map),i=At(l=>{const c=s.current.get(l);c&&(c.release(),s.current.delete(l))},[s]),a=At((l,c)=>{s.current.has(c)&&n([])},[]);return Io(()=>{const l=t.current;Ls(r.current,o.current).forEach(c=>{if(s.current.has(c))return;const d=_o(l,new _d(c),p=>a(p,c),e);s.current.set(c,d),l.getState().nextTree?l.getState().queuedComponentCallbacks_DEPRECATED.push(()=>{a(l.getState(),c)}):a(l.getState(),c)}),Ls(o.current,r.current).forEach(c=>{i(c)}),o.current=r.current}),Io(()=>{const l=s.current;return Ls(r.current,new Set(l.keys())).forEach(c=>{const d=_o(t.current,new _d(c),f=>a(f,c),e);l.set(c,d)}),()=>l.forEach((c,d)=>i(d))},[e,t,i,a]),Dx(()=>{function l(v){return x=>{rl(t.current,v,x)}}function c(v){return()=>rl(t.current,v,Mx)}function d(v){var x;r.current.has(v.key)||(r.current=FR(r.current,v.key));const C=t.current.getState();return Ci(t.current,v,Ho().early&&(x=C.nextTree)!==null&&x!==void 0?x:C.currentTree)}function f(v){const x=d(v);return dp(x,v,t)}function p(v){return[f(v),l(v)]}function h(v){return[d(v),l(v)]}return{getRecoilValue:f,getRecoilValueLoadable:d,getRecoilState:p,getRecoilStateLoadable:h,getSetRecoilState:l,getResetRecoilState:c}},[r,t])}const WR={current:0};function HR(e){const t=dn(),n=Si(),r=At(()=>{var a;const l=t.current,c=l.getState(),d=Ho().early&&(a=c.nextTree)!==null&&a!==void 0?a:c.currentTree;return{loadable:Ci(l,e,d),key:e.key}},[t,e]),o=At(a=>{let l;return()=>{var c,d;const f=a();return(c=l)!==null&&c!==void 0&&c.loadable.is(f.loadable)&&((d=l)===null||d===void 0?void 0:d.key)===f.key?l:(l=f,f)}},[]),s=Dx(()=>o(r),[r,o]),i=At(a=>{const l=t.current;return _o(l,e,a,n).release},[t,e,n]);return BR(i,s,s).loadable}function GR(e){const t=dn(),n=At(()=>{var c;const d=t.current,f=d.getState(),p=Ho().early&&(c=f.nextTree)!==null&&c!==void 0?c:f.currentTree;return Ci(d,e,p)},[t,e]),r=At(()=>n(),[n]),o=Si(),s=At((c,d)=>{const f=t.current;return _o(f,e,()=>{if(!we("recoil_suppress_rerender_in_callback"))return d();const h=n();l.current.is(h)||d(),l.current=h},o).release},[t,e,o,n]),i=VR();if(i==null)throw ue("Recoil hooks must be used in components contained within a component.");const a=OR(i,r,s),l=Is(a);return Io(()=>{l.current=a}),a}function Id(e){const t=dn(),n=Si(),r=At(()=>{var l;const c=t.current,d=c.getState(),f=Ho().early&&(l=d.nextTree)!==null&&l!==void 0?l:d.currentTree;return Ci(c,e,f)},[t,e]),o=At(()=>({loadable:r(),key:e.key}),[r,e.key]),s=At(l=>{const c=o();return l.loadable.is(c.loadable)&&l.key===c.key?l:c},[o]);Io(()=>{const l=_o(t.current,e,c=>{a(s)},n);return a(s),l.release},[n,e,t,s]);const[i,a]=up(o);return i.key!==e.key?o().loadable:i.loadable}function KR(e){const t=dn(),[,n]=up([]),r=Si(),o=At(()=>{var a;const l=t.current,c=l.getState(),d=Ho().early&&(a=c.nextTree)!==null&&a!==void 0?a:c.currentTree;return Ci(l,e,d)},[t,e]),s=o(),i=Is(s);return Io(()=>{i.current=s}),Io(()=>{const a=t.current,l=a.getState(),c=_o(a,e,f=>{var p;if(!we("recoil_suppress_rerender_in_callback"))return n([]);const h=o();(p=i.current)!==null&&p!==void 0&&p.is(h)||n(h),i.current=h},r);if(l.nextTree)a.getState().queuedComponentCallbacks_DEPRECATED.push(()=>{i.current=null,n([])});else{var d;if(!we("recoil_suppress_rerender_in_callback"))return n([]);const f=o();(d=i.current)!==null&&d!==void 0&&d.is(f)||n(f),i.current=f}return c.release},[r,o,e,t]),s}function fp(e){return we("recoil_memory_managament_2020")&&cp(e),{TRANSITION_SUPPORT:Id,SYNC_EXTERNAL_STORE:DR()?HR:Id,MUTABLE_SOURCE:GR,LEGACY:KR}[Ho().mode](e)}function Ox(e){const t=dn(),n=fp(e);return dp(n,e,t)}function Xl(e){const t=dn();return At(n=>{rl(t.current,e,n)},[t,e])}function JR(e){const t=dn();return At(()=>{rl(t.current,e,Mx)},[t,e])}function YR(e){return[Ox(e),Xl(e)]}function ZR(e){return[fp(e),Xl(e)]}function QR(){const e=dn();return(t,n={})=>{MR(()=>{e.current.addTransactionMetadata(n),t.forEach((r,o)=>zR(e.current,new _d(o),r))})}}function Bx(e){return we("recoil_memory_managament_2020")&&cp(e),Id(e)}function Vx(e){const t=dn(),n=Bx(e);return dp(n,e,t)}function XR(e){return[Vx(e),Xl(e)]}var qR={recoilComponentGetRecoilValueCount_FOR_TESTING:WR,useRecoilInterface:$R,useRecoilState:YR,useRecoilStateLoadable:ZR,useRecoilValue:Ox,useRecoilValueLoadable:fp,useResetRecoilState:JR,useSetRecoilState:Xl,useSetUnvalidatedAtomValues:QR,useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE:Bx,useRecoilValue_TRANSITION_SUPPORT_UNSTABLE:Vx,useRecoilState_TRANSITION_SUPPORT_UNSTABLE:XR};function eT(e,t){const n=new Map;for(const[r,o]of e)t(o,r)&&n.set(r,o);return n}var tT=eT;function nT(e,t){const n=new Set;for(const r of e)t(r)&&n.add(r);return n}var rT=nT;function oT(...e){const t=new Map;for(let n=0;nt.current.subscribeToTransactions(e).release,[e,t])}function jm(e){const t=e.atomValues.toMap(),n=nl(tT(t,(r,o)=>{const i=zx(o).persistence_UNSTABLE;return i!=null&&i.type!=="none"&&r.state==="hasValue"}),r=>r.contents);return sT(e.nonvalidatedAtoms.toMap(),n)}function pT(e){ec(ql(t=>{let n=t.getState().previousTree;const r=t.getState().currentTree;n||(n=t.getState().currentTree);const o=jm(r),s=jm(n),i=nl(lT,l=>{var c,d,f,p;return{persistence_UNSTABLE:{type:(c=(d=l.persistence_UNSTABLE)===null||d===void 0?void 0:d.type)!==null&&c!==void 0?c:"none",backButton:(f=(p=l.persistence_UNSTABLE)===null||p===void 0?void 0:p.backButton)!==null&&f!==void 0?f:!1}}}),a=rT(r.dirtyAtoms,l=>o.has(l)||s.has(l));e({atomValues:o,previousAtomValues:s,atomInfo:i,modifiedAtoms:a,transactionMetadata:{...r.transactionMetadata}})},[e]))}function hT(e){ec(ql(t=>{const n=ol(t,"latest"),r=ol(t,"previous");e({snapshot:n,previousSnapshot:r})},[e]))}function mT(){const e=pp(),[t,n]=fT(()=>ol(e.current)),r=Ix(t),o=Rm(),s=Rm();if(ec(ql(a=>n(ol(a)),[])),Fx(()=>{const a=t.retain();if(o.current&&!Tm){var l;window.clearTimeout(o.current),o.current=null,(l=s.current)===null||l===void 0||l.call(s),s.current=null}return()=>{window.setTimeout(a,10)}},[t]),r!==t&&!Tm){if(o.current){var i;window.clearTimeout(o.current),o.current=null,(i=s.current)===null||i===void 0||i.call(s),s.current=null}s.current=t.retain(),o.current=window.setTimeout(()=>{var a;o.current=null,(a=s.current)===null||a===void 0||a.call(s),s.current=null},dT)}return t}function Ux(e,t){var n;const r=e.getState(),o=(n=r.nextTree)!==null&&n!==void 0?n:r.currentTree,s=t.getStore_INTERNAL().getState().currentTree;iT(()=>{const i=new Set;for(const c of[o.atomValues.keys(),s.atomValues.keys()])for(const d of c){var a,l;((a=o.atomValues.get(d))===null||a===void 0?void 0:a.contents)!==((l=s.atomValues.get(d))===null||l===void 0?void 0:l.contents)&&zx(d).shouldRestoreFromSnapshots&&i.add(d)}i.forEach(c=>{uT(e,new cT(c),s.atomValues.has(c)?Ne(s.atomValues.get(c)):aT)}),e.replaceState(c=>({...c,stateID:t.getID()}))})}function gT(){const e=pp();return ql(t=>Ux(e.current,t),[e])}var $x={useRecoilSnapshot:mT,gotoSnapshot:Ux,useGotoRecoilSnapshot:gT,useRecoilTransactionObserver:hT,useTransactionObservation_DEPRECATED:pT,useTransactionSubscription_DEPRECATED:ec};const{peekNodeInfo:vT}=fr,{useStoreRef:yT}=jn;function xT(){const e=yT();return({key:t})=>vT(e.current,e.current.getState().currentTree,t)}var wT=xT;const{reactMode:ST}=yi,{RecoilRoot:CT,useStoreRef:bT}=jn,{useMemo:AT}=V;function kT(){ST().mode==="MUTABLE_SOURCE"&&console.warn("Warning: There are known issues using useRecoilBridgeAcrossReactRoots() in recoil_mutable_source rendering mode. Please consider upgrading to recoil_sync_external_store mode.");const e=bT().current;return AT(()=>{function t({children:n}){return V.createElement(CT,{store_INTERNAL:e},n)}return t},[e])}var ET=kT;const{loadableWithValue:RT}=vi,{initializeNode:TT}=fr,{DEFAULT_VALUE:jT,getNode:PT}=Et,{copyTreeState:NT,getRecoilValueAsLoadable:LT,invalidateDownstreams:_T,writeLoadableToTreeState:IT}=un;function Pm(e){return PT(e.key).nodeType==="atom"}class MT{constructor(t,n){ce(this,"_store",void 0),ce(this,"_treeState",void 0),ce(this,"_changes",void 0),ce(this,"get",r=>{if(this._changes.has(r.key))return this._changes.get(r.key);if(!Pm(r))throw ue("Reading selectors within atomicUpdate is not supported");const o=LT(this._store,r,this._treeState);if(o.state==="hasValue")return o.contents;throw o.state==="hasError"?o.contents:ue(`Expected Recoil atom ${r.key} to have a value, but it is in a loading state.`)}),ce(this,"set",(r,o)=>{if(!Pm(r))throw ue("Setting selectors within atomicUpdate is not supported");if(typeof o=="function"){const s=this.get(r);this._changes.set(r.key,o(s))}else TT(this._store,r.key,"set"),this._changes.set(r.key,o)}),ce(this,"reset",r=>{this.set(r,jT)}),this._store=t,this._treeState=n,this._changes=new Map}newTreeState_INTERNAL(){if(this._changes.size===0)return this._treeState;const t=NT(this._treeState);for(const[n,r]of this._changes)IT(t,n,RT(r));return _T(this._store,t),t}}function DT(e){return t=>{e.replaceState(n=>{const r=new MT(e,n);return t(r),r.newTreeState_INTERNAL()})}}var OT={atomicUpdater:DT},BT=OT.atomicUpdater,Wx=Object.freeze({__proto__:null,atomicUpdater:BT});function VT(e,t){if(!e)throw new Error(t)}var zT=VT,ws=zT;const{atomicUpdater:FT}=Wx,{batchUpdates:UT}=Gl,{DEFAULT_VALUE:$T}=Et,{useStoreRef:WT}=jn,{refreshRecoilValue:HT,setRecoilValue:Nm}=un,{cloneSnapshot:GT}=Zl,{gotoSnapshot:KT}=$x,{useCallback:JT}=V;class Hx{}const YT=new Hx;function Gx(e,t,n,r){let o=YT,s;if(UT(()=>{const a="useRecoilCallback() expects a function that returns a function: it accepts a function of the type (RecoilInterface) => (Args) => ReturnType and returns a callback function (Args) => ReturnType, where RecoilInterface is an object {snapshot, set, ...} and Args and ReturnType are the argument and return types of the callback you want to create. Please see the docs at recoiljs.org for details.";if(typeof t!="function")throw ue(a);const l=ox({...r??{},set:(d,f)=>Nm(e,d,f),reset:d=>Nm(e,d,$T),refresh:d=>HT(e,d),gotoSnapshot:d=>KT(e,d),transact_UNSTABLE:d=>FT(e)(d)},{snapshot:()=>{const d=GT(e);return s=d.retain(),d}}),c=t(l);if(typeof c!="function")throw ue(a);o=c(...n)}),o instanceof Hx&&ws(!1),ke(o))o=o.finally(()=>{var a;(a=s)===null||a===void 0||a()});else{var i;(i=s)===null||i===void 0||i()}return o}function ZT(e,t){const n=WT();return JT((...r)=>Gx(n.current,e,r),t!=null?[...t,n]:void 0)}var Kx={recoilCallback:Gx,useRecoilCallback:ZT};const{useStoreRef:QT}=jn,{refreshRecoilValue:XT}=un,{useCallback:qT}=V;function ej(e){const t=QT();return qT(()=>{const n=t.current;XT(n,e)},[e,t])}var tj=ej;const{atomicUpdater:nj}=Wx,{useStoreRef:rj}=jn,{useMemo:oj}=V;function sj(e,t){const n=rj();return oj(()=>(...r)=>{nj(n.current)(s=>{e(s)(...r)})},t!=null?[...t,n]:void 0)}var ij=sj;class aj{constructor(t){ce(this,"value",void 0),this.value=t}}var lj={WrappedValue:aj},cj=lj.WrappedValue,Jx=Object.freeze({__proto__:null,WrappedValue:cj});const{isFastRefreshEnabled:uj}=yi;class Lm extends Error{}class dj{constructor(t){var n,r,o;ce(this,"_name",void 0),ce(this,"_numLeafs",void 0),ce(this,"_root",void 0),ce(this,"_onHit",void 0),ce(this,"_onSet",void 0),ce(this,"_mapNodeValue",void 0),this._name=t==null?void 0:t.name,this._numLeafs=0,this._root=null,this._onHit=(n=t==null?void 0:t.onHit)!==null&&n!==void 0?n:()=>{},this._onSet=(r=t==null?void 0:t.onSet)!==null&&r!==void 0?r:()=>{},this._mapNodeValue=(o=t==null?void 0:t.mapNodeValue)!==null&&o!==void 0?o:s=>s}size(){return this._numLeafs}root(){return this._root}get(t,n){var r;return(r=this.getLeafNode(t,n))===null||r===void 0?void 0:r.value}getLeafNode(t,n){if(this._root==null)return;let r=this._root;for(;r;){if(n==null||n.onNodeVisit(r),r.type==="leaf")return this._onHit(r),r;const o=this._mapNodeValue(t(r.nodeKey));r=r.branches.get(o)}}set(t,n,r){const o=()=>{var s,i,a,l;let c,d;for(const[C,g]of t){var f,p,h;const m=this._root;if((m==null?void 0:m.type)==="leaf")throw this.invalidCacheError();const y=c;if(c=y?y.branches.get(d):m,c=(f=c)!==null&&f!==void 0?f:{type:"branch",nodeKey:C,parent:y,branches:new Map,branchKey:d},c.type!=="branch"||c.nodeKey!==C)throw this.invalidCacheError();y==null||y.branches.set(d,c),r==null||(p=r.onNodeVisit)===null||p===void 0||p.call(r,c),d=this._mapNodeValue(g),this._root=(h=this._root)!==null&&h!==void 0?h:c}const v=c?(s=c)===null||s===void 0?void 0:s.branches.get(d):this._root;if(v!=null&&(v.type!=="leaf"||v.branchKey!==d))throw this.invalidCacheError();const x={type:"leaf",value:n,parent:c,branchKey:d};(i=c)===null||i===void 0||i.branches.set(d,x),this._root=(a=this._root)!==null&&a!==void 0?a:x,this._numLeafs++,this._onSet(x),r==null||(l=r.onNodeVisit)===null||l===void 0||l.call(r,x)};try{o()}catch(s){if(s instanceof Lm)this.clear(),o();else throw s}}delete(t){const n=this.root();if(!n)return!1;if(t===n)return this._root=null,this._numLeafs=0,!0;let r=t.parent,o=t.branchKey;for(;r;){var s;if(r.branches.delete(o),r===n)return r.branches.size===0?(this._root=null,this._numLeafs=0):this._numLeafs--,!0;if(r.branches.size>0)break;o=(s=r)===null||s===void 0?void 0:s.branchKey,r=r.parent}for(;r!==n;r=r.parent)if(r==null)return!1;return this._numLeafs--,!0}clear(){this._numLeafs=0,this._root=null}invalidCacheError(){const t=uj()?"Possible Fast Refresh module reload detected. This may also be caused by an selector returning inconsistent values. Resetting cache.":"Invalid cache values. This happens when selectors do not return consistent values for the same input dependency values. That may also be caused when using Fast Refresh to change a selector implementation. Resetting cache.";throw qf(t+(this._name!=null?` - ${this._name}`:"")),new Lm}}var fj={TreeCache:dj},pj=fj.TreeCache,Yx=Object.freeze({__proto__:null,TreeCache:pj});class hj{constructor(t){var n;ce(this,"_maxSize",void 0),ce(this,"_size",void 0),ce(this,"_head",void 0),ce(this,"_tail",void 0),ce(this,"_map",void 0),ce(this,"_keyMapper",void 0),this._maxSize=t.maxSize,this._size=0,this._head=null,this._tail=null,this._map=new Map,this._keyMapper=(n=t.mapKey)!==null&&n!==void 0?n:r=>r}head(){return this._head}tail(){return this._tail}size(){return this._size}maxSize(){return this._maxSize}has(t){return this._map.has(this._keyMapper(t))}get(t){const n=this._keyMapper(t),r=this._map.get(n);if(r)return this.set(t,r.value),r.value}set(t,n){const r=this._keyMapper(t);this._map.get(r)&&this.delete(t);const s=this.head(),i={key:t,right:s,left:null,value:n};s?s.left=i:this._tail=i,this._map.set(r,i),this._head=i,this._size++,this._maybeDeleteLRU()}_maybeDeleteLRU(){this.size()>this.maxSize()&&this.deleteLru()}deleteLru(){const t=this.tail();t&&this.delete(t.key)}delete(t){const n=this._keyMapper(t);if(!this._size||!this._map.has(n))return;const r=Ne(this._map.get(n)),o=r.right,s=r.left;o&&(o.left=r.left),s&&(s.right=r.right),r===this.head()&&(this._head=o),r===this.tail()&&(this._tail=s),this._map.delete(n),this._size--}clear(){this._size=0,this._head=null,this._tail=null,this._map=new Map}}var mj={LRUCache:hj},gj=mj.LRUCache,Zx=Object.freeze({__proto__:null,LRUCache:gj});const{LRUCache:vj}=Zx,{TreeCache:yj}=Yx;function xj({name:e,maxSize:t,mapNodeValue:n=r=>r}){const r=new vj({maxSize:t}),o=new yj({name:e,mapNodeValue:n,onHit:s=>{r.set(s,!0)},onSet:s=>{const i=r.tail();r.set(s,!0),i&&o.size()>t&&o.delete(i.key)}});return o}var _m=xj;function Jt(e,t,n){if(typeof e=="string"&&!e.includes('"')&&!e.includes("\\"))return`"${e}"`;switch(typeof e){case"undefined":return"";case"boolean":return e?"true":"false";case"number":case"symbol":return String(e);case"string":return JSON.stringify(e);case"function":if((t==null?void 0:t.allowFunctions)!==!0)throw ue("Attempt to serialize function in a Recoil cache key");return`__FUNCTION(${e.name})__`}if(e===null)return"null";if(typeof e!="object"){var r;return(r=JSON.stringify(e))!==null&&r!==void 0?r:""}if(ke(e))return"__PROMISE__";if(Array.isArray(e))return`[${e.map((o,s)=>Jt(o,t,s.toString()))}]`;if(typeof e.toJSON=="function")return Jt(e.toJSON(n),t,n);if(e instanceof Map){const o={};for(const[s,i]of e)o[typeof s=="string"?s:Jt(s,t)]=i;return Jt(o,t,n)}return e instanceof Set?Jt(Array.from(e).sort((o,s)=>Jt(o,t).localeCompare(Jt(s,t))),t,n):Symbol!==void 0&&e[Symbol.iterator]!=null&&typeof e[Symbol.iterator]=="function"?Jt(Array.from(e),t,n):`{${Object.keys(e).filter(o=>e[o]!==void 0).sort().map(o=>`${Jt(o,t)}:${Jt(e[o],t,o)}`).join(",")}}`}function wj(e,t={allowFunctions:!1}){return Jt(e,t)}var tc=wj;const{TreeCache:Sj}=Yx,Qi={equality:"reference",eviction:"keep-all",maxSize:1/0};function Cj({equality:e=Qi.equality,eviction:t=Qi.eviction,maxSize:n=Qi.maxSize}=Qi,r){const o=bj(e);return Aj(t,n,o,r)}function bj(e){switch(e){case"reference":return t=>t;case"value":return t=>tc(t)}throw ue(`Unrecognized equality policy ${e}`)}function Aj(e,t,n,r){switch(e){case"keep-all":return new Sj({name:r,mapNodeValue:n});case"lru":return _m({name:r,maxSize:Ne(t),mapNodeValue:n});case"most-recent":return _m({name:r,maxSize:1,mapNodeValue:n})}throw ue(`Unrecognized eviction policy ${e}`)}var kj=Cj;function Ej(e){return()=>null}var Rj={startPerfBlock:Ej};const{isLoadable:Tj,loadableWithError:Xi,loadableWithPromise:jj,loadableWithValue:eu}=vi,{WrappedValue:Qx}=Jx,{getNodeLoadable:qi,peekNodeLoadable:Pj,setNodeValue:Nj}=fr,{saveDepsToStore:Lj}=xi,{DEFAULT_VALUE:_j,getConfigDeletionHandler:Ij,getNode:Mj,registerNode:Im}=Et,{isRecoilValue:Dj}=Lo,{markRecoilValueModified:Mm}=un,{retainedByOptionWithDefault:Oj}=Hr,{recoilCallback:Bj}=Kx,{startPerfBlock:Vj}=Rj;class Xx{}const ss=new Xx,is=[],ea=new Map,zj=(()=>{let e=0;return()=>e++})();function qx(e){let t=null;const{key:n,get:r,cachePolicy_UNSTABLE:o}=e,s=e.set!=null?e.set:void 0,i=new Set,a=kj(o??{equality:"reference",eviction:"keep-all"},n),l=Oj(e.retainedBy_UNSTABLE),c=new Map;let d=0;function f(){return!we("recoil_memory_managament_2020")||d>0}function p(R){return R.getState().knownSelectors.add(n),d++,()=>{d--}}function h(){return Ij(n)!==void 0&&!f()}function v(R,j,B,J,$){Z(j,J,$),x(R,B)}function x(R,j){D(R,j)&&N(R),g(j,!0)}function C(R,j){D(R,j)&&(Ne(I(R)).stateVersions.clear(),g(j,!1))}function g(R,j){const B=ea.get(R);if(B!=null){for(const J of B)Mm(J,Ne(t));j&&ea.delete(R)}}function m(R,j){let B=ea.get(j);B==null&&ea.set(j,B=new Set),B.add(R)}function y(R,j,B,J,$,te){return j.then(le=>{if(!f())throw N(R),ss;const ee=eu(le);return v(R,B,$,ee,J),le}).catch(le=>{if(!f())throw N(R),ss;if(ke(le))return S(R,le,B,J,$,te);const ee=Xi(le);throw v(R,B,$,ee,J),le})}function S(R,j,B,J,$,te){return j.then(le=>{if(!f())throw N(R),ss;te.loadingDepKey!=null&&te.loadingDepPromise===j?B.atomValues.set(te.loadingDepKey,eu(le)):R.getState().knownSelectors.forEach(me=>{B.atomValues.delete(me)});const ee=_(R,B);if(ee&&ee.state!=="loading"){if((D(R,$)||I(R)==null)&&x(R,$),ee.state==="hasValue")return ee.contents;throw ee.contents}if(!D(R,$)){const me=M(R,B);if(me!=null)return me.loadingLoadable.contents}const[ge,Se]=L(R,B,$);if(ge.state!=="loading"&&v(R,B,$,ge,Se),ge.state==="hasError")throw ge.contents;return ge.contents}).catch(le=>{if(le instanceof Xx)throw ss;if(!f())throw N(R),ss;const ee=Xi(le);throw v(R,B,$,ee,J),le})}function A(R,j,B,J){var $,te,le,ee;if(D(R,J)||j.version===(($=R.getState())===null||$===void 0||(te=$.currentTree)===null||te===void 0?void 0:te.version)||j.version===((le=R.getState())===null||le===void 0||(ee=le.nextTree)===null||ee===void 0?void 0:ee.version)){var ge,Se,me;Lj(n,B,R,(ge=(Se=R.getState())===null||Se===void 0||(me=Se.nextTree)===null||me===void 0?void 0:me.version)!==null&&ge!==void 0?ge:R.getState().currentTree.version)}for(const ye of B)i.add(ye)}function L(R,j,B){const J=Vj(n);let $=!0,te=!0;const le=()=>{J(),te=!1};let ee,ge=!1,Se;const me={loadingDepKey:null,loadingDepPromise:null},ye=new Map;function Mt({key:ut}){const ot=qi(R,j,ut);switch(ye.set(ut,ot),$||(A(R,j,new Set(ye.keys()),B),C(R,B)),ot.state){case"hasValue":return ot.contents;case"hasError":throw ot.contents;case"loading":throw me.loadingDepKey=ut,me.loadingDepPromise=ot.contents,ot.contents}throw ue("Invalid Loadable state")}const fn=ut=>(...ot)=>{if(te)throw ue("Callbacks from getCallback() should only be called asynchronously after the selector is evalutated. It can be used for selectors to return objects with callbacks that can work with Recoil state without a subscription.");return t==null&&ws(!1),Bj(R,ut,ot,{node:t})};try{ee=r({get:Mt,getCallback:fn}),ee=Dj(ee)?Mt(ee):ee,Tj(ee)&&(ee.state==="hasError"&&(ge=!0),ee=ee.contents),ke(ee)?ee=y(R,ee,j,ye,B,me).finally(le):le(),ee=ee instanceof Qx?ee.value:ee}catch(ut){ee=ut,ke(ee)?ee=S(R,ee,j,ye,B,me).finally(le):(ge=!0,le())}return ge?Se=Xi(ee):ke(ee)?Se=jj(ee):Se=eu(ee),$=!1,O(R,B,ye),A(R,j,new Set(ye.keys()),B),[Se,ye]}function _(R,j){let B=j.atomValues.get(n);if(B!=null)return B;const J=new Set;try{B=a.get(te=>(typeof te!="string"&&ws(!1),qi(R,j,te).contents),{onNodeVisit:te=>{te.type==="branch"&&te.nodeKey!==n&&J.add(te.nodeKey)}})}catch(te){throw ue(`Problem with cache lookup for selector "${n}": ${te.message}`)}if(B){var $;j.atomValues.set(n,B),A(R,j,J,($=I(R))===null||$===void 0?void 0:$.executionID)}return B}function k(R,j){const B=_(R,j);if(B!=null)return N(R),B;const J=M(R,j);if(J!=null){var $;return(($=J.loadingLoadable)===null||$===void 0?void 0:$.state)==="loading"&&m(R,J.executionID),J.loadingLoadable}const te=zj(),[le,ee]=L(R,j,te);return le.state==="loading"?(T(R,te,le,ee,j),m(R,te)):(N(R),Z(j,le,ee)),le}function M(R,j){const B=Sx([c.has(R)?[Ne(c.get(R))]:[],Ul(op(c,([$])=>$!==R),([,$])=>$)]);function J($){for(const[te,le]of $)if(!qi(R,j,te).is(le))return!0;return!1}for(const $ of B){if($.stateVersions.get(j.version)||!J($.depValuesDiscoveredSoFarDuringAsyncWork))return $.stateVersions.set(j.version,!0),$;$.stateVersions.set(j.version,!1)}}function I(R){return c.get(R)}function T(R,j,B,J,$){c.set(R,{depValuesDiscoveredSoFarDuringAsyncWork:J,executionID:j,loadingLoadable:B,stateVersions:new Map([[$.version,!0]])})}function O(R,j,B){if(D(R,j)){const J=I(R);J!=null&&(J.depValuesDiscoveredSoFarDuringAsyncWork=B)}}function N(R){c.delete(R)}function D(R,j){var B;return j===((B=I(R))===null||B===void 0?void 0:B.executionID)}function H(R){return Array.from(R.entries()).map(([j,B])=>[j,B.contents])}function Z(R,j,B){R.atomValues.set(n,j);try{a.set(H(B),j)}catch(J){throw ue(`Problem with setting cache for selector "${n}": ${J.message}`)}}function ne(R){if(is.includes(n)){const j=`Recoil selector has circular dependencies: ${is.slice(is.indexOf(n)).join(" โ†’ ")}`;return Xi(ue(j))}is.push(n);try{return R()}finally{is.pop()}}function z(R,j){const B=j.atomValues.get(n);return B??a.get(J=>{var $;return typeof J!="string"&&ws(!1),($=Pj(R,j,J))===null||$===void 0?void 0:$.contents})}function W(R,j){return ne(()=>k(R,j))}function q(R){R.atomValues.delete(n)}function X(R,j){t==null&&ws(!1);for(const J of i){var B;const $=Mj(J);(B=$.clearCache)===null||B===void 0||B.call($,R,j)}i.clear(),q(j),a.clear(),Mm(R,t)}return s!=null?t=Im({key:n,nodeType:"selector",peek:z,get:W,set:(j,B,J)=>{let $=!1;const te=new Map;function le({key:me}){if($)throw ue("Recoil: Async selector sets are not currently supported.");const ye=qi(j,B,me);if(ye.state==="hasValue")return ye.contents;if(ye.state==="loading"){const Mt=`Getting value of asynchronous atom or selector "${me}" in a pending state while setting selector "${n}" is not yet supported.`;throw ue(Mt)}else throw ye.contents}function ee(me,ye){if($)throw ue("Recoil: Async selector sets are not currently supported.");const Mt=typeof ye=="function"?ye(le(me)):ye;Nj(j,B,me.key,Mt).forEach((ut,ot)=>te.set(ot,ut))}function ge(me){ee(me,_j)}const Se=s({set:ee,get:le,reset:ge},J);if(Se!==void 0)throw ke(Se)?ue("Recoil: Async selector sets are not currently supported."):ue("Recoil: selector set should be a void function.");return $=!0,te},init:p,invalidate:q,clearCache:X,shouldDeleteConfigOnRelease:h,dangerouslyAllowMutability:e.dangerouslyAllowMutability,shouldRestoreFromSnapshots:!1,retainedBy:l}):t=Im({key:n,nodeType:"selector",peek:z,get:W,init:p,invalidate:q,clearCache:X,shouldDeleteConfigOnRelease:h,dangerouslyAllowMutability:e.dangerouslyAllowMutability,shouldRestoreFromSnapshots:!1,retainedBy:l})}qx.value=e=>new Qx(e);var Mo=qx;const{isLoadable:Fj,loadableWithError:tu,loadableWithPromise:nu,loadableWithValue:Qr}=vi,{WrappedValue:e1}=Jx,{peekNodeInfo:Uj}=fr,{DEFAULT_VALUE:br,DefaultValue:On,getConfigDeletionHandler:t1,registerNode:$j,setConfigDeletionHandler:Wj}=Et,{isRecoilValue:Hj}=Lo,{getRecoilValueAsLoadable:Gj,markRecoilValueModified:Kj,setRecoilValue:Dm,setRecoilValueLoadable:Jj}=un,{retainedByOptionWithDefault:Yj}=Hr,as=e=>e instanceof e1?e.value:e;function Zj(e){const{key:t,persistence_UNSTABLE:n}=e,r=Yj(e.retainedBy_UNSTABLE);let o=0;function s(m){return nu(m.then(y=>(i=Qr(y),y)).catch(y=>{throw i=tu(y),y}))}let i=ke(e.default)?s(e.default):Fj(e.default)?e.default.state==="loading"?s(e.default.contents):e.default:Qr(as(e.default));i.contents;let a;const l=new Map;function c(m){return m}function d(m,y){const S=y.then(A=>{var L,_;return((_=((L=m.getState().nextTree)!==null&&L!==void 0?L:m.getState().currentTree).atomValues.get(t))===null||_===void 0?void 0:_.contents)===S&&Dm(m,g,A),A}).catch(A=>{var L,_;throw((_=((L=m.getState().nextTree)!==null&&L!==void 0?L:m.getState().currentTree).atomValues.get(t))===null||_===void 0?void 0:_.contents)===S&&Jj(m,g,tu(A)),A});return S}function f(m,y,S){var A;o++;const L=()=>{var N;o--,(N=l.get(m))===null||N===void 0||N.forEach(D=>D()),l.delete(m)};if(m.getState().knownAtoms.add(t),i.state==="loading"){const N=()=>{var D;((D=m.getState().nextTree)!==null&&D!==void 0?D:m.getState().currentTree).atomValues.has(t)||Kj(m,g)};i.contents.finally(N)}const _=(A=e.effects)!==null&&A!==void 0?A:e.effects_UNSTABLE;if(_!=null){let ne=function(j){if(D&&j.key===t){const B=N;return B instanceof On?p(m,y):ke(B)?nu(B.then(J=>J instanceof On?i.toPromise():J)):Qr(B)}return Gj(m,j)},z=function(j){return ne(j).toPromise()},W=function(j){var B;const J=Uj(m,(B=m.getState().nextTree)!==null&&B!==void 0?B:m.getState().currentTree,j.key);return D&&j.key===t&&!(N instanceof On)?{...J,isSet:!0,loadable:ne(j)}:J};var I=ne,T=z,O=W;let N=br,D=!0,H=!1,Z=null;const q=j=>B=>{if(D){const J=ne(g),$=J.state==="hasValue"?J.contents:br;N=typeof B=="function"?B($):B,ke(N)&&(N=N.then(te=>(Z={effect:j,value:te},te)))}else{if(ke(B))throw ue("Setting atoms to async values is not implemented.");typeof B!="function"&&(Z={effect:j,value:as(B)}),Dm(m,g,typeof B=="function"?J=>{const $=as(B(J));return Z={effect:j,value:$},$}:as(B))}},X=j=>()=>q(j)(br),R=j=>B=>{var J;const{release:$}=m.subscribeToTransactions(te=>{var le;let{currentTree:ee,previousTree:ge}=te.getState();ge||(ge=ee);const Se=(le=ee.atomValues.get(t))!==null&&le!==void 0?le:i;if(Se.state==="hasValue"){var me,ye,Mt,fn;const ut=Se.contents,ot=(me=ge.atomValues.get(t))!==null&&me!==void 0?me:i,Ni=ot.state==="hasValue"?ot.contents:br;((ye=Z)===null||ye===void 0?void 0:ye.effect)!==j||((Mt=Z)===null||Mt===void 0?void 0:Mt.value)!==ut?B(ut,Ni,!ee.atomValues.has(t)):((fn=Z)===null||fn===void 0?void 0:fn.effect)===j&&(Z=null)}},t);l.set(m,[...(J=l.get(m))!==null&&J!==void 0?J:[],$])};for(const j of _)try{const B=j({node:g,storeID:m.storeID,parentStoreID_UNSTABLE:m.parentStoreID,trigger:S,setSelf:q(j),resetSelf:X(j),onSet:R(j),getPromise:z,getLoadable:ne,getInfo_UNSTABLE:W});if(B!=null){var k;l.set(m,[...(k=l.get(m))!==null&&k!==void 0?k:[],B])}}catch(B){N=B,H=!0}if(D=!1,!(N instanceof On)){var M;const j=H?tu(N):ke(N)?nu(d(m,N)):Qr(as(N));j.contents,y.atomValues.set(t,j),(M=m.getState().nextTree)===null||M===void 0||M.atomValues.set(t,j)}}return L}function p(m,y){var S,A;return(S=(A=y.atomValues.get(t))!==null&&A!==void 0?A:a)!==null&&S!==void 0?S:i}function h(m,y){if(y.atomValues.has(t))return Ne(y.atomValues.get(t));if(y.nonvalidatedAtoms.has(t)){if(a!=null)return a;if(n==null)return i;const S=y.nonvalidatedAtoms.get(t),A=n.validator(S,br);return a=A instanceof On?i:Qr(A),a}else return i}function v(){a=void 0}function x(m,y,S){if(y.atomValues.has(t)){const A=Ne(y.atomValues.get(t));if(A.state==="hasValue"&&S===A.contents)return new Map}else if(!y.nonvalidatedAtoms.has(t)&&S instanceof On)return new Map;return a=void 0,new Map().set(t,Qr(S))}function C(){return t1(t)!==void 0&&o<=0}const g=$j({key:t,nodeType:"atom",peek:p,get:h,set:x,init:f,invalidate:v,shouldDeleteConfigOnRelease:C,dangerouslyAllowMutability:e.dangerouslyAllowMutability,persistence_UNSTABLE:e.persistence_UNSTABLE?{type:e.persistence_UNSTABLE.type,backButton:e.persistence_UNSTABLE.backButton}:void 0,shouldRestoreFromSnapshots:!0,retainedBy:r});return g}function hp(e){const{...t}=e,n="default"in e?e.default:new Promise(()=>{});return Hj(n)?Qj({...t,default:n}):Zj({...t,default:n})}function Qj(e){const t=hp({...e,default:br,persistence_UNSTABLE:e.persistence_UNSTABLE===void 0?void 0:{...e.persistence_UNSTABLE,validator:r=>r instanceof On?r:Ne(e.persistence_UNSTABLE).validator(r,br)},effects:e.effects,effects_UNSTABLE:e.effects_UNSTABLE}),n=Mo({key:`${e.key}__withFallback`,get:({get:r})=>{const o=r(t);return o instanceof On?e.default:o},set:({set:r},o)=>r(t,o),cachePolicy_UNSTABLE:{eviction:"most-recent"},dangerouslyAllowMutability:e.dangerouslyAllowMutability});return Wj(n.key,t1(e.key)),n}hp.value=e=>new e1(e);var n1=hp;class Xj{constructor(t){var n;ce(this,"_map",void 0),ce(this,"_keyMapper",void 0),this._map=new Map,this._keyMapper=(n=t==null?void 0:t.mapKey)!==null&&n!==void 0?n:r=>r}size(){return this._map.size}has(t){return this._map.has(this._keyMapper(t))}get(t){return this._map.get(this._keyMapper(t))}set(t,n){this._map.set(this._keyMapper(t),n)}delete(t){this._map.delete(this._keyMapper(t))}clear(){this._map.clear()}}var qj={MapCache:Xj},e3=qj.MapCache,t3=Object.freeze({__proto__:null,MapCache:e3});const{LRUCache:Om}=Zx,{MapCache:n3}=t3,ta={equality:"reference",eviction:"none",maxSize:1/0};function r3({equality:e=ta.equality,eviction:t=ta.eviction,maxSize:n=ta.maxSize}=ta){const r=o3(e);return s3(t,n,r)}function o3(e){switch(e){case"reference":return t=>t;case"value":return t=>tc(t)}throw ue(`Unrecognized equality policy ${e}`)}function s3(e,t,n){switch(e){case"keep-all":return new n3({mapKey:n});case"lru":return new Om({mapKey:n,maxSize:Ne(t)});case"most-recent":return new Om({mapKey:n,maxSize:1})}throw ue(`Unrecognized eviction policy ${e}`)}var r1=r3;const{setConfigDeletionHandler:i3}=Et;function a3(e){var t,n;const r=r1({equality:(t=(n=e.cachePolicyForParams_UNSTABLE)===null||n===void 0?void 0:n.equality)!==null&&t!==void 0?t:"value",eviction:"keep-all"});return o=>{var s,i;const a=r.get(o);if(a!=null)return a;const{cachePolicyForParams_UNSTABLE:l,...c}=e,d="default"in e?e.default:new Promise(()=>{}),f=n1({...c,key:`${e.key}__${(s=tc(o))!==null&&s!==void 0?s:"void"}`,default:typeof d=="function"?d(o):d,retainedBy_UNSTABLE:typeof e.retainedBy_UNSTABLE=="function"?e.retainedBy_UNSTABLE(o):e.retainedBy_UNSTABLE,effects:typeof e.effects=="function"?e.effects(o):typeof e.effects_UNSTABLE=="function"?e.effects_UNSTABLE(o):(i=e.effects)!==null&&i!==void 0?i:e.effects_UNSTABLE});return r.set(o,f),i3(f.key,()=>{r.delete(o)}),f}}var l3=a3;const{setConfigDeletionHandler:c3}=Et;let u3=0;function d3(e){var t,n;const r=r1({equality:(t=(n=e.cachePolicyForParams_UNSTABLE)===null||n===void 0?void 0:n.equality)!==null&&t!==void 0?t:"value",eviction:"keep-all"});return o=>{var s;let i;try{i=r.get(o)}catch(p){throw ue(`Problem with cache lookup for selector ${e.key}: ${p.message}`)}if(i!=null)return i;const a=`${e.key}__selectorFamily/${(s=tc(o,{allowFunctions:!0}))!==null&&s!==void 0?s:"void"}/${u3++}`,l=p=>e.get(o)(p),c=e.cachePolicy_UNSTABLE,d=typeof e.retainedBy_UNSTABLE=="function"?e.retainedBy_UNSTABLE(o):e.retainedBy_UNSTABLE;let f;if(e.set!=null){const p=e.set;f=Mo({key:a,get:l,set:(v,x)=>p(o)(v,x),cachePolicy_UNSTABLE:c,dangerouslyAllowMutability:e.dangerouslyAllowMutability,retainedBy_UNSTABLE:d})}else f=Mo({key:a,get:l,cachePolicy_UNSTABLE:c,dangerouslyAllowMutability:e.dangerouslyAllowMutability,retainedBy_UNSTABLE:d});return r.set(o,f),c3(f.key,()=>{r.delete(o)}),f}}var pr=d3;const f3=pr({key:"__constant",get:e=>()=>e,cachePolicyForParams_UNSTABLE:{equality:"reference"}});function p3(e){return f3(e)}var h3=p3;const m3=pr({key:"__error",get:e=>()=>{throw ue(e)},cachePolicyForParams_UNSTABLE:{equality:"reference"}});function g3(e){return m3(e)}var v3=g3;function y3(e){return e}var x3=y3;const{loadableWithError:o1,loadableWithPromise:s1,loadableWithValue:i1}=vi;function nc(e,t){const n=Array(t.length).fill(void 0),r=Array(t.length).fill(void 0);for(const[o,s]of t.entries())try{n[o]=e(s)}catch(i){r[o]=i}return[n,r]}function w3(e){return e!=null&&!ke(e)}function rc(e){return Array.isArray(e)?e:Object.getOwnPropertyNames(e).map(t=>e[t])}function Md(e,t){return Array.isArray(e)?t:Object.getOwnPropertyNames(e).reduce((n,r,o)=>({...n,[r]:t[o]}),{})}function bo(e,t,n){const r=n.map((o,s)=>o==null?i1(t[s]):ke(o)?s1(o):o1(o));return Md(e,r)}function S3(e,t){return t.map((n,r)=>n===void 0?e[r]:n)}const C3=pr({key:"__waitForNone",get:e=>({get:t})=>{const n=rc(e),[r,o]=nc(t,n);return bo(e,r,o)},dangerouslyAllowMutability:!0}),b3=pr({key:"__waitForAny",get:e=>({get:t})=>{const n=rc(e),[r,o]=nc(t,n);return o.some(s=>!ke(s))?bo(e,r,o):new Promise(s=>{for(const[i,a]of o.entries())ke(a)&&a.then(l=>{r[i]=l,o[i]=void 0,s(bo(e,r,o))}).catch(l=>{o[i]=l,s(bo(e,r,o))})})},dangerouslyAllowMutability:!0}),A3=pr({key:"__waitForAll",get:e=>({get:t})=>{const n=rc(e),[r,o]=nc(t,n);if(o.every(i=>i==null))return Md(e,r);const s=o.find(w3);if(s!=null)throw s;return Promise.all(o).then(i=>Md(e,S3(r,i)))},dangerouslyAllowMutability:!0}),k3=pr({key:"__waitForAllSettled",get:e=>({get:t})=>{const n=rc(e),[r,o]=nc(t,n);return o.every(s=>!ke(s))?bo(e,r,o):Promise.all(o.map((s,i)=>ke(s)?s.then(a=>{r[i]=a,o[i]=void 0}).catch(a=>{r[i]=void 0,o[i]=a}):null)).then(()=>bo(e,r,o))},dangerouslyAllowMutability:!0}),E3=pr({key:"__noWait",get:e=>({get:t})=>{try{return Mo.value(i1(t(e)))}catch(n){return Mo.value(ke(n)?s1(n):o1(n))}},dangerouslyAllowMutability:!0});var R3={waitForNone:C3,waitForAny:b3,waitForAll:A3,waitForAllSettled:k3,noWait:E3};const{RecoilLoadable:T3}=vi,{DefaultValue:j3}=Et,{RecoilRoot:P3,useRecoilStoreID:N3}=jn,{isRecoilValue:L3}=Lo,{retentionZone:_3}=Wl,{freshSnapshot:I3}=Zl,{useRecoilState:M3,useRecoilState_TRANSITION_SUPPORT_UNSTABLE:D3,useRecoilStateLoadable:O3,useRecoilValue:B3,useRecoilValue_TRANSITION_SUPPORT_UNSTABLE:V3,useRecoilValueLoadable:z3,useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE:F3,useResetRecoilState:U3,useSetRecoilState:$3}=qR,{useGotoRecoilSnapshot:W3,useRecoilSnapshot:H3,useRecoilTransactionObserver:G3}=$x,{useRecoilCallback:K3}=Kx,{noWait:J3,waitForAll:Y3,waitForAllSettled:Z3,waitForAny:Q3,waitForNone:X3}=R3;var bi={DefaultValue:j3,isRecoilValue:L3,RecoilLoadable:T3,RecoilEnv:Wo,RecoilRoot:P3,useRecoilStoreID:N3,useRecoilBridgeAcrossReactRoots_UNSTABLE:ET,atom:n1,selector:Mo,atomFamily:l3,selectorFamily:pr,constSelector:h3,errorSelector:v3,readOnlySelector:x3,noWait:J3,waitForNone:X3,waitForAny:Q3,waitForAll:Y3,waitForAllSettled:Z3,useRecoilValue:B3,useRecoilValueLoadable:z3,useRecoilState:M3,useRecoilStateLoadable:O3,useSetRecoilState:$3,useResetRecoilState:U3,useGetRecoilValueInfo_UNSTABLE:wT,useRecoilRefresher_UNSTABLE:tj,useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE:F3,useRecoilValue_TRANSITION_SUPPORT_UNSTABLE:V3,useRecoilState_TRANSITION_SUPPORT_UNSTABLE:D3,useRecoilCallback:K3,useRecoilTransaction_UNSTABLE:ij,useGotoRecoilSnapshot:W3,useRecoilSnapshot:H3,useRecoilTransactionObserver_UNSTABLE:G3,snapshot_UNSTABLE:I3,useRetain:cp,retentionZone:_3},q3=bi.RecoilRoot,Be=bi.atom,ze=bi.useRecoilValue,Re=bi.useRecoilState,Xe=bi.useSetRecoilState;const a1=w.createContext({transformPagePoint:e=>e,isStatic:!1,reducedMotion:"never"}),oc=w.createContext({}),sc=w.createContext(null),ic=typeof document<"u",sl=ic?w.useLayoutEffect:w.useEffect,l1=w.createContext({strict:!1});function eP(e,t,n,r){const{visualElement:o}=w.useContext(oc),s=w.useContext(l1),i=w.useContext(sc),a=w.useContext(a1).reducedMotion,l=w.useRef();r=r||s.renderer,!l.current&&r&&(l.current=r(e,{visualState:t,parent:o,props:n,presenceContext:i,blockInitialAnimation:i?i.initial===!1:!1,reducedMotionConfig:a}));const c=l.current;return w.useInsertionEffect(()=>{c&&c.update(n,i)}),sl(()=>{c&&c.render()}),w.useEffect(()=>{c&&c.updateFeatures()}),(window.HandoffAppearAnimations?sl:w.useEffect)(()=>{c&&c.animationState&&c.animationState.animateChanges()}),c}function po(e){return typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"current")}function tP(e,t,n){return w.useCallback(r=>{r&&e.mount&&e.mount(r),t&&(r?t.mount(r):t.unmount()),n&&(typeof n=="function"?n(r):po(n)&&(n.current=r))},[t])}function ii(e){return typeof e=="string"||Array.isArray(e)}function ac(e){return typeof e=="object"&&typeof e.start=="function"}const mp=["animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"],gp=["initial",...mp];function lc(e){return ac(e.animate)||gp.some(t=>ii(e[t]))}function c1(e){return!!(lc(e)||e.variants)}function nP(e,t){if(lc(e)){const{initial:n,animate:r}=e;return{initial:n===!1||ii(n)?n:void 0,animate:ii(r)?r:void 0}}return e.inherit!==!1?t:{}}function rP(e){const{initial:t,animate:n}=nP(e,w.useContext(oc));return w.useMemo(()=>({initial:t,animate:n}),[Bm(t),Bm(n)])}function Bm(e){return Array.isArray(e)?e.join(" "):e}const Vm={animation:["animate","variants","whileHover","whileTap","exit","whileInView","whileFocus","whileDrag"],exit:["exit"],drag:["drag","dragControls"],focus:["whileFocus"],hover:["whileHover","onHoverStart","onHoverEnd"],tap:["whileTap","onTap","onTapStart","onTapCancel"],pan:["onPan","onPanStart","onPanSessionStart","onPanEnd"],inView:["whileInView","onViewportEnter","onViewportLeave"],layout:["layout","layoutId"]},ai={};for(const e in Vm)ai[e]={isEnabled:t=>Vm[e].some(n=>!!t[n])};function oP(e){for(const t in e)ai[t]={...ai[t],...e[t]}}const vp=w.createContext({}),u1=w.createContext({}),sP=Symbol.for("motionComponentSymbol");function iP({preloadedFeatures:e,createVisualElement:t,useRender:n,useVisualState:r,Component:o}){e&&oP(e);function s(a,l){let c;const d={...w.useContext(a1),...a,layoutId:aP(a)},{isStatic:f}=d,p=rP(a),h=r(a,f);if(!f&&ic){p.visualElement=eP(o,h,d,t);const v=w.useContext(u1),x=w.useContext(l1).strict;p.visualElement&&(c=p.visualElement.loadFeatures(d,x,e,v))}return w.createElement(oc.Provider,{value:p},c&&p.visualElement?w.createElement(c,{visualElement:p.visualElement,...d}):null,n(o,a,tP(h,p.visualElement,l),h,f,p.visualElement))}const i=w.forwardRef(s);return i[sP]=o,i}function aP({layoutId:e}){const t=w.useContext(vp).id;return t&&e!==void 0?t+"-"+e:e}function lP(e){function t(r,o={}){return iP(e(r,o))}if(typeof Proxy>"u")return t;const n=new Map;return new Proxy(t,{get:(r,o)=>(n.has(o)||n.set(o,t(o)),n.get(o))})}const cP=["animate","circle","defs","desc","ellipse","g","image","line","filter","marker","mask","metadata","path","pattern","polygon","polyline","rect","stop","switch","symbol","svg","text","tspan","use","view"];function yp(e){return typeof e!="string"||e.includes("-")?!1:!!(cP.indexOf(e)>-1||/[A-Z]/.test(e))}const il={};function uP(e){Object.assign(il,e)}const Ai=["transformPerspective","x","y","z","translateX","translateY","translateZ","scale","scaleX","scaleY","rotate","rotateX","rotateY","rotateZ","skew","skewX","skewY"],Gr=new Set(Ai);function d1(e,{layout:t,layoutId:n}){return Gr.has(e)||e.startsWith("origin")||(t||n!==void 0)&&(!!il[e]||e==="opacity")}const kt=e=>!!(e&&e.getVelocity),dP={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},fP=Ai.length;function pP(e,{enableHardwareAcceleration:t=!0,allowTransformNone:n=!0},r,o){let s="";for(let i=0;it=>typeof t=="string"&&t.startsWith(e),p1=f1("--"),Dd=f1("var(--"),hP=/var\s*\(\s*--[\w-]+(\s*,\s*(?:(?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)+)?\s*\)/g,mP=(e,t)=>t&&typeof e=="number"?t.transform(e):e,sr=(e,t,n)=>Math.min(Math.max(n,e),t),Kr={test:e=>typeof e=="number",parse:parseFloat,transform:e=>e},Ms={...Kr,transform:e=>sr(0,1,e)},na={...Kr,default:1},Ds=e=>Math.round(e*1e5)/1e5,cc=/(-)?([\d]*\.?[\d])+/g,h1=/(#[0-9a-f]{3,8}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))/gi,gP=/^(#[0-9a-f]{3,8}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;function ki(e){return typeof e=="string"}const Ei=e=>({test:t=>ki(t)&&t.endsWith(e)&&t.split(" ").length===1,parse:parseFloat,transform:t=>`${t}${e}`}),_n=Ei("deg"),cn=Ei("%"),oe=Ei("px"),vP=Ei("vh"),yP=Ei("vw"),zm={...cn,parse:e=>cn.parse(e)/100,transform:e=>cn.transform(e*100)},Fm={...Kr,transform:Math.round},m1={borderWidth:oe,borderTopWidth:oe,borderRightWidth:oe,borderBottomWidth:oe,borderLeftWidth:oe,borderRadius:oe,radius:oe,borderTopLeftRadius:oe,borderTopRightRadius:oe,borderBottomRightRadius:oe,borderBottomLeftRadius:oe,width:oe,maxWidth:oe,height:oe,maxHeight:oe,size:oe,top:oe,right:oe,bottom:oe,left:oe,padding:oe,paddingTop:oe,paddingRight:oe,paddingBottom:oe,paddingLeft:oe,margin:oe,marginTop:oe,marginRight:oe,marginBottom:oe,marginLeft:oe,rotate:_n,rotateX:_n,rotateY:_n,rotateZ:_n,scale:na,scaleX:na,scaleY:na,scaleZ:na,skew:_n,skewX:_n,skewY:_n,distance:oe,translateX:oe,translateY:oe,translateZ:oe,x:oe,y:oe,z:oe,perspective:oe,transformPerspective:oe,opacity:Ms,originX:zm,originY:zm,originZ:oe,zIndex:Fm,fillOpacity:Ms,strokeOpacity:Ms,numOctaves:Fm};function xp(e,t,n,r){const{style:o,vars:s,transform:i,transformOrigin:a}=e;let l=!1,c=!1,d=!0;for(const f in t){const p=t[f];if(p1(f)){s[f]=p;continue}const h=m1[f],v=mP(p,h);if(Gr.has(f)){if(l=!0,i[f]=v,!d)continue;p!==(h.default||0)&&(d=!1)}else f.startsWith("origin")?(c=!0,a[f]=v):o[f]=v}if(t.transform||(l||r?o.transform=pP(e.transform,n,d,r):o.transform&&(o.transform="none")),c){const{originX:f="50%",originY:p="50%",originZ:h=0}=a;o.transformOrigin=`${f} ${p} ${h}`}}const wp=()=>({style:{},transform:{},transformOrigin:{},vars:{}});function g1(e,t,n){for(const r in t)!kt(t[r])&&!d1(r,n)&&(e[r]=t[r])}function xP({transformTemplate:e},t,n){return w.useMemo(()=>{const r=wp();return xp(r,t,{enableHardwareAcceleration:!n},e),Object.assign({},r.vars,r.style)},[t])}function wP(e,t,n){const r=e.style||{},o={};return g1(o,r,e),Object.assign(o,xP(e,t,n)),e.transformValues?e.transformValues(o):o}function SP(e,t,n){const r={},o=wP(e,t,n);return e.drag&&e.dragListener!==!1&&(r.draggable=!1,o.userSelect=o.WebkitUserSelect=o.WebkitTouchCallout="none",o.touchAction=e.drag===!0?"none":`pan-${e.drag==="x"?"y":"x"}`),e.tabIndex===void 0&&(e.onTap||e.onTapStart||e.whileTap)&&(r.tabIndex=0),r.style=o,r}const CP=new Set(["animate","exit","variants","initial","style","values","variants","transition","transformTemplate","transformValues","custom","inherit","onLayoutAnimationStart","onLayoutAnimationComplete","onLayoutMeasure","onBeforeLayoutMeasure","onAnimationStart","onAnimationComplete","onUpdate","onDragStart","onDrag","onDragEnd","onMeasureDragConstraints","onDirectionLock","onDragTransitionEnd","_dragX","_dragY","onHoverStart","onHoverEnd","onViewportEnter","onViewportLeave","ignoreStrict","viewport"]);function al(e){return e.startsWith("while")||e.startsWith("drag")&&e!=="draggable"||e.startsWith("layout")||e.startsWith("onTap")||e.startsWith("onPan")||CP.has(e)}let v1=e=>!al(e);function bP(e){e&&(v1=t=>t.startsWith("on")?!al(t):e(t))}try{bP(require("@emotion/is-prop-valid").default)}catch{}function AP(e,t,n){const r={};for(const o in e)o==="values"&&typeof e.values=="object"||(v1(o)||n===!0&&al(o)||!t&&!al(o)||e.draggable&&o.startsWith("onDrag"))&&(r[o]=e[o]);return r}function Um(e,t,n){return typeof e=="string"?e:oe.transform(t+n*e)}function kP(e,t,n){const r=Um(t,e.x,e.width),o=Um(n,e.y,e.height);return`${r} ${o}`}const EP={offset:"stroke-dashoffset",array:"stroke-dasharray"},RP={offset:"strokeDashoffset",array:"strokeDasharray"};function TP(e,t,n=1,r=0,o=!0){e.pathLength=1;const s=o?EP:RP;e[s.offset]=oe.transform(-r);const i=oe.transform(t),a=oe.transform(n);e[s.array]=`${i} ${a}`}function Sp(e,{attrX:t,attrY:n,attrScale:r,originX:o,originY:s,pathLength:i,pathSpacing:a=1,pathOffset:l=0,...c},d,f,p){if(xp(e,c,d,p),f){e.style.viewBox&&(e.attrs.viewBox=e.style.viewBox);return}e.attrs=e.style,e.style={};const{attrs:h,style:v,dimensions:x}=e;h.transform&&(x&&(v.transform=h.transform),delete h.transform),x&&(o!==void 0||s!==void 0||v.transform)&&(v.transformOrigin=kP(x,o!==void 0?o:.5,s!==void 0?s:.5)),t!==void 0&&(h.x=t),n!==void 0&&(h.y=n),r!==void 0&&(h.scale=r),i!==void 0&&TP(h,i,a,l,!1)}const y1=()=>({...wp(),attrs:{}}),Cp=e=>typeof e=="string"&&e.toLowerCase()==="svg";function jP(e,t,n,r){const o=w.useMemo(()=>{const s=y1();return Sp(s,t,{enableHardwareAcceleration:!1},Cp(r),e.transformTemplate),{...s.attrs,style:{...s.style}}},[t]);if(e.style){const s={};g1(s,e.style,e),o.style={...s,...o.style}}return o}function PP(e=!1){return(n,r,o,{latestValues:s},i)=>{const l=(yp(n)?jP:SP)(r,s,i,n),d={...AP(r,typeof n=="string",e),...l,ref:o},{children:f}=r,p=w.useMemo(()=>kt(f)?f.get():f,[f]);return w.createElement(n,{...d,children:p})}}const bp=e=>e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();function x1(e,{style:t,vars:n},r,o){Object.assign(e.style,t,o&&o.getProjectionStyles(r));for(const s in n)e.style.setProperty(s,n[s])}const w1=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]);function S1(e,t,n,r){x1(e,t,void 0,r);for(const o in t.attrs)e.setAttribute(w1.has(o)?o:bp(o),t.attrs[o])}function Ap(e,t){const{style:n}=e,r={};for(const o in n)(kt(n[o])||t.style&&kt(t.style[o])||d1(o,e))&&(r[o]=n[o]);return r}function C1(e,t){const n=Ap(e,t);for(const r in e)if(kt(e[r])||kt(t[r])){const o=Ai.indexOf(r)!==-1?"attr"+r.charAt(0).toUpperCase()+r.substring(1):r;n[o]=e[r]}return n}function kp(e,t,n,r={},o={}){return typeof t=="function"&&(t=t(n!==void 0?n:e.custom,r,o)),typeof t=="string"&&(t=e.variants&&e.variants[t]),typeof t=="function"&&(t=t(n!==void 0?n:e.custom,r,o)),t}function b1(e){const t=w.useRef(null);return t.current===null&&(t.current=e()),t.current}const ll=e=>Array.isArray(e),NP=e=>!!(e&&typeof e=="object"&&e.mix&&e.toValue),LP=e=>ll(e)?e[e.length-1]||0:e;function ka(e){const t=kt(e)?e.get():e;return NP(t)?t.toValue():t}function _P({scrapeMotionValuesFromProps:e,createRenderState:t,onMount:n},r,o,s){const i={latestValues:IP(r,o,s,e),renderState:t()};return n&&(i.mount=a=>n(r,a,i)),i}const A1=e=>(t,n)=>{const r=w.useContext(oc),o=w.useContext(sc),s=()=>_P(e,t,r,o);return n?s():b1(s)};function IP(e,t,n,r){const o={},s=r(e,{});for(const p in s)o[p]=ka(s[p]);let{initial:i,animate:a}=e;const l=lc(e),c=c1(e);t&&c&&!l&&e.inherit!==!1&&(i===void 0&&(i=t.initial),a===void 0&&(a=t.animate));let d=n?n.initial===!1:!1;d=d||i===!1;const f=d?a:i;return f&&typeof f!="boolean"&&!ac(f)&&(Array.isArray(f)?f:[f]).forEach(h=>{const v=kp(e,h);if(!v)return;const{transitionEnd:x,transition:C,...g}=v;for(const m in g){let y=g[m];if(Array.isArray(y)){const S=d?y.length-1:0;y=y[S]}y!==null&&(o[m]=y)}for(const m in x)o[m]=x[m]}),o}const MP={useVisualState:A1({scrapeMotionValuesFromProps:C1,createRenderState:y1,onMount:(e,t,{renderState:n,latestValues:r})=>{try{n.dimensions=typeof t.getBBox=="function"?t.getBBox():t.getBoundingClientRect()}catch{n.dimensions={x:0,y:0,width:0,height:0}}Sp(n,r,{enableHardwareAcceleration:!1},Cp(t.tagName),e.transformTemplate),S1(t,n)}})},DP={useVisualState:A1({scrapeMotionValuesFromProps:Ap,createRenderState:wp})};function OP(e,{forwardMotionProps:t=!1},n,r){return{...yp(e)?MP:DP,preloadedFeatures:n,useRender:PP(t),createVisualElement:r,Component:e}}function yn(e,t,n,r={passive:!0}){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n)}const k1=e=>e.pointerType==="mouse"?typeof e.button!="number"||e.button<=0:e.isPrimary!==!1;function uc(e,t="page"){return{point:{x:e[t+"X"],y:e[t+"Y"]}}}const BP=e=>t=>k1(t)&&e(t,uc(t));function Sn(e,t,n,r){return yn(e,t,BP(n),r)}const VP=(e,t)=>n=>t(e(n)),er=(...e)=>e.reduce(VP);function E1(e){let t=null;return()=>{const n=()=>{t=null};return t===null?(t=e,n):!1}}const $m=E1("dragHorizontal"),Wm=E1("dragVertical");function R1(e){let t=!1;if(e==="y")t=Wm();else if(e==="x")t=$m();else{const n=$m(),r=Wm();n&&r?t=()=>{n(),r()}:(n&&n(),r&&r())}return t}function T1(){const e=R1(!0);return e?(e(),!1):!0}class hr{constructor(t){this.isMounted=!1,this.node=t}update(){}}const He=e=>e;function zP(e){let t=[],n=[],r=0,o=!1,s=!1;const i=new WeakSet,a={schedule:(l,c=!1,d=!1)=>{const f=d&&o,p=f?t:n;return c&&i.add(l),p.indexOf(l)===-1&&(p.push(l),f&&o&&(r=t.length)),l},cancel:l=>{const c=n.indexOf(l);c!==-1&&n.splice(c,1),i.delete(l)},process:l=>{if(o){s=!0;return}if(o=!0,[t,n]=[n,t],n.length=0,r=t.length,r)for(let c=0;c(f[p]=zP(()=>n=!0),f),{}),i=f=>s[f].process(o),a=f=>{n=!1,o.delta=r?1e3/60:Math.max(Math.min(f-o.timestamp,FP),1),o.timestamp=f,o.isProcessing=!0,ra.forEach(i),o.isProcessing=!1,n&&t&&(r=!1,e(a))},l=()=>{n=!0,r=!0,o.isProcessing||e(a)};return{schedule:ra.reduce((f,p)=>{const h=s[p];return f[p]=(v,x=!1,C=!1)=>(n||l(),h.schedule(v,x,C)),f},{}),cancel:f=>ra.forEach(p=>s[p].cancel(f)),state:o,steps:s}}const{schedule:Le,cancel:Rn,state:at,steps:ru}=UP(typeof requestAnimationFrame<"u"?requestAnimationFrame:He,!0);function Hm(e,t){const n="pointer"+(t?"enter":"leave"),r="onHover"+(t?"Start":"End"),o=(s,i)=>{if(s.type==="touch"||T1())return;const a=e.getProps();e.animationState&&a.whileHover&&e.animationState.setActive("whileHover",t),a[r]&&Le.update(()=>a[r](s,i))};return Sn(e.current,n,o,{passive:!e.getProps()[r]})}class $P extends hr{mount(){this.unmount=er(Hm(this.node,!0),Hm(this.node,!1))}unmount(){}}class WP extends hr{constructor(){super(...arguments),this.isActive=!1}onFocus(){let t=!1;try{t=this.node.current.matches(":focus-visible")}catch{t=!0}!t||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!0),this.isActive=!0)}onBlur(){!this.isActive||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!1),this.isActive=!1)}mount(){this.unmount=er(yn(this.node.current,"focus",()=>this.onFocus()),yn(this.node.current,"blur",()=>this.onBlur()))}unmount(){}}const j1=(e,t)=>t?e===t?!0:j1(e,t.parentElement):!1;function ou(e,t){if(!t)return;const n=new PointerEvent("pointer"+e);t(n,uc(n))}class HP extends hr{constructor(){super(...arguments),this.removeStartListeners=He,this.removeEndListeners=He,this.removeAccessibleListeners=He,this.startPointerPress=(t,n)=>{if(this.removeEndListeners(),this.isPressing)return;const r=this.node.getProps(),s=Sn(window,"pointerup",(a,l)=>{if(!this.checkPressEnd())return;const{onTap:c,onTapCancel:d}=this.node.getProps();Le.update(()=>{j1(this.node.current,a.target)?c&&c(a,l):d&&d(a,l)})},{passive:!(r.onTap||r.onPointerUp)}),i=Sn(window,"pointercancel",(a,l)=>this.cancelPress(a,l),{passive:!(r.onTapCancel||r.onPointerCancel)});this.removeEndListeners=er(s,i),this.startPress(t,n)},this.startAccessiblePress=()=>{const t=s=>{if(s.key!=="Enter"||this.isPressing)return;const i=a=>{a.key!=="Enter"||!this.checkPressEnd()||ou("up",(l,c)=>{const{onTap:d}=this.node.getProps();d&&Le.update(()=>d(l,c))})};this.removeEndListeners(),this.removeEndListeners=yn(this.node.current,"keyup",i),ou("down",(a,l)=>{this.startPress(a,l)})},n=yn(this.node.current,"keydown",t),r=()=>{this.isPressing&&ou("cancel",(s,i)=>this.cancelPress(s,i))},o=yn(this.node.current,"blur",r);this.removeAccessibleListeners=er(n,o)}}startPress(t,n){this.isPressing=!0;const{onTapStart:r,whileTap:o}=this.node.getProps();o&&this.node.animationState&&this.node.animationState.setActive("whileTap",!0),r&&Le.update(()=>r(t,n))}checkPressEnd(){return this.removeEndListeners(),this.isPressing=!1,this.node.getProps().whileTap&&this.node.animationState&&this.node.animationState.setActive("whileTap",!1),!T1()}cancelPress(t,n){if(!this.checkPressEnd())return;const{onTapCancel:r}=this.node.getProps();r&&Le.update(()=>r(t,n))}mount(){const t=this.node.getProps(),n=Sn(this.node.current,"pointerdown",this.startPointerPress,{passive:!(t.onTapStart||t.onPointerStart)}),r=yn(this.node.current,"focus",this.startAccessiblePress);this.removeStartListeners=er(n,r)}unmount(){this.removeStartListeners(),this.removeEndListeners(),this.removeAccessibleListeners()}}const Od=new WeakMap,su=new WeakMap,GP=e=>{const t=Od.get(e.target);t&&t(e)},KP=e=>{e.forEach(GP)};function JP({root:e,...t}){const n=e||document;su.has(n)||su.set(n,{});const r=su.get(n),o=JSON.stringify(t);return r[o]||(r[o]=new IntersectionObserver(KP,{root:e,...t})),r[o]}function YP(e,t,n){const r=JP(t);return Od.set(e,n),r.observe(e),()=>{Od.delete(e),r.unobserve(e)}}const ZP={some:0,all:1};class QP extends hr{constructor(){super(...arguments),this.hasEnteredView=!1,this.isInView=!1}startObserver(){this.unmount();const{viewport:t={}}=this.node.getProps(),{root:n,margin:r,amount:o="some",once:s}=t,i={root:n?n.current:void 0,rootMargin:r,threshold:typeof o=="number"?o:ZP[o]},a=l=>{const{isIntersecting:c}=l;if(this.isInView===c||(this.isInView=c,s&&!c&&this.hasEnteredView))return;c&&(this.hasEnteredView=!0),this.node.animationState&&this.node.animationState.setActive("whileInView",c);const{onViewportEnter:d,onViewportLeave:f}=this.node.getProps(),p=c?d:f;p&&p(l)};return YP(this.node.current,i,a)}mount(){this.startObserver()}update(){if(typeof IntersectionObserver>"u")return;const{props:t,prevProps:n}=this.node;["amount","margin","root"].some(XP(t,n))&&this.startObserver()}unmount(){}}function XP({viewport:e={}},{viewport:t={}}={}){return n=>e[n]!==t[n]}const qP={inView:{Feature:QP},tap:{Feature:HP},focus:{Feature:WP},hover:{Feature:$P}};function P1(e,t){if(!Array.isArray(t))return!1;const n=t.length;if(n!==e.length)return!1;for(let r=0;rt[r]=n.get()),t}function tN(e){const t={};return e.values.forEach((n,r)=>t[r]=n.getVelocity()),t}function dc(e,t,n){const r=e.getProps();return kp(r,t,n!==void 0?n:r.custom,eN(e),tN(e))}const nN="framerAppearId",rN="data-"+bp(nN);let oN=He,Ep=He;const tr=e=>e*1e3,Cn=e=>e/1e3,sN={current:!1},N1=e=>Array.isArray(e)&&typeof e[0]=="number";function L1(e){return!!(!e||typeof e=="string"&&_1[e]||N1(e)||Array.isArray(e)&&e.every(L1))}const Ss=([e,t,n,r])=>`cubic-bezier(${e}, ${t}, ${n}, ${r})`,_1={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:Ss([0,.65,.55,1]),circOut:Ss([.55,0,1,.45]),backIn:Ss([.31,.01,.66,-.59]),backOut:Ss([.33,1.53,.69,.99])};function I1(e){if(e)return N1(e)?Ss(e):Array.isArray(e)?e.map(I1):_1[e]}function iN(e,t,n,{delay:r=0,duration:o,repeat:s=0,repeatType:i="loop",ease:a,times:l}={}){const c={[t]:n};l&&(c.offset=l);const d=I1(a);return Array.isArray(d)&&(c.easing=d),e.animate(c,{delay:r,duration:o,easing:Array.isArray(d)?"linear":d,fill:"both",iterations:s+1,direction:i==="reverse"?"alternate":"normal"})}function aN(e,{repeat:t,repeatType:n="loop"}){const r=t&&n!=="loop"&&t%2===1?0:e.length-1;return e[r]}const M1=(e,t,n)=>(((1-3*n+3*t)*e+(3*n-6*t))*e+3*t)*e,lN=1e-7,cN=12;function uN(e,t,n,r,o){let s,i,a=0;do i=t+(n-t)/2,s=M1(i,r,o)-e,s>0?n=i:t=i;while(Math.abs(s)>lN&&++auN(s,0,1,e,n);return s=>s===0||s===1?s:M1(o(s),t,r)}const dN=Ri(.42,0,1,1),fN=Ri(0,0,.58,1),D1=Ri(.42,0,.58,1),pN=e=>Array.isArray(e)&&typeof e[0]!="number",O1=e=>t=>t<=.5?e(2*t)/2:(2-e(2*(1-t)))/2,B1=e=>t=>1-e(1-t),V1=e=>1-Math.sin(Math.acos(e)),Rp=B1(V1),hN=O1(Rp),z1=Ri(.33,1.53,.69,.99),Tp=B1(z1),mN=O1(Tp),gN=e=>(e*=2)<1?.5*Tp(e):.5*(2-Math.pow(2,-10*(e-1))),vN={linear:He,easeIn:dN,easeInOut:D1,easeOut:fN,circIn:V1,circInOut:hN,circOut:Rp,backIn:Tp,backInOut:mN,backOut:z1,anticipate:gN},Gm=e=>{if(Array.isArray(e)){Ep(e.length===4);const[t,n,r,o]=e;return Ri(t,n,r,o)}else if(typeof e=="string")return vN[e];return e},jp=(e,t)=>n=>!!(ki(n)&&gP.test(n)&&n.startsWith(e)||t&&Object.prototype.hasOwnProperty.call(n,t)),F1=(e,t,n)=>r=>{if(!ki(r))return r;const[o,s,i,a]=r.match(cc);return{[e]:parseFloat(o),[t]:parseFloat(s),[n]:parseFloat(i),alpha:a!==void 0?parseFloat(a):1}},yN=e=>sr(0,255,e),iu={...Kr,transform:e=>Math.round(yN(e))},Rr={test:jp("rgb","red"),parse:F1("red","green","blue"),transform:({red:e,green:t,blue:n,alpha:r=1})=>"rgba("+iu.transform(e)+", "+iu.transform(t)+", "+iu.transform(n)+", "+Ds(Ms.transform(r))+")"};function xN(e){let t="",n="",r="",o="";return e.length>5?(t=e.substring(1,3),n=e.substring(3,5),r=e.substring(5,7),o=e.substring(7,9)):(t=e.substring(1,2),n=e.substring(2,3),r=e.substring(3,4),o=e.substring(4,5),t+=t,n+=n,r+=r,o+=o),{red:parseInt(t,16),green:parseInt(n,16),blue:parseInt(r,16),alpha:o?parseInt(o,16)/255:1}}const Bd={test:jp("#"),parse:xN,transform:Rr.transform},ho={test:jp("hsl","hue"),parse:F1("hue","saturation","lightness"),transform:({hue:e,saturation:t,lightness:n,alpha:r=1})=>"hsla("+Math.round(e)+", "+cn.transform(Ds(t))+", "+cn.transform(Ds(n))+", "+Ds(Ms.transform(r))+")"},ft={test:e=>Rr.test(e)||Bd.test(e)||ho.test(e),parse:e=>Rr.test(e)?Rr.parse(e):ho.test(e)?ho.parse(e):Bd.parse(e),transform:e=>ki(e)?e:e.hasOwnProperty("red")?Rr.transform(e):ho.transform(e)},Me=(e,t,n)=>-n*e+n*t+e;function au(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function wN({hue:e,saturation:t,lightness:n,alpha:r}){e/=360,t/=100,n/=100;let o=0,s=0,i=0;if(!t)o=s=i=n;else{const a=n<.5?n*(1+t):n+t-n*t,l=2*n-a;o=au(l,a,e+1/3),s=au(l,a,e),i=au(l,a,e-1/3)}return{red:Math.round(o*255),green:Math.round(s*255),blue:Math.round(i*255),alpha:r}}const lu=(e,t,n)=>{const r=e*e;return Math.sqrt(Math.max(0,n*(t*t-r)+r))},SN=[Bd,Rr,ho],CN=e=>SN.find(t=>t.test(e));function Km(e){const t=CN(e);let n=t.parse(e);return t===ho&&(n=wN(n)),n}const U1=(e,t)=>{const n=Km(e),r=Km(t),o={...n};return s=>(o.red=lu(n.red,r.red,s),o.green=lu(n.green,r.green,s),o.blue=lu(n.blue,r.blue,s),o.alpha=Me(n.alpha,r.alpha,s),Rr.transform(o))};function bN(e){var t,n;return isNaN(e)&&ki(e)&&(((t=e.match(cc))===null||t===void 0?void 0:t.length)||0)+(((n=e.match(h1))===null||n===void 0?void 0:n.length)||0)>0}const $1={regex:hP,countKey:"Vars",token:"${v}",parse:He},W1={regex:h1,countKey:"Colors",token:"${c}",parse:ft.parse},H1={regex:cc,countKey:"Numbers",token:"${n}",parse:Kr.parse};function cu(e,{regex:t,countKey:n,token:r,parse:o}){const s=e.tokenised.match(t);s&&(e["num"+n]=s.length,e.tokenised=e.tokenised.replace(t,r),e.values.push(...s.map(o)))}function cl(e){const t=e.toString(),n={value:t,tokenised:t,values:[],numVars:0,numColors:0,numNumbers:0};return n.value.includes("var(--")&&cu(n,$1),cu(n,W1),cu(n,H1),n}function G1(e){return cl(e).values}function K1(e){const{values:t,numColors:n,numVars:r,tokenised:o}=cl(e),s=t.length;return i=>{let a=o;for(let l=0;ltypeof e=="number"?0:e;function kN(e){const t=G1(e);return K1(e)(t.map(AN))}const ir={test:bN,parse:G1,createTransformer:K1,getAnimatableNone:kN},J1=(e,t)=>n=>`${n>0?t:e}`;function Y1(e,t){return typeof e=="number"?n=>Me(e,t,n):ft.test(e)?U1(e,t):e.startsWith("var(")?J1(e,t):Q1(e,t)}const Z1=(e,t)=>{const n=[...e],r=n.length,o=e.map((s,i)=>Y1(s,t[i]));return s=>{for(let i=0;i{const n={...e,...t},r={};for(const o in n)e[o]!==void 0&&t[o]!==void 0&&(r[o]=Y1(e[o],t[o]));return o=>{for(const s in r)n[s]=r[s](o);return n}},Q1=(e,t)=>{const n=ir.createTransformer(t),r=cl(e),o=cl(t);return r.numVars===o.numVars&&r.numColors===o.numColors&&r.numNumbers>=o.numNumbers?er(Z1(r.values,o.values),n):J1(e,t)},li=(e,t,n)=>{const r=t-e;return r===0?1:(n-e)/r},Jm=(e,t)=>n=>Me(e,t,n);function RN(e){return typeof e=="number"?Jm:typeof e=="string"?ft.test(e)?U1:Q1:Array.isArray(e)?Z1:typeof e=="object"?EN:Jm}function TN(e,t,n){const r=[],o=n||RN(e[0]),s=e.length-1;for(let i=0;it[0];e[0]>e[s-1]&&(e=[...e].reverse(),t=[...t].reverse());const i=TN(t,r,o),a=i.length,l=c=>{let d=0;if(a>1)for(;dl(sr(e[0],e[s-1],c)):l}function jN(e,t){const n=e[e.length-1];for(let r=1;r<=t;r++){const o=li(0,t,r);e.push(Me(n,1,o))}}function PN(e){const t=[0];return jN(t,e.length-1),t}function NN(e,t){return e.map(n=>n*t)}function LN(e,t){return e.map(()=>t||D1).splice(0,e.length-1)}function ul({duration:e=300,keyframes:t,times:n,ease:r="easeInOut"}){const o=pN(r)?r.map(Gm):Gm(r),s={done:!1,value:t[0]},i=NN(n&&n.length===t.length?n:PN(t),e),a=X1(i,t,{ease:Array.isArray(o)?o:LN(t,o)});return{calculatedDuration:e,next:l=>(s.value=a(l),s.done=l>=e,s)}}function q1(e,t){return t?e*(1e3/t):0}const _N=5;function ew(e,t,n){const r=Math.max(t-_N,0);return q1(n-e(r),t-r)}const uu=.001,IN=.01,Ym=10,MN=.05,DN=1;function ON({duration:e=800,bounce:t=.25,velocity:n=0,mass:r=1}){let o,s;oN(e<=tr(Ym));let i=1-t;i=sr(MN,DN,i),e=sr(IN,Ym,Cn(e)),i<1?(o=c=>{const d=c*i,f=d*e,p=d-n,h=Vd(c,i),v=Math.exp(-f);return uu-p/h*v},s=c=>{const f=c*i*e,p=f*n+n,h=Math.pow(i,2)*Math.pow(c,2)*e,v=Math.exp(-f),x=Vd(Math.pow(c,2),i);return(-o(c)+uu>0?-1:1)*((p-h)*v)/x}):(o=c=>{const d=Math.exp(-c*e),f=(c-n)*e+1;return-uu+d*f},s=c=>{const d=Math.exp(-c*e),f=(n-c)*(e*e);return d*f});const a=5/e,l=VN(o,s,a);if(e=tr(e),isNaN(l))return{stiffness:100,damping:10,duration:e};{const c=Math.pow(l,2)*r;return{stiffness:c,damping:i*2*Math.sqrt(r*c),duration:e}}}const BN=12;function VN(e,t,n){let r=n;for(let o=1;oe[n]!==void 0)}function UN(e){let t={velocity:0,stiffness:100,damping:10,mass:1,isResolvedFromDuration:!1,...e};if(!Zm(e,FN)&&Zm(e,zN)){const n=ON(e);t={...t,...n,velocity:0,mass:1},t.isResolvedFromDuration=!0}return t}function tw({keyframes:e,restDelta:t,restSpeed:n,...r}){const o=e[0],s=e[e.length-1],i={done:!1,value:o},{stiffness:a,damping:l,mass:c,velocity:d,duration:f,isResolvedFromDuration:p}=UN(r),h=d?-Cn(d):0,v=l/(2*Math.sqrt(a*c)),x=s-o,C=Cn(Math.sqrt(a/c)),g=Math.abs(x)<5;n||(n=g?.01:2),t||(t=g?.005:.5);let m;if(v<1){const y=Vd(C,v);m=S=>{const A=Math.exp(-v*C*S);return s-A*((h+v*C*x)/y*Math.sin(y*S)+x*Math.cos(y*S))}}else if(v===1)m=y=>s-Math.exp(-C*y)*(x+(h+C*x)*y);else{const y=C*Math.sqrt(v*v-1);m=S=>{const A=Math.exp(-v*C*S),L=Math.min(y*S,300);return s-A*((h+v*C*x)*Math.sinh(L)+y*x*Math.cosh(L))/y}}return{calculatedDuration:p&&f||null,next:y=>{const S=m(y);if(p)i.done=y>=f;else{let A=h;y!==0&&(v<1?A=ew(m,y,S):A=0);const L=Math.abs(A)<=n,_=Math.abs(s-S)<=t;i.done=L&&_}return i.value=i.done?s:S,i}}}function Qm({keyframes:e,velocity:t=0,power:n=.8,timeConstant:r=325,bounceDamping:o=10,bounceStiffness:s=500,modifyTarget:i,min:a,max:l,restDelta:c=.5,restSpeed:d}){const f=e[0],p={done:!1,value:f},h=k=>a!==void 0&&kl,v=k=>a===void 0?l:l===void 0||Math.abs(a-k)-x*Math.exp(-k/r),y=k=>g+m(k),S=k=>{const M=m(k),I=y(k);p.done=Math.abs(M)<=c,p.value=p.done?g:I};let A,L;const _=k=>{h(p.value)&&(A=k,L=tw({keyframes:[p.value,v(p.value)],velocity:ew(y,k,p.value),damping:o,stiffness:s,restDelta:c,restSpeed:d}))};return _(0),{calculatedDuration:null,next:k=>{let M=!1;return!L&&A===void 0&&(M=!0,S(k),_(k)),A!==void 0&&k>A?L.next(k-A):(!M&&S(k),p)}}}const $N=e=>{const t=({timestamp:n})=>e(n);return{start:()=>Le.update(t,!0),stop:()=>Rn(t),now:()=>at.isProcessing?at.timestamp:performance.now()}},Xm=2e4;function qm(e){let t=0;const n=50;let r=e.next(t);for(;!r.done&&t=Xm?1/0:t}const WN={decay:Qm,inertia:Qm,tween:ul,keyframes:ul,spring:tw};function dl({autoplay:e=!0,delay:t=0,driver:n=$N,keyframes:r,type:o="keyframes",repeat:s=0,repeatDelay:i=0,repeatType:a="loop",onPlay:l,onStop:c,onComplete:d,onUpdate:f,...p}){let h=1,v=!1,x,C;const g=()=>{C=new Promise(X=>{x=X})};g();let m;const y=WN[o]||ul;let S;y!==ul&&typeof r[0]!="number"&&(S=X1([0,100],r,{clamp:!1}),r=[0,100]);const A=y({...p,keyframes:r});let L;a==="mirror"&&(L=y({...p,keyframes:[...r].reverse(),velocity:-(p.velocity||0)}));let _="idle",k=null,M=null,I=null;A.calculatedDuration===null&&s&&(A.calculatedDuration=qm(A));const{calculatedDuration:T}=A;let O=1/0,N=1/0;T!==null&&(O=T+i,N=O*(s+1)-i);let D=0;const H=X=>{if(M===null)return;h>0&&(M=Math.min(M,X)),h<0&&(M=Math.min(X-N/h,M)),k!==null?D=k:D=Math.round(X-M)*h;const R=D-t*(h>=0?1:-1),j=h>=0?R<0:R>N;D=Math.max(R,0),_==="finished"&&k===null&&(D=N);let B=D,J=A;if(s){const ee=D/O;let ge=Math.floor(ee),Se=ee%1;!Se&&ee>=1&&(Se=1),Se===1&&ge--,ge=Math.min(ge,s+1);const me=!!(ge%2);me&&(a==="reverse"?(Se=1-Se,i&&(Se-=i/O)):a==="mirror"&&(J=L));let ye=sr(0,1,Se);D>N&&(ye=a==="reverse"&&me?1:0),B=ye*O}const $=j?{done:!1,value:r[0]}:J.next(B);S&&($.value=S($.value));let{done:te}=$;!j&&T!==null&&(te=h>=0?D>=N:D<=0);const le=k===null&&(_==="finished"||_==="running"&&te);return f&&f($.value),le&&z(),$},Z=()=>{m&&m.stop(),m=void 0},ne=()=>{_="idle",Z(),x(),g(),M=I=null},z=()=>{_="finished",d&&d(),Z(),x()},W=()=>{if(v)return;m||(m=n(H));const X=m.now();l&&l(),k!==null?M=X-k:(!M||_==="finished")&&(M=X),_==="finished"&&g(),I=M,k=null,_="running",m.start()};e&&W();const q={then(X,R){return C.then(X,R)},get time(){return Cn(D)},set time(X){X=tr(X),D=X,k!==null||!m||h===0?k=X:M=m.now()-X/h},get duration(){const X=A.calculatedDuration===null?qm(A):A.calculatedDuration;return Cn(X)},get speed(){return h},set speed(X){X===h||!m||(h=X,q.time=Cn(D))},get state(){return _},play:W,pause:()=>{_="paused",k=D},stop:()=>{v=!0,_!=="idle"&&(_="idle",c&&c(),ne())},cancel:()=>{I!==null&&H(I),ne()},complete:()=>{_="finished"},sample:X=>(M=0,H(X))};return q}function HN(e){let t;return()=>(t===void 0&&(t=e()),t)}const GN=HN(()=>Object.hasOwnProperty.call(Element.prototype,"animate")),KN=new Set(["opacity","clipPath","filter","transform","backgroundColor"]),oa=10,JN=2e4,YN=(e,t)=>t.type==="spring"||e==="backgroundColor"||!L1(t.ease);function ZN(e,t,{onUpdate:n,onComplete:r,...o}){if(!(GN()&&KN.has(t)&&!o.repeatDelay&&o.repeatType!=="mirror"&&o.damping!==0&&o.type!=="inertia"))return!1;let i=!1,a,l;const c=()=>{l=new Promise(g=>{a=g})};c();let{keyframes:d,duration:f=300,ease:p,times:h}=o;if(YN(t,o)){const g=dl({...o,repeat:0,delay:0});let m={done:!1,value:d[0]};const y=[];let S=0;for(;!m.done&&Sv.cancel(),C=()=>{Le.update(x),a(),c()};return v.onfinish=()=>{e.set(aN(d,o)),r&&r(),C()},{then(g,m){return l.then(g,m)},get timeline(){return v.timeline},set timeline(g){v.timeline=g,v.onfinish=null},get time(){return Cn(v.currentTime||0)},set time(g){v.currentTime=tr(g)},get speed(){return v.playbackRate},set speed(g){v.playbackRate=g},get duration(){return Cn(f)},play:()=>{i||(v.play(),Rn(x))},pause:()=>v.pause(),stop:()=>{if(i=!0,v.playState==="idle")return;const{currentTime:g}=v;if(g){const m=dl({...o,autoplay:!1});e.setWithVelocity(m.sample(g-oa).value,m.sample(g).value,oa)}C()},complete:()=>v.finish(),cancel:C}}function QN({keyframes:e,delay:t,onUpdate:n,onComplete:r}){const o=()=>(n&&n(e[e.length-1]),r&&r(),{time:0,speed:1,duration:0,play:He,pause:He,stop:He,then:s=>(s(),Promise.resolve()),cancel:He,complete:He});return t?dl({keyframes:[0,1],duration:0,delay:t,onComplete:o}):o()}const XN={type:"spring",stiffness:500,damping:25,restSpeed:10},qN=e=>({type:"spring",stiffness:550,damping:e===0?2*Math.sqrt(550):30,restSpeed:10}),e4={type:"keyframes",duration:.8},t4={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},n4=(e,{keyframes:t})=>t.length>2?e4:Gr.has(e)?e.startsWith("scale")?qN(t[1]):XN:t4,zd=(e,t)=>e==="zIndex"?!1:!!(typeof t=="number"||Array.isArray(t)||typeof t=="string"&&(ir.test(t)||t==="0")&&!t.startsWith("url(")),r4=new Set(["brightness","contrast","saturate","opacity"]);function o4(e){const[t,n]=e.slice(0,-1).split("(");if(t==="drop-shadow")return e;const[r]=n.match(cc)||[];if(!r)return e;const o=n.replace(r,"");let s=r4.has(t)?1:0;return r!==n&&(s*=100),t+"("+s+o+")"}const s4=/([a-z-]*)\(.*?\)/g,Fd={...ir,getAnimatableNone:e=>{const t=e.match(s4);return t?t.map(o4).join(" "):e}},i4={...m1,color:ft,backgroundColor:ft,outlineColor:ft,fill:ft,stroke:ft,borderColor:ft,borderTopColor:ft,borderRightColor:ft,borderBottomColor:ft,borderLeftColor:ft,filter:Fd,WebkitFilter:Fd},Pp=e=>i4[e];function nw(e,t){let n=Pp(e);return n!==Fd&&(n=ir),n.getAnimatableNone?n.getAnimatableNone(t):void 0}const rw=e=>/^0[^.\s]+$/.test(e);function a4(e){if(typeof e=="number")return e===0;if(e!==null)return e==="none"||e==="0"||rw(e)}function l4(e,t,n,r){const o=zd(t,n);let s;Array.isArray(n)?s=[...n]:s=[null,n];const i=r.from!==void 0?r.from:e.get();let a;const l=[];for(let c=0;co=>{const s=ow(r,e)||{},i=s.delay||r.delay||0;let{elapsed:a=0}=r;a=a-tr(i);const l=l4(t,e,n,s),c=l[0],d=l[l.length-1],f=zd(e,c),p=zd(e,d);let h={keyframes:l,velocity:t.getVelocity(),ease:"easeOut",...s,delay:-a,onUpdate:v=>{t.set(v),s.onUpdate&&s.onUpdate(v)},onComplete:()=>{o(),s.onComplete&&s.onComplete()}};if(c4(s)||(h={...h,...n4(e,h)}),h.duration&&(h.duration=tr(h.duration)),h.repeatDelay&&(h.repeatDelay=tr(h.repeatDelay)),!f||!p||sN.current||s.type===!1)return QN(h);if(t.owner&&t.owner.current instanceof HTMLElement&&!t.owner.getProps().onUpdate){const v=ZN(t,e,h);if(v)return v}return dl(h)};function fl(e){return!!(kt(e)&&e.add)}const u4=e=>/^\-?\d*\.?\d+$/.test(e);function Lp(e,t){e.indexOf(t)===-1&&e.push(t)}function _p(e,t){const n=e.indexOf(t);n>-1&&e.splice(n,1)}class Ip{constructor(){this.subscriptions=[]}add(t){return Lp(this.subscriptions,t),()=>_p(this.subscriptions,t)}notify(t,n,r){const o=this.subscriptions.length;if(o)if(o===1)this.subscriptions[0](t,n,r);else for(let s=0;s!isNaN(parseFloat(e));class f4{constructor(t,n={}){this.version="10.13.0",this.timeDelta=0,this.lastUpdated=0,this.canTrackVelocity=!1,this.events={},this.updateAndNotify=(r,o=!0)=>{this.prev=this.current,this.current=r;const{delta:s,timestamp:i}=at;this.lastUpdated!==i&&(this.timeDelta=s,this.lastUpdated=i,Le.postRender(this.scheduleVelocityCheck)),this.prev!==this.current&&this.events.change&&this.events.change.notify(this.current),this.events.velocityChange&&this.events.velocityChange.notify(this.getVelocity()),o&&this.events.renderRequest&&this.events.renderRequest.notify(this.current)},this.scheduleVelocityCheck=()=>Le.postRender(this.velocityCheck),this.velocityCheck=({timestamp:r})=>{r!==this.lastUpdated&&(this.prev=this.current,this.events.velocityChange&&this.events.velocityChange.notify(this.getVelocity()))},this.hasAnimated=!1,this.prev=this.current=t,this.canTrackVelocity=d4(this.current),this.owner=n.owner}onChange(t){return this.on("change",t)}on(t,n){this.events[t]||(this.events[t]=new Ip);const r=this.events[t].add(n);return t==="change"?()=>{r(),Le.read(()=>{this.events.change.getSize()||this.stop()})}:r}clearListeners(){for(const t in this.events)this.events[t].clear()}attach(t,n){this.passiveEffect=t,this.stopPassiveEffect=n}set(t,n=!0){!n||!this.passiveEffect?this.updateAndNotify(t,n):this.passiveEffect(t,this.updateAndNotify)}setWithVelocity(t,n,r){this.set(n),this.prev=t,this.timeDelta=r}jump(t){this.updateAndNotify(t),this.prev=t,this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}get(){return this.current}getPrevious(){return this.prev}getVelocity(){return this.canTrackVelocity?q1(parseFloat(this.current)-parseFloat(this.prev),this.timeDelta):0}start(t){return this.stop(),new Promise(n=>{this.hasAnimated=!0,this.animation=t(n),this.events.animationStart&&this.events.animationStart.notify()}).then(()=>{this.events.animationComplete&&this.events.animationComplete.notify(),this.clearAnimation()})}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel&&this.events.animationCancel.notify()),this.clearAnimation()}isAnimating(){return!!this.animation}clearAnimation(){delete this.animation}destroy(){this.clearListeners(),this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}}function Do(e,t){return new f4(e,t)}const sw=e=>t=>t.test(e),p4={test:e=>e==="auto",parse:e=>e},iw=[Kr,oe,cn,_n,yP,vP,p4],ls=e=>iw.find(sw(e)),h4=[...iw,ft,ir],m4=e=>h4.find(sw(e));function g4(e,t,n){e.hasValue(t)?e.getValue(t).set(n):e.addValue(t,Do(n))}function v4(e,t){const n=dc(e,t);let{transitionEnd:r={},transition:o={},...s}=n?e.makeTargetAnimatable(n,!1):{};s={...s,...r};for(const i in s){const a=LP(s[i]);g4(e,i,a)}}function y4(e,t,n){var r,o;const s=Object.keys(t).filter(a=>!e.hasValue(a)),i=s.length;if(i)for(let a=0;al.remove(f))),c.push(x)}return i&&Promise.all(c).then(()=>{i&&v4(e,i)}),c}function Ud(e,t,n={}){const r=dc(e,t,n.custom);let{transition:o=e.getDefaultTransition()||{}}=r||{};n.transitionOverride&&(o=n.transitionOverride);const s=r?()=>Promise.all(aw(e,r,n)):()=>Promise.resolve(),i=e.variantChildren&&e.variantChildren.size?(l=0)=>{const{delayChildren:c=0,staggerChildren:d,staggerDirection:f}=o;return C4(e,t,c+l,d,f,n)}:()=>Promise.resolve(),{when:a}=o;if(a){const[l,c]=a==="beforeChildren"?[s,i]:[i,s];return l().then(()=>c())}else return Promise.all([s(),i(n.delay)])}function C4(e,t,n=0,r=0,o=1,s){const i=[],a=(e.variantChildren.size-1)*r,l=o===1?(c=0)=>c*r:(c=0)=>a-c*r;return Array.from(e.variantChildren).sort(b4).forEach((c,d)=>{c.notify("AnimationStart",t),i.push(Ud(c,t,{...s,delay:n+l(d)}).then(()=>c.notify("AnimationComplete",t)))}),Promise.all(i)}function b4(e,t){return e.sortNodePosition(t)}function A4(e,t,n={}){e.notify("AnimationStart",t);let r;if(Array.isArray(t)){const o=t.map(s=>Ud(e,s,n));r=Promise.all(o)}else if(typeof t=="string")r=Ud(e,t,n);else{const o=typeof t=="function"?dc(e,t,n.custom):t;r=Promise.all(aw(e,o,n))}return r.then(()=>e.notify("AnimationComplete",t))}const k4=[...mp].reverse(),E4=mp.length;function R4(e){return t=>Promise.all(t.map(({animation:n,options:r})=>A4(e,n,r)))}function T4(e){let t=R4(e);const n=P4();let r=!0;const o=(l,c)=>{const d=dc(e,c);if(d){const{transition:f,transitionEnd:p,...h}=d;l={...l,...h,...p}}return l};function s(l){t=l(e)}function i(l,c){const d=e.getProps(),f=e.getVariantContext(!0)||{},p=[],h=new Set;let v={},x=1/0;for(let g=0;gx&&A;const I=Array.isArray(S)?S:[S];let T=I.reduce(o,{});L===!1&&(T={});const{prevResolvedValues:O={}}=y,N={...O,...T},D=H=>{M=!0,h.delete(H),y.needsAnimating[H]=!0};for(const H in N){const Z=T[H],ne=O[H];v.hasOwnProperty(H)||(Z!==ne?ll(Z)&&ll(ne)?!P1(Z,ne)||k?D(H):y.protectedKeys[H]=!0:Z!==void 0?D(H):h.add(H):Z!==void 0&&h.has(H)?D(H):y.protectedKeys[H]=!0)}y.prevProp=S,y.prevResolvedValues=T,y.isActive&&(v={...v,...T}),r&&e.blockInitialAnimation&&(M=!1),M&&!_&&p.push(...I.map(H=>({animation:H,options:{type:m,...l}})))}if(h.size){const g={};h.forEach(m=>{const y=e.getBaseTarget(m);y!==void 0&&(g[m]=y)}),p.push({animation:g})}let C=!!p.length;return r&&d.initial===!1&&!e.manuallyAnimateOnMount&&(C=!1),r=!1,C?t(p):Promise.resolve()}function a(l,c,d){var f;if(n[l].isActive===c)return Promise.resolve();(f=e.variantChildren)===null||f===void 0||f.forEach(h=>{var v;return(v=h.animationState)===null||v===void 0?void 0:v.setActive(l,c)}),n[l].isActive=c;const p=i(d,l);for(const h in n)n[h].protectedKeys={};return p}return{animateChanges:i,setActive:a,setAnimateFunction:s,getState:()=>n}}function j4(e,t){return typeof t=="string"?t!==e:Array.isArray(t)?!P1(t,e):!1}function gr(e=!1){return{isActive:e,protectedKeys:{},needsAnimating:{},prevResolvedValues:{}}}function P4(){return{animate:gr(!0),whileInView:gr(),whileHover:gr(),whileTap:gr(),whileDrag:gr(),whileFocus:gr(),exit:gr()}}class N4 extends hr{constructor(t){super(t),t.animationState||(t.animationState=T4(t))}updateAnimationControlsSubscription(){const{animate:t}=this.node.getProps();this.unmount(),ac(t)&&(this.unmount=t.subscribe(this.node))}mount(){this.updateAnimationControlsSubscription()}update(){const{animate:t}=this.node.getProps(),{animate:n}=this.node.prevProps||{};t!==n&&this.updateAnimationControlsSubscription()}unmount(){}}let L4=0;class _4 extends hr{constructor(){super(...arguments),this.id=L4++}update(){if(!this.node.presenceContext)return;const{isPresent:t,onExitComplete:n,custom:r}=this.node.presenceContext,{isPresent:o}=this.node.prevPresenceContext||{};if(!this.node.animationState||t===o)return;const s=this.node.animationState.setActive("exit",!t,{custom:r??this.node.getProps().custom});n&&!t&&s.then(()=>n(this.id))}mount(){const{register:t}=this.node.presenceContext||{};t&&(this.unmount=t(this.id))}unmount(){}}const I4={animation:{Feature:N4},exit:{Feature:_4}},eg=(e,t)=>Math.abs(e-t);function M4(e,t){const n=eg(e.x,t.x),r=eg(e.y,t.y);return Math.sqrt(n**2+r**2)}class lw{constructor(t,n,{transformPagePoint:r}={}){if(this.startEvent=null,this.lastMoveEvent=null,this.lastMoveEventInfo=null,this.handlers={},this.updatePoint=()=>{if(!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const c=fu(this.lastMoveEventInfo,this.history),d=this.startEvent!==null,f=M4(c.offset,{x:0,y:0})>=3;if(!d&&!f)return;const{point:p}=c,{timestamp:h}=at;this.history.push({...p,timestamp:h});const{onStart:v,onMove:x}=this.handlers;d||(v&&v(this.lastMoveEvent,c),this.startEvent=this.lastMoveEvent),x&&x(this.lastMoveEvent,c)},this.handlePointerMove=(c,d)=>{this.lastMoveEvent=c,this.lastMoveEventInfo=du(d,this.transformPagePoint),Le.update(this.updatePoint,!0)},this.handlePointerUp=(c,d)=>{if(this.end(),!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const{onEnd:f,onSessionEnd:p}=this.handlers,h=fu(c.type==="pointercancel"?this.lastMoveEventInfo:du(d,this.transformPagePoint),this.history);this.startEvent&&f&&f(c,h),p&&p(c,h)},!k1(t))return;this.handlers=n,this.transformPagePoint=r;const o=uc(t),s=du(o,this.transformPagePoint),{point:i}=s,{timestamp:a}=at;this.history=[{...i,timestamp:a}];const{onSessionStart:l}=n;l&&l(t,fu(s,this.history)),this.removeListeners=er(Sn(window,"pointermove",this.handlePointerMove),Sn(window,"pointerup",this.handlePointerUp),Sn(window,"pointercancel",this.handlePointerUp))}updateHandlers(t){this.handlers=t}end(){this.removeListeners&&this.removeListeners(),Rn(this.updatePoint)}}function du(e,t){return t?{point:t(e.point)}:e}function tg(e,t){return{x:e.x-t.x,y:e.y-t.y}}function fu({point:e},t){return{point:e,delta:tg(e,cw(t)),offset:tg(e,D4(t)),velocity:O4(t,.1)}}function D4(e){return e[0]}function cw(e){return e[e.length-1]}function O4(e,t){if(e.length<2)return{x:0,y:0};let n=e.length-1,r=null;const o=cw(e);for(;n>=0&&(r=e[n],!(o.timestamp-r.timestamp>tr(t)));)n--;if(!r)return{x:0,y:0};const s=Cn(o.timestamp-r.timestamp);if(s===0)return{x:0,y:0};const i={x:(o.x-r.x)/s,y:(o.y-r.y)/s};return i.x===1/0&&(i.x=0),i.y===1/0&&(i.y=0),i}function Lt(e){return e.max-e.min}function $d(e,t=0,n=.01){return Math.abs(e-t)<=n}function ng(e,t,n,r=.5){e.origin=r,e.originPoint=Me(t.min,t.max,e.origin),e.scale=Lt(n)/Lt(t),($d(e.scale,1,1e-4)||isNaN(e.scale))&&(e.scale=1),e.translate=Me(n.min,n.max,e.origin)-e.originPoint,($d(e.translate)||isNaN(e.translate))&&(e.translate=0)}function Os(e,t,n,r){ng(e.x,t.x,n.x,r?r.originX:void 0),ng(e.y,t.y,n.y,r?r.originY:void 0)}function rg(e,t,n){e.min=n.min+t.min,e.max=e.min+Lt(t)}function B4(e,t,n){rg(e.x,t.x,n.x),rg(e.y,t.y,n.y)}function og(e,t,n){e.min=t.min-n.min,e.max=e.min+Lt(t)}function Bs(e,t,n){og(e.x,t.x,n.x),og(e.y,t.y,n.y)}function V4(e,{min:t,max:n},r){return t!==void 0&&en&&(e=r?Me(n,e,r.max):Math.min(e,n)),e}function sg(e,t,n){return{min:t!==void 0?e.min+t:void 0,max:n!==void 0?e.max+n-(e.max-e.min):void 0}}function z4(e,{top:t,left:n,bottom:r,right:o}){return{x:sg(e.x,n,o),y:sg(e.y,t,r)}}function ig(e,t){let n=t.min-e.min,r=t.max-e.max;return t.max-t.minr?n=li(t.min,t.max-r,e.min):r>o&&(n=li(e.min,e.max-o,t.min)),sr(0,1,n)}function $4(e,t){const n={};return t.min!==void 0&&(n.min=t.min-e.min),t.max!==void 0&&(n.max=t.max-e.min),n}const Wd=.35;function W4(e=Wd){return e===!1?e=0:e===!0&&(e=Wd),{x:ag(e,"left","right"),y:ag(e,"top","bottom")}}function ag(e,t,n){return{min:lg(e,t),max:lg(e,n)}}function lg(e,t){return typeof e=="number"?e:e[t]||0}const cg=()=>({translate:0,scale:1,origin:0,originPoint:0}),mo=()=>({x:cg(),y:cg()}),ug=()=>({min:0,max:0}),$e=()=>({x:ug(),y:ug()});function on(e){return[e("x"),e("y")]}function uw({top:e,left:t,right:n,bottom:r}){return{x:{min:t,max:n},y:{min:e,max:r}}}function H4({x:e,y:t}){return{top:t.min,right:e.max,bottom:t.max,left:e.min}}function G4(e,t){if(!t)return e;const n=t({x:e.left,y:e.top}),r=t({x:e.right,y:e.bottom});return{top:n.y,left:n.x,bottom:r.y,right:r.x}}function pu(e){return e===void 0||e===1}function Hd({scale:e,scaleX:t,scaleY:n}){return!pu(e)||!pu(t)||!pu(n)}function wr(e){return Hd(e)||dw(e)||e.z||e.rotate||e.rotateX||e.rotateY}function dw(e){return dg(e.x)||dg(e.y)}function dg(e){return e&&e!=="0%"}function pl(e,t,n){const r=e-n,o=t*r;return n+o}function fg(e,t,n,r,o){return o!==void 0&&(e=pl(e,o,r)),pl(e,n,r)+t}function Gd(e,t=0,n=1,r,o){e.min=fg(e.min,t,n,r,o),e.max=fg(e.max,t,n,r,o)}function fw(e,{x:t,y:n}){Gd(e.x,t.translate,t.scale,t.originPoint),Gd(e.y,n.translate,n.scale,n.originPoint)}function K4(e,t,n,r=!1){const o=n.length;if(!o)return;t.x=t.y=1;let s,i;for(let a=0;a1.0000000000001||e<.999999999999?e:1}function Bn(e,t){e.min=e.min+t,e.max=e.max+t}function hg(e,t,[n,r,o]){const s=t[o]!==void 0?t[o]:.5,i=Me(e.min,e.max,s);Gd(e,t[n],t[r],i,t.scale)}const J4=["x","scaleX","originX"],Y4=["y","scaleY","originY"];function go(e,t){hg(e.x,t,J4),hg(e.y,t,Y4)}function pw(e,t){return uw(G4(e.getBoundingClientRect(),t))}function Z4(e,t,n){const r=pw(e,n),{scroll:o}=t;return o&&(Bn(r.x,o.offset.x),Bn(r.y,o.offset.y)),r}const Q4=new WeakMap;class X4{constructor(t){this.openGlobalLock=null,this.isDragging=!1,this.currentDirection=null,this.originPoint={x:0,y:0},this.constraints=!1,this.hasMutatedConstraints=!1,this.elastic=$e(),this.visualElement=t}start(t,{snapToCursor:n=!1}={}){const{presenceContext:r}=this.visualElement;if(r&&r.isPresent===!1)return;const o=l=>{this.stopAnimation(),n&&this.snapToCursor(uc(l,"page").point)},s=(l,c)=>{const{drag:d,dragPropagation:f,onDragStart:p}=this.getProps();if(d&&!f&&(this.openGlobalLock&&this.openGlobalLock(),this.openGlobalLock=R1(d),!this.openGlobalLock))return;this.isDragging=!0,this.currentDirection=null,this.resolveConstraints(),this.visualElement.projection&&(this.visualElement.projection.isAnimationBlocked=!0,this.visualElement.projection.target=void 0),on(v=>{let x=this.getAxisMotionValue(v).get()||0;if(cn.test(x)){const{projection:C}=this.visualElement;if(C&&C.layout){const g=C.layout.layoutBox[v];g&&(x=Lt(g)*(parseFloat(x)/100))}}this.originPoint[v]=x}),p&&Le.update(()=>p(l,c),!1,!0);const{animationState:h}=this.visualElement;h&&h.setActive("whileDrag",!0)},i=(l,c)=>{const{dragPropagation:d,dragDirectionLock:f,onDirectionLock:p,onDrag:h}=this.getProps();if(!d&&!this.openGlobalLock)return;const{offset:v}=c;if(f&&this.currentDirection===null){this.currentDirection=q4(v),this.currentDirection!==null&&p&&p(this.currentDirection);return}this.updateAxis("x",c.point,v),this.updateAxis("y",c.point,v),this.visualElement.render(),h&&h(l,c)},a=(l,c)=>this.stop(l,c);this.panSession=new lw(t,{onSessionStart:o,onStart:s,onMove:i,onSessionEnd:a},{transformPagePoint:this.visualElement.getTransformPagePoint()})}stop(t,n){const r=this.isDragging;if(this.cancel(),!r)return;const{velocity:o}=n;this.startAnimation(o);const{onDragEnd:s}=this.getProps();s&&Le.update(()=>s(t,n))}cancel(){this.isDragging=!1;const{projection:t,animationState:n}=this.visualElement;t&&(t.isAnimationBlocked=!1),this.panSession&&this.panSession.end(),this.panSession=void 0;const{dragPropagation:r}=this.getProps();!r&&this.openGlobalLock&&(this.openGlobalLock(),this.openGlobalLock=null),n&&n.setActive("whileDrag",!1)}updateAxis(t,n,r){const{drag:o}=this.getProps();if(!r||!sa(t,o,this.currentDirection))return;const s=this.getAxisMotionValue(t);let i=this.originPoint[t]+r[t];this.constraints&&this.constraints[t]&&(i=V4(i,this.constraints[t],this.elastic[t])),s.set(i)}resolveConstraints(){const{dragConstraints:t,dragElastic:n}=this.getProps(),{layout:r}=this.visualElement.projection||{},o=this.constraints;t&&po(t)?this.constraints||(this.constraints=this.resolveRefConstraints()):t&&r?this.constraints=z4(r.layoutBox,t):this.constraints=!1,this.elastic=W4(n),o!==this.constraints&&r&&this.constraints&&!this.hasMutatedConstraints&&on(s=>{this.getAxisMotionValue(s)&&(this.constraints[s]=$4(r.layoutBox[s],this.constraints[s]))})}resolveRefConstraints(){const{dragConstraints:t,onMeasureDragConstraints:n}=this.getProps();if(!t||!po(t))return!1;const r=t.current,{projection:o}=this.visualElement;if(!o||!o.layout)return!1;const s=Z4(r,o.root,this.visualElement.getTransformPagePoint());let i=F4(o.layout.layoutBox,s);if(n){const a=n(H4(i));this.hasMutatedConstraints=!!a,a&&(i=uw(a))}return i}startAnimation(t){const{drag:n,dragMomentum:r,dragElastic:o,dragTransition:s,dragSnapToOrigin:i,onDragTransitionEnd:a}=this.getProps(),l=this.constraints||{},c=on(d=>{if(!sa(d,n,this.currentDirection))return;let f=l&&l[d]||{};i&&(f={min:0,max:0});const p=o?200:1e6,h=o?40:1e7,v={type:"inertia",velocity:r?t[d]:0,bounceStiffness:p,bounceDamping:h,timeConstant:750,restDelta:1,restSpeed:10,...s,...f};return this.startAxisValueAnimation(d,v)});return Promise.all(c).then(a)}startAxisValueAnimation(t,n){const r=this.getAxisMotionValue(t);return r.start(Np(t,r,0,n))}stopAnimation(){on(t=>this.getAxisMotionValue(t).stop())}getAxisMotionValue(t){const n="_drag"+t.toUpperCase(),r=this.visualElement.getProps(),o=r[n];return o||this.visualElement.getValue(t,(r.initial?r.initial[t]:void 0)||0)}snapToCursor(t){on(n=>{const{drag:r}=this.getProps();if(!sa(n,r,this.currentDirection))return;const{projection:o}=this.visualElement,s=this.getAxisMotionValue(n);if(o&&o.layout){const{min:i,max:a}=o.layout.layoutBox[n];s.set(t[n]-Me(i,a,.5))}})}scalePositionWithinConstraints(){if(!this.visualElement.current)return;const{drag:t,dragConstraints:n}=this.getProps(),{projection:r}=this.visualElement;if(!po(n)||!r||!this.constraints)return;this.stopAnimation();const o={x:0,y:0};on(i=>{const a=this.getAxisMotionValue(i);if(a){const l=a.get();o[i]=U4({min:l,max:l},this.constraints[i])}});const{transformTemplate:s}=this.visualElement.getProps();this.visualElement.current.style.transform=s?s({},""):"none",r.root&&r.root.updateScroll(),r.updateLayout(),this.resolveConstraints(),on(i=>{if(!sa(i,t,null))return;const a=this.getAxisMotionValue(i),{min:l,max:c}=this.constraints[i];a.set(Me(l,c,o[i]))})}addListeners(){if(!this.visualElement.current)return;Q4.set(this.visualElement,this);const t=this.visualElement.current,n=Sn(t,"pointerdown",l=>{const{drag:c,dragListener:d=!0}=this.getProps();c&&d&&this.start(l)}),r=()=>{const{dragConstraints:l}=this.getProps();po(l)&&(this.constraints=this.resolveRefConstraints())},{projection:o}=this.visualElement,s=o.addEventListener("measure",r);o&&!o.layout&&(o.root&&o.root.updateScroll(),o.updateLayout()),r();const i=yn(window,"resize",()=>this.scalePositionWithinConstraints()),a=o.addEventListener("didUpdate",({delta:l,hasLayoutChanged:c})=>{this.isDragging&&c&&(on(d=>{const f=this.getAxisMotionValue(d);f&&(this.originPoint[d]+=l[d].translate,f.set(f.get()+l[d].translate))}),this.visualElement.render())});return()=>{i(),n(),s(),a&&a()}}getProps(){const t=this.visualElement.getProps(),{drag:n=!1,dragDirectionLock:r=!1,dragPropagation:o=!1,dragConstraints:s=!1,dragElastic:i=Wd,dragMomentum:a=!0}=t;return{...t,drag:n,dragDirectionLock:r,dragPropagation:o,dragConstraints:s,dragElastic:i,dragMomentum:a}}}function sa(e,t,n){return(t===!0||t===e)&&(n===null||n===e)}function q4(e,t=10){let n=null;return Math.abs(e.y)>t?n="y":Math.abs(e.x)>t&&(n="x"),n}class e5 extends hr{constructor(t){super(t),this.removeGroupControls=He,this.removeListeners=He,this.controls=new X4(t)}mount(){const{dragControls:t}=this.node.getProps();t&&(this.removeGroupControls=t.subscribe(this.controls)),this.removeListeners=this.controls.addListeners()||He}unmount(){this.removeGroupControls(),this.removeListeners()}}const mg=e=>(t,n)=>{e&&Le.update(()=>e(t,n))};class t5 extends hr{constructor(){super(...arguments),this.removePointerDownListener=He}onPointerDown(t){this.session=new lw(t,this.createPanHandlers(),{transformPagePoint:this.node.getTransformPagePoint()})}createPanHandlers(){const{onPanSessionStart:t,onPanStart:n,onPan:r,onPanEnd:o}=this.node.getProps();return{onSessionStart:mg(t),onStart:mg(n),onMove:r,onEnd:(s,i)=>{delete this.session,o&&Le.update(()=>o(s,i))}}}mount(){this.removePointerDownListener=Sn(this.node.current,"pointerdown",t=>this.onPointerDown(t))}update(){this.session&&this.session.updateHandlers(this.createPanHandlers())}unmount(){this.removePointerDownListener(),this.session&&this.session.end()}}function n5(){const e=w.useContext(sc);if(e===null)return[!0,null];const{isPresent:t,onExitComplete:n,register:r}=e,o=w.useId();return w.useEffect(()=>r(o),[]),!t&&n?[!1,()=>n&&n(o)]:[!0]}const Ea={hasAnimatedSinceResize:!0,hasEverUpdated:!1};function gg(e,t){return t.max===t.min?0:e/(t.max-t.min)*100}const cs={correct:(e,t)=>{if(!t.target)return e;if(typeof e=="string")if(oe.test(e))e=parseFloat(e);else return e;const n=gg(e,t.target.x),r=gg(e,t.target.y);return`${n}% ${r}%`}},r5={correct:(e,{treeScale:t,projectionDelta:n})=>{const r=e,o=ir.parse(e);if(o.length>5)return r;const s=ir.createTransformer(e),i=typeof o[0]!="number"?1:0,a=n.x.scale*t.x,l=n.y.scale*t.y;o[0+i]/=a,o[1+i]/=l;const c=Me(a,l,.5);return typeof o[2+i]=="number"&&(o[2+i]/=c),typeof o[3+i]=="number"&&(o[3+i]/=c),s(o)}};class o5 extends V.Component{componentDidMount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r,layoutId:o}=this.props,{projection:s}=t;uP(s5),s&&(n.group&&n.group.add(s),r&&r.register&&o&&r.register(s),s.root.didUpdate(),s.addEventListener("animationComplete",()=>{this.safeToRemove()}),s.setOptions({...s.options,onExitComplete:()=>this.safeToRemove()})),Ea.hasEverUpdated=!0}getSnapshotBeforeUpdate(t){const{layoutDependency:n,visualElement:r,drag:o,isPresent:s}=this.props,i=r.projection;return i&&(i.isPresent=s,o||t.layoutDependency!==n||n===void 0?i.willUpdate():this.safeToRemove(),t.isPresent!==s&&(s?i.promote():i.relegate()||Le.postRender(()=>{const a=i.getStack();(!a||!a.members.length)&&this.safeToRemove()}))),null}componentDidUpdate(){const{projection:t}=this.props.visualElement;t&&(t.root.didUpdate(),queueMicrotask(()=>{!t.currentAnimation&&t.isLead()&&this.safeToRemove()}))}componentWillUnmount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r}=this.props,{projection:o}=t;o&&(o.scheduleCheckAfterUnmount(),n&&n.group&&n.group.remove(o),r&&r.deregister&&r.deregister(o))}safeToRemove(){const{safeToRemove:t}=this.props;t&&t()}render(){return null}}function hw(e){const[t,n]=n5(),r=w.useContext(vp);return V.createElement(o5,{...e,layoutGroup:r,switchLayoutGroup:w.useContext(u1),isPresent:t,safeToRemove:n})}const s5={borderRadius:{...cs,applyTo:["borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"]},borderTopLeftRadius:cs,borderTopRightRadius:cs,borderBottomLeftRadius:cs,borderBottomRightRadius:cs,boxShadow:r5},mw=["TopLeft","TopRight","BottomLeft","BottomRight"],i5=mw.length,vg=e=>typeof e=="string"?parseFloat(e):e,yg=e=>typeof e=="number"||oe.test(e);function a5(e,t,n,r,o,s){o?(e.opacity=Me(0,n.opacity!==void 0?n.opacity:1,l5(r)),e.opacityExit=Me(t.opacity!==void 0?t.opacity:1,0,c5(r))):s&&(e.opacity=Me(t.opacity!==void 0?t.opacity:1,n.opacity!==void 0?n.opacity:1,r));for(let i=0;irt?1:n(li(e,t,r))}function wg(e,t){e.min=t.min,e.max=t.max}function Ot(e,t){wg(e.x,t.x),wg(e.y,t.y)}function Sg(e,t,n,r,o){return e-=t,e=pl(e,1/n,r),o!==void 0&&(e=pl(e,1/o,r)),e}function u5(e,t=0,n=1,r=.5,o,s=e,i=e){if(cn.test(t)&&(t=parseFloat(t),t=Me(i.min,i.max,t/100)-i.min),typeof t!="number")return;let a=Me(s.min,s.max,r);e===s&&(a-=t),e.min=Sg(e.min,t,n,a,o),e.max=Sg(e.max,t,n,a,o)}function Cg(e,t,[n,r,o],s,i){u5(e,t[n],t[r],t[o],t.scale,s,i)}const d5=["x","scaleX","originX"],f5=["y","scaleY","originY"];function bg(e,t,n,r){Cg(e.x,t,d5,n?n.x:void 0,r?r.x:void 0),Cg(e.y,t,f5,n?n.y:void 0,r?r.y:void 0)}function Ag(e){return e.translate===0&&e.scale===1}function vw(e){return Ag(e.x)&&Ag(e.y)}function Kd(e,t){return e.x.min===t.x.min&&e.x.max===t.x.max&&e.y.min===t.y.min&&e.y.max===t.y.max}function kg(e){return Lt(e.x)/Lt(e.y)}class p5{constructor(){this.members=[]}add(t){Lp(this.members,t),t.scheduleRender()}remove(t){if(_p(this.members,t),t===this.prevLead&&(this.prevLead=void 0),t===this.lead){const n=this.members[this.members.length-1];n&&this.promote(n)}}relegate(t){const n=this.members.findIndex(o=>t===o);if(n===0)return!1;let r;for(let o=n;o>=0;o--){const s=this.members[o];if(s.isPresent!==!1){r=s;break}}return r?(this.promote(r),!0):!1}promote(t,n){const r=this.lead;if(t!==r&&(this.prevLead=r,this.lead=t,t.show(),r)){r.instance&&r.scheduleRender(),t.scheduleRender(),t.resumeFrom=r,n&&(t.resumeFrom.preserveOpacity=!0),r.snapshot&&(t.snapshot=r.snapshot,t.snapshot.latestValues=r.animationValues||r.latestValues),t.root&&t.root.isUpdating&&(t.isLayoutDirty=!0);const{crossfade:o}=t.options;o===!1&&r.hide()}}exitAnimationComplete(){this.members.forEach(t=>{const{options:n,resumingFrom:r}=t;n.onExitComplete&&n.onExitComplete(),r&&r.options.onExitComplete&&r.options.onExitComplete()})}scheduleRender(){this.members.forEach(t=>{t.instance&&t.scheduleRender(!1)})}removeLeadSnapshot(){this.lead&&this.lead.snapshot&&(this.lead.snapshot=void 0)}}function Eg(e,t,n){let r="";const o=e.x.translate/t.x,s=e.y.translate/t.y;if((o||s)&&(r=`translate3d(${o}px, ${s}px, 0) `),(t.x!==1||t.y!==1)&&(r+=`scale(${1/t.x}, ${1/t.y}) `),n){const{rotate:l,rotateX:c,rotateY:d}=n;l&&(r+=`rotate(${l}deg) `),c&&(r+=`rotateX(${c}deg) `),d&&(r+=`rotateY(${d}deg) `)}const i=e.x.scale*t.x,a=e.y.scale*t.y;return(i!==1||a!==1)&&(r+=`scale(${i}, ${a})`),r||"none"}const h5=(e,t)=>e.depth-t.depth;class m5{constructor(){this.children=[],this.isDirty=!1}add(t){Lp(this.children,t),this.isDirty=!0}remove(t){_p(this.children,t),this.isDirty=!0}forEach(t){this.isDirty&&this.children.sort(h5),this.isDirty=!1,this.children.forEach(t)}}function g5(e,t){const n=performance.now(),r=({timestamp:o})=>{const s=o-n;s>=t&&(Rn(r),e(s-t))};return Le.read(r,!0),()=>Rn(r)}function v5(e){window.MotionDebug&&window.MotionDebug.record(e)}function y5(e){return e instanceof SVGElement&&e.tagName!=="svg"}function x5(e,t,n){const r=kt(e)?e:Do(e);return r.start(Np("",r,t,n)),r.animation}const Rg=["","X","Y","Z"],Tg=1e3;let w5=0;const Sr={type:"projectionFrame",totalNodes:0,resolvedTargetDeltas:0,recalculatedProjection:0};function yw({attachResizeListener:e,defaultParent:t,measureScroll:n,checkIsScrollRoot:r,resetTransform:o}){return class{constructor(i={},a=t==null?void 0:t()){this.id=w5++,this.animationId=0,this.children=new Set,this.options={},this.isTreeAnimating=!1,this.isAnimationBlocked=!1,this.isLayoutDirty=!1,this.isProjectionDirty=!1,this.isSharedProjectionDirty=!1,this.isTransformDirty=!1,this.updateManuallyBlocked=!1,this.updateBlockedByResize=!1,this.isUpdating=!1,this.isSVG=!1,this.needsReset=!1,this.shouldResetTransform=!1,this.treeScale={x:1,y:1},this.eventHandlers=new Map,this.hasTreeAnimated=!1,this.updateScheduled=!1,this.checkUpdateFailed=()=>{this.isUpdating&&(this.isUpdating=!1,this.clearAllSnapshots())},this.updateProjection=()=>{Sr.totalNodes=Sr.resolvedTargetDeltas=Sr.recalculatedProjection=0,this.nodes.forEach(b5),this.nodes.forEach(T5),this.nodes.forEach(j5),this.nodes.forEach(A5),v5(Sr)},this.hasProjected=!1,this.isVisible=!0,this.animationProgress=0,this.sharedNodes=new Map,this.latestValues=i,this.root=a?a.root||a:this,this.path=a?[...a.path,a]:[],this.parent=a,this.depth=a?a.depth+1:0;for(let l=0;lthis.root.updateBlockedByResize=!1;e(i,()=>{this.root.updateBlockedByResize=!0,f&&f(),f=g5(p,250),Ea.hasAnimatedSinceResize&&(Ea.hasAnimatedSinceResize=!1,this.nodes.forEach(Pg))})}l&&this.root.registerSharedNode(l,this),this.options.animate!==!1&&d&&(l||c)&&this.addEventListener("didUpdate",({delta:f,hasLayoutChanged:p,hasRelativeTargetChanged:h,layout:v})=>{if(this.isTreeAnimationBlocked()){this.target=void 0,this.relativeTarget=void 0;return}const x=this.options.transition||d.getDefaultTransition()||I5,{onLayoutAnimationStart:C,onLayoutAnimationComplete:g}=d.getProps(),m=!this.targetLayout||!Kd(this.targetLayout,v)||h,y=!p&&h;if(this.options.layoutRoot||this.resumeFrom&&this.resumeFrom.instance||y||p&&(m||!this.currentAnimation)){this.resumeFrom&&(this.resumingFrom=this.resumeFrom,this.resumingFrom.resumingFrom=void 0),this.setAnimationOrigin(f,y);const S={...ow(x,"layout"),onPlay:C,onComplete:g};(d.shouldReduceMotion||this.options.layoutRoot)&&(S.delay=0,S.type=!1),this.startAnimation(S)}else p||Pg(this),this.isLead()&&this.options.onExitComplete&&this.options.onExitComplete();this.targetLayout=v})}unmount(){this.options.layoutId&&this.willUpdate(),this.root.nodes.remove(this);const i=this.getStack();i&&i.remove(this),this.parent&&this.parent.children.delete(this),this.instance=void 0,Rn(this.updateProjection)}blockUpdate(){this.updateManuallyBlocked=!0}unblockUpdate(){this.updateManuallyBlocked=!1}isUpdateBlocked(){return this.updateManuallyBlocked||this.updateBlockedByResize}isTreeAnimationBlocked(){return this.isAnimationBlocked||this.parent&&this.parent.isTreeAnimationBlocked()||!1}startUpdate(){this.isUpdateBlocked()||(this.isUpdating=!0,this.nodes&&this.nodes.forEach(P5),this.animationId++)}getTransformTemplate(){const{visualElement:i}=this.options;return i&&i.getProps().transformTemplate}willUpdate(i=!0){if(this.root.hasTreeAnimated=!0,this.root.isUpdateBlocked()){this.options.onExitComplete&&this.options.onExitComplete();return}if(!this.root.isUpdating&&this.root.startUpdate(),this.isLayoutDirty)return;this.isLayoutDirty=!0;for(let d=0;dthis.update()))}clearAllSnapshots(){this.nodes.forEach(k5),this.sharedNodes.forEach(N5)}scheduleUpdateProjection(){Le.preRender(this.updateProjection,!1,!0)}scheduleCheckAfterUnmount(){Le.postRender(()=>{this.isLayoutDirty?this.root.didUpdate():this.root.checkUpdateFailed()})}updateSnapshot(){this.snapshot||!this.instance||(this.snapshot=this.measure())}updateLayout(){if(!this.instance||(this.updateScroll(),!(this.options.alwaysMeasureLayout&&this.isLead())&&!this.isLayoutDirty))return;if(this.resumeFrom&&!this.resumeFrom.instance)for(let l=0;l{const A=S/1e3;Ng(f.x,i.x,A),Ng(f.y,i.y,A),this.setTargetDelta(f),this.relativeTarget&&this.relativeTargetOrigin&&this.layout&&this.relativeParent&&this.relativeParent.layout&&(Bs(p,this.layout.layoutBox,this.relativeParent.layout.layoutBox),L5(this.relativeTarget,this.relativeTargetOrigin,p,A),y&&Kd(this.relativeTarget,y)&&(this.isProjectionDirty=!1),y||(y=$e()),Ot(y,this.relativeTarget)),x&&(this.animationValues=d,a5(d,c,this.latestValues,A,m,g)),this.root.scheduleUpdateProjection(),this.scheduleRender(),this.animationProgress=A},this.mixTargetDelta(this.options.layoutRoot?1e3:0)}startAnimation(i){this.notifyListeners("animationStart"),this.currentAnimation&&this.currentAnimation.stop(),this.resumingFrom&&this.resumingFrom.currentAnimation&&this.resumingFrom.currentAnimation.stop(),this.pendingAnimation&&(Rn(this.pendingAnimation),this.pendingAnimation=void 0),this.pendingAnimation=Le.update(()=>{Ea.hasAnimatedSinceResize=!0,this.currentAnimation=x5(0,Tg,{...i,onUpdate:a=>{this.mixTargetDelta(a),i.onUpdate&&i.onUpdate(a)},onComplete:()=>{i.onComplete&&i.onComplete(),this.completeAnimation()}}),this.resumingFrom&&(this.resumingFrom.currentAnimation=this.currentAnimation),this.pendingAnimation=void 0})}completeAnimation(){this.resumingFrom&&(this.resumingFrom.currentAnimation=void 0,this.resumingFrom.preserveOpacity=void 0);const i=this.getStack();i&&i.exitAnimationComplete(),this.resumingFrom=this.currentAnimation=this.animationValues=void 0,this.notifyListeners("animationComplete")}finishAnimation(){this.currentAnimation&&(this.mixTargetDelta&&this.mixTargetDelta(Tg),this.currentAnimation.stop()),this.completeAnimation()}applyTransformsToTarget(){const i=this.getLead();let{targetWithTransforms:a,target:l,layout:c,latestValues:d}=i;if(!(!a||!l||!c)){if(this!==i&&this.layout&&c&&xw(this.options.animationType,this.layout.layoutBox,c.layoutBox)){l=this.target||$e();const f=Lt(this.layout.layoutBox.x);l.x.min=i.target.x.min,l.x.max=l.x.min+f;const p=Lt(this.layout.layoutBox.y);l.y.min=i.target.y.min,l.y.max=l.y.min+p}Ot(a,l),go(a,d),Os(this.projectionDeltaWithTransform,this.layoutCorrected,a,d)}}registerSharedNode(i,a){this.sharedNodes.has(i)||this.sharedNodes.set(i,new p5),this.sharedNodes.get(i).add(a);const c=a.options.initialPromotionConfig;a.promote({transition:c?c.transition:void 0,preserveFollowOpacity:c&&c.shouldPreserveFollowOpacity?c.shouldPreserveFollowOpacity(a):void 0})}isLead(){const i=this.getStack();return i?i.lead===this:!0}getLead(){var i;const{layoutId:a}=this.options;return a?((i=this.getStack())===null||i===void 0?void 0:i.lead)||this:this}getPrevLead(){var i;const{layoutId:a}=this.options;return a?(i=this.getStack())===null||i===void 0?void 0:i.prevLead:void 0}getStack(){const{layoutId:i}=this.options;if(i)return this.root.sharedNodes.get(i)}promote({needsReset:i,transition:a,preserveFollowOpacity:l}={}){const c=this.getStack();c&&c.promote(this,l),i&&(this.projectionDelta=void 0,this.needsReset=!0),a&&this.setOptions({transition:a})}relegate(){const i=this.getStack();return i?i.relegate(this):!1}resetRotation(){const{visualElement:i}=this.options;if(!i)return;let a=!1;const{latestValues:l}=i;if((l.rotate||l.rotateX||l.rotateY||l.rotateZ)&&(a=!0),!a)return;const c={};for(let d=0;d{var a;return(a=i.currentAnimation)===null||a===void 0?void 0:a.stop()}),this.root.nodes.forEach(jg),this.root.sharedNodes.clear()}}}function S5(e){e.updateLayout()}function C5(e){var t;const n=((t=e.resumeFrom)===null||t===void 0?void 0:t.snapshot)||e.snapshot;if(e.isLead()&&e.layout&&n&&e.hasListeners("didUpdate")){const{layoutBox:r,measuredBox:o}=e.layout,{animationType:s}=e.options,i=n.source!==e.layout.source;s==="size"?on(f=>{const p=i?n.measuredBox[f]:n.layoutBox[f],h=Lt(p);p.min=r[f].min,p.max=p.min+h}):xw(s,n.layoutBox,r)&&on(f=>{const p=i?n.measuredBox[f]:n.layoutBox[f],h=Lt(r[f]);p.max=p.min+h,e.relativeTarget&&!e.currentAnimation&&(e.isProjectionDirty=!0,e.relativeTarget[f].max=e.relativeTarget[f].min+h)});const a=mo();Os(a,r,n.layoutBox);const l=mo();i?Os(l,e.applyTransform(o,!0),n.measuredBox):Os(l,r,n.layoutBox);const c=!vw(a);let d=!1;if(!e.resumeFrom){const f=e.getClosestProjectingParent();if(f&&!f.resumeFrom){const{snapshot:p,layout:h}=f;if(p&&h){const v=$e();Bs(v,n.layoutBox,p.layoutBox);const x=$e();Bs(x,r,h.layoutBox),Kd(v,x)||(d=!0),f.options.layoutRoot&&(e.relativeTarget=x,e.relativeTargetOrigin=v,e.relativeParent=f)}}}e.notifyListeners("didUpdate",{layout:r,snapshot:n,delta:l,layoutDelta:a,hasLayoutChanged:c,hasRelativeTargetChanged:d})}else if(e.isLead()){const{onExitComplete:r}=e.options;r&&r()}e.options.transition=void 0}function b5(e){Sr.totalNodes++,e.parent&&(e.isProjecting()||(e.isProjectionDirty=e.parent.isProjectionDirty),e.isSharedProjectionDirty||(e.isSharedProjectionDirty=!!(e.isProjectionDirty||e.parent.isProjectionDirty||e.parent.isSharedProjectionDirty)),e.isTransformDirty||(e.isTransformDirty=e.parent.isTransformDirty))}function A5(e){e.isProjectionDirty=e.isSharedProjectionDirty=e.isTransformDirty=!1}function k5(e){e.clearSnapshot()}function jg(e){e.clearMeasurements()}function E5(e){e.isLayoutDirty=!1}function R5(e){const{visualElement:t}=e.options;t&&t.getProps().onBeforeLayoutMeasure&&t.notify("BeforeLayoutMeasure"),e.resetTransform()}function Pg(e){e.finishAnimation(),e.targetDelta=e.relativeTarget=e.target=void 0,e.isProjectionDirty=!0}function T5(e){e.resolveTargetDelta()}function j5(e){e.calcProjection()}function P5(e){e.resetRotation()}function N5(e){e.removeLeadSnapshot()}function Ng(e,t,n){e.translate=Me(t.translate,0,n),e.scale=Me(t.scale,1,n),e.origin=t.origin,e.originPoint=t.originPoint}function Lg(e,t,n,r){e.min=Me(t.min,n.min,r),e.max=Me(t.max,n.max,r)}function L5(e,t,n,r){Lg(e.x,t.x,n.x,r),Lg(e.y,t.y,n.y,r)}function _5(e){return e.animationValues&&e.animationValues.opacityExit!==void 0}const I5={duration:.45,ease:[.4,0,.1,1]};let hl;const M5=()=>navigator.userAgent.toLowerCase().includes("applewebkit/");function _g(e){e.min=hl(e.min),e.max=hl(e.max)}function D5(e){hl||(hl=M5()?Math.round:t=>Math.round(t*2)/2),_g(e.x),_g(e.y)}function xw(e,t,n){return e==="position"||e==="preserve-aspect"&&!$d(kg(t),kg(n),.2)}const O5=yw({attachResizeListener:(e,t)=>yn(e,"resize",t),measureScroll:()=>({x:document.documentElement.scrollLeft||document.body.scrollLeft,y:document.documentElement.scrollTop||document.body.scrollTop}),checkIsScrollRoot:()=>!0}),hu={current:void 0},ww=yw({measureScroll:e=>({x:e.scrollLeft,y:e.scrollTop}),defaultParent:()=>{if(!hu.current){const e=new O5({});e.mount(window),e.setOptions({layoutScroll:!0}),hu.current=e}return hu.current},resetTransform:(e,t)=>{e.style.transform=t!==void 0?t:"none"},checkIsScrollRoot:e=>window.getComputedStyle(e).position==="fixed"}),B5={pan:{Feature:t5},drag:{Feature:e5,ProjectionNode:ww,MeasureLayout:hw}},V5=/var\((--[a-zA-Z0-9-_]+),? ?([a-zA-Z0-9 ()%#.,-]+)?\)/;function z5(e){const t=V5.exec(e);if(!t)return[,];const[,n,r]=t;return[n,r]}function Jd(e,t,n=1){const[r,o]=z5(e);if(!r)return;const s=window.getComputedStyle(t).getPropertyValue(r);return s?s.trim():Dd(o)?Jd(o,t,n+1):o}function F5(e,{...t},n){const r=e.current;if(!(r instanceof Element))return{target:t,transitionEnd:n};n&&(n={...n}),e.values.forEach(o=>{const s=o.get();if(!Dd(s))return;const i=Jd(s,r);i&&o.set(i)});for(const o in t){const s=t[o];if(!Dd(s))continue;const i=Jd(s,r);i&&(t[o]=i,n||(n={}),n[o]===void 0&&(n[o]=s))}return{target:t,transitionEnd:n}}const U5=new Set(["width","height","top","left","right","bottom","x","y","translateX","translateY"]),Sw=e=>U5.has(e),$5=e=>Object.keys(e).some(Sw),Ig=e=>e===Kr||e===oe,Mg=(e,t)=>parseFloat(e.split(", ")[t]),Dg=(e,t)=>(n,{transform:r})=>{if(r==="none"||!r)return 0;const o=r.match(/^matrix3d\((.+)\)$/);if(o)return Mg(o[1],t);{const s=r.match(/^matrix\((.+)\)$/);return s?Mg(s[1],e):0}},W5=new Set(["x","y","z"]),H5=Ai.filter(e=>!W5.has(e));function G5(e){const t=[];return H5.forEach(n=>{const r=e.getValue(n);r!==void 0&&(t.push([n,r.get()]),r.set(n.startsWith("scale")?1:0))}),t.length&&e.render(),t}const Oo={width:({x:e},{paddingLeft:t="0",paddingRight:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),height:({y:e},{paddingTop:t="0",paddingBottom:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),top:(e,{top:t})=>parseFloat(t),left:(e,{left:t})=>parseFloat(t),bottom:({y:e},{top:t})=>parseFloat(t)+(e.max-e.min),right:({x:e},{left:t})=>parseFloat(t)+(e.max-e.min),x:Dg(4,13),y:Dg(5,14)};Oo.translateX=Oo.x;Oo.translateY=Oo.y;const K5=(e,t,n)=>{const r=t.measureViewportBox(),o=t.current,s=getComputedStyle(o),{display:i}=s,a={};i==="none"&&t.setStaticValue("display",e.display||"block"),n.forEach(c=>{a[c]=Oo[c](r,s)}),t.render();const l=t.measureViewportBox();return n.forEach(c=>{const d=t.getValue(c);d&&d.jump(a[c]),e[c]=Oo[c](l,s)}),e},J5=(e,t,n={},r={})=>{t={...t},r={...r};const o=Object.keys(t).filter(Sw);let s=[],i=!1;const a=[];if(o.forEach(l=>{const c=e.getValue(l);if(!e.hasValue(l))return;let d=n[l],f=ls(d);const p=t[l];let h;if(ll(p)){const v=p.length,x=p[0]===null?1:0;d=p[x],f=ls(d);for(let C=x;C=0?window.pageYOffset:null,c=K5(t,e,a);return s.length&&s.forEach(([d,f])=>{e.getValue(d).set(f)}),e.render(),ic&&l!==null&&window.scrollTo({top:l}),{target:c,transitionEnd:r}}else return{target:t,transitionEnd:r}};function Y5(e,t,n,r){return $5(t)?J5(e,t,n,r):{target:t,transitionEnd:r}}const Z5=(e,t,n,r)=>{const o=F5(e,t,r);return t=o.target,r=o.transitionEnd,Y5(e,t,n,r)},Yd={current:null},Cw={current:!1};function Q5(){if(Cw.current=!0,!!ic)if(window.matchMedia){const e=window.matchMedia("(prefers-reduced-motion)"),t=()=>Yd.current=e.matches;e.addListener(t),t()}else Yd.current=!1}function X5(e,t,n){const{willChange:r}=t;for(const o in t){const s=t[o],i=n[o];if(kt(s))e.addValue(o,s),fl(r)&&r.add(o);else if(kt(i))e.addValue(o,Do(s,{owner:e})),fl(r)&&r.remove(o);else if(i!==s)if(e.hasValue(o)){const a=e.getValue(o);!a.hasAnimated&&a.set(s)}else{const a=e.getStaticValue(o);e.addValue(o,Do(a!==void 0?a:s,{owner:e}))}}for(const o in n)t[o]===void 0&&e.removeValue(o);return t}const Og=new WeakMap,bw=Object.keys(ai),q5=bw.length,Bg=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"],eL=gp.length;class tL{constructor({parent:t,props:n,presenceContext:r,reducedMotionConfig:o,visualState:s},i={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.values=new Map,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.scheduleRender=()=>Le.render(this.render,!1,!0);const{latestValues:a,renderState:l}=s;this.latestValues=a,this.baseTarget={...a},this.initialValues=n.initial?{...a}:{},this.renderState=l,this.parent=t,this.props=n,this.presenceContext=r,this.depth=t?t.depth+1:0,this.reducedMotionConfig=o,this.options=i,this.isControllingVariants=lc(n),this.isVariantNode=c1(n),this.isVariantNode&&(this.variantChildren=new Set),this.manuallyAnimateOnMount=!!(t&&t.current);const{willChange:c,...d}=this.scrapeMotionValuesFromProps(n,{});for(const f in d){const p=d[f];a[f]!==void 0&&kt(p)&&(p.set(a[f],!1),fl(c)&&c.add(f))}}scrapeMotionValuesFromProps(t,n){return{}}mount(t){this.current=t,Og.set(t,this),this.projection&&!this.projection.instance&&this.projection.mount(t),this.parent&&this.isVariantNode&&!this.isControllingVariants&&(this.removeFromVariantTree=this.parent.addVariantChild(this)),this.values.forEach((n,r)=>this.bindToMotionValue(r,n)),Cw.current||Q5(),this.shouldReduceMotion=this.reducedMotionConfig==="never"?!1:this.reducedMotionConfig==="always"?!0:Yd.current,this.parent&&this.parent.children.add(this),this.update(this.props,this.presenceContext)}unmount(){Og.delete(this.current),this.projection&&this.projection.unmount(),Rn(this.notifyUpdate),Rn(this.render),this.valueSubscriptions.forEach(t=>t()),this.removeFromVariantTree&&this.removeFromVariantTree(),this.parent&&this.parent.children.delete(this);for(const t in this.events)this.events[t].clear();for(const t in this.features)this.features[t].unmount();this.current=null}bindToMotionValue(t,n){const r=Gr.has(t),o=n.on("change",i=>{this.latestValues[t]=i,this.props.onUpdate&&Le.update(this.notifyUpdate,!1,!0),r&&this.projection&&(this.projection.isTransformDirty=!0)}),s=n.on("renderRequest",this.scheduleRender);this.valueSubscriptions.set(t,()=>{o(),s()})}sortNodePosition(t){return!this.current||!this.sortInstanceNodePosition||this.type!==t.type?0:this.sortInstanceNodePosition(this.current,t.current)}loadFeatures({children:t,...n},r,o,s){let i,a;for(let l=0;lthis.scheduleRender(),animationType:typeof c=="string"?c:"both",initialPromotionConfig:s,layoutScroll:p,layoutRoot:h})}return a}updateFeatures(){for(const t in this.features){const n=this.features[t];n.isMounted?n.update():(n.mount(),n.isMounted=!0)}}triggerBuild(){this.build(this.renderState,this.latestValues,this.options,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):$e()}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,n){this.latestValues[t]=n}makeTargetAnimatable(t,n=!0){return this.makeTargetAnimatableFromInstance(t,this.props,n)}update(t,n){(t.transformTemplate||this.props.transformTemplate)&&this.scheduleRender(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=n;for(let r=0;rn.variantChildren.delete(t)}addValue(t,n){n!==this.values.get(t)&&(this.removeValue(t),this.bindToMotionValue(t,n)),this.values.set(t,n),this.latestValues[t]=n.get()}removeValue(t){this.values.delete(t);const n=this.valueSubscriptions.get(t);n&&(n(),this.valueSubscriptions.delete(t)),delete this.latestValues[t],this.removeValueFromRenderState(t,this.renderState)}hasValue(t){return this.values.has(t)}getValue(t,n){if(this.props.values&&this.props.values[t])return this.props.values[t];let r=this.values.get(t);return r===void 0&&n!==void 0&&(r=Do(n,{owner:this}),this.addValue(t,r)),r}readValue(t){var n;return this.latestValues[t]!==void 0||!this.current?this.latestValues[t]:(n=this.getBaseTargetFromProps(this.props,t))!==null&&n!==void 0?n:this.readValueFromInstance(this.current,t,this.options)}setBaseTarget(t,n){this.baseTarget[t]=n}getBaseTarget(t){var n;const{initial:r}=this.props,o=typeof r=="string"||typeof r=="object"?(n=kp(this.props,r))===null||n===void 0?void 0:n[t]:void 0;if(r&&o!==void 0)return o;const s=this.getBaseTargetFromProps(this.props,t);return s!==void 0&&!kt(s)?s:this.initialValues[t]!==void 0&&o===void 0?void 0:this.baseTarget[t]}on(t,n){return this.events[t]||(this.events[t]=new Ip),this.events[t].add(n)}notify(t,...n){this.events[t]&&this.events[t].notify(...n)}}class Aw extends tL{sortInstanceNodePosition(t,n){return t.compareDocumentPosition(n)&2?1:-1}getBaseTargetFromProps(t,n){return t.style?t.style[n]:void 0}removeValueFromRenderState(t,{vars:n,style:r}){delete n[t],delete r[t]}makeTargetAnimatableFromInstance({transition:t,transitionEnd:n,...r},{transformValues:o},s){let i=w4(r,t||{},this);if(o&&(n&&(n=o(n)),r&&(r=o(r)),i&&(i=o(i))),s){y4(this,r,i);const a=Z5(this,r,i,n);n=a.transitionEnd,r=a.target}return{transition:t,transitionEnd:n,...r}}}function nL(e){return window.getComputedStyle(e)}class rL extends Aw{readValueFromInstance(t,n){if(Gr.has(n)){const r=Pp(n);return r&&r.default||0}else{const r=nL(t),o=(p1(n)?r.getPropertyValue(n):r[n])||0;return typeof o=="string"?o.trim():o}}measureInstanceViewportBox(t,{transformPagePoint:n}){return pw(t,n)}build(t,n,r,o){xp(t,n,r,o.transformTemplate)}scrapeMotionValuesFromProps(t,n){return Ap(t,n)}handleChildMotionValue(){this.childSubscription&&(this.childSubscription(),delete this.childSubscription);const{children:t}=this.props;kt(t)&&(this.childSubscription=t.on("change",n=>{this.current&&(this.current.textContent=`${n}`)}))}renderInstance(t,n,r,o){x1(t,n,r,o)}}class oL extends Aw{constructor(){super(...arguments),this.isSVGTag=!1}getBaseTargetFromProps(t,n){return t[n]}readValueFromInstance(t,n){if(Gr.has(n)){const r=Pp(n);return r&&r.default||0}return n=w1.has(n)?n:bp(n),t.getAttribute(n)}measureInstanceViewportBox(){return $e()}scrapeMotionValuesFromProps(t,n){return C1(t,n)}build(t,n,r,o){Sp(t,n,r,this.isSVGTag,o.transformTemplate)}renderInstance(t,n,r,o){S1(t,n,r,o)}mount(t){this.isSVGTag=Cp(t.tagName),super.mount(t)}}const sL=(e,t)=>yp(e)?new oL(t,{enableHardwareAcceleration:!1}):new rL(t,{enableHardwareAcceleration:!0}),iL={layout:{ProjectionNode:ww,MeasureLayout:hw}},aL={...I4,...qP,...B5,...iL},Mp=lP((e,t)=>OP(e,t,aL,sL));function kw(){const e=w.useRef(!1);return sl(()=>(e.current=!0,()=>{e.current=!1}),[]),e}function lL(){const e=kw(),[t,n]=w.useState(0),r=w.useCallback(()=>{e.current&&n(t+1)},[t]);return[w.useCallback(()=>Le.postRender(r),[r]),t]}class cL extends w.Component{getSnapshotBeforeUpdate(t){const n=this.props.childRef.current;if(n&&t.isPresent&&!this.props.isPresent){const r=this.props.sizeRef.current;r.height=n.offsetHeight||0,r.width=n.offsetWidth||0,r.top=n.offsetTop,r.left=n.offsetLeft}return null}componentDidUpdate(){}render(){return this.props.children}}function uL({children:e,isPresent:t}){const n=w.useId(),r=w.useRef(null),o=w.useRef({width:0,height:0,top:0,left:0});return w.useInsertionEffect(()=>{const{width:s,height:i,top:a,left:l}=o.current;if(t||!r.current||!s||!i)return;r.current.dataset.motionPopId=n;const c=document.createElement("style");return document.head.appendChild(c),c.sheet&&c.sheet.insertRule(` + [data-motion-pop-id="${n}"] { + position: absolute !important; + width: ${s}px !important; + height: ${i}px !important; + top: ${a}px !important; + left: ${l}px !important; + } + `),()=>{document.head.removeChild(c)}},[t]),w.createElement(cL,{isPresent:t,childRef:r,sizeRef:o},w.cloneElement(e,{ref:r}))}const mu=({children:e,initial:t,isPresent:n,onExitComplete:r,custom:o,presenceAffectsLayout:s,mode:i})=>{const a=b1(dL),l=w.useId(),c=w.useMemo(()=>({id:l,initial:t,isPresent:n,custom:o,onExitComplete:d=>{a.set(d,!0);for(const f of a.values())if(!f)return;r&&r()},register:d=>(a.set(d,!1),()=>a.delete(d))}),s?void 0:[n]);return w.useMemo(()=>{a.forEach((d,f)=>a.set(f,!1))},[n]),w.useEffect(()=>{!n&&!a.size&&r&&r()},[n]),i==="popLayout"&&(e=w.createElement(uL,{isPresent:n},e)),w.createElement(sc.Provider,{value:c},e)};function dL(){return new Map}function fL(e){return w.useEffect(()=>()=>e(),[])}const qr=e=>e.key||"";function pL(e,t){e.forEach(n=>{const r=qr(n);t.set(r,n)})}function hL(e){const t=[];return w.Children.forEach(e,n=>{w.isValidElement(n)&&t.push(n)}),t}const mL=({children:e,custom:t,initial:n=!0,onExitComplete:r,exitBeforeEnter:o,presenceAffectsLayout:s=!0,mode:i="sync"})=>{const a=w.useContext(vp).forceRender||lL()[0],l=kw(),c=hL(e);let d=c;const f=w.useRef(new Map).current,p=w.useRef(d),h=w.useRef(new Map).current,v=w.useRef(!0);if(sl(()=>{v.current=!1,pL(c,h),p.current=d}),fL(()=>{v.current=!0,h.clear(),f.clear()}),v.current)return w.createElement(w.Fragment,null,d.map(m=>w.createElement(mu,{key:qr(m),isPresent:!0,initial:n?void 0:!1,presenceAffectsLayout:s,mode:i},m)));d=[...d];const x=p.current.map(qr),C=c.map(qr),g=x.length;for(let m=0;m{if(C.indexOf(y)!==-1)return;const S=h.get(y);if(!S)return;const A=x.indexOf(y);let L=m;if(!L){const _=()=>{h.delete(y),f.delete(y);const k=p.current.findIndex(M=>M.key===y);if(p.current.splice(k,1),!f.size){if(p.current=c,l.current===!1)return;a(),r&&r()}};L=w.createElement(mu,{key:qr(S),isPresent:!1,onExitComplete:_,custom:t,presenceAffectsLayout:s,mode:i},S),f.set(y,L)}d.splice(A,0,L)}),d=d.map(m=>{const y=m.key;return f.has(y)?m:w.createElement(mu,{key:qr(m),isPresent:!0,presenceAffectsLayout:s,mode:i},m)}),w.createElement(w.Fragment,null,f.size?d:d.map(m=>w.cloneElement(m)))};function gL(){for(var e=0,t,n,r="";ee&&(t=0,r=n,n=new Map)}return{get:function(i){var a=n.get(i);if(a!==void 0)return a;if((a=r.get(i))!==void 0)return o(i,a),a},set:function(i,a){n.has(i)?n.set(i,a):o(i,a)}}}var Tw="!";function bL(e){var t=e.separator||":",n=t.length===1,r=t[0],o=t.length;return function(i){for(var a=[],l=0,c=0,d,f=0;fc?d-c:void 0;return{modifiers:a,hasImportantModifier:v,baseClassName:x,maybePostfixModifierPosition:C}}}function AL(e){if(e.length<=1)return e;var t=[],n=[];return e.forEach(function(r){var o=r[0]==="[";o?(t.push.apply(t,n.sort().concat([r])),n=[]):n.push(r)}),t.push.apply(t,n.sort()),t}function kL(e){return{cache:CL(e.cacheSize),splitModifiers:bL(e),...vL(e)}}var EL=/\s+/;function RL(e,t){var n=t.splitModifiers,r=t.getClassGroupId,o=t.getConflictingClassGroupIds,s=new Set;return e.trim().split(EL).map(function(i){var a=n(i),l=a.modifiers,c=a.hasImportantModifier,d=a.baseClassName,f=a.maybePostfixModifierPosition,p=r(f?d.substring(0,f):d),h=!!f;if(!p){if(!f)return{isTailwindClass:!1,originalClassName:i};if(p=r(d),!p)return{isTailwindClass:!1,originalClassName:i};h=!1}var v=AL(l).join(":"),x=c?v+Tw:v;return{isTailwindClass:!0,modifierId:x,classGroupId:p,originalClassName:i,hasPostfixModifier:h}}).reverse().filter(function(i){if(!i.isTailwindClass)return!0;var a=i.modifierId,l=i.classGroupId,c=i.hasPostfixModifier,d=a+l;return s.has(d)?!1:(s.add(d),o(l,c).forEach(function(f){return s.add(a+f)}),!0)}).reverse().map(function(i){return i.originalClassName}).join(" ")}function TL(){for(var e=arguments.length,t=new Array(e),n=0;ne.reduce((n,r,o)=>n.concat(r||[],t[o]||[]),[]),KL=(e,t="")=>{let n=e.join(" ").trim().replace(/\n/g," ").replace(/\s{2,}/g," ").split(" ").filter(o=>o!==","),r=t?t.split(" "):[];return $L(...n.concat(r).filter(o=>o!==" "))},JL=([e])=>e.charAt(0)!=="$",gu=e=>e[Nw]===!0,Lw=e=>(t,...n)=>{let r=(o=[])=>{let s=V.forwardRef((i,a)=>{let{$as:l=e,style:c={},...d}=i,f=gu(e)?e:l,p=o?o.reduce((v,x)=>Object.assign(v,typeof x=="function"?x(i):x),{}):{},h=gu(f)?d:Object.fromEntries(Object.entries(d).filter(JL));return V.createElement(f,{...h,style:{...p,...c},ref:a,className:KL(GL(t,n.map(v=>v({...d,$as:l}))),d.className),...gu(e)?{$as:l}:{}})});return s[Nw]=!0,typeof e!="string"?s.displayName=e.displayName||e.name||"tw.Component":s.displayName="tw."+e,s.withStyle=i=>r(o.concat(i)),s};return r()},YL=HL.reduce((e,t)=>({...e,[t]:Lw(t)}),{}),ZL=Object.assign(Lw,YL),b=ZL;const _w="/assets/logo-f382c619.svg",QL="/assets/bg3-1869f4c7.svg",Op="/assets/bottom-890eee8a.svg",vu=b.span` + text-[#4771B7] +`,XL=b.button` + mt-10 + rounded-[20px] + text-[40px] + font-semibold + w-[220px] + h-[85px] + bg-[#4771B7] + text-[#FFFFFF] + transition duration-500 ease-in-out + hover:bg-[#6787BC] +`,qL=b.div` + font-semibold + text-[64px] +`,e_=b.div` + relative + w-[100vw] + h-[100vh] +`,t_=b.div` + h-full + flex flex-col justify-center + ml-[150px] +`,n_=b.div` + flex + flex-col + items-center + justify-center + absolute + left-[50%] + bottom-5 + translate-x-[-50%] +`,r_=b.span` + font-semibold + text-[25px] + mb-[10px] +`;function o_(){const e=qe(),t=()=>{e("/home")};return u.jsxs(e_,{id:"page1",children:[u.jsx("img",{src:QL,className:"absolute bg-cover w-[40vw] h-[100vh] object-cover rounded-l-full top-0 right-0"}),u.jsx("img",{src:_w,className:"z-0 absolute w-[200px] left-7 top-5"}),u.jsxs(t_,{children:[u.jsxs(qL,{children:["๋‹ค์–‘ํ•œ ",u.jsx(vu,{children:"๋ ˆ์ € ์„œ๋น„์Šค"}),"๋ฅผ ",u.jsx("br",{}),u.jsx(vu,{children:"์—ฐ๊ฒฐ"}),"ํ•ด์ฃผ๋Š”",u.jsx("br",{})," ",u.jsx(vu,{children:"์•กํ‹ฐ์˜จ"}),"์ž…๋‹ˆ๋‹ค."]}),u.jsx(XL,{onClick:t,children:"์‹œ์ž‘ํ•˜๊ธฐ"})]}),u.jsxs(n_,{children:[u.jsx(r_,{children:"์—‘ํ‹ฐ์˜จ ์•Œ์•„๋ณด๊ธฐ"}),u.jsx("a",{href:"#page2",children:u.jsx("img",{src:Op,className:"w-[80px] cursor-pointer animate-bounce duration-500 ease-in-out hover:w-[100px]"})})]})]})}const s_=({child:e})=>u.jsx(u.Fragment,{children:u.jsx("div",{className:"layout middle overflow-y-hidden",children:e})}),i_="/assets/activity-224a3acc.svg",Iw="/assets/top-4895b10f.svg",a_=b.div` + relative + bg-[#ECF1F8] + w-[100vw] + h-[100vh] + flex + flex-col + items-center + justify-center +`,l_=b.div` + font-semibold + text-[3rem] + text-[#4771B7] + my-[30px] +`,c_=b.p` + text-[30px] + mb-[30px] +`;function u_(){return u.jsxs(a_,{id:"page2",children:[u.jsx("a",{className:"absolute top-5 left-[50%] translate-x-[-50%] z-50",href:"#page1",children:u.jsx("img",{src:Iw,className:"w-[80px] animate-topbounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})}),u.jsx(l_,{"data-aos":"fade-up","data-aos-offset":"200","data-aos-easing":"ease-in-out","data-aos-duration":"1000",children:"์ œ์ฃผ๋„ ์ˆ˜์ƒ๋ ˆ์ €๋Š” ๋ชจ๋‘ ์—‘ํ‹ฐ์˜จ์œผ๋กœ"}),u.jsx(c_,{"data-aos":"fade-up","data-aos-delay":"500","data-aos-offset":"100","data-aos-easing":"ease-in-out","data-aos-duration":"1000",children:"๋ฌด๋”์šด ์—ฌ๋ฆ„ ์นœ๊ตฌ๋“ค๊ณผ ํ•จ๊ป˜ ์งœ๋ฆฟํ•œ ์ถ”์–ต์„ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”."}),u.jsx("img",{"data-aos":"zoom-in","data-aos-delay":"1000","data-aos-easing":"ease-in-out","data-aos-duration":"1000",src:i_,className:"w-[800px] h-[500px] mb-[20px]"}),u.jsx("a",{className:"absolute bottom-5 left-[50%] translate-x-[-50%] z-50",href:"#page3",children:u.jsx("img",{src:Op,className:"w-[80px] animate-bounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})})]})}const d_="/assets/page3-7ff6dd6c.svg",Bp="/assets/w_top-70b5cea1.svg",Mw="/assets/w_bottom-545fa504.svg",Dw=b.div` + relative + bg-[#4771B7] + w-[100vw] + h-[100vh] + flex + flex-col + items-center justify-center +`,Ow=b.div` + mb-10 + bg-[#4771B7] + w-full + h-full + flex + items-center + justify-around +`,Bw=b.div` + flex + flex-col + items-center +`,Vw=b.div` + text-[#FFFFFF] + text-[48px] + font-semibold + text-center + mb-[30px] +`,zw=b.p` + text-[#FFFFFF] + text-[32px] + mb-[30px] +`,Fw=b.button` + w-[330px] + h-[65px] + text-[25px] + font-medium + border + bg-white + text-center + rounded-[30px] + shadow-md + shadow-[#cdd2d8] + cursor-pointer +`;function f_(){const e=qe();return u.jsxs(Dw,{id:"page3",children:[u.jsx("a",{className:"absolute top-5 left-[50%] translate-x-[-50%] z-50",href:"#page2",children:u.jsx("img",{src:Bp,className:"w-[80px] animate-topbounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})}),u.jsxs(Ow,{children:[u.jsx("img",{src:d_,"data-aos":"fade-right","data-aos-easing":"ease-in-out","data-aos-duration":"1000",className:"w-[600px] h-[700px] mt-10"}),u.jsxs(Bw,{children:[u.jsxs(Vw,{"data-aos":"fade-down","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",children:["์ œ์ฃผ๋„์˜ ๋ชจ๋“  ๋ ˆ์ €๋ฅผ",u.jsx("br",{})," ์ง€๋„๋กœ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ™•์ธํ•ด ๋ณด์„ธ์š” !"]}),u.jsx(zw,{"data-aos":"flip-right","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",children:"์ถ”์ฒœ์ƒํ’ˆ๋„ ๋†“์น˜์ง€ ๋ง๊ณ  ํ™•์ธํ•ด ๋ณด์„ธ์š” ."}),u.jsx(Fw,{"data-aos":"flip-right","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",onClick:()=>e("/home"),children:"ํ™ˆ์œผ๋กœ ์ด๋™ํ•˜๊ธฐ"})]})]}),u.jsx("a",{className:"absolute bottom-5 left-[50%] translate-x-[-50%] z-50",href:"#page4",children:u.jsx("img",{src:Mw,className:"w-[80px] mb-[15px] animate-bounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})})]})}const p_="/assets/page4(2)-7dac419e.svg",h_=b.div` + relative + bg-[#ECF1F8] + w-[100vw] + h-[100vh] + flex + flex-col + items-center +`,m_=b.div` + bg-[#ECF1F8] + w-full + h-[100vh] + flex + items-center + justify-around +`,g_=b.div` + flex + flex-col + items-center +`,v_=b.div` + text-[#4771B7] + text-[48px] + font-semibold + text-center + mb-[67px] +`,y_=b.p` + text-[32px] + mb-[67px] + text-center +`,x_=b.button` + w-[330px] + h-[65px] + text-[25px] + font-medium + border + shadow-md + shadow-[#8F9296] + bg-white + text-center + rounded-[30px] + cursor-pointer +`;function w_(){const e=qe();return u.jsxs(h_,{id:"page4",children:[u.jsx("a",{className:"absolute top-5 left-[50%] translate-x-[-50%] z-50",href:"#page3",children:u.jsx("img",{src:Iw,className:"w-[80px] mt-[15px] animate-topbounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})}),u.jsxs(m_,{children:[u.jsxs(g_,{children:[u.jsxs(v_,{children:["์ฆ๊ธฐ๊ณ  ์‹ถ์€ ๋ ˆ์ €๋ฅผ ๊ณ ๋ฅด๊ณ ",u.jsx("br",{}),"์˜ˆ์•ฝํ•˜๊ณ  ๊ฒฐ์ œ๊นŒ์ง€ ์ง„ํ–‰ํ•ด ๋ณด์„ธ์š” !"]}),u.jsxs(y_,{children:["๋งˆ์Œ์— ๋“œ๋Š” ์—…์ฒด๋Š” ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ๋‹ด์•„๋‘๊ณ ",u.jsx("br",{}),"ํ•œ๋ˆˆ์— ๋น„๊ตํ•ด ๋ณด์„ธ์š” !"]}),u.jsx(x_,{onClick:()=>e("/home"),children:"์—…์ฒด ๋ณด๋Ÿฌ๊ฐ€๊ธฐ"})]}),u.jsx("img",{src:p_,"data-aos":"fade-left","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",className:"w-[600px] h-[650px]"})]}),u.jsx("a",{className:"absolute bottom-5 left-[50%] translate-x-[-50%] z-50",href:"#page5",children:u.jsx("img",{src:Op,className:"w-[80px] mt-[5px] animate-bounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})})]})}const S_="/assets/page5-abd4f884.svg";function C_(){const e=qe();return u.jsxs(Dw,{id:"page5",children:[u.jsx("a",{className:"absolute top-5 left-[50%] translate-x-[-50%] z-50",href:"#page4",children:u.jsx("img",{src:Bp,className:"w-[80px] mt-[15px] animate-topbounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})}),u.jsxs(Ow,{children:[u.jsx("img",{src:S_,"data-aos":"fade-right","data-aos-easing":"ease-in-out","data-aos-duration":"1000",className:"w-[600px] h-[650px]"}),u.jsxs(Bw,{children:[u.jsxs(Vw,{"data-aos":"fade-down","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",children:["๋‹ค์–‘ํ•œ ๊ฒฐ์ œ ๋ฐฉ์‹์œผ๋กœ",u.jsx("br",{})," ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ฒฐ์ œ๋ฅผ ์ง„ํ–‰ํ•ด ๋ณด์„ธ์š” !"]}),u.jsx(zw,{"data-aos":"flip-right","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",children:"๊ฒฐ์ œ ์™„๋ฃŒ ํ›„ ์˜ˆ์•ฝ๋‚ด์—ญ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”."}),u.jsx(Fw,{"data-aos":"flip-right","data-aos-delay":"500","data-aos-easing":"ease-in-out","data-aos-duration":"1000",onClick:()=>e("/home"),children:"์—‘ํ‹ฐ์˜จ ์‹œ์ž‘ํ•˜๊ธฐ"})]})]}),u.jsxs("div",{className:"flex flex-col items-center mb-[10px] absolute bottom-5 left-[50%] translate-x-[-50%] z-50",children:[u.jsx("div",{className:"font-medium text-white text-[18px] ml-1",children:"๋‹ค์‹œ ๊ฐ์ƒํ•˜๋ ค๋ฉด ๋ˆ„๋ฅด์„ธ์š”!"}),u.jsx("a",{href:"#page1",children:u.jsx("img",{src:Mw,className:"w-[80px] mt-[5px] animate-bounce cursor-pointer duration-500 ease-in-out hover:w-[100px]"})})]})]})}const b_=()=>u.jsx(s_,{child:u.jsxs(A_,{children:[u.jsx(o_,{}),u.jsx(u_,{}),u.jsx(f_,{}),u.jsx(w_,{}),u.jsx(C_,{})]})}),A_=b.div` + pt-60px + overflow-hidden +`;var Uw={color:void 0,size:void 0,className:void 0,style:void 0,attr:void 0},Ug=V.createContext&&V.createContext(Uw),nr=globalThis&&globalThis.__assign||function(){return nr=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0||(o[n]=e[n]);return o}const je=typeof window<"u"&&typeof document<"u"?w.useLayoutEffect:w.useEffect,re=(e,t,n)=>{je(()=>{if(!e||!n)return;const r=(...o)=>o===void 0?n(e):n(e,...o);return kakao.maps.event.addListener(e,t,r),()=>{kakao.maps.event.removeListener(e,t,r)}},[e,t,n])};var hn;(function(e){e[e.INITIALIZED=0]="INITIALIZED",e[e.LOADING=1]="LOADING",e[e.SUCCESS=2]="SUCCESS",e[e.FAILURE=3]="FAILURE"})(hn||(hn={}));let ml=class dt{constructor({appkey:t,id:n="__reactKakaoMapsSdkloaderId",libraries:r=[],nonce:o,retries:s=3,url:i="//dapi.kakao.com/v2/maps/sdk.js"}){if(this.id=void 0,this.appkey=void 0,this.url=void 0,this.libraries=void 0,this.nonce=void 0,this.retries=void 0,this.callbacks=[],this.done=!1,this.loading=!1,this.errors=[],this.onerrorEvent=void 0,this.id=n,this.appkey=t,this.libraries=r,this.nonce=o,this.retries=s,this.url=i,dt.instance){if(!dt.equalOptions(this.options,dt.instance.options))throw new Error(`Loader must not be called again with different options. ${JSON.stringify(this.options)} !== ${JSON.stringify(dt.instance.options)}`);return dt.instance}dt.instance=this}get options(){return{appkey:this.appkey,id:this.id,libraries:this.libraries,nonce:this.nonce,retries:this.retries,url:this.url}}static isLoaded(){return new Promise(t=>dt.instance?dt.instance.status===hn.FAILURE||dt.instance.status===hn.INITIALIZED?t(!1):(dt.instance.status===hn.LOADING&&dt.loadcheckcallbacks.push(n=>t(!n)),t(!0)):window.kakao&&window.kakao.maps?window.kakao.maps.load(()=>{t(!0)}):dt.loadcheckcallbacks.push(n=>{t(!n)}))}load(){return new Promise((t,n)=>{this.loadCallback(r=>{r?n(r.error):t(window.kakao)})})}get status(){return this.onerrorEvent?hn.FAILURE:this.done?hn.SUCCESS:this.loading?hn.LOADING:hn.INITIALIZED}get failed(){return this.done&&!this.loading&&this.errors.length>=this.retries+1}loadCallback(t){this.callbacks.push(t),this.execute()}resetIfRetryingFailed(){this.failed&&this.reset()}reset(){this.deleteScript(),this.done=!1,this.loading=!1,this.errors=[],this.onerrorEvent=void 0}execute(){if(this.resetIfRetryingFailed(),this.done)this.callback();else{if(window.kakao&&window.kakao.maps)return console.warn("Kakao Maps์ด ์ด๋ฏธ ์™ธ๋ถ€ ์š”์†Œ์— ์˜ํ•ด ๋กœ๋”ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.์„ค์ •ํ•œ ์˜ต์…˜๊ณผ ์ผ์น˜ ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด์— ๋”ฐ๋ฅธ ์˜ˆ์ƒ์น˜ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."),void window.kakao.maps.load(this.callback);this.loading||(this.loading=!0,this.setScript())}}setScript(){document.getElementById(this.id)&&this.callback();const t=this.createUrl(),n=document.createElement("script");n.id=this.id,n.type="text/javascript",n.src=t,n.onerror=this.loadErrorCallback.bind(this),n.onload=this.callback.bind(this),n.defer=!0,n.async=!0,this.nonce&&(n.nonce=this.nonce),document.head.appendChild(n)}loadErrorCallback(t,n,r,o,s){if(this.errors.push({event:t,source:n,lineno:r,colno:o,error:s}),this.errors.length<=this.retries){const i=this.errors.length*2**this.errors.length;console.log(`Failed to load Kakao Maps script, retrying in ${i} ms.`),setTimeout(()=>{this.deleteScript(),this.setScript()},i)}else this.onerrorEvent=this.errors[this.errors.length-1],this.callback()}createUrl(){let t=this.url;return t+=`?appkey=${this.appkey}`,this.libraries.length&&(t+=`&libraries=${this.libraries.join(",")}`),t+="&autoload=false",t}deleteScript(){const t=document.getElementById(this.id);t&&t.remove()}callback(){kakao.maps.load(()=>{this.done=!0,this.loading=!1,this.callbacks.forEach(t=>{t(this.onerrorEvent)}),this.callbacks=[],dt.loadcheckcallbacks.forEach(t=>{t(this.onerrorEvent)}),dt.loadcheckcallbacks=[]})}static equalOptions(t,n){if(t.appkey!==n.appkey||t.id!==n.id||t.libraries.length!==n.libraries.length)return!1;for(let r=0;r{let{id:n,as:r,children:o,center:s,isPanto:i=!1,padding:a=32,disableDoubleClick:l,disableDoubleClickZoom:c,draggable:d,zoomable:f,keyboardShortcuts:p,level:h,maxLevel:v,minLevel:x,mapTypeId:C,projectionId:g,scrollwheel:m,tileAnimation:y,onBoundsChanged:S,onCenterChanged:A,onClick:L,onDoubleClick:_,onDrag:k,onDragEnd:M,onDragStart:I,onIdle:T,onMaptypeidChanged:O,onMouseMove:N,onRightClick:D,onTileLoaded:H,onZoomChanged:Z,onZoomStart:ne,onCreate:z}=e,W=Kw(e,P_);const q=r||"div",[X,R]=w.useState(!1),[j,B]=w.useState(),J=w.useRef(null);return je(()=>{ml.isLoaded().then(R)},[]),je(()=>{if(!X)return;const $=J.current;if(!$)return;const te="lat"in s?new kakao.maps.LatLng(s.lat,s.lng):new kakao.maps.Coords(s.x,s.y),le=new kakao.maps.Map($,{center:te,disableDoubleClick:l,disableDoubleClickZoom:c,draggable:d,keyboardShortcuts:p,level:h,mapTypeId:C,projectionId:g,scrollwheel:m,tileAnimation:y});return B(le),()=>{$.innerHTML=""}},[X,l,c,C,y]),w.useImperativeHandle(t,()=>j,[j]),je(()=>{j&&z&&z(j)},[j,z]),je(()=>{if(!j)return;let $=j.getCenter();$ instanceof kakao.maps.Coords&&($=$.toLatLng());const te="lat"in s?new kakao.maps.LatLng(s.lat,s.lng):new kakao.maps.Coords(s.x,s.y);te instanceof kakao.maps.LatLng&&te.equals($)||te instanceof kakao.maps.Coords&&te.toLatLng().equals($)||(i?j.panTo(te,a):j.setCenter(te))},[j,s.lat,s.lng,s.x,s.y]),je(()=>{j&&d!==void 0&&j.setDraggable(d)},[j,d]),je(()=>{j&&f!==void 0&&j.setZoomable(f)},[j,f]),je(()=>{j&&p&&typeof p=="boolean"&&j.setKeyboardShortcuts(p)},[j,p]),je(()=>{j&&h&&j.setLevel(h)},[j,h]),je(()=>{j&&C&&j.setMapTypeId(C)},[j,C]),je(()=>{j&&g&&j.setProjectionId(g)},[j,g]),je(()=>{j&&v&&j.setMaxLevel(v)},[j,v]),je(()=>{j&&x&&j.setMinLevel(x)},[j,x]),re(j,"bounds_changed",S),re(j,"center_changed",A),re(j,"click",L),re(j,"dblclick",_),re(j,"drag",k),re(j,"dragstart",I),re(j,"dragend",M),re(j,"idle",T),re(j,"maptypeid_changed",O),re(j,"mousemove",N),re(j,"rightclick",D),re(j,"tilesloaded",H),re(j,"zoom_changed",Z),re(j,"zoom_start",ne),V.createElement(V.Fragment,null,V.createElement(q,Bo({id:n||"react-kakao-maps-sdk-map-container"},W,{ref:J})),j&&V.createElement(Jw.Provider,{value:j},o))}),Rt=e=>{const t=w.useContext(Jw);if(!t)throw new Error((e?e+" Component":"useMap")+" must exist inside Map Component!");return t},Vp=V.forwardRef(({map:e,position:t,marker:n,children:r,altitude:o,disableAutoPan:s,range:i,removable:a,zIndex:l,onCreate:c},d)=>{const f=w.useRef(document.createElement("div")),p=w.useMemo(()=>{const h=new kakao.maps.InfoWindow({altitude:o,disableAutoPan:s,range:i,removable:a,zIndex:l,content:f.current,position:t});return f.current.style.display="none",h},[s,a]);return w.useImperativeHandle(d,()=>p,[p]),w.useLayoutEffect(()=>(p.open(e,n),()=>{p.close()}),[e,n]),w.useLayoutEffect(()=>{c&&c(p)},[p,c]),w.useLayoutEffect(()=>{p&&p.setPosition(t)},[p,t]),w.useLayoutEffect(()=>{p&&o&&p.setAltitude(o)},[p,o]),w.useLayoutEffect(()=>{p&&i&&p.setRange(i)},[p,i]),w.useLayoutEffect(()=>{p&&l&&p.setZIndex(l)},[p,l]),f.current.parentElement&&Ml.createPortal(r,f.current.parentElement)}),zp=V.createContext(void 0);V.forwardRef(({children:e,averageCenter:t,calculator:n,clickable:r,disableClickZoom:o,gridSize:s,hoverable:i,minClusterSize:a,minLevel:l,styles:c,texts:d,onClusterclick:f,onClusterdblclick:p,onClustered:h,onClusterout:v,onClusterover:x,onClusterrightclick:C,onCreate:g},m)=>{const y=Rt("MarkerClusterer"),S=w.useMemo(()=>{if(window.kakao.maps.MarkerClusterer)return new kakao.maps.MarkerClusterer({averageCenter:t,calculator:n,clickable:r,disableClickZoom:o,gridSize:s,hoverable:i,minClusterSize:a,minLevel:l,styles:c,texts:d});console.warn("clusterer ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ณ„๋„ ๋กœ๋“œ ํ•ด์•ผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. `https://apis.map.kakao.com/web/guide/#loadlibrary`")},[]);return w.useImperativeHandle(m,()=>S,[S]),w.useLayoutEffect(()=>{S==null||S.setMap(y)},[y,S]),w.useLayoutEffect(()=>{S&&g&&g(S)},[S,g]),w.useLayoutEffect(()=>{S&&s&&(S.setGridSize(s),S.redraw())},[S,s]),w.useLayoutEffect(()=>{S&&a&&(S.setMinClusterSize(a),S.redraw())},[S,a]),w.useLayoutEffect(()=>{S&&t!==void 0&&(S.setAverageCenter(t),S.redraw())},[S,t]),w.useLayoutEffect(()=>{S&&l&&(S.setMinLevel(l),S.redraw())},[S,l]),w.useLayoutEffect(()=>{S&&d&&(S.setTexts(d),S.redraw())},[S,d]),w.useLayoutEffect(()=>{S&&n&&(S.setCalculator(n),S.redraw())},[S,n]),w.useLayoutEffect(()=>{S&&c&&(S.setStyles(c),S.redraw())},[S,c]),re(S,"clusterclick",f),re(S,"clusterover",x),re(S,"clusterout",v),re(S,"clusterdblclick",p),re(S,"clusterrightclick",C),re(S,"clustered",h),S?V.createElement(zp.Provider,{value:S},e):null});const Zw=V.forwardRef(({map:e,position:t,children:n,altitude:r,clickable:o,draggable:s,image:i,infoWindowOptions:a,onCreate:l,onClick:c,onDragEnd:d,onDragStart:f,onMouseOut:p,onMouseOver:h,opacity:v,range:x,title:C,zIndex:g},m)=>{const y=w.useContext(zp),S=w.useMemo(()=>new kakao.maps.Marker({altitude:r,clickable:o,draggable:s,image:i,opacity:v,range:x,title:C,zIndex:g,position:t}),[]);return w.useImperativeHandle(m,()=>S,[S]),w.useLayoutEffect(()=>(y?y.addMarker(S):S.setMap(e),()=>{y?y.removeMarker(S):S.setMap(null)}),[e,y,S]),w.useLayoutEffect(()=>{l&&l(S)},[S,l]),re(S,"click",c),re(S,"dragstart",f),re(S,"dragend",d),re(S,"mouseout",p),re(S,"mouseover",h),w.useLayoutEffect(()=>{e&&S&&t&&S.setPosition(t)},[e,S,t]),w.useLayoutEffect(()=>{e&&S&&i&&S.setImage(i)},[e,S,i]),w.useLayoutEffect(()=>{e&&S&&r&&S.setAltitude(r)},[e,S,r]),w.useLayoutEffect(()=>{e&&S&&o!==void 0&&S.setClickable(o)},[e,S,o]),w.useLayoutEffect(()=>{e&&S&&s!==void 0&&S.setDraggable(s)},[e,S,s]),w.useLayoutEffect(()=>{e&&S&&v&&S.setOpacity(v)},[e,S,v]),w.useLayoutEffect(()=>{e&&S&&x&&S.setRange(x)},[e,S,x]),w.useLayoutEffect(()=>{e&&S&&C&&S.setTitle(C)},[e,S,C]),w.useLayoutEffect(()=>{e&&S&&g&&S.setZIndex(g)},[e,S,g]),n?V.createElement(Vp,{position:t,map:e,marker:S,altitude:a==null?void 0:a.altitude,disableAutoPan:a==null?void 0:a.disableAutoPan,range:a==null?void 0:a.range,removable:a==null?void 0:a.removable,zIndex:a==null?void 0:a.zIndex},n):null}),Qw=V.forwardRef(({image:e,position:t,children:n,clickable:r,draggable:o,infoWindowOptions:s,onClick:i,onDragEnd:a,onDragStart:l,onMouseOut:c,onMouseOver:d,onCreate:f,opacity:p,title:h,zIndex:v},x)=>{const C=Rt("MapMarker"),g=w.useMemo(()=>{var y,S,A,L,_,k,M,I,T,O,N,D;return e&&new kakao.maps.MarkerImage(e.src,new kakao.maps.Size(e.size.width,e.size.height),{alt:(y=e.options)==null?void 0:y.alt,coords:(S=e.options)==null?void 0:S.coords,offset:((A=e.options)==null?void 0:A.offset)&&new kakao.maps.Point((L=e.options)==null?void 0:L.offset.x,(_=e.options)==null?void 0:_.offset.y),shape:(k=e.options)==null?void 0:k.shape,spriteOrigin:((M=e.options)==null?void 0:M.spriteOrigin)&&new kakao.maps.Point((I=e.options)==null?void 0:I.spriteOrigin.x,(T=e.options)==null?void 0:T.spriteOrigin.y),spriteSize:((O=e.options)==null?void 0:O.spriteSize)&&new kakao.maps.Size((N=e.options)==null?void 0:N.spriteSize.width,(D=e.options)==null?void 0:D.spriteSize.height)})},[e]),m=w.useMemo(()=>"lat"in t?new kakao.maps.LatLng(t.lat,t.lng):new kakao.maps.Coords(t.x,t.y).toLatLng(),[t.lat,t.lng,t.x,t.y]);return V.createElement(Zw,{map:C,position:m,image:g,clickable:r,draggable:o,infoWindowOptions:s,onClick:i,onDragEnd:a,onDragStart:l,onMouseOut:c,onMouseOver:d,onCreate:f,opacity:p,title:h,zIndex:v,ref:x},n)});V.forwardRef(({position:e,children:t,disableAutoPan:n,removable:r,zIndex:o,onCreate:s},i)=>{const a=Rt("MapInfoWindow"),l=w.useMemo(()=>new kakao.maps.LatLng(e.lat,e.lng),[e.lat,e.lng]);return V.createElement(Vp,{disableAutoPan:n,removable:r,zIndex:o,map:a,position:l,onCreate:s,ref:i},t)});const N_=V.forwardRef(({position:e,children:t,clickable:n,xAnchor:r,yAnchor:o,zIndex:s,onCreate:i},a)=>{const l=w.useContext(zp),c=Rt("CustomOverlayMap"),d=w.useRef(document.createElement("div")),f=w.useMemo(()=>new kakao.maps.LatLng(e.lat,e.lng),[e.lat,e.lng]),p=w.useMemo(()=>{const h=new kakao.maps.CustomOverlay({clickable:n,xAnchor:r,yAnchor:o,zIndex:s,position:f,content:d.current});return d.current.style.display="none",h},[n,r,o]);return w.useImperativeHandle(a,()=>p,[p]),w.useLayoutEffect(()=>{if(c)return l?l.addMarker(p):p.setMap(c),()=>{l?l.removeMarker(p):p.setMap(null)}},[c,l,p]),w.useLayoutEffect(()=>{i&&i(p)},[p,i]),w.useLayoutEffect(()=>{p.setPosition(f)},[p,f]),w.useLayoutEffect(()=>{s&&p.setZIndex(s)},[p,s]),d.current.parentElement&&Ml.createPortal(t,d.current.parentElement)}),Xw=V.forwardRef(({position:e=kakao.maps.ControlPosition.TOPRIGHT},t)=>{const n=Rt("MapTypeControl"),r=w.useMemo(()=>new kakao.maps.MapTypeControl,[]);return w.useImperativeHandle(t,()=>r,[r]),w.useLayoutEffect(()=>(n.addControl(r,e),()=>{n.removeControl(r)}),[n,r,e]),null}),qw=V.forwardRef(({position:e=kakao.maps.ControlPosition.RIGHT},t)=>{const n=Rt("ZoomControl"),r=w.useMemo(()=>new kakao.maps.ZoomControl,[]);return w.useImperativeHandle(t,()=>r,[r]),w.useEffect(()=>(n.addControl(r,e),()=>{n.removeControl(r)}),[n,e]),null});V.forwardRef(({center:e,radius:t,fillColor:n,fillOpacity:r,strokeColor:o,strokeOpacity:s,strokeStyle:i,strokeWeight:a,zIndex:l,onMouseover:c,onMouseout:d,onMousemove:f,onMousedown:p,onClick:h,onCreate:v},x)=>{const C=Rt("Circle"),g=w.useMemo(()=>new kakao.maps.LatLng(e.lat,e.lng),[e.lat,e.lng]),m=w.useMemo(()=>new kakao.maps.Circle({center:g,radius:t,fillColor:n,fillOpacity:r,strokeColor:o,strokeOpacity:s,strokeStyle:i,strokeWeight:a,zIndex:l}),[]);return w.useImperativeHandle(x,()=>m,[m]),w.useLayoutEffect(()=>(m.setMap(C),()=>{m.setMap(null)}),[C,m]),w.useLayoutEffect(()=>{v&&v(m)},[m,v]),w.useLayoutEffect(()=>{m&&m.setPosition(g)},[m,g]),w.useLayoutEffect(()=>{m.setRadius(t)},[m,t]),w.useLayoutEffect(()=>{l&&m.setZIndex(l)},[m,l]),w.useLayoutEffect(()=>{m.setOptions({fillColor:n,fillOpacity:r,strokeColor:o,strokeOpacity:s,strokeStyle:i,strokeWeight:a})},[m,n,r,o,s,i,a]),re(m,"mouseover",c),re(m,"mouseout",d),re(m,"mousemove",f),re(m,"mousedown",p),re(m,"click",h),null});V.forwardRef(({path:e,endArrow:t,onClick:n,onMousedown:r,onMousemove:o,onMouseout:s,onMouseover:i,onCreate:a,strokeColor:l,strokeOpacity:c,strokeStyle:d,strokeWeight:f,zIndex:p},h)=>{const v=Rt("Polyline"),x=w.useMemo(()=>e.every(g=>g instanceof Array)?e.map(g=>g.map(m=>new kakao.maps.LatLng(m.lat,m.lng))):e.map(g=>new kakao.maps.LatLng(g.lat,g.lng)),[e]),C=w.useMemo(()=>new kakao.maps.Polyline({path:x,endArrow:t,strokeColor:l,strokeOpacity:c,strokeStyle:d,strokeWeight:f,zIndex:p}),[]);return w.useImperativeHandle(h,()=>C,[C]),w.useLayoutEffect(()=>(C.setMap(v),()=>C.setMap(null)),[v,C]),w.useLayoutEffect(()=>{a&&a(C)},[C,a]),w.useLayoutEffect(()=>{C.setOptions({endArrow:t,strokeColor:l,strokeOpacity:c,strokeStyle:d,strokeWeight:f})},[C,t,l,c,d,f]),w.useLayoutEffect(()=>{C.setPath(x)},[C,x]),w.useLayoutEffect(()=>{p&&C.setZIndex(p)},[C,p]),re(C,"mouseover",i),re(C,"mouseout",s),re(C,"mousemove",o),re(C,"mousedown",r),re(C,"click",n),null});V.forwardRef(({path:e,onClick:t,onMousedown:n,onMousemove:r,onMouseout:o,onMouseover:s,onCreate:i,strokeColor:a,strokeOpacity:l,strokeStyle:c,strokeWeight:d,fillColor:f,fillOpacity:p,zIndex:h},v)=>{const x=Rt("Polygon"),C=w.useMemo(()=>e.every(m=>m instanceof Array)?e.map(m=>m.map(y=>new kakao.maps.LatLng(y.lat,y.lng))):e.map(m=>new kakao.maps.LatLng(m.lat,m.lng)),[e]),g=w.useMemo(()=>new kakao.maps.Polygon({path:C,fillColor:f,fillOpacity:p,strokeColor:a,strokeOpacity:l,strokeStyle:c,strokeWeight:d,zIndex:h}),[]);return w.useImperativeHandle(v,()=>g,[g]),w.useLayoutEffect(()=>(g.setMap(x),()=>g.setMap(null)),[x,g]),w.useLayoutEffect(()=>{i&&i(g)},[g,i]),w.useLayoutEffect(()=>{g.setOptions({fillColor:f,fillOpacity:p,strokeColor:a,strokeOpacity:l,strokeStyle:c,strokeWeight:d})},[g,f,p,a,l,c,d]),w.useLayoutEffect(()=>{g.setPath(C)},[g,C]),w.useLayoutEffect(()=>{h&&g.setZIndex(h)},[g,h]),re(g,"mouseover",s),re(g,"mouseout",o),re(g,"mousemove",r),re(g,"mousedown",n),re(g,"click",t),null});V.forwardRef(({bounds:e,onClick:t,onMousedown:n,onMousemove:r,onMouseout:o,onMouseover:s,onCreate:i,strokeColor:a,strokeOpacity:l,strokeStyle:c,strokeWeight:d,fillColor:f,fillOpacity:p,zIndex:h},v)=>{const x=Rt("Rectangle"),C=w.useMemo(()=>new kakao.maps.LatLngBounds(new kakao.maps.LatLng(e.sw.lat,e.sw.lng),new kakao.maps.LatLng(e.ne.lat,e.ne.lng)),[e]),g=w.useMemo(()=>new kakao.maps.Rectangle({bounds:C,fillColor:f,fillOpacity:p,strokeColor:a,strokeOpacity:l,strokeStyle:c,strokeWeight:d,zIndex:h}),[]);return w.useImperativeHandle(v,()=>g,[g]),w.useLayoutEffect(()=>(g.setMap(x),()=>g.setMap(null)),[x,g]),w.useLayoutEffect(()=>{i&&i(g)},[g,i]),w.useLayoutEffect(()=>{g.setOptions({fillColor:f,fillOpacity:p,strokeColor:a,strokeOpacity:l,strokeStyle:c,strokeWeight:d})},[g,f,p,a,l,c,d]),w.useLayoutEffect(()=>{g.setBounds(C)},[g,C]),w.useLayoutEffect(()=>{h&&g.setZIndex(h)},[g,h]),re(g,"mouseover",s),re(g,"mouseout",o),re(g,"mousemove",r),re(g,"mousedown",n),re(g,"click",t),null});V.forwardRef(({center:e,rx:t,ry:n,fillColor:r,fillOpacity:o,strokeColor:s,strokeOpacity:i,strokeStyle:a,strokeWeight:l,zIndex:c,onMouseover:d,onMouseout:f,onMousemove:p,onMousedown:h,onClick:v,onCreate:x},C)=>{const g=Rt("Ellipse"),m=w.useMemo(()=>new kakao.maps.LatLng(e.lat,e.lng),[e.lat,e.lng]),y=w.useMemo(()=>new kakao.maps.Ellipse({center:m,rx:t,ry:n,fillColor:r,fillOpacity:o,strokeColor:s,strokeOpacity:i,strokeStyle:a,strokeWeight:l,zIndex:c}),[]);return w.useImperativeHandle(C,()=>y,[y]),w.useLayoutEffect(()=>(y.setMap(g),()=>{y.setMap(null)}),[g,y]),w.useLayoutEffect(()=>{x&&x(y)},[y,x]),w.useLayoutEffect(()=>{y&&y.setPosition(m)},[y,m]),w.useLayoutEffect(()=>{y.setRadius(t,n)},[y,t,n]),w.useLayoutEffect(()=>{c&&y.setZIndex(c)},[y,c]),w.useLayoutEffect(()=>{y.setOptions({fillColor:r,fillOpacity:o,strokeColor:s,strokeOpacity:i,strokeStyle:a,strokeWeight:l})},[y,r,o,s,i,a,l]),re(y,"mouseover",d),re(y,"mouseout",f),re(y,"mousemove",p),re(y,"mousedown",h),re(y,"click",v),null});V.forwardRef(({draw:e,onAdd:t,onRemove:n,onCreate:r},o)=>{const s=Rt(),i=w.useMemo(()=>{class a extends kakao.maps.AbstractOverlay{constructor(c,d,f){super(),this.draw=c,this.onAdd=d,this.onRemove=f}}return new a(e,t,n)},[e,t,n]);return w.useImperativeHandle(o,()=>i,[i]),w.useLayoutEffect(()=>(i.setMap(s),()=>{i.setMap(null)}),[s,i]),w.useLayoutEffect(()=>{r&&r(i)},[i,r]),null});const L_=["id","as","children","position","pan","panoId","panoX","panoY","tilt","zoom","onCreate","onInit","onPanoidChange","onPositionChanged","onViewpointChange","onErrorGetNearestPanoId"],eS=V.createContext(void 0);V.forwardRef((e,t)=>{let{id:n,as:r,children:o,position:s,pan:i,panoId:a,panoX:l,panoY:c,tilt:d,zoom:f,onCreate:p,onInit:h,onPanoidChange:v,onPositionChanged:x,onViewpointChange:C,onErrorGetNearestPanoId:g}=e,m=Kw(e,L_);const y=r||"div",[S,A]=w.useState(!1),[L,_]=w.useState(!0),[k,M]=w.useState(),I=w.useRef(null);return je(()=>{ml.isLoaded().then(A)},[]),je(()=>{if(!S)return;const T=I.current;if(!T)return;const O=new kakao.maps.Roadview(T,{pan:i,panoId:a,panoX:l,panoY:c,tilt:d,zoom:f});return M(O),()=>{T.innerHTML=""}},[S,l,c,f]),w.useImperativeHandle(t,()=>k,[k]),je(()=>{k&&p&&p(k)},[k,p]),je(()=>{if(!k||a||k.getPosition().getLat()===s.lat&&k.getPosition().getLng()===s.lng)return;const T=new kakao.maps.LatLng(s.lat,s.lng);new kakao.maps.RoadviewClient().getNearestPanoId(T,s.radius,O=>{O===null&&g?g(k):k.setPanoId(O,T)})},[k,a,s.lat,s.lng,s.radius,g]),je(()=>{if(!k||!a||a===k.getPanoId()||k.getPosition().getLat()===s.lat&&k.getPosition().getLng()===s.lng)return;const T=new kakao.maps.LatLng(s.lat,s.lng);k.setPanoId(a,T)},[k,a,s.lat,s.lng]),je(()=>{if(!k)return;const T=k.getViewpoint();T.pan===i&&T.tilt===d||(i&&(T.pan=i),d&&(T.tilt=d),k.setViewpoint(T))},[k,i,d]),re(k,"init",T=>{_(!1),h&&h(T)}),re(k,"panoid_changed",v),re(k,"viewpoint_changed",C),re(k,"position_changed",x),V.createElement(V.Fragment,null,V.createElement(y,Bo({ref:I,id:n||"react-kakao-maps-sdk-roadview-container"},m)),k&&!L&&V.createElement(eS.Provider,{value:k},o))});const Fp=e=>{const t=w.useContext(eS);if(!t)throw new Error((e?e+" Component":"useRoadview")+" must exist inside Roadview Component!");return t};V.forwardRef(({position:e,children:t,clickable:n,xAnchor:r,yAnchor:o,zIndex:s,altitude:i,range:a,onCreate:l},c)=>{const d=Fp("CustomOverlayRoadview"),f=w.useRef(document.createElement("div")),p=w.useMemo(()=>"lat"in e?new kakao.maps.LatLng(e.lat,e.lng):new kakao.maps.Viewpoint(e.pan,e.tilt,e.zoom,e.panoId),[e.lat,e.lng,e.pan,e.tilt,e.zoom,e.panoId]),h=w.useMemo(()=>{const v=new kakao.maps.CustomOverlay({clickable:n,xAnchor:r,yAnchor:o,zIndex:s,position:p,content:f.current});return f.current.style.display="none",v},[n,r,o]);return w.useImperativeHandle(c,()=>h,[h]),w.useLayoutEffect(()=>{if(d)return h.setMap(d),()=>{h.setMap(null)}},[h,d]),w.useLayoutEffect(()=>{l&&l(h)},[h,l]),w.useLayoutEffect(()=>{h.setPosition(p)},[h,p]),w.useLayoutEffect(()=>{s&&h.setZIndex(s)},[h,s]),w.useLayoutEffect(()=>{i&&h.setAltitude(i)},[h,i]),w.useLayoutEffect(()=>{a&&h.setRange(a)},[h,a]),f.current.parentElement&&Ml.createPortal(t,f.current.parentElement)});V.forwardRef(({image:e,position:t,children:n,altitude:r,clickable:o,infoWindowOptions:s,onClick:i,onDragEnd:a,onDragStart:l,onMouseOut:c,onMouseOver:d,onCreate:f,opacity:p,range:h,title:v,zIndex:x},C)=>{const g=Fp("RoadviewMarker"),m=w.useMemo(()=>{var S,A,L,_,k,M,I,T,O,N,D,H;return e&&new kakao.maps.MarkerImage(e.src,new kakao.maps.Size(e.size.width,e.size.height),{alt:(S=e.options)==null?void 0:S.alt,coords:(A=e.options)==null?void 0:A.coords,offset:((L=e.options)==null?void 0:L.offset)&&new kakao.maps.Point((_=e.options)==null?void 0:_.offset.x,(k=e.options)==null?void 0:k.offset.y),shape:(M=e.options)==null?void 0:M.shape,spriteOrigin:((I=e.options)==null?void 0:I.spriteOrigin)&&new kakao.maps.Point((T=e.options)==null?void 0:T.spriteOrigin.x,(O=e.options)==null?void 0:O.spriteOrigin.y),spriteSize:((N=e.options)==null?void 0:N.spriteSize)&&new kakao.maps.Size((D=e.options)==null?void 0:D.spriteSize.width,(H=e.options)==null?void 0:H.spriteSize.height)})},[e]),y=w.useMemo(()=>"lat"in t?new kakao.maps.LatLng(t.lat,t.lng):"x"in t?new kakao.maps.Coords(t.x,t.y).toLatLng():new kakao.maps.Viewpoint(t.pan,t.tilt,t.zoom,t.panoId),[t.lat,t.lng,t.x,t.y,t.pan,t.tilt,t.zoom,t==null?void 0:t.panoId]);return V.createElement(Zw,{map:g,position:y,image:m,altitude:r,clickable:o,infoWindowOptions:s,onClick:i,onDragEnd:a,onDragStart:l,onMouseOut:c,onMouseOver:d,onCreate:f,opacity:p,range:h,title:v,zIndex:x,ref:C},n)});V.forwardRef(({position:e,children:t,altitude:n,disableAutoPan:r,range:o,removable:s,zIndex:i,onCreate:a},l)=>{const c=Fp("RoadviewInfoWindow"),d=w.useMemo(()=>"lat"in e?new kakao.maps.LatLng(e.lat,e.lng):new kakao.maps.Viewpoint(e.pan,e.tilt,e.zoom,e.panoId),[e.lat,e.lng,e.pan,e.tilt,e.zoom,e.panoId]);return V.createElement(Vp,{altitude:n,disableAutoPan:r,range:o,removable:s,zIndex:i,map:c,position:d,onCreate:a,ref:l},t)});const tS=V.createContext(void 0);function Ln(e,t,n){w.useLayoutEffect(()=>{e&&n&&e.addListener(t,(...r)=>r===void 0?n(e):n(e,...r))},[n,e,t])}V.forwardRef(function({arrowOptions:e,circleOptions:t,ellipseOptions:n,markerOptions:r,polygonOptions:o,polylineOptions:s,rectangleOptions:i,drawingMode:a,guideTooltip:l,onSelect:c,onDrawstart:d,onDraw:f,onDrawend:p,onDrawnext:h,onCancle:v,onRemove:x,onStateChanged:C,onCreate:g,children:m},y){const S=Rt("Toolbox"),A=w.useMemo(()=>{if(window.kakao.maps.drawing)return new kakao.maps.drawing.DrawingManager({map:S,drawingMode:a,guideTooltip:l,arrowOptions:e,circleOptions:t,ellipseOptions:n,markerOptions:r,polygonOptions:o,polylineOptions:s,rectangleOptions:i});console.warn("drawing ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ณ„๋„ ๋กœ๋“œ ํ•ด์•ผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. `https://apis.map.kakao.com/web/guide/#loadlibrary`")},[]);return w.useImperativeHandle(y,()=>A,[A]),w.useLayoutEffect(()=>{A&&g&&g(A)},[A,g]),Ln(A,"select",c),Ln(A,"drawstart",d),Ln(A,"draw",f),Ln(A,"drawend",p),Ln(A,"drawnext",h),Ln(A,"cancel",v),Ln(A,"remove",x),Ln(A,"state_changed",C),A?V.createElement(tS.Provider,{value:A},m):null});V.forwardRef(function({position:e},t){e=e||kakao.maps.ControlPosition.TOP;const n=Rt("Toolbox"),r=w.useContext(tS);if(!r)throw new Error("Toolbox must exist inside DrawingManager Component!`");const o=w.useMemo(()=>new kakao.maps.drawing.Toolbox({drawingManager:r}),[r]);return w.useImperativeHandle(t,()=>o,[o]),w.useLayoutEffect(()=>{const s=o.getElement();return n.addControl(s,e),()=>{n.removeControl(s)}},[n,o,e]),null});V.forwardRef(({id:e="react-kakao-maps-sdk-staticmap-container",style:t,className:n,center:r,marker:o,level:s,mapTypeId:i,onCreate:a},l)=>{const[c,d]=w.useState(),f=w.useRef(null);return je(()=>{if(!window.kakao)return void console.warn("kakao map javascript api๋ฅผ ๋จผ์ € ๋ถˆ๋Ÿฌ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. `https://apis.map.kakao.com/web/guide`");const p=f.current;p&&kakao.maps.load(()=>{const h=Array.isArray(o)?o.map(x=>Bo({},x,{position:new kakao.maps.LatLng(x.position.lat,x.position.lng)})):typeof o=="object"&&o.position?Bo({},o,{position:new kakao.maps.LatLng(o.position.lat,o.position.lng)}):o,v=new kakao.maps.StaticMap(p,{center:new kakao.maps.LatLng(r.lat,r.lng),level:s,mapTypeId:i,marker:h});d(v)})},[JSON.stringify(o)]),w.useImperativeHandle(l,()=>c,[c]),je(()=>{c&&c.setCenter(new kakao.maps.LatLng(r.lat,r.lng))},[c,r.lat,r.lng]),je(()=>{c&&s&&c.setLevel(s)},[c,s]),je(()=>{c&&i&&c.setMapTypeId(i)},[c,i]),je(()=>{c&&a&&a(c)},[c,a]),V.createElement("div",{id:e,style:t,className:n,ref:f})});const __="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACSCAYAAACqjkOzAAAAAXNSR0IArs4c6QAAABplWElmTU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAATwHXnAAAACXBIWXMAABYlAAAWJQFJUiTwAAALPUlEQVR4Ae2df6wdRRXHz/a1tVTCDyNiQRujaVOtQCoRQaMWWhSERPhDwB+JISESCSGGBMNfYEnQ8EMBKa2glWjkR8sf0AT5YUGbALaVYIGCkhZBilihDSC0oby+94bvmbul7/b+eHt3z+ybM3smue/euztz5pzPfN/c2d3ZWSJLRsAIGAEjYASMgBEwAkbACBgBI2AEjIARMAJGwAgYASNgBIyAETACRsAIGAEjYASMgBEwAkbACBgBI2AEjIARMAJGwAgYASNgBIyAETACgxPIBi+SVgn3IH2EptHxNIWORWTzyNEn8f5RvA7FawZenHbj9QZe/6OMXsD7czRGT9AeWp99nV7D98amRgrIraGjIJpzIJbTIIhjKrW+o6dg448Q053ZybSpki2FhRsjIPcX35t8D419AdppQaC22ghR3gTbt2Un+l4rUDXxmE1eQG4VTafDIJqMfgzss2pCvw1Cupq207LsLBquqc5JqSZpAaHXOR1Ur4d4PjUpdB39C/X+CL3RvZNSfw2VJikgjHEOxhhnGfh9pwaGRaq4HWOkCzBG+n+RzJryJCcg92eajyOqu9EIcyJriC04cjszO4mejcyvSu5MqVQ6ssJuLX0LP1fr4VZs4mFSc9g372Nk3Kq4k4yAMN45HyBWopEOrAIkaNmWbytzX4NWVZfxJH7C0CDnQTi3AJqWeByO0n6AwfVv6mroUPVoAd4zfojn+5DNrYrEszcWFtG5ENHv9m7Q+K5aQO5hOo6G6BGAn64RPnweplH6craI/qbUfzVdfgdf9wB9COeWN2LH7I6dujZsxTnrBdkp9Lout1veqhxEOx7rzKA/IATt4uFWmM2x+JhabaLqr0oB0VoMmolOVUW6v7On5jH1zxXhXnVjIHcfrmwdQFvQBx0cIc/yLjl6k96hudk3cAVNUdLXA82gJcmJhwWT0SE0k36iSDveVVU9EA7ZPwGvufeZqg10IX8djSDfHBza/7tQ/ggy6eqBHKZkhBXPOpybuRTN+BW8z8Jcww/4F39ubbsUbbYuWLtxbBldEsx+AMNqeiCMfQ5CF78NDGYG4LAKFzqvKHqhM79gexn8OEvcF0e7MBY6AmOht8RtBzCopweaSd9F/NLi4YlfJ2cL6eyi4uE24LxchsviK4taLmX0QUTJsapIegRE9G1hok/jBN6xGG88VNauLwsbKP90WRs9yknH2qOa6ptV/IS5h+hwjA7+i3ClBL8ZvceXIIAd1RESYXD/YYxdHoOtuRL2YGMMY64jssX0qpC9YGakGiSYg97wEC3Gu4yvPMbYQ2dIiYf987ZgE6Lc5f2t/mcKol1U3Ux4CzKNEtpPR18VrOJyTC39p6A9byq3ebmg3YWCtoKZ0iGgjD4vRGArbaZfCtnqNNOyvbVzR4ktcjGXqLx4kegFhNtyhjC+mF88pL45l2bn4wcsUMptLxUxn9FnfOwixsIZiV5AuOLFV9yniSAYpdtF7PQzIlfH9Dz2frVN+r74BTSVPi5CydFzmLj1ioitPkZ8HairT5biu6RiL17jwDnjF1CGq+8SKRM/V9PbK6m6MpweiDzFLyDCmVmJ5OhlCTOFbMjVFe8dJjmI+AWUCY1/CFeY6ksydcnFHizy+AXkxI6aDghGsdOwTF1ysXd6KLQlfgGR0NndTGgwXgS8XF1SZ7aLeF0qT/wCckJTPB0dXYpQmUJSdUnFXiaGgmXiF9AUfxG1YDh9smU0D/eRHdknh8guXFj9GE58zhMxRuFPO1T1M34BkZ/eKbNI01ANy71kYtNOhnFB9aWqDRy6fPQCwpXuEVzl3iwE4kJ3s9hRXYdLue0LO3aU2YCYfexlytZYJnoB5Sw2CDGZjRk7FwnZ6jTTsi11s6NUzJ1+Cm7RIqBHBWNeghXMPi1oz5vKbS4RtCsZs6Bb7aZ0COhderDd7QrfeM7xNLrHzyKsYGZ8UW8LNjF4ljlrzsYlYx7vrPBnFQLCwgM8cf1xwdjnorEfxgINs6ra9DZgC3akprOyS4/nMVd1L3h5FQLKKdwhTONoLGrwBHoPni5bKvmysIHC0ueYpGMtFV+RQiom1XMg/mcio634KHOZoJ1OPPeF8TU7R7Ml52y3hyr7TY2AOGzc0LcM50Z+KIugzRrfmboaiz79FfMgt+AceGvNnsOwFtEoFskcoi/ip++bKHFCWynJL2O0HPed8Wr6KpIuAf0JjTjdT9bS9NM7iBDGsGbZvOxrEK+SpKohcrCrlbAt4+ZqTeLhAFUJyLfIGP28TMuoKKMwNlU/YXtFgAH1eoxFvrD3exLvjjZg4Hy8tlj09UBM2NE12kBP6K/SmHQKaAfO+pJ/cuCE7aIkwwu4S59jUpdUCgjP4BpFL3SdOtq9HEYsPqZe+yPerlJAnuewX52+dZ4mYsAFXHsdh+63FsgXZRa1AsLDbnehF1oeJdVBnEIMPpZBykSUV62AcoZLIaJ3I+I5mCst32XupR+sZrHcqgWEw15+DPdtYjTqNgTffQx11ytYn2oBeQ4j/sQinhSgLvGivupPiqoXEJaB+wekc786+cDn3HeFru9zWb2AfCgjdO2+kJR80uhzF7QqL2V0iYPcWvo7ti/oti/CbRuxTPDnIvRrYJfS6IE47DFFvZAmXyeQVDoCymgVYq1vCZcJwPbZ/TKOHNnXJFIyAsLh8Ah6oeujbxX46H2N3tFiDiYjIB/ubv8U5JifMfEWVsdX/6Tm8dJKSkD+ASXOP/57fIzxfIZvWh6iUhRaUgLKg74B78GW8i0Ktks+9ol9SyolJyCML/6D62Mro2sl+OR9i86xag4lJ6AcR4yXCGL0qZp6UDpJAeE//Un0Qny7cRwJvnif4vBG1IskBZQTiunyRky+iAoomUsZ3ajg7o1NOGn32W77atvm6Bn0PkfVVl/NFaXcA/GjtH9RM8/O6mLwodMrsS1pC+g1P9mMl4aZrLQNT33WO+GtALWkBYQ7HXhxzhsLcAiV5cbch1D2J91u0gLydHfSr3BEtrN20lwn1514Sl5A2en0BgRU/90bfLcF1514Sl5Avv2GcRNinXdvcF1cZwNSIwTk1xt09Nva2hN1aVnjsCqTRgjIQ9qDBRn4PojQievguhqSGiMg3P35IgQUfvFK1OHrMgElSeAqRBXyHjK2zXU0JjWmB+IWxeKVz+It5DIq9+R1mICSJTBCPwsWW0jbwZyuZrhRPRCjwt2gvOL9mmrYupZek9vuujPVjY0TkG9IRz8Vb9AQNsWdlDeY9HSOfrgw1WMdrtbLLGrpaD2mbIRbfLxfIJO8r5k9UAv6lYLsJW0JuhXeVHN7IJ4ttJaeAuKqk7020UI6BiBDnh4Ir4SSNTS2B/INLjFugY2mioc111gB+X+47XQX+o3nS/7zcZ/zPB7Iclfp8gkUbLSA8qV1q5w5vkrr8rxS2m20gDzE7fR79CSvDAyUy3DZhqfGCyifclrmtptrU5+uWuR/o/EC8pCG6dfohXYUAebzcF4uY6nhg+hcAPlC34MsfHCD5sXBJXVvPdA+mrzg99v7vvb8xHlULw7eM7ISO0xAOTRcingTP2PLJmSIPD7vhBmbkcEENL6dR/3k+93jN7V9dlhfjPNYep+ACeh9FH6qx6v4umLcpv0/rsCUDc5jKSdgAtpfCmM9Jt/zZHneZ6mNgAmoDQd6oUX0EjZ164VW5Pv2K9Hsr1ObHX6P6HfSxXSg33d2nmMlblO+uEdu22wEjIARMAJGwAgYASNgBIyAETACRsAIGAEjYASMgBEwAkbACBgBI2AEjIARMAJGwAgYASNgBIyAETACRsAIGAEjYASMgBEwAkbACBgBI2AEBiTwHqI4L00ErGrhAAAAAElFTkSuQmCC",I_="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAAAXNSR0IArs4c6QAAABplWElmTU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAATwHXnAAAACXBIWXMAABYlAAAWJQFJUiTwAAAMhklEQVR4Ae2deWwcVx3H39vDOduE+ogdaJq2JLQ4cWzK0YAoIPinAgn4Iy2XOKSqFREgzlAaByhxrh4kJSVFaWmhIoUkf9BKIIQgAqmFuITitWM3JmnTJC21E9tN49aNvcc8fr/xbuOs1+PZnd+M35v5rWTtzjt+x+d9PTs78+aNEPxiAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTIAJMAEmwASYABNgAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTIAJMAEmEFECMqJ5v5l2/3eb6uKzxfVCyutiSl6jhLxKSFUvlHiLFHI2NlRCjQopzgol+6VQxy2peoVSz+RGRXv9PV1n3jQWwQ+RFFD/hpUrEyL+GanEx0E4qzyNu1KdSoo/ZkXud/UbDx/2ZMvAzpER0AtfXjp7/uULvwCiWSulbPFjrJRSHbDX+vnwS2f3XPmrE6N++NDNZugF1LOmsap+eXKtknKdlKIhiAFQSvRJpe7qP5rZ1bi/Jx2Ez5nyEWoBDbSu+oQUsR0gnKtnAjAI6XklrG/WtnX+YSb8B+EzlAJ6/vtXLViQvHQXfFV9LgiI0/mAr7bHzmWG11697fi56dqaVh86AfVtWNWYVPL3IJ5lOg0GiOhYRqpPN2zs7NEpLq+xxLwa0Kn/0PrmNUkh23UTDzLCmDA2jFEnZl5jCY2A4HjnNjhXsxd+Bc33CsWv/nZsEKMdq19OArYbiq+wgQ3Nt8SU2I3/5gHzq8wdfJ9ZUtxauzH1UGUG9OllBnAHXoPrm78EsnnEGPEUcgERwa+0r9RsSv26UGTiu9ECGly/6r0yJp+EI4wqE+HDRZK0stQHazZ1/svM+IUw9hjoxW81XiZjsf3migclI6swB8yFBRQsATl3fvI34HJJsG598bYkn4uR3wZG7oEGWptvgf/eG30ZzhkxKm8cz2lGnHtyapzq+37QUlsVF8fgJ/sCT5lr11m9ms7K5Q1bOga0C80hIOP2QMm4ujN84sERkguTCfVjh7HSssqoPVDf7c1Lq5LyGJBMaEnTe1DZdEYta9iaOuHdVDAWjNoDJRNiHWDxUzwH4RTf7bls7obcaLqhvzc9C//wM5ZhHfg/6OPQJJJJ8T0f7ZObNmYPNPT1t1+qFl7SBwHPJaeg1L60VD9xe6ETL9hWKflDOHl5E3UscHZxRJ57fXH1zueGqW37Yc/P/2bSeNWCSz5PLR6c+AVBfrGmLfXXcoLNC+3mwdaWB6Hfo5QT1eBqzDzMFew+UE5MM9XWmK8wGKTPkkJSoktZo9fVtHWUJZ6JMWBftAGz7rsmlnv9TJ6r14Ac+hvxFXb6jhWLEvHEy/BLhUTwcJfF0fQbb3xg8b1HBx3YuK56+TvLa6rmzv0HXG1f7rqTY0NlZXPZxYs2d592bKZBJcmA+J1HTCY+RiYeOMYQKvspKvFg7rYtsInHLzQs4AJHPPFRGlv+WjFEQOJDVBjgvq8f1bR1H6GyV7CDNtF2YdvrO0xP+bBXG0H0N0JAAOI9RDBOnTzT8TMiW5PM5G2fmlRRWQFVzpV5d9lLewHtWyPi8PXV6DIfx2aWUve/e7fIODbyUIm20YcHExe6SvHO8dwvFOn4SXsB3fCOpiVw6SJJAQ/u1XqMwo6TDTofssrO3cmZBnXaCyim1OUUnJQQvTBx638UtpxsoA/05dTGbR1V7m79VdJOewHFhaytJLHiPrBnID1XU2x/4jaVr5iM1Uy0q+Nn7QWkYvF5NODUizR23Fgh8iVj2t5hUqCgvYBgMQSS4x8lY+cLSfv9TuWLKnc/89VeQLB0CsmvJqmsOX6CnGibyhdV7hNjo/6svYCklaM6u0tyMO5uACSJL7rc3UVdSSvtBZQTimSKJyzv0lQJoEr6UPmiyr2SHNz20V5AImfBRVTvL7hqfA3cR/ZW75acLQyta3ob+nJu5a5WSeX7aQd3kUzdSnsB9bT3nMAb8KZOwX0N7Bl8X+7FqooRTTtR6Wef6j7pPruZaam9gD7yd5GF+TZHKfDEpPzav2+l+VVXKh60jT5K1ZVdBjnbuZfdMdgO2gsIcVhCPU2EZckVdS3fILI1yUzeNsnNjoQ5T4qTssAIAcE0z6eokoZleu8cbF1xLZW9gh20ibYL217fKXP2GotTfyMEpHJjf3ZKopw6nHMsZOJxnEVYTj+ntrYtsGnbdmpYRh1lzmW4LbupEQKq3XykD6ahHio7uyk64NTTWXPmHRi441rPq7aiDbRFN53VXtj8EOY8RfhaFRshICQGFyh/S0pOiiYZm/0M3FkB02Ure2FftAHTTUjPMZHnWll6rnrBKQszXvbE9TnzTsEdC/SXJLS6L0ycT58fWUI5Z9vPETZGQAhhsLUZl+79qo9A8M7UJ6yc+qfI5o4NnBCvoK/apeIykYgvi8Xl+6WMfRKKVvsVA0zMfwDuU1vrl31qu8bcWIiJW0Jsjwt1G9UdGiVgrgaBrI4jlURc1JOcTy7hZcoiZWGOU1ZrWGHMMRCyq2tLHYPZfk9oyJEkJMwNcyQxFpARowSETHJZcW9AbAJ3Y2JuRh0DFUZ0cENzO/xsfl9hOwzvcJri6ZqNqetNy8W4PRAClpZ1t2mgp4vX1JyMFNCBo12Pw+m249MNijn16vh4TuZEXIjUSAHdtF/kYH1lo36tFICXesdcMKdSdbqXGSkghJodU4/AXsg+T6M7ZOf41CvjuTi30rXWWAHBw25HYIEoIxZhchp8zAFzcWqjc52xAkKo1ljmfjhzO6YzYKfYMHbMwamN7nVGC6ju7p5+eBT3Ht0hTxkfxG7nMGUD/SuMFhDilRacWIR/Zf1RF0UIMduxFxWbtmm8gKq3dDwL0P9kGniMOR+7gaFfCNl4AWEqlqXuuZCSGZ9MjLkUWSMvZZRKBKZ6/AemerSUqtOtDL69OmDKxrt0i6uSeEKxB8LE4T5yY/ZCJsU6nahCI6DuJ1P74P6xAJdwmQ7tFPUQox3rFNWmFYdGQHgTnqWsHboPAMaIseoep9v4QiMgTDg2PPIQ/J4fdpt80O0wNowxaL9++guVgPABJXBz324/gXmxjbGZ8hAVt3mGSkB20mPWfXAsRLIolVuIrtphTBhbyF6hE1D1XV0vwey+vbqNE8aEsekWl9d4QicgBAK3Nmg3b1rHmLyKB/uHUkB1m1MpOGA9QAGIwgbGgjFR2NLNRigFhJAtldPmxKJOsVALMDSXMkqBGWptPgyPpVxRqi6wMqW6q9tSKwPzF7Cj0O6BxjmqnwbMs4Q7HWIoERZRUagF1P/f7J78c1GJcJVnBn1jDOX1Mqt1qAXUuL8HFudUO2duSNTO8RhmLgK/PYdaQAhvJJv7BZyDed1vkMX20Sf6Li4P23boBXTF1sNn4ZkTgd+9gT7Rd9gEU5xP6AWECVvW2Ha8A6I4eb+20Rf69Mu+TnYjIaD8eoMPBwj+YVPWOPTKJBICQkhZYS/IEMQ8nGzel9exMaJ/ZARU39b1Avyspl2os8QQow/0VaIqlEWRERCOXkZa23y9hwwOfmwfoZRK6aQiJaCGjZ09MKEdlobx54W20Yc/1vW0GikB2UOQEVt8Gwo/bfsWtDfDkRNQzdbUITjJ9xdv2Cb3Rptoe3JNuEsiJyAcTjjQ3Uw9rH7YpI7RD3uhns7hBAweU3AQVr0nWdQSxNNe09bh2+LjTnnMdF0k90AIXQlrExV8SltUMQVlJ7J7IAAsh1pbOuFBKd4meylxuLqtYxXYg5mr0XtFdg+EA27JnOdjobyNSIoH/12iLCDxt96u/TDyz1W638C+aKPS/mHoF2kB2csFC7Wt0oGEn+7bTF2et9Kci/tFWkAI40xv5lG4AlH289mxD/YtBhq17cgLCKecwuSvsm8Bwj5hn67q5p8h8gJCSJkx60F4G3QDLN9mMN+njC7hbMoCgnG1Fy233C98AI+Fu8/kxcEppcwCytN8bUTiouWvTQcX22Db6dpFpZ4FlB/pK3ekXoVzi7umH3i5a7zt9C2j0IIFNGGUc1ZmO5zbGZ1QdNFHrMM2FxVGfIMFNEEAizZ3n4ZL9b+cUHTxR6iz21xcGuktFlDR8KfVGD4NsdTk+2y+rqhHtDdZQEXjv3jTkZNwWXTyXgjK7Lqi9lHfNOq58UEN1tiZ09+eVbcIjqnVzbZPJfdiWVD+2Q8TYAJMgAkwASbABJgAE2ACTIAJMAEmwASYABNgAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTIAJMAEmwASYABNgAkyACTABJmAAgf8Dr1rs1v/JgMcAAAAASUVORK5CYII=",M_="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJIAAACQCAYAAADjszKFAAAAAXNSR0IArs4c6QAAABplWElmTU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAATwHXnAAAACXBIWXMAABYlAAAWJQFJUiTwAAAMgElEQVR4Ae2dfWxVZx3Hn+fe9pYyMuYszg0kRgOZ4rYgUTcNiq4rWTRRQ3vH2ESJS5kIlJho/Es3EzW+TFpaXuw2Ubax0UJkicZQYGvCJswFEREkQ+degG7SvcBGX27vOY+/3+kt3pZzb8+953fOfZ5zfk0I5z4vv5fP8+05p+c8z3OF4B8mwASYABNgAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTIAJMAEmwASYABNgAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTEBrAlLr6EIK7t5tDe+rmaJuFgmxQIrE9UKoDykp3y+Veo8ScgqGIYUagrK3oOw1+PSiEvZJYYvDw0Py0JblPf8NKVRt3cRWSKu76m9IJpNLQSBfBGHc5G+E1FEQ3B8ty3qiI73vmD9bZvaOlZC+sXXRlCunVd8tZWKVlGJ+EEOmlDgipNp4/kLmsd+u6B0KwoeONmMhpKaueamZctYquHR9Dwbh2pAGog8ufT8/o05v6k4fz4Tks2JuIi+klu6GL4mEbIVEP1wJykqIfwtbrWtr6vlDJfyH5TOyQmruqp9em0hsklIuCwtmMT9Kqe2Dtr2qM73vfLF2ptZFUkjf3vn5eVWi+vcgojk6DQyI6VRWjHx1Y+PTx3WKiyKWBIURnWy0dN/WBCI6pJuIkBHGhLFhjDoxo4glUkKCAVoJ90M7YMCmUcAJwoYTG8ToxBqEgwrZjMylbW33bffIhOyU8HtfIZYluVUCLnS2at7QtPehkjpq2tgI6JOxW7uz4esgn62miGgsH0dMSqzY0Njzu7EyU/83XkhruhZ/MpkQB+AdRsrIQVAiY9liYXt6z1+MjD8XtNFC+mbX4qunJdQRuO+YbfIgwEXulXdtOf/h9J43Tc3D5JttCSJ61HQRoXAwB8wFD1lIIRNo2bn4HhiA20N2G5g7zAVzCsxBwIaN/A1Y07VwRjJRewp+lacHzCdU83Dz/bZtDc5tTx84F6pjAmdGXtoSidr7oyYiHEv4q/OqRLL2PoJxDd2EcWekdY8v+qBIpU4B9qrQaYXiUGVFJjOn9c7el0JxR+TEuDOSqk7BVJDgRARv6w8qW3zfsrOfzVjD156xTtfgPzzGMqzDNkT8XczIKpVKfdelQusio85Iax791JWJ2qv6IOip5FSV6BoRmR95faGKL4arReoHcD1K08eiLlpD569rv/u5C+S2AzJo1OUhOWX6XcCBWkR9lrCWtzfu21cK45zg7lizq/7BpEhug750E+akvCKX6+ZSYqpkW8MubfJOSlgwLfbvAwMDC9qXlCai/BiwL9pAW/nl/o9pc/UfT3ELxlzaWrbfeo1MVZ2FSwmV+F8YGB7+TOey3v7iiLzVNm9fVDe1puZZaD3XW49JWsEyFZXJXte2bP/rk7TUoppqUAJPxq5O1pOJSKmLYsT6CpWIMHnHFtiEl/oXSWDgL0xN1a0ktkIwYoyQElJ8jooHrE/7YevSff+ksjdmB22i7bHPvv9XapFvGyEZMEZIwOMTFEzwBelgf/8GCltuNtA2+nCrK6OMJOcy/JbcxQghNXWJJGQ2r+Ts3Dt0dK48POJe5b80Z7vDvyXnSfdHc7lTmAvUhhFCukY0zIaXmtUUJIbt7HYKO8VskPmAOVaYezFfutQZIaRkUnyAAhhcck5uST91hsJWMRvoA30Va+O1jip3r/7KbWeEkISSM8pNML8fvBQlftaTb338MZUvadt14y3r+ckQIYkrKPDBbPtXKex4sUHlS4mktiti8jmYIaSEIrk/gtvXwfzkgz0m8kWWe7DZmiEkWxL9laVqg8WZb53IF1nu+bHRH5shJClInhbDdjYkN+1ehoHMF1HuXmL208YQISmSqacwlfVGP7BK6UvmS9LkXkrs5bQ1QkgjljxbTnIT+8CzqOvv7frCzInl1J/X7Fo0C31R2LVHsoE/rqCI0wghnTgx/JKAhYQUCdckqgLf5iahUjTTXSDnYyftlynyDtqGEULqva83q6R6gQjG6uZfLyD6K/DyiHK2V19eU3oJ5oy5l94z/B5GCMnBosRzFHjgkjO7tq5uLYUtNxtoG3241ZVcRpRzyX7L6GCMkKRUz5SRn2sX2OL4/nVP1H/EtdJHIdpE2z5MjOtKmfM4wwF8MEZIAwNDe8jyhznRojq5G2c1Utl0bIFNWG9H8hQe4yLNmSrRAnaMEVLn1w70wTKg5wvkUU7x3NpUzf7mRxb6nrSPNtAWBEEzzRYMYa6YczmJVaKPMUJy4Cj1OCUk2FPpxqlTpx6GlSD15drFvmgDbZVrw7Ufca6uPggLjZn8jzk7E+xTqVfg8kH/qkOvdW2DA5nMbMo55YSacTVllJAwg5adDbjl8bdcsyEohEvKQdho/UlbZP9sKevUOXHO2bNohphxdVIm5yRE1adhWv6XAdwtBO5cTcBcps1tjT2rXCs1LTRqgSQyhFcP66WSK8lWlEwYGEcgCXFLUlTB/N4qMVPMmtAi4I+4DAlyDNgLuXmz7pEg/Q2Ne0/Bg7onyUloYhBzwxw1CcdzGMYJCTOzhHrAc4aGNTQ1NyOF1LFk77NwH0HypFsnnWFOmJtOMXmNxUghjSYnf+E1SXPamZuTsUI6a+/ZDcujXzRHJJNECrk4OU3STNdqY4XUnRYWfGujcX/dFBIC5oI5FarXvdxYISHYNwfUVjgrOc95dAddND7IwcmlaCO9K40W0iPLey7aQhizGVUhKWAOmEuhehPKjRYSAs7amQ54Gj1sAmy3GDF2zMGtzqQy44W0Kd37GvzZ/JhJ0PNjxdgxh/wyE4+NFxJCV7b1ALxWgF9us34wZozdrKjdo42EkNrT+0/AS7g/uaeocSnE7MSucYheQ4uEkDBZ2Cntl16T1qWdiTEXYmfcNJJCiWA5fCnMX2GC2fxibXSpgwvxkbbGPR/XJR6/cUTmjOSAkMKcs5JJsXpQWaSEdPTYcBdc5ELbusYD3wJN1KujsRaoNrA4UkJyFhMq1ar9OECMpix89MoyUkLCpK2hCw/B/ccFrwDCboexYYxh+w3aX+SEhF8EI4XqDBpcufYxNpO+rMZrnpETEiZuyUwbPOoj2pzLK8rJ22FMGNvkLc1rEUkhtS/pPQ1DsUPD4diRi03D0PyFFEkhIRJp6zevW8eY/Mnn/70jK6TW9N6/wY0tLqPW4gdjwZi0CCaAICIrJGQFXxuqzQNKnWIJQEewzDDiPy27Go7B5ukfq2Sa8Jb/H21Lem6oZAxB+470GQnhKVv+KmiIk9nXIYbJYvRbH3kh9anTOOmtktvD9OVi8DtWWvePvJC608dhE1PVXrlRUO2jMVQugjA8R15ICHF4aGALPAx8Nwyg+T7QJ/rOL4vqcSyEtPmuZ96CAazEapPNOd9R1c+lvGIhJMx2cHBwfZirTdAX+rxEOuIHsRGSsx+jUr8JbTzBl0l7QPrlEhshISjLFrDxhAphA3SVHfXld3jM6R8rIXWke/4DqwRINzR1HWrw4fhyrYxmYayEhEM4IjI/C3INHNpGH9GUS+GsYiekjY1PHwccuwsj8V2zO+fDtyGTDMROSM7gjFg/DWyQgrQdWND+DcdSSG1L9z8Pl6C9/vGNt4A20fb40nh8iqWQcGjha9B/Qj3EQdikjjEoe5GfRlIMHEwxOQhTTG4u1sZrHZyNDsFUkcA2cfcaR6XaxfaM5AC3xY/JwFPaIgsqPEOxPiMBZrluZ8NR+G4Tf5POlDrW2thzE9gzbmsdKqnF+4yE896U8H2vlLMRWxGhGOMuJNGnerrhGeK/yv7NhL6OjbINRKNj7IWEWxLbSpX9JBr7mrytMZWMYy8kBNmnzm6Ds9KZkqFCH6dvyR2j14GFBGPqTIVVZez4Bn3iMI3Wi+xZSDlKbwyqB+Gw3wu0XJv+XJ8SukS3KQspN7a4YTo8VPS8wQO2NX2TdUpZs5DyaMoLzsbp7+QVFTp8J9e2UH3syllIeUPeuqL3bfgm0E15Ra6H2AbbulbGtJCFNHHgh+31sIxoaGLx2GenDtqMfeb/RwmwkCYooW3Z/tfhRe7DE4ovfcQ6bHOpgA8cAiwkFyGMyJECiwRUdrTOpVPMi1hILgLYuOSpl+HF2WVnJSzDOpcusS+qij2BAgAG+9/4Tm3de7H2jlyTHVhWoDkXMwEmwASYABNgAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTIAJMAEmwASYABNgAkyACTABJsAEmAATYAJMgAkwASbABJgAE2ACTEBvAv8D0hDzloVahxEAAAAASUVORK5CYII=",D_="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAAAXNSR0IArs4c6QAAABplWElmTU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAATwHXnAAAACXBIWXMAABYlAAAWJQFJUiTwAAAMbUlEQVR4Ae1da2wdRxWe2Xv9IE5bUzWEBBIhUKrS0FYlgjbFz9io4iEBP5LyEg8JJRA11LZExS+gSICgba7TpElxWwptU0j8g1TiVdU3dm3TpEQhtCElSqC0TRrHxCKBxMT2vXeHc9Z26zj3vWf2zuyelay7dx7fOeebz7O7szNzheCDGWAGmAFmgBlgBpgBZoAZYAaYAWaAGWAGmAFmgBlgBpgBZoAZYAaYAWaAGWAGmAFmgBlgBpgBZoAZYAaYAWaAGWAGmAFmgBlgBpgBZoAZiCgDMqJxvxn2bV9/5h01NbW3Ok5slRTqOiHke5VQ75RSvF0oUesVlGJCKXFWCnlaCPWKEvKo62YOTk5O7H/+odv/9SZYBE8iKaD2zuduUCL2WRDDJ6SUN/lpd6XUiyC630qR+VVfovmwHywb60ZGQC1f6a916mNflI6zEYK+WUdjKSEOQa/1YOZsaufAz1sndNgwDTP0Alq5dnf14mVLNzpK3S2kXBJIAyg14kr5k9ETp7Yf6V03FYjNChkJtYDa7hr6pIjJbgjyfZXgF3qkf4iM6khuafxNJewHYTOUAmpf/+xVoq52O/Q4nw+CxII2lHpKjE9s7Ov56H8KlrWsQOgE1No5vDIm1K9BPCuMaguljmeE/Ex/ouGIUX75dMbxWd+o6mu6htY6Qu03TjzIEggafUMfjSLNpzOhEVBb1/AGqeQueCxf6JMTbdXRN/QRfdVmJGDgUFzC1nQMfk1KpwcG/6yIBwYlYfjIXb+3u+mRgNub3JwVhOeLuq1z+MuQ/5gt4pmNBUUE519NJhp+MZtm46fVAlrTOfhhRzpDQHy1jeSDz1Ouchv3Jpr+ZKn/wtp7oNWdf7jaEbLXYvGgZqoxBoyFBRQsA3KBqHsSnmyWB2tWgzWIwYsFntM0oGuHtLIHWtOFN83yY9rZCcgAxoIxBWSO1Ix1qm/cNLiopso5DixcRcpEhcHgsezcVFpdO7S16UyFXSnJvHU9EIjnHogwVOLBFoNeqL46Lr+H5zYdVvVALR3974k58eMw3BO3ieRifYUn+3TGTa8Y6G59tdg6lS5nVQ8Ud6ru1ikeGJvZ5wr1baXSTemJ1JKRE6dq8A/PMW06T+zT1WgYW0zGv6ULXweuNT3QLZt+d+UV8StH4FllATkRSu2GF53fL/ZF58wL2+/AdWcduS9CjZ9PnV/6wtaP/5cemx7RmkvBFbGFXyAXD0z8Akq/1Jdo7CuF2hmh3dHeOfQw1HschEQ4UU3WebEKsaMUnypV1ppLmJLO5yhJgqeelyaVWlWqeOb6gHURA7Hmpvs9p47Vrz/56ltxCWu7q2+xjNWegkBIBA83q8cyF9IfGehpHctHTrF5Lev7r4ktjP8R7mGuLbZOgXKuykwsTW5pHy1QruLZJA2iPQpZ1Q42iHxV4ynX/TSVeDB2xEJMWOUxTsQFvOKrbSPC0gpD1ChafYRbDKeZygI8aX13sLv5b1R4sziIidiz3/1/qhb/GPoRrBAQDLN9iIQKpV4/N/7yAyRYWUA8bLCRJauMJKKYy7BcShXzBbR2dwwmzqwsJajcZdW2gz0bUrnz/eVMY6tt/lBmaktxvYDYSbA0ghgvoKbFi5fDZLEqCg5ckXqKAicfBqGNaow9ny0T8owXUDwmlhERdXRvou0NIqycMDM2juYsUEIGYewlWC2tqPECcmJyUWkh5ShNPFaTw8p0MpEtJWPX5LVjQKbxAoIb6DoKnuA+6gQFTjEYVLZijjJ2hcksD8YLSClJcv8DjXpxNmjdn1S2qGLXGa/xApJSkTw1wZD723QSORebyhZV7HN9oz43XkBUo7vQqFQ34wXbgM4W2ch2QZ/LLWC8gNyMopniKeWN5ZJUcj0iW2SxlxxA8RXMF5Dj4ktUiuO6NZ3Jd1EA5cNo2dT/bsiHrfIIDjetfdjBr5fGCwj2/HoVgiTZpMkRVdq3e4nHY1TTTqbcw85rfhtYd33jBTQw0JoGEo7RECHvXLX+pyRPddn8mcaWd2bLKyPt2EzsZVQNrorxAkIqYMLWCySUwCK++rrrv0mClQXEwyZa7EgWcxY/KZNsEdAwVdDwXu2epo7n3k+FN4uDmIg9+93vJwiILGa/vuSrb4WAYCDomXxBlJYn66ocZw/OIiytXu7SiIWYVKPmaIk25ty++82xQkBD3U0jMLp7wG+ws/Vx6mmsLp5s7Bj0PRkeMRCLcDor7vtyAGOe9dfkTysEhARK5f6SkkhYCXpjjZQHYWUFTpct68C6iIFYZQHkqEQdaw4zJMkwaGrH4U1cr6t6He4z6F9JGLQuDKbFXsyMp5ZTztnW2cLWCAhJaO8a3g4f39BFCK5MVVI9LVXm+cykOn7mzJl/o61FixZdHauRK2B6xW2wx+GnQMSrdfkAuDv6Njds1IhPCh0nRdMMNpXOJKrjsQ1gRsulF4UB9zKrcel9HH5mZcmypZdE5P236f2XczHGS4wa/kVLQ+iKefCB5uPwePu0LvxK42JsGGOl/SjFvlUCwsBcpe4vJUCbytoYm94OWVPrwdMPbiZ+iyb4ysDCaDsslb61MsbLt2pdD+SFKtW95YdsaE1LY7JSQH0nTu+B+4VXDJVCyW5hLBhTyRUNqGClgETvugz87KRVTyv52tqLBWLKV8bUPDsFBGyOjY0/BmP+3jiNqeQW5RfE4MVSVGHzClkroJeeuH0c3m9YsQlT3maHGLxY8hYyN9NaASGl6Yn0NpgsNGkuvQU8A9+9GAoUMznbagENbG89raTYaTLB+XxD3zGGfGVMz7NaQB65KXU/vMOCGRB2HZ7P4LtdXl/urfUCSm5tehlGQ39/eWhmp6DP6LvZXhb2znoBYYhKpu8rHKpZJWz0ORuDVr7KyBYI/IzknyGYm7PlmZYG19tDyc0NHzTNr3L8CUUPhIFLJazphWzytZCoQiOg9KHUbriYBbaFSyFic+erE9O+5i5hU05oBISL8JQruk0nH320YcFgsTyGRkAY8IXM+Ufggd7c35gA3zwfi20dC8qFSkDeD5RIt8dY3sE3W35EpVgOQyUgDDqdymyBQTpYl2fWgT6hb2Z55d+b0AloYGvrSaBll39qyBF2zfhGDlxJwNAJCMnMqJRxrwhM9IlCeKEUEPxk5F/gkT5JQRANhkpO+0SDZhJKKAWEBMM9hzEDiyb5Qi2+0LzKyEYMrGQ9DOkfyJYXYNpfYaXpDQHaC9RUaHsgZBHWWW0OlM0sxkzwIYtbZEmhFtDoyZGdcC2r3DYpYNvzgay5zAMKtYCO9K6bUlJurRTtaBt9qJT9IOyGWkBI4ORF9RCsu7oQBJlzbaBNtD03LYznoRfQ8I7GszDZowKrN+SOadthlM1bMYVeQBjqlHITga7egNUWns23eA7tWSQE5O03KOXPAmtFsGXLHod+OYmEgJCkqanMvbB4Azct13qgDbSl1YhB4JER0OC25n/CVFLSjTqztSPaQFvZ8sKYFhkBYeNlhPwxvFbQtoYMsdFGGIWSK6ZICag/0XAE3pJp3EZF7Zm2kYvu8KVHSkBe87mZH2lrRp3Y2pz2Bxw5ASW3tByAK82z/mi7vDZiIvblOeFOiZyAsDmlK35I3aw6MKl91IEX6ukc+QiDjTr3wUadNJtaKrUfNsjUufl4vlAqmhfJHggZh/VZP6BinhKLyqegcCLbAwHBsr1z+EUhhb/JXkoc7ks03AR42oYHghJDOXYi2wNhgyvh+r4XmsGIpHhQcFEWkEiePN0L/cbfy/nP8+pAXQ+jbAD7K0ZaQLhdsKvcskeOvbqWbs9LJd1oCwhYHH3j9ONwLSv599mxDtalaghbcSIvoOlpr6UvAYINMu8L+3TVYkQdeQEhSWNnxh+GkeSxYgjDMlgW6xRbPszlWEDQurjRN0zDKHrjAyxr8+bglIJmAc2wmVbpbfAsfr4QuVgGyxYqF5V8FtBMS8Pa9XNSKfxN1rwHlsGyeQtFKJMFNKexlTuZgPubiTlJl5xiHpa5JDHiX1hAcwSQ3NI+Cl8fnZM0//TRmTLz0yP7nQU0r+lhQU7WyffQ+6Qxb17xyH9lAc2TwN4H214TbpZeCNK8vHnlo/7Vqt+ND6qxzv3vXFf9gnp4Xy/u8GwqsQvTgrLPdpgBZoAZYAaYAWaAGWAGmAFmgBlgBpgBZoAZYAaYAWaAGWAGmAFmgBlgBpgBZoAZYAaYAWaAGWAGmAFmgBlgBpgBZoAZYAaYAWaAGWAGmAFmwAIG/g+lc+tnjGMZ1AAAAABJRU5ErkJggg==",O_="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJIAAACSCAYAAACue5OOAAAAAXNSR0IArs4c6QAAABplWElmTU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAATwHXnAAAACXBIWXMAABYlAAAWJQFJUiTwAAAMD0lEQVR4Ae1da2wcVxU+s9kkjg3xK84LiChVooBpqxAgTVGMw0uqQAJ+QHlJCKkCESGEkED8AooECCgQoCQISisQbUn50VQCVeVRm7jUMSEJbTBUDW1paR6uE8dJcRw7uzt8Z7Ju1+tZ7+zsmd05M2cke3fu4zvnfPfbOzN3771LZIcxYAwYA8aAMWAMGAPGgDFgDBgDxoAxYAwYA8aAMWAMGAPGgDFgDBgDxoAxYAwYA8aAMWAMGAPGgDFgDBgDxoAxYAwYA8aAMWAMGAPGgDFgDBgDxkDyGXCSH2L1CE/fQKuXL6frUXIrCNmM19fgby051InzFkZwiS7h3zm8PY2/p3D+OF4Pz8zQwbWP0PN4n+ojtUKa6KNrMkvoQ2j9dzsOXVePClyXHkX93xXy9OuuA3SsHiytdVMlpKf7qaWT6GOUoV0IfEsUjYae6igV6Mfouu66ahC9WEqOVAhptJeWre+hXRmHvojL1bqGtK1LpwouffvkOO3pHaXZhthsopHEC2min94DAe3G5evqZvCMy96TENTnugbpt82w3yibiRXSxFZqz6ykPRDQRxpF5mJ2IKi7CxdoV9dhOr9YOa15iRTS2Z3Um3XoPjTKxpg1zPGcS+/vHqDRmPlVtzuZuhFiBjD5NvrAEqKDcCtuImKmNrJv7GPMaKvbnUQJabKfPuW4tA+Xs5fVzUxEAOwb+8i+RmSiKbCJubShYW5GI/0UT2U6YnLJxX3TJzsG6famtLywUR2kVwn6XD99HE9md6oR0Vw8EBOe6D7ROUi/mEvS+qpeSOd30JtpKQ2hAZYpbYRZukw72ofor0r999xWLaTz26nLXUFHEcQGzY2A0fBnnWna0j5ME1rj0Hyz7dAK+pV2EbFwvBgQy5W3OqWkVkh4hL4ZlN+ok3Zfr28sxuSbGfdElZe2UzuoZ8VSOg7n2+NOcC3+4SlucjpHm9YN0Xgt9eJQVmWPtCJLtyRNRCwGDF90ILavxkEYtfqgrkfCo/6r8ah/HDcW2VqDVVHepRyGBDZiSOA/KvwtOqmuR8KnlqeCRCmiYbdAX8rnqW+mQOueG6Pl/MfvOY3zwN1wZI2M2BDjFyLDjwhYVY90dhutXNJGp+B0qzQfuD+5N0/0taBfqPIXw/je7Mto9A+K+0I0lZ+i9d0jdEEaOyo8VT0SRPRRcRFhAhp6mXd2DNBNQUXEjcFluQ7XxVzuU5INhBjbOFZJzKixVAkJBH9YkhAMBD42m6Ot+L7rj2FxuS5jMFZYDL960rH62ZBMg786jrFttKaljU7CWynxPzFVoLesH6QzEgyc7KdVbRn6C7A2SeABo3AJl7c1IzQmhBcpjFSjROokg7esoHfgRcRf9B5Tl3P0PikRsX+MxZiMzecCR6alld4ugNMQCJGGaYSnrkNvlbKD+5qvrDpA/5LCm8NhTMaeO6/3FaLsrxejUfXVCAmEvEmCFDTOs0++QD+UwPLDYGy24ZcXIk0k5hB2a66iQkj3Ei3BzVxvzdH5VXDptjcexsSNiA4PGzYk4DG08DqOXQIragwVQnpXH6aJOJh1JHDkLtHdAjCLQgjaWObFvqi1eGSqEJKbpVeJ0OXS46uG6YQI1iIgng3YWqRI4Cyx2ANbDFdQhZAwWb4nXHjza+HeRXSsZz76/DMxWy6tmo8czzMVQkKjtInQ59B/RXCCgMjZiu2KmFIaVAgJPZLI/REezadLg4/yvZQtqdijjJWxVQgJY0giT1lOBpNzG3RI2ZKKPeqwVQgJj/4yo8Wu0E17kFYRsiUWexCf6yijQkj4VIpMPUWjXFsHVzVVlbIlFXtNzocorEJImYL3ZW2I8MqqOLT5zHZ6RVmq+OnZfnolxr14C8G6Dwgy8uGKup0EgAohHSFv2qnIZlXZlui3ucEwvNR0l9mjBXpGoqGjxlAhpJ2DlMMMxidEyHDoM3/bKvMU6OePhw0bfnm1pnHMHHut9ZpRXoWQisSMSBCES8WGq19On5XA8sNgbLbhlxciTSTmEHZrrqJGSPh0PlxzdBUq4NH8ljN99NoK2aGTGZOxQwOUVZSMuQxa/FSNkHJ5elAqevQYbUuztJ9nNUphMhZjMrYUpmTMUj5VwlEjpJ4hTNInOlQpkBDpm1oz9KfxHfXvcssYjAUfpKbZ8gbxhzjmEHE1pYoaITE76OrvkWQJvce1y7J0eLLfm8YbCprrMgZjhQKoUEk61gpmxJIRv56DLx+tDraA4X1IhA80XHzWtbk0fdGlDZJzyoXpWgCnSkjs/eROb8vjTy+IRC6BV9rej2XTj+SwNHx8/MqeRT091JXFUmosF78BN9TvhbntcibnI0HUe7Fmbtf81HifqRPS8320cXnWmzSm6rJcgwwKMznavPoA9jdQdKhrDCYYN6L3K+K4Jlc5Nm0i4gDVCYmdxmXnu/yaxENrbOoubXPiOb8Tm7I7tG3uPBGvLo20D3i/G6cuHJU9ErOMS8B31LFdxWHNMakV0u8HaD+If6pK26jJ5lg4JjUOlzmqVkjYlCjvFOj7ZfGoPeVYOCatAagVEhM+PUF34pM8oZX8Ob85Bo5l7lzjq2ohrX3Mm8u9VyPxZT7vLcZSlqznVLWQmObZgrfOfkYP5Qs8nSnGsCBDU4J6Ia0epNP4SuEuTaSX+sq+cwylaRrfqxcSk57PYYASvzSkrgHgs+e7OscXOpwIIXUP0T8R2gMLw4t9ygNF32PvaDUHEyEkDrJQoFurBRu3fI0+V+JQ7VckfgHhR2GOIKAtfnlxS8N1+GjHQ/SGuPkV1p/E9EhMADZcUNMrafI1iLgSJaQjmOWIp6DGbV0ThGGfMuwj++qTpTYpUULyFlIS7Y57a+CytlvLwsegXCZKSBx04SLdjoa6EJSARpdj39jHRtuN2l7ihOT9EEwBP9se1wO+afqxmqA0Jk5IHDi+Qv8BhidFNucKSmSgcvDJ8y1QYV2FEimk7kF6DrMn98WuKeCT51vsHKvfoUQKiWnBYF/s5nXH0af6JXQFIbFC6hykv+Mxm5dRx+JgX9inWDgTgROJFRJzFadBvzj5EoGOcCeR8AMrc49hiffrmxkmeqN/YOXsNc30IWrbie6RmDxs5vm9qEmshh8HH6r5WG9+4oV0cgyT3oR/c7Ym0mHb86GmSvoKJ15IvaM0i9HkHzWradg2+9As+42ym3gheURepp/gPuV/jSJ1zo5nE7bnzpP8mgohdTxM59CIzVhtsrdoO8ka8mJLhZA4UvxwMS+mbORqk5miTY/opP9LjZC8PShduqNRDYrL2h2a9oCsl5fUCMkjKo+NJ9wGbIDONthWio5UCanjAD2NthXd0LSCVu4p2qqQnbzkVAmJmw+/x/At9Ep4Ko/oALZnIyL4uMKmTkjdAzSKkeb9UTUIY7ONqPDjips6IXFDOHn6ZlQNEiV2VD5L4KZSSO1/pkO4tv1BgsBSDMZk7NK0tLxPpZC4cbGX9jekGzkKTGkfo8JL/DSSxYjDhqbDmEhz/WJlAue5dBAbiUa2iXtgP5pUMLU9EvOdd+nrUrxLYkn51EicVPdIINrBfgGPgoS6Jp3h3ugY1vFfB7zohhUaqYoQtlLdI3HDYxPQuu+VihipFRHrLu1CogcH6Tf4XuzfIT6EXhWuyxhh6yelXuqF5G1J7GK0O+yBupq3NQ4bdnm91AuJCTkxTr/EdelEOTnVzrkO161WLg35JiS0sjcdN8SObxg3ujUN02iDfBBMSEWWZiboZ3jmOhOENK8Mynp1AldIdkETUrF9vQ3THWw+EfRAWe2brAcNNUg5E1IJS1ibfxuewl4oSfJ9y2W4rG9mShNNSCUNj7X5k/jKZE9Jkv9blPHK+uemMtWEVNbsM1NYJODSpbLkl06R55V5KcXegQETUpkM1ozQWIHo52XJL55yHpd5McHeeAyYkPyE4FRYJMCT+jnPjgUMmJAWUELU+RA9g8HGBb0Sp3GeT5XUJ2VTz0AFAi5eoM+3rvQybyoW2cdpFYpbsjFgDBgDxoAxYAwYA8aAMWAMGAPGgDFgDBgDxoAxYAwYA8aAMWAMGAPGgDFgDBgDxoAxYAwYA8aAMWAMGAPGgDFgDBgDxoAxYAwYA8aAMWAMGAPGgDGQAgb+D9zgBhreD67WAAAAAElFTkSuQmCC";function B_({marker:e}){return u.jsxs(Yw,{center:{lat:33.35910359999967,lng:126.53439149999889},style:{width:"100%",height:"600px",borderRadius:"10px",border:"1px solid #4771B7"},level:10,children:[u.jsx(Xw,{position:kakao.maps.ControlPosition.TOPLEFT}),u.jsx(qw,{position:kakao.maps.ControlPosition.TOPRIGHT}),e.map(t=>u.jsx(V_,{position:{lat:t.latitude,lng:t.longitude},content:t},t.storeId))]})}const V_=({position:e,content:t})=>{const[n,r]=w.useState(!1),[o,s]=w.useState("");return w.useEffect(()=>{switch(t.category){case"์Šค๋…ธํด๋ง/๋‹ค์ด๋น™":return s(D_);case"์ˆ˜์ƒ๋ ˆ์ €":return s(__);case"์„œํ•‘":return s(O_);case"์Šน๋งˆ":return s(M_);case"ATV":return s(I_)}},[]),u.jsxs(u.Fragment,{children:[u.jsx(Qw,{position:e,onClick:()=>r(i=>!i),image:{src:o&&o,size:{width:40,height:43}}}),n&&u.jsx(N_,{position:e,yAnchor:1,children:u.jsxs(z_,{children:[u.jsxs("div",{children:[u.jsx("div",{className:"mb-1 font-medium text-xs text-gray-400",children:t.category}),u.jsx(Ie,{to:`/category/${t.storeId}`,className:"font-bold hover:text-[#4771B7] duration-300",children:t.storeName})]}),u.jsx("button",{className:"absolute top-1 right-2 text-right font-bold",onClick:()=>r(!1),children:u.jsx(Gw,{size:"22"})})]})})]})},z_=b.section` + relative + min-w-[150px] + bg-white/60 + backdrop-blur-sm + px-3 py-2 + border-[1px] border-black rounded-[10px] +`,F_=b.div` + w-[400vw] + flex + overflow-hidden + duration-1000 +`,U_=b.div` + absolute top-[50%] left-[3%] + translate-y-[-50%] + cursor-pointer +`,$_=b.div` + absolute top-[50%] right-[3%] + translate-y-[-50%] + cursor-pointer +`,W_=Be({key:"homeDataState",default:{}});function H_(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=Re(W_),[r,o]=w.useState(0),s={0:"translate-x-0 bg-[#4770b755]",1:"translate-x-[-100vw] bg-[#879fa8]",2:"translate-x-[-200vw] bg-[#e4c767]",3:"translate-x-[-300vw] bg-[#678fe4]"},i=()=>{o(r===0?t.recommend.length-1:r-1)},a=()=>{r===t.recommend.length-1?o(0):o(r+1)},l=async()=>{const d=await(await fetch(`${e}/main`)).json();n(d)};return w.useEffect(()=>{if(t.recommend){const c=setInterval(()=>{r===t.recommend.length-1?o(0):o(r+1)},3e3);return()=>{clearInterval(c)}}},[r,t]),w.useEffect(()=>{window.scrollTo(0,0);try{l()}catch(c){console.error(c)}},[]),u.jsxs("section",{children:[u.jsxs("section",{className:"relative overflow-x-hidden",children:[u.jsx(F_,{className:`${s[r]}`,children:t.recommend&&t.recommend.map(c=>u.jsx(j_,{data:c},c.storeId))}),u.jsx(U_,{onClick:i,children:u.jsx(Ww,{className:"arrow-left",size:"60",color:"white"})}),u.jsx($_,{onClick:a,children:u.jsx(Hw,{className:"arrow-right",size:"60",color:"white"})})]}),u.jsxs("section",{className:"w-[70%] mt-10 mx-auto",children:[u.jsx("div",{className:"font-bold text-2xl mb-5",children:"๋ชจ๋“  ๋ ˆ์ € ํ•œ๋ˆˆ์— ๋ณด๊ธฐ"}),u.jsx("div",{className:"rounded-xl h-[600px] mb-20",children:t.data&&u.jsx(B_,{marker:t.data})})]})]})}var Up={};Object.defineProperty(Up,"__esModule",{value:!0});var fc=Up.recoilPersist=void 0;const G_=(e={})=>{if(typeof window>"u")return{persistAtom:()=>{}};const{key:t="recoil-persist",storage:n=localStorage,converter:r=JSON}=e,o=({onSet:c,node:d,trigger:f,setSelf:p})=>{if(f==="get"){const h=i();typeof h.then=="function"&&h.then(v=>{v.hasOwnProperty(d.key)&&p(v[d.key])}),h.hasOwnProperty(d.key)&&p(h[d.key])}c(async(h,v,x)=>{const C=i();typeof C.then=="function"?C.then(g=>s(h,g,d.key,x)):s(h,C,d.key,x)})},s=(c,d,f,p)=>{p?delete d[f]:d[f]=c,l(d)},i=()=>{const c=n.getItem(t);return c==null?{}:typeof c=="string"?a(c):typeof c.then=="function"?c.then(a):{}},a=c=>{if(c===void 0)return{};try{return r.parse(c)}catch(d){return console.error(d),{}}},l=c=>{try{typeof n.mergeItem=="function"?n.mergeItem(t,r.stringify(c)):n.setItem(t,r.stringify(c))}catch(d){console.error(d)}};return{persistAtom:o}};fc=Up.recoilPersist=G_;const{persistAtom:$p}=fc(),mr=Be({key:"isLoginState",default:!1,effects_UNSTABLE:[$p]}),pc=Be({key:"isProfile",default:"",effects_UNSTABLE:[$p]}),Ti=Be({key:"Role",default:"",effects_UNSTABLE:[$p]});function nS(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+=e;else if(typeof e=="object")if(Array.isArray(e))for(t=0;ttypeof e=="number"&&!isNaN(e),Vr=e=>typeof e=="string",wt=e=>typeof e=="function",Ra=e=>Vr(e)||wt(e)?e:null,yu=e=>w.isValidElement(e)||Vr(e)||wt(e)||Vs(e);function K_(e,t,n){n===void 0&&(n=300);const{scrollHeight:r,style:o}=e;requestAnimationFrame(()=>{o.minHeight="initial",o.height=r+"px",o.transition=`all ${n}ms`,requestAnimationFrame(()=>{o.height="0",o.padding="0",o.margin="0",setTimeout(t,n)})})}function hc(e){let{enter:t,exit:n,appendPosition:r=!1,collapse:o=!0,collapseDuration:s=300}=e;return function(i){let{children:a,position:l,preventExitTransition:c,done:d,nodeRef:f,isIn:p}=i;const h=r?`${t}--${l}`:t,v=r?`${n}--${l}`:n,x=w.useRef(0);return w.useLayoutEffect(()=>{const C=f.current,g=h.split(" "),m=y=>{y.target===f.current&&(C.dispatchEvent(new Event("d")),C.removeEventListener("animationend",m),C.removeEventListener("animationcancel",m),x.current===0&&y.type!=="animationcancel"&&C.classList.remove(...g))};C.classList.add(...g),C.addEventListener("animationend",m),C.addEventListener("animationcancel",m)},[]),w.useEffect(()=>{const C=f.current,g=()=>{C.removeEventListener("animationend",g),o?K_(C,d,s):d()};p||(c?g():(x.current=1,C.className+=` ${v}`,C.addEventListener("animationend",g)))},[p]),V.createElement(V.Fragment,null,a)}}function $g(e,t){return e!=null?{content:e.content,containerId:e.props.containerId,id:e.props.toastId,theme:e.props.theme,type:e.props.type,data:e.props.data||{},isLoading:e.props.isLoading,icon:e.props.icon,status:t}:{}}const Bt={list:new Map,emitQueue:new Map,on(e,t){return this.list.has(e)||this.list.set(e,[]),this.list.get(e).push(t),this},off(e,t){if(t){const n=this.list.get(e).filter(r=>r!==t);return this.list.set(e,n),this}return this.list.delete(e),this},cancelEmit(e){const t=this.emitQueue.get(e);return t&&(t.forEach(clearTimeout),this.emitQueue.delete(e)),this},emit(e){this.list.has(e)&&this.list.get(e).forEach(t=>{const n=setTimeout(()=>{t(...[].slice.call(arguments,1))},0);this.emitQueue.has(e)||this.emitQueue.set(e,[]),this.emitQueue.get(e).push(n)})}},aa=e=>{let{theme:t,type:n,...r}=e;return V.createElement("svg",{viewBox:"0 0 24 24",width:"100%",height:"100%",fill:t==="colored"?"currentColor":`var(--toastify-icon-color-${n})`,...r})},xu={info:function(e){return V.createElement(aa,{...e},V.createElement("path",{d:"M12 0a12 12 0 1012 12A12.013 12.013 0 0012 0zm.25 5a1.5 1.5 0 11-1.5 1.5 1.5 1.5 0 011.5-1.5zm2.25 13.5h-4a1 1 0 010-2h.75a.25.25 0 00.25-.25v-4.5a.25.25 0 00-.25-.25h-.75a1 1 0 010-2h1a2 2 0 012 2v4.75a.25.25 0 00.25.25h.75a1 1 0 110 2z"}))},warning:function(e){return V.createElement(aa,{...e},V.createElement("path",{d:"M23.32 17.191L15.438 2.184C14.728.833 13.416 0 11.996 0c-1.42 0-2.733.833-3.443 2.184L.533 17.448a4.744 4.744 0 000 4.368C1.243 23.167 2.555 24 3.975 24h16.05C22.22 24 24 22.044 24 19.632c0-.904-.251-1.746-.68-2.44zm-9.622 1.46c0 1.033-.724 1.823-1.698 1.823s-1.698-.79-1.698-1.822v-.043c0-1.028.724-1.822 1.698-1.822s1.698.79 1.698 1.822v.043zm.039-12.285l-.84 8.06c-.057.581-.408.943-.897.943-.49 0-.84-.367-.896-.942l-.84-8.065c-.057-.624.25-1.095.779-1.095h1.91c.528.005.84.476.784 1.1z"}))},success:function(e){return V.createElement(aa,{...e},V.createElement("path",{d:"M12 0a12 12 0 1012 12A12.014 12.014 0 0012 0zm6.927 8.2l-6.845 9.289a1.011 1.011 0 01-1.43.188l-4.888-3.908a1 1 0 111.25-1.562l4.076 3.261 6.227-8.451a1 1 0 111.61 1.183z"}))},error:function(e){return V.createElement(aa,{...e},V.createElement("path",{d:"M11.983 0a12.206 12.206 0 00-8.51 3.653A11.8 11.8 0 000 12.207 11.779 11.779 0 0011.8 24h.214A12.111 12.111 0 0024 11.791 11.766 11.766 0 0011.983 0zM10.5 16.542a1.476 1.476 0 011.449-1.53h.027a1.527 1.527 0 011.523 1.47 1.475 1.475 0 01-1.449 1.53h-.027a1.529 1.529 0 01-1.523-1.47zM11 12.5v-6a1 1 0 012 0v6a1 1 0 11-2 0z"}))},spinner:function(){return V.createElement("div",{className:"Toastify__spinner"})}};function J_(e){const[,t]=w.useReducer(h=>h+1,0),[n,r]=w.useState([]),o=w.useRef(null),s=w.useRef(new Map).current,i=h=>n.indexOf(h)!==-1,a=w.useRef({toastKey:1,displayedToast:0,count:0,queue:[],props:e,containerId:null,isToastActive:i,getToast:h=>s.get(h)}).current;function l(h){let{containerId:v}=h;const{limit:x}=a.props;!x||v&&a.containerId!==v||(a.count-=a.queue.length,a.queue=[])}function c(h){r(v=>h==null?[]:v.filter(x=>x!==h))}function d(){const{toastContent:h,toastProps:v,staleId:x}=a.queue.shift();p(h,v,x)}function f(h,v){let{delay:x,staleId:C,...g}=v;if(!yu(h)||function(O){return!o.current||a.props.enableMultiContainer&&O.containerId!==a.props.containerId||s.has(O.toastId)&&O.updateId==null}(g))return;const{toastId:m,updateId:y,data:S}=g,{props:A}=a,L=()=>c(m),_=y==null;_&&a.count++;const k={...A,style:A.toastStyle,key:a.toastKey++,...Object.fromEntries(Object.entries(g).filter(O=>{let[N,D]=O;return D!=null})),toastId:m,updateId:y,data:S,closeToast:L,isIn:!1,className:Ra(g.className||A.toastClassName),bodyClassName:Ra(g.bodyClassName||A.bodyClassName),progressClassName:Ra(g.progressClassName||A.progressClassName),autoClose:!g.isLoading&&(M=g.autoClose,I=A.autoClose,M===!1||Vs(M)&&M>0?M:I),deleteToast(){const O=$g(s.get(m),"removed");s.delete(m),Bt.emit(4,O);const N=a.queue.length;if(a.count=m==null?a.count-a.displayedToast:a.count-1,a.count<0&&(a.count=0),N>0){const D=m==null?a.props.limit:1;if(N===1||D===1)a.displayedToast++,d();else{const H=D>N?N:D;a.displayedToast=H;for(let Z=0;ZW in xu)(D)&&(ne=xu[D](z))),ne}(k),wt(g.onOpen)&&(k.onOpen=g.onOpen),wt(g.onClose)&&(k.onClose=g.onClose),k.closeButton=A.closeButton,g.closeButton===!1||yu(g.closeButton)?k.closeButton=g.closeButton:g.closeButton===!0&&(k.closeButton=!yu(A.closeButton)||A.closeButton);let T=h;w.isValidElement(h)&&!Vr(h.type)?T=w.cloneElement(h,{closeToast:L,toastProps:k,data:S}):wt(h)&&(T=h({closeToast:L,toastProps:k,data:S})),A.limit&&A.limit>0&&a.count>A.limit&&_?a.queue.push({toastContent:T,toastProps:k,staleId:C}):Vs(x)?setTimeout(()=>{p(T,k,C)},x):p(T,k,C)}function p(h,v,x){const{toastId:C}=v;x&&s.delete(x);const g={content:h,props:v};s.set(C,g),r(m=>[...m,C].filter(y=>y!==x)),Bt.emit(4,$g(g,g.props.updateId==null?"added":"updated"))}return w.useEffect(()=>(a.containerId=e.containerId,Bt.cancelEmit(3).on(0,f).on(1,h=>o.current&&c(h)).on(5,l).emit(2,a),()=>{s.clear(),Bt.emit(3,a)}),[]),w.useEffect(()=>{a.props=e,a.isToastActive=i,a.displayedToast=n.length}),{getToastToRender:function(h){const v=new Map,x=Array.from(s.values());return e.newestOnTop&&x.reverse(),x.forEach(C=>{const{position:g}=C.props;v.has(g)||v.set(g,[]),v.get(g).push(C)}),Array.from(v,C=>h(C[0],C[1]))},containerRef:o,isToastActive:i}}function Wg(e){return e.targetTouches&&e.targetTouches.length>=1?e.targetTouches[0].clientX:e.clientX}function Hg(e){return e.targetTouches&&e.targetTouches.length>=1?e.targetTouches[0].clientY:e.clientY}function Y_(e){const[t,n]=w.useState(!1),[r,o]=w.useState(!1),s=w.useRef(null),i=w.useRef({start:0,x:0,y:0,delta:0,removalDistance:0,canCloseOnClick:!0,canDrag:!1,boundingRect:null,didMove:!1}).current,a=w.useRef(e),{autoClose:l,pauseOnHover:c,closeToast:d,onClick:f,closeOnClick:p}=e;function h(S){if(e.draggable){S.nativeEvent.type==="touchstart"&&S.nativeEvent.preventDefault(),i.didMove=!1,document.addEventListener("mousemove",g),document.addEventListener("mouseup",m),document.addEventListener("touchmove",g),document.addEventListener("touchend",m);const A=s.current;i.canCloseOnClick=!0,i.canDrag=!0,i.boundingRect=A.getBoundingClientRect(),A.style.transition="",i.x=Wg(S.nativeEvent),i.y=Hg(S.nativeEvent),e.draggableDirection==="x"?(i.start=i.x,i.removalDistance=A.offsetWidth*(e.draggablePercent/100)):(i.start=i.y,i.removalDistance=A.offsetHeight*(e.draggablePercent===80?1.5*e.draggablePercent:e.draggablePercent/100))}}function v(S){if(i.boundingRect){const{top:A,bottom:L,left:_,right:k}=i.boundingRect;S.nativeEvent.type!=="touchend"&&e.pauseOnHover&&i.x>=_&&i.x<=k&&i.y>=A&&i.y<=L?C():x()}}function x(){n(!0)}function C(){n(!1)}function g(S){const A=s.current;i.canDrag&&A&&(i.didMove=!0,t&&C(),i.x=Wg(S),i.y=Hg(S),i.delta=e.draggableDirection==="x"?i.x-i.start:i.y-i.start,i.start!==i.x&&(i.canCloseOnClick=!1),A.style.transform=`translate${e.draggableDirection}(${i.delta}px)`,A.style.opacity=""+(1-Math.abs(i.delta/i.removalDistance)))}function m(){document.removeEventListener("mousemove",g),document.removeEventListener("mouseup",m),document.removeEventListener("touchmove",g),document.removeEventListener("touchend",m);const S=s.current;if(i.canDrag&&i.didMove&&S){if(i.canDrag=!1,Math.abs(i.delta)>i.removalDistance)return o(!0),void e.closeToast();S.style.transition="transform 0.2s, opacity 0.2s",S.style.transform=`translate${e.draggableDirection}(0)`,S.style.opacity="1"}}w.useEffect(()=>{a.current=e}),w.useEffect(()=>(s.current&&s.current.addEventListener("d",x,{once:!0}),wt(e.onOpen)&&e.onOpen(w.isValidElement(e.children)&&e.children.props),()=>{const S=a.current;wt(S.onClose)&&S.onClose(w.isValidElement(S.children)&&S.children.props)}),[]),w.useEffect(()=>(e.pauseOnFocusLoss&&(document.hasFocus()||C(),window.addEventListener("focus",x),window.addEventListener("blur",C)),()=>{e.pauseOnFocusLoss&&(window.removeEventListener("focus",x),window.removeEventListener("blur",C))}),[e.pauseOnFocusLoss]);const y={onMouseDown:h,onTouchStart:h,onMouseUp:v,onTouchEnd:v};return l&&c&&(y.onMouseEnter=C,y.onMouseLeave=x),p&&(y.onClick=S=>{f&&f(S),i.canCloseOnClick&&d()}),{playToast:x,pauseToast:C,isRunning:t,preventExitTransition:r,toastRef:s,eventHandlers:y}}function rS(e){let{closeToast:t,theme:n,ariaLabel:r="close"}=e;return V.createElement("button",{className:`Toastify__close-button Toastify__close-button--${n}`,type:"button",onClick:o=>{o.stopPropagation(),t(o)},"aria-label":r},V.createElement("svg",{"aria-hidden":"true",viewBox:"0 0 14 16"},V.createElement("path",{fillRule:"evenodd",d:"M7.71 8.23l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75L1 11.98l3.75-3.75L1 4.48 2.48 3l3.75 3.75L9.98 3l1.48 1.48-3.75 3.75z"})))}function Z_(e){let{delay:t,isRunning:n,closeToast:r,type:o="default",hide:s,className:i,style:a,controlledProgress:l,progress:c,rtl:d,isIn:f,theme:p}=e;const h=s||l&&c===0,v={...a,animationDuration:`${t}ms`,animationPlayState:n?"running":"paused",opacity:h?0:1};l&&(v.transform=`scaleX(${c})`);const x=Wn("Toastify__progress-bar",l?"Toastify__progress-bar--controlled":"Toastify__progress-bar--animated",`Toastify__progress-bar-theme--${p}`,`Toastify__progress-bar--${o}`,{"Toastify__progress-bar--rtl":d}),C=wt(i)?i({rtl:d,type:o,defaultClassName:x}):Wn(x,i);return V.createElement("div",{role:"progressbar","aria-hidden":h?"true":"false","aria-label":"notification timer",className:C,style:v,[l&&c>=1?"onTransitionEnd":"onAnimationEnd"]:l&&c<1?null:()=>{f&&r()}})}const Q_=e=>{const{isRunning:t,preventExitTransition:n,toastRef:r,eventHandlers:o}=Y_(e),{closeButton:s,children:i,autoClose:a,onClick:l,type:c,hideProgressBar:d,closeToast:f,transition:p,position:h,className:v,style:x,bodyClassName:C,bodyStyle:g,progressClassName:m,progressStyle:y,updateId:S,role:A,progress:L,rtl:_,toastId:k,deleteToast:M,isIn:I,isLoading:T,iconOut:O,closeOnClick:N,theme:D}=e,H=Wn("Toastify__toast",`Toastify__toast-theme--${D}`,`Toastify__toast--${c}`,{"Toastify__toast--rtl":_},{"Toastify__toast--close-on-click":N}),Z=wt(v)?v({rtl:_,position:h,type:c,defaultClassName:H}):Wn(H,v),ne=!!L||!a,z={closeToast:f,type:c,theme:D};let W=null;return s===!1||(W=wt(s)?s(z):w.isValidElement(s)?w.cloneElement(s,z):rS(z)),V.createElement(p,{isIn:I,done:M,position:h,preventExitTransition:n,nodeRef:r},V.createElement("div",{id:k,onClick:l,className:Z,...o,style:x,ref:r},V.createElement("div",{...I&&{role:A},className:wt(C)?C({type:c}):Wn("Toastify__toast-body",C),style:g},O!=null&&V.createElement("div",{className:Wn("Toastify__toast-icon",{"Toastify--animate-icon Toastify__zoom-enter":!T})},O),V.createElement("div",null,i)),W,V.createElement(Z_,{...S&&!ne?{key:`pb-${S}`}:{},rtl:_,theme:D,delay:a,isRunning:t,isIn:I,closeToast:f,hide:d,type:c,style:y,className:m,controlledProgress:ne,progress:L||0})))},mc=function(e,t){return t===void 0&&(t=!1),{enter:`Toastify--animate Toastify__${e}-enter`,exit:`Toastify--animate Toastify__${e}-exit`,appendPosition:t}},X_=hc(mc("bounce",!0));hc(mc("slide",!0));hc(mc("zoom"));hc(mc("flip"));const Vo=w.forwardRef((e,t)=>{const{getToastToRender:n,containerRef:r,isToastActive:o}=J_(e),{className:s,style:i,rtl:a,containerId:l}=e;function c(d){const f=Wn("Toastify__toast-container",`Toastify__toast-container--${d}`,{"Toastify__toast-container--rtl":a});return wt(s)?s({position:d,rtl:a,defaultClassName:f}):Wn(f,Ra(s))}return w.useEffect(()=>{t&&(t.current=r.current)},[]),V.createElement("div",{ref:r,className:"Toastify",id:l},n((d,f)=>{const p=f.length?{...i}:{...i,pointerEvents:"none"};return V.createElement("div",{className:c(d),style:p,key:`container-${d}`},f.map((h,v)=>{let{content:x,props:C}=h;return V.createElement(Q_,{...C,isIn:o(C.toastId),style:{...C.style,"--nth":v+1,"--len":f.length},key:`toast-${C.key}`},x)}))}))});Vo.displayName="ToastContainer",Vo.defaultProps={position:"top-right",transition:X_,autoClose:5e3,closeButton:rS,pauseOnHover:!0,pauseOnFocusLoss:!0,closeOnClick:!0,draggable:!0,draggablePercent:80,draggableDirection:"x",role:"alert",theme:"light"};let wu,Cr=new Map,Cs=[],q_=1;function oS(){return""+q_++}function eI(e){return e&&(Vr(e.toastId)||Vs(e.toastId))?e.toastId:oS()}function zs(e,t){return Cr.size>0?Bt.emit(0,e,t):Cs.push({content:e,options:t}),t.toastId}function gl(e,t){return{...t,type:t&&t.type||e,toastId:eI(t)}}function la(e){return(t,n)=>zs(t,gl(e,n))}function pe(e,t){return zs(e,gl("default",t))}pe.loading=(e,t)=>zs(e,gl("default",{isLoading:!0,autoClose:!1,closeOnClick:!1,closeButton:!1,draggable:!1,...t})),pe.promise=function(e,t,n){let r,{pending:o,error:s,success:i}=t;o&&(r=Vr(o)?pe.loading(o,n):pe.loading(o.render,{...n,...o}));const a={isLoading:null,autoClose:null,closeOnClick:null,closeButton:null,draggable:null},l=(d,f,p)=>{if(f==null)return void pe.dismiss(r);const h={type:d,...a,...n,data:p},v=Vr(f)?{render:f}:f;return r?pe.update(r,{...h,...v}):pe(v.render,{...h,...v}),p},c=wt(e)?e():e;return c.then(d=>l("success",i,d)).catch(d=>l("error",s,d)),c},pe.success=la("success"),pe.info=la("info"),pe.error=la("error"),pe.warning=la("warning"),pe.warn=pe.warning,pe.dark=(e,t)=>zs(e,gl("default",{theme:"dark",...t})),pe.dismiss=e=>{Cr.size>0?Bt.emit(1,e):Cs=Cs.filter(t=>e!=null&&t.options.toastId!==e)},pe.clearWaitingQueue=function(e){return e===void 0&&(e={}),Bt.emit(5,e)},pe.isActive=e=>{let t=!1;return Cr.forEach(n=>{n.isToastActive&&n.isToastActive(e)&&(t=!0)}),t},pe.update=function(e,t){t===void 0&&(t={}),setTimeout(()=>{const n=function(r,o){let{containerId:s}=o;const i=Cr.get(s||wu);return i&&i.getToast(r)}(e,t);if(n){const{props:r,content:o}=n,s={delay:100,...r,...t,toastId:t.toastId||e,updateId:oS()};s.toastId!==e&&(s.staleId=e);const i=s.render||o;delete s.render,zs(i,s)}},0)},pe.done=e=>{pe.update(e,{progress:1})},pe.onChange=e=>(Bt.on(4,e),()=>{Bt.off(4,e)}),pe.POSITION={TOP_LEFT:"top-left",TOP_RIGHT:"top-right",TOP_CENTER:"top-center",BOTTOM_LEFT:"bottom-left",BOTTOM_RIGHT:"bottom-right",BOTTOM_CENTER:"bottom-center"},pe.TYPE={INFO:"info",SUCCESS:"success",WARNING:"warning",ERROR:"error",DEFAULT:"default"},Bt.on(2,e=>{wu=e.containerId||e,Cr.set(wu,e),Cs.forEach(t=>{Bt.emit(0,t.content,t.options)}),Cs=[]}).on(3,e=>{Cr.delete(e.containerId||e),Cr.size===0&&Bt.off(0).off(1).off(5)});const tI=b.div` + flex + flex-col + items-center + mb-[40px] +`,nI=b.div` + flex + justify-center + items-center + mb-[50px] + min-h-[60vh] +`,rI=b.div` + flex + flex-col + items-center + justify-center + w-[400px] + h-[500px] + border + rounded-[10px] + border-[#4771B7] + bg-[#EDF1F8] +`,oI=b.p` + text-center + text-[20px] + font-medium + my-[30px] +`,Wp="/assets/headerlogo-2a4f0716.svg",sI=b.button` +border +border-[#D8D8D8] +h-[35px] +w-[255px] +my-[4px] +cursor-pointer +text-[13px] +py-[5px] +my-[8px] +rounded-[10px] +font-semibold +text-center +`;function vl({children:e,color:t,bgColor:n,clickHandler:r,disabled:o}){const s={backgroundColor:n,color:t};return u.jsx(sI,{onClick:r,style:s,disabled:o,children:e})}const sS="/assets/google-60b8f21d.svg";function iI(){const e=qe(),t="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[n,r]=w.useState(!1),[o,s]=w.useState({email:"",password:""}),i=Xe(mr),a=Xe(pc),l=Xe(Ti),c=h=>{const{name:v,value:x}=h.target;s({...o,[v]:x})},d=async h=>{if(r(!0),!n){h.preventDefault();try{const v=await fetch(`${t}/auth/login`,{method:"POST",headers:{"Access-Control-Allow-Origin":"*"},body:JSON.stringify({username:o.email,password:o.password}),credentials:"include"}),x=await v.json(),C=v.headers.get("Authorization"),g=x.nickname,m=x.profileImage,y=x.role;v.ok?(i(!0),pe(`๐ŸŒŠ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ! ${g}๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค `),setTimeout(()=>{e("/home"),i(!0)},2e3),a(m),l(y),sessionStorage.setItem("Authorization",C)):v.status===401&&(pe("๐Ÿšจ ์ด๋ฉ”์ผ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"),setTimeout(()=>{r(!1)},3e3))}catch(v){console.error(v),pe("๐Ÿšจ ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค!"),setTimeout(()=>{r(!1)},3e3)}}},f=h=>{if(h.key==="Enter"){if(r(!0),n)return;d(h)}},p=async h=>{h.preventDefault(),window.location.href=`${t}/oauth2/authorization/google`};return u.jsxs(nI,{children:[u.jsx(Vo,{toastClassName:"h-[20px] rounded-md text-sm font-medium bg-[#EDF1F8] text-[#4771B7] text-center mt-[70px]",position:"top-center",limit:1,closeButton:!1,autoClose:2e3,hideProgressBar:!0}),u.jsxs(rI,{children:[u.jsx("img",{src:Wp,className:"pl-[30px]"}),u.jsxs(oI,{children:["๋ ˆ์ € ์Šคํฌ์ธ ๋Š”",u.jsx("br",{})," ",u.jsx("span",{className:"text-[#4771B7]",children:"์•กํ‹ฐ์˜จ"}),"์—์„œ ์‹œ์ž‘ํ•ด๋ณด์„ธ์š”."]}),u.jsxs(tI,{children:[u.jsxs("div",{children:[u.jsx("label",{htmlFor:"email",className:"font-medium",children:"์ด๋ฉ”์ผ"}),u.jsx("input",{id:"email",name:"email",type:"text",value:o.email,onChange:c,className:"border border-[#9A9A9A] text-[13px] h-[30px] w-[200px] ml-4 rounded-md mb-3 p-2",onKeyDown:f})]}),u.jsxs("div",{children:[u.jsx("label",{htmlFor:"password",className:"font-medium",children:"๋น„๋ฐ€๋ฒˆํ˜ธ"}),u.jsx("input",{id:"password",name:"password",type:"password",value:o.password,onChange:c,className:"border border-[#9A9A9A] text-[13px] h-[30px] w-[200px] ml-3 rounded-md mr-3 p-2",onKeyDown:f})]})]}),u.jsx(vl,{bgColor:"#FFFFFF",color:"#000000",clickHandler:p,children:u.jsxs("div",{className:"flex justify-center items-center",children:[u.jsx("img",{src:sS,className:"mr-2"}),u.jsx("span",{className:"font-medium",children:"๊ตฌ๊ธ€๋กœ ๋กœ๊ทธ์ธํ•˜๊ธฐ"})]})}),u.jsx(vl,{bgColor:"#4771B7",color:"#FFFFFF",clickHandler:d,children:u.jsx("span",{className:"font-medium",children:"๋กœ๊ทธ์ธ"})})]})]})}const aI=b.div` + flex + justify-center + items-center + mb-[50px] + min-h-[60vh] +`,lI=b.div` + flex + flex-col + items-center + justify-center + w-[540px] + h-[550px] + border + rounded-[10px] + border-[#4771B7] + bg-[#EDF1F8] +`,fs=b.p` + text-[12px] + pt-1 + h-[20px] + text-red-500 +`,ps=b.div` + pr-4 +`,hs=b.input` + border-[1px] + border-[#9A9A9A] + rounded-md + p-2 + py-[2px] + w-[280px] + h-[30px] + text-[13px] +`,ms=b.label` + mr-[15px] +`;function cI(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",t=qe(),[n,r]=w.useState(!1),[o,s]=w.useState(""),[i,a]=w.useState({name:"",password:"",email:"",phone:""}),[l,c]=w.useState(""),[d,f]=w.useState(""),[p,h]=w.useState(""),[v,x]=w.useState(""),[C,g]=w.useState(""),[m,y]=w.useState(!0),S=k=>{const{name:M,value:I}=k.target;if(M==="name"){if(!I){f("");return}/^[a-zA-Z0-9]{4,}$/.test(I)?f("์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค."):f("์˜๋ฌธ, ์ˆซ์ž๋กœ๋งŒ 4์ž ์ด์ƒ์œผ๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.")}else if(M==="email"){if(!I){c("");return}I&&/^[A-Za-z0-9_]+[A-Za-z0-9]*[@]{1}[A-Za-z0-9]+[A-Za-z0-9]*[.]{1}[A-Za-z]{1,3}$/.test(I)?c("์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค."):c("์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค.")}else if(M==="password"){if(!I){h("");return}/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/.test(I)?h("์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค."):h("์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์—ฌ 8์ž ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.")}else if(M==="passwordConfirm"){if(!I){x("");return}i.password===I?x("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค."):x("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")}else if(M==="phone"){if(!I){g("");return}const T=/^(010)-[0-9]{4}-[0-9]{4}$/;let O="";O=I.replace(/(\d{3})(\d{4})(\d{4})/,"$1-$2-$3"),s(O),T.test(O)?g("์˜ฌ๋ฐ”๋ฅธ ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์ž…๋‹ˆ๋‹ค."):g("์ „ํ™”๋ฒˆํ˜ธ์— -๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.")}a({...i,[M]:I})};w.useEffect(()=>{y(!(l==="์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค."&&d==="์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค."&&p==="์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค."&&v==="๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค."&&C==="์˜ฌ๋ฐ”๋ฅธ ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์ž…๋‹ˆ๋‹ค."))},[l,d,p,v,C]);const A=async k=>{if(k.preventDefault(),r(!0),!n)if(m)alert("๐Ÿšจ ๊ฐ€์ž…์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•ด์ฃผ์„ธ์š” !"),setTimeout(()=>{r(!1)},3e3);else try{const M=await fetch(`${e}/signup`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:i.email,password:i.password,phoneNumber:i.phone,nickname:i.name})});M.ok?(pe("ํšŒ์›๊ฐ€์ž…์„ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค !"),setTimeout(()=>{t("/login")},2e3)):M.status===403?(pe("๐Ÿšจ ์ค‘๋ณต๋œ ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค."),setTimeout(()=>{r(!1)},3e3)):M.status===409?(pe("๐Ÿšจ ์ค‘๋ณต๋œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค."),setTimeout(()=>{r(!1)},3e3)):M.status===422&&(pe("๐Ÿšจ ์ค‘๋ณต๋œ ์ „ํ™”๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค."),setTimeout(()=>{r(!1)},3e3))}catch(M){console.error("ํšŒ์›๊ฐ€์ž… ์š”์ฒญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค",M),setTimeout(()=>{r(!1)},3e3)}},L=async k=>{k.preventDefault(),window.location.href=`${e}/oauth2/authorization/google`},_=k=>{k.key==="Enter"&&A(k)};return u.jsxs(aI,{children:[u.jsx(Vo,{toastClassName:"h-[20px] rounded-md text-sm font-medium bg-[#EDF1F8] text-[#4771B7] text-center mt-[70px]",position:"top-center",limit:1,closeButton:!1,autoClose:3e3,hideProgressBar:!0}),u.jsxs(lI,{children:[u.jsxs("div",{className:"flex pt-2",children:[u.jsx(ms,{htmlFor:"email",children:"์ด๋ฉ”์ผ"}),u.jsxs(ps,{children:[u.jsx(hs,{id:"email",name:"email",type:"email",value:i.email,onChange:S,onKeyDown:_}),u.jsx(fs,{className:l==="์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค."?"text-[#21C55D]":"text-red-600",children:l})]})]}),u.jsxs("div",{className:"flex pt-2",children:[u.jsx(ms,{htmlFor:"name",children:"๋‹‰๋„ค์ž„"}),u.jsxs(ps,{children:[u.jsx(hs,{id:"name",name:"name",type:"text",value:i.name,onChange:S,onKeyDown:_}),u.jsx(fs,{className:d==="์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค."?"text-[#21C55D]":"text-red-600",children:d})]})]}),u.jsxs("div",{className:"flex pt-2 pr-[12px]",children:[u.jsx(ms,{htmlFor:"password",children:"๋น„๋ฐ€๋ฒˆํ˜ธ"}),u.jsxs(ps,{children:[u.jsx(hs,{id:"password",name:"password",type:"password",value:i.password,onChange:S,onKeyDown:_}),u.jsx(fs,{className:p==="์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค."?"text-[#21C55D]":"text-red-600",children:p})]})]}),u.jsxs("div",{className:"flex pt-2 pr-[50px]",children:[u.jsx(ms,{htmlFor:"passwordConfirm",children:"๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ"}),u.jsxs(ps,{children:[u.jsx(hs,{id:"passwordConfirm",name:"passwordConfirm",type:"password",onChange:S,onKeyDown:_}),u.jsx(fs,{className:v==="๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค."?"text-[#21C55D]":"text-red-600",children:v})]})]}),u.jsxs("div",{className:"flex pt-2 pr-[15px] mb-[30px]",children:[u.jsx(ms,{htmlFor:"phone",children:"์ „ํ™”๋ฒˆํ˜ธ"}),u.jsxs(ps,{children:[u.jsx(hs,{id:"phone",type:"text",name:"phone",value:o,onChange:S,onKeyDown:_,maxLength:13}),u.jsx(fs,{className:C==="์˜ฌ๋ฐ”๋ฅธ ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์ž…๋‹ˆ๋‹ค."?"text-[#21C55D]":"text-red-600",children:C})]})]}),u.jsx(vl,{bgColor:"#FFFFFF",color:"#000000",clickHandler:L,children:u.jsxs("div",{className:"flex justify-center items-center",children:[u.jsx("img",{src:sS,className:"mr-2"}),u.jsx("span",{className:"font-medium",children:"๊ตฌ๊ธ€๋กœ ํšŒ์›๊ฐ€์ž…ํ•˜๊ธฐ"})]})}),u.jsx(vl,{bgColor:"#4771B7",color:"#FFFFFF",clickHandler:A,disabled:n,children:u.jsx("span",{className:"font-medium",children:"๊ฐ€์ž… ์ง„ํ–‰ํ•˜๊ธฐ"})})]})]})}const uI=b.div` + flex + justify-center + items-center + min-h-[77vh] +`,dI=b.div` + flex + flex-col + justify-center + w-[700px] +`,fI=b.p` + text-2xl + font-semibold + justify-start + p-10 +`,pI=b.form` + justify-center +`,hI=b.div` + flex + space-x-5 + justify-end + py-2 +`,Qd=b.input` + border-[1px] + border-[#9A9A9A] + rounded-md + w-[78%] + px-2 + py-[2px] +`,mI=b.div` + flex + space-x-4 + justify-end + py-2 +`,gI=b.input` + border-[1px] + border-[#9A9A9A] + rounded-md + w-[100%] + px-2 + py-[2px] +`,vI=b.p` + pt-1 + text-gray-950 +`,yI=b.p` + pt-1 + text-green-500 +`,xI=b.p` + pt-1 + text-amber-600 +`,Gg=b.p` + pt-1 + text-red-500 +`,wI=b.div` + flex + space-x-5 + justify-end + py-2 +`,SI=b.div` + flex + space-x-5 + justify-end + py-2 +`,CI=b.div` + flex + space-x-5 + justify-end + w-[55%] +`,bI=b.label` + w-[9%] +`,AI=b.input` + border-[1px] + border-[#9A9A9A] + rounded-md + w-[60%] + px-2 + py-[2px] +`,kI=b.div` + flex + space-x-5 + justify-end + w-[45%] +`,EI=b.div` + flex + flex-row + justify-end + py-2 +`,RI=b.button` + font-semibold + rounded-md + text-xl + px-14 + py-3 + bg-[#4771B7] + text-white +`,TI=b.button` + font-semibold + text-xl + px-14 + py-3 + opacity-50 + bg-[#4771B7] + text-white + cursor-default +`,jI=b.div` + flex + justify-center + pt-4 +`;function PI({repreName:e,handleRepreNameChange:t}){return u.jsxs(hI,{children:[u.jsx("label",{children:"๋Œ€ํ‘œ์ž ๋ช…"}),u.jsx(Qd,{placeholder:"ex. ํ™๊ธธ๋™",type:"text",value:e,onChange:t})]})}function NI({regiNumber:e,handleRegiNumberChange:t,isInputTouched:n,isRegiNumberIncomplete:r,isRegiNumberValid:o,setIsInputTouched:s,isDuplicateChecked:i,setIsDuplicateChecked:a}){const l="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[c,d]=w.useState(!1),[f,p]=w.useState(""),h=async()=>{try{const v=sessionStorage.getItem("Authorization"),x=await fetch(`${l}/partners/verify?number=${e}`,{method:"GET",headers:{Authorization:v}});x.ok?x.status===200&&(d(!1),p("์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค."),a(!0),alert("์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‚ฌ์—…์ž๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.")):(d(!0),p("์ค‘๋ณต๋œ ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค."),a(!0),alert("์ค‘๋ณต๋œ ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค."))}catch(v){console.error("์ค‘๋ณตํ™•์ธ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.",v)}};return w.useEffect(()=>{a(!1)},[e]),u.jsxs(mI,{children:[u.jsx("label",{children:"์‚ฌ์—…์ž๋“ฑ๋ก๋ฒˆํ˜ธ"}),u.jsxs("div",{className:"w-[78%] flex flex-row",children:[u.jsxs("div",{className:"pr-4 w-[100%]",children:[u.jsx(gI,{placeholder:"ex. 123-45-67890",type:"text",value:e,onChange:t,maxLength:12,onBlur:()=>s(!0)}),n&&!e&&u.jsx(vI,{children:"์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."}),!i&&o&&u.jsx(xI,{children:"์ค‘๋ณตํ™•์ธ์„ ์ง„ํ–‰ํ•ด์ฃผ์„ธ์š”."}),o&&i&&u.jsx(yI,{children:f}),r&&u.jsx(Gg,{children:"์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ๋Š” 10์ž๋ฆฌ๋กœ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."}),c&&i&&u.jsx(Gg,{children:f})]}),u.jsx("button",{className:`rounded-md px-4 h-7 w-28 bg-[#4771B7] text-white ${o?"cursor-pointer":"opacity-50 bg-[#4771B7] cursor-default"}`,type:"button",disabled:!o,onClick:h,children:"์ค‘๋ณตํ™•์ธ"})]})]})}const LI=b.select` + border-[1px] + border-[#9A9A9A] + rounded-md + w-[100%] + mr-[40px] + px-2 + py-[4px] +`;function _I({value:e,onChange:t}){return u.jsxs(LI,{value:e,onChange:t,children:[u.jsx("option",{value:"select",children:"์„ ํƒ"}),u.jsx("option",{value:"์Šคํฌ์ธ  ์„œ๋น„์Šค์—…",children:"์Šคํฌ์ธ  ์„œ๋น„์Šค์—…"},"sprtsService"),u.jsx("option",{value:"์œก์ƒ ์˜ค๋ฝ๊ด€๋ จ ์„œ๋น„์Šค์—…",children:"์œก์ƒ ์˜ค๋ฝ๊ด€๋ จ ์„œ๋น„์Šค์—…"},"groundSports"),u.jsx("option",{value:"ํ•ด์ƒ ์˜ค๋ฝ๊ด€๋ จ ์„œ๋น„์Šค์—…",children:"ํ•ด์ƒ ์˜ค๋ฝ๊ด€๋ จ ์„œ๋น„์Šค์—…"},"oceanSports")]})}function II({businessSector:e,setBusinessSector:t}){return u.jsxs(EI,{children:[u.jsxs(CI,{children:[u.jsx(bI,{children:"์—…ํƒœ"}),u.jsx(AI,{type:"text",name:"business",value:"์Šคํฌ์ธ  ๋ฐ ์—ฌ๊ฐ€๊ด€๋ จ ์„œ๋น„์Šค์—…",readOnly:!0,onClick:n=>n.preventDefault(),style:{pointerEvents:"none"}})]}),u.jsxs(kI,{children:[u.jsx("label",{children:"์—…์ข…"}),u.jsx("div",{children:u.jsx(_I,{value:e,onChange:n=>t(n.target.value)})})]})]})}function MI({isFormValid:e,handleSubmit:t,businessSector:n,isDuplicateChecked:r}){const s=e&&!(n==="select")&&r;return u.jsx(jI,{children:s?u.jsx(RI,{type:"button",onClick:t,children:"๋“ฑ๋กํ•˜๊ธฐ"}):u.jsx(TI,{type:"button",children:"๋“ฑ๋กํ•˜๊ธฐ"})})}function DI(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",t=qe(),[n,r]=Re(mr),[o,s]=w.useState(""),[i,a]=w.useState(""),[l,c]=w.useState(""),[d,f]=w.useState(""),[p,h]=w.useState("select"),[v,x]=w.useState(!1),[C,g]=w.useState(!1),m=k=>{const T=k.target.value.replace(/\D/g,"").slice(0,10).replace(/(\d{3})(\d{2})(\d{5})/,"$1-$2-$3");s(T)},y=o.match(/^\d{3}-\d{2}-\d{5}$/),S=o.length>0&&!y,A=new Date().toISOString().split("T")[0];w.useEffect(()=>{x(!0)},[]);const L=o&&y&&i.length>0&&l.length>0&&d.length>0&&p!=="select",_=async k=>{k.preventDefault();const M={owner:i,businessName:l,registrationNumber:o,businessCategory:p};try{const I=sessionStorage.getItem("Authorization"),T=await fetch(`${e}/partners`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:I},body:JSON.stringify(M),credentials:"include"});T.ok?T.status===201&&(alert("ํŒŒํŠธ๋„ˆ๋“ฑ๋ก์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํ•ด์ฃผ์„ธ์š”."),r(!1),sessionStorage.removeItem("Authorization"),t("/login")):alert("ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.")}catch(I){console.error("๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜: ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.",I)}};return u.jsx(uI,{children:u.jsx("div",{className:"p-10",children:u.jsxs(dI,{children:[u.jsx(fI,{children:"ํŒŒํŠธ๋„ˆ ๋“ฑ๋กํ•˜๊ธฐ"}),u.jsxs(pI,{children:[u.jsx(PI,{repreName:i,handleRepreNameChange:k=>a(k.target.value)}),u.jsx(NI,{regiNumber:o,handleRegiNumberChange:m,isInputTouched:v,isRegiNumberValid:y,isRegiNumberIncomplete:S,setIsInputTouched:x,isDuplicateChecked:C,setIsDuplicateChecked:g}),u.jsxs(wI,{children:[u.jsx("label",{children:"์—…์ฒด๋ช…"}),u.jsx(Qd,{placeholder:"ex. OO๋ ˆ์ €",type:"text",value:l,onChange:k=>c(k.target.value)})]}),u.jsxs(SI,{children:[u.jsx("label",{children:"๊ฐœ์—… ์ผ์ž"}),u.jsx(Qd,{placeholder:"2023-00-00",type:"date",value:d,max:A,onChange:k=>f(k.target.value)})]}),u.jsx(II,{businessSector:p,setBusinessSector:h}),u.jsx(MI,{isFormValid:L,handleSubmit:_,businessSector:p,isDuplicateChecked:C})]})]})})})}const iS=Be({key:"keyword",default:""}),Hp=Be({key:"search",default:!1}),aS=Be({key:"loading",default:!1}),Xr=b.div` + flex + flex-col + justify-center + items-center + transition duration-500 ease-in-out + hover:scale-110 +`,OI=b.div` + flex + justify-center + items-center + my-7 +`,BI=b.div` + flex + w-[700px] + justify-around + text-sm + grow-1 +`,VI="/assets/all-234340ae.svg",zI="/assets/atv-768e6dd8.svg",FI="/assets/diving-783d9b05.svg",UI="/assets/riding-bae27c4c.svg",$I="/assets/surf-91428e94.svg",WI="/assets/waterleisure-6804039d.svg";function HI(){return u.jsx(OI,{children:u.jsxs(BI,{children:[u.jsx(Xr,{children:u.jsxs(Ie,{to:"/category?category_name=all&sort=likeCount",children:[u.jsx("img",{src:VI,className:"w-[25px] mb-2 ml-[2px]"}),u.jsx("span",{children:"์ „์ฒด"})]})}),u.jsx(Xr,{children:u.jsxs(Ie,{to:"/category?category_name=์Šค๋…ธํด๋ง/๋‹ค์ด๋น™&sort=likeCount",children:[u.jsx("img",{src:FI,className:"w-[25px] mb-2 ml-[30px]"}),u.jsx("span",{children:"์Šค๋…ธํด๋ง/๋‹ค์ด๋น™"})]})}),u.jsx(Xr,{className:"mr-[10px]",children:u.jsxs(Ie,{to:"/category?category_name=์ˆ˜์ƒ๋ ˆ์ €&sort=likeCount",children:[u.jsx("img",{src:WI,className:"w-[25px] mb-2 ml-[12px]"}),u.jsx("span",{children:"์ˆ˜์ƒ๋ ˆ์ €"})]})}),u.jsx(Xr,{className:"mr-[10px]",children:u.jsxs(Ie,{to:"/category?category_name=์„œํ•‘&sort=likeCount",children:[u.jsx("img",{src:$I,className:"w-[25px] mb-2"}),u.jsx("span",{children:"์„œํ•‘"})]})}),u.jsx(Xr,{className:"mr-[10px]",children:u.jsxs(Ie,{to:"/category?category_name=์Šน๋งˆ&sort=likeCount",children:[u.jsx("img",{src:UI,className:"w-[25px] h-[25px] mb-2"}),u.jsx("span",{children:"์Šน๋งˆ"})]})}),u.jsx(Xr,{children:u.jsxs(Ie,{to:"/category?category_name=ATV&sort=likeCount",children:[u.jsx("img",{src:zI,className:"w-[25px] h-[25px] mb-2 ml-[2px]"}),u.jsx("span",{className:"mr-[10px]",children:"ATV"})]})})]})})}function lS(){const e=ze(Hp);return u.jsxs(u.Fragment,{children:[!e&&u.jsx(HI,{}),u.jsx(Ol,{})]})}function GI(e){return et({tag:"svg",attr:{role:"img",viewBox:"0 0 24 24"},child:[{tag:"title",attr:{},child:[]},{tag:"path",attr:{d:"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"}}]})(e)}function KI(e){return et({tag:"svg",attr:{role:"img",viewBox:"0 0 24 24"},child:[{tag:"title",attr:{},child:[]},{tag:"path",attr:{d:"M4.459 4.208c.746.606 1.026.56 2.428.466l13.215-.793c.28 0 .047-.28-.046-.326L17.86 1.968c-.42-.326-.981-.7-2.055-.607L3.01 2.295c-.466.046-.56.28-.374.466zm.793 3.08v13.904c0 .747.373 1.027 1.214.98l14.523-.84c.841-.046.935-.56.935-1.167V6.354c0-.606-.233-.933-.748-.887l-15.177.887c-.56.047-.747.327-.747.933zm14.337.745c.093.42 0 .84-.42.888l-.7.14v10.264c-.608.327-1.168.514-1.635.514-.748 0-.935-.234-1.495-.933l-4.577-7.186v6.952L12.21 19s0 .84-1.168.84l-3.222.186c-.093-.186 0-.653.327-.746l.84-.233V9.854L7.822 9.76c-.094-.42.14-1.026.793-1.073l3.456-.233 4.764 7.279v-6.44l-1.215-.139c-.093-.514.28-.887.747-.933zM1.936 1.035l13.31-.98c1.634-.14 2.055-.047 3.082.7l4.249 2.986c.7.513.934.653.934 1.213v16.378c0 1.026-.373 1.634-1.68 1.726l-15.458.934c-.98.047-1.448-.093-1.962-.747l-3.129-4.06c-.56-.747-.793-1.306-.793-1.96V2.667c0-.839.374-1.54 1.447-1.632z"}}]})(e)}const JI=b.section` + text-[#9b9b9b] text-sm font-medium + border-t-[1px] border-[#4771B7] + w-full h-[15vh] + flex justify-center + py-5 +`;function YI(){return u.jsxs(JI,{children:[u.jsxs("div",{children:[u.jsxs("div",{className:"flex items-center mb-3",children:[u.jsx("img",{className:"w-[100px]",src:_w,alt:"๋กœ๊ณ "}),u.jsx("div",{className:"ml-3",children:"ํŒ€์žฅ: ๊น€ํƒœ์šฐ | ๋ถ€ํŒ€์žฅ: ๊ฐ•๋™์šฐ | ํŒ€์›: ๊น€๋ฏผ์ง€, ํ˜„์ฑ„์€, ์‹ ์ด์ˆ˜"})]}),u.jsx("div",{className:"mb-3 font-bold text-[#9b9b9b]",children:"Copyright @ 2023 ActiOn"}),u.jsx("div",{className:"text-xs",children:"์ƒํ˜ธ๋ช… (์ฃผ)์•กํ‹ฐ์˜จ | ๋Œ€ํ‘œ ๊น€ํƒœ์šฐ | ๊ฐœ์ธ์ •๋ณด๋ณดํ˜ธ์ฑ…์ž„์ž ๊ฐ•๋™์šฐ | ์ด๋ฉ”์ผ zop1234@hanmail.net | ๋งˆ์ผ€ํŒ…/์ œํœด ๋ฌธ์˜ zop1234@hanmail.net | ๊ด‘๊ณ  ๋งค์ฒด ๋ฌธ์˜ zop1234@hanmail.net"})]}),u.jsxs("div",{className:"flex",children:[u.jsx("a",{href:"https://www.notion.so/codestates/IE5-8c32fc4f250f4bfea452017e93129644?pvs=4",children:u.jsx(KI,{className:"mr-5",size:"30"})}),u.jsx("a",{href:"https://github.com/codestates-seb/seb44_main_005",children:u.jsx(GI,{size:"30"})})]})]})}function Gp(){const e=ze(aS);return u.jsxs(u.Fragment,{children:[u.jsx(Ol,{}),!e&&u.jsx(YI,{})]})}const{persistAtom:ZI}=fc(),cS=Be({key:"open",default:!1,effects_UNSTABLE:[ZI]}),gc="/assets/profile-087f0ee3.svg",yl="/assets/search-03c9f968.svg",QI=b.div` + relative +`,XI=b.input` + z-40 + relative + border + border-[#4771B7] + rounded-[30px] + w-[500px] + h-[40px] + pl-5 + text-sm + focus:outline-none +`,qI=b.div` + z-10 + border-[0.5px] + border-t-none + border-[#4771B7] + absolute + w-[500px] + h-auto + bg-white + p-[8px] + top-[16px] + rounded-b-lg +`,e7=b.li` + z-10 + relative + px-[8px] + py-[4px] + w-full + + text-[14px] + font-medium + hover:bg-[#EDF1F8] + hover:text-[#4771B7] + cursor-pointer + tracking-[0.5px] +`,t7=b.img` + absolute + w-[16px] + right-[5px] + top-1.5 +`;function n7(){const[e,t]=Re(iS),[n,r]=w.useState([]),[o,s]=w.useState(!1),i=w.useRef(null),a=qe(),l="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",c=async()=>{try{const p=await fetch(`${l}/search?keyword=${encodeURIComponent(e)}`,{headers:{Authorization:sessionStorage.getItem("Authorization")}});if(!p.ok)throw new Error("Failed to fetch data");const h=await p.json();r(h.data)}catch(p){console.error(p)}},d=async()=>{try{await a(`/search?keyword=${encodeURIComponent(e)}`),t(e)}catch(p){console.error(p)}},f=p=>{p.key==="Enter"&&(i.current.blur(),d(),s(!1))};return w.useEffect(()=>{const p=setTimeout(()=>{e&&c()},100);return()=>{clearTimeout(p)}},[e]),u.jsxs(QI,{children:[u.jsx(XI,{type:"text",autoComplete:"off",id:"keyword",ref:i,value:e,onChange:p=>t(p.currentTarget.value),onKeyUp:f,placeholder:"์ƒํ’ˆ์„ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”",onFocus:()=>s(!0),onBlur:()=>s(!1)}),u.jsx("img",{src:yl,onClick:d,className:"absolute ml-2 w-[30px] top-[5px] left-[452px] cursor-pointer z-50"}),o&&n.length>0&&u.jsx(qI,{children:u.jsx("ul",{className:"pt-[20px]",children:n.map(p=>u.jsxs(e7,{onMouseDown:h=>{h.stopPropagation(),t(p.title),a(`/search?keyword=${encodeURIComponent(p.title)}`)},children:[u.jsx(t7,{src:yl,onClick:()=>s(!1)}),u.jsx("a",{href:`/search?keyword=${encodeURIComponent(e)}`,children:p.title})]},p.title))})})]})}const r7=b.header` + h-[8vh] + flex + justify-between + border-b-[0.5px] + border-[#4771B7] + w-full +`,o7=b.div` + flex + items-center + ml-5 +`,s7=b.div` + flex + justify-center + items-center + w-[200px] + text-sm +`,i7=b.div` + flex + justify-center + w-[400px] + text-sm + leading-0 + items-center +`,Kg=b.img` + w-[30px] + h-[30px] + ml-[40px] + transition duration-500 ease-in-out + focus:translate-y-6 + rounded-full + object-cover +`,a7=b.ul` + absolute + w-[120px] + top-[25px] + right-[10px] + text-center + border + border-[#4771B7] + rounded-[5px] + bg-[#D6DFEF] +`,Jg=b.li` + px-[25px] + py-[10px] + cursor-pointer + hover:text-[#4771B7] +`,l7=b.div` +relative +`;function c7(){const e=Xe(mr),t=Xe(cS),n=async()=>{confirm("์ •๋ง๋กœ ๋กœ๊ทธ์•„์›ƒ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ ?")==!0&&(await fetch("/logout",{method:"POST",headers:{"Content-Type":"application/json",Authorization:sessionStorage.getItem("Authorization"),"Access-Control-Allow-Origin":"*"},credentials:"include"}),t(!1),e(!1),localStorage.removeItem("recoil-persist"),sessionStorage.removeItem("Authorization"),sessionStorage.removeItem("memberId"),sessionStorage.removeItem("access_token"),window.location.href="/home")};return u.jsx(l7,{children:u.jsxs(a7,{children:[u.jsx(Jg,{className:"border-b-[1px] border-[#4771B7]",children:u.jsx(Ie,{to:"/my",onClick:()=>t(!1),children:"๋งˆ์ดํŽ˜์ด์ง€"})}),u.jsx(Jg,{children:u.jsx("div",{onClick:n,children:"๋กœ๊ทธ์•„์›ƒ"})})]})})}function u7(){const[e,t]=Re(cS),n=Xe(iS),r=ze(pc),o=ze(Ti),s=ze(mr),i=Xe(Hp),a=qe(),l=()=>{s?a("/partner"):(pe("๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค."),a("/login"))},c=()=>{a("/home"),i(!1),n("")},d=()=>{t(!e)};return u.jsxs(r7,{children:[u.jsxs(o7,{children:[u.jsx("img",{className:"w-[140px] h-[40px] cursor-pointer",alt:"logo",src:Wp,onClick:c}),u.jsx(n7,{})]}),s?u.jsxs(s7,{children:[u.jsx(Ie,{to:o==="PARTNER"?"/store/add":"/partner",className:"mt-1",children:o==="PARTNER"?"์—…์ฒด ๋“ฑ๋ก":"ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก"}),r!=="default image"?u.jsx(Kg,{src:r,onClick:d}):u.jsx(Kg,{src:gc,onClick:d}),e&&u.jsx(c7,{})]}):u.jsxs(i7,{children:[u.jsx("div",{className:"cursor-pointer mr-[50px]",onClick:l,children:"ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก"}),u.jsx(Ie,{to:"/login",className:"mr-[50px]",children:"๋กœ๊ทธ์ธ"}),u.jsx(Ie,{to:"/register",className:"border border-[#4771B7] text-[#4771B7] px-[30px] py-2",children:"ํšŒ์›๊ฐ€์ž…"})]})]})}function Kp(){return u.jsxs(u.Fragment,{children:[u.jsx(u7,{}),u.jsx(Ol,{})]})}function d7(){return u.jsx(Mp.div,{initial:{opacity:0,scale:.5},animate:{opacity:1,scale:1},transition:{duration:.8,delay:.5,ease:[0,.71,.2,1.01]},children:u.jsxs(Xf,{children:[u.jsx(xe,{path:"/",element:u.jsx(b_,{})}),u.jsx(xe,{element:u.jsx(Kp,{}),children:u.jsxs(xe,{element:u.jsx(Gp,{}),children:[u.jsx(xe,{path:"/partner",element:u.jsx(DI,{})}),u.jsxs(xe,{element:u.jsx(lS,{}),children:[u.jsx(xe,{path:"/home",element:u.jsx(H_,{})}),u.jsx(xe,{path:"/login",element:u.jsx(iI,{})}),u.jsx(xe,{path:"/register",element:u.jsx(cI,{})})]})]})})]})})}const f7=b.div` + flex + w-[800px] + h-[200px] + border + my-6 + border-[#AEC1DF] + hover:shadow-[0_0_20px_5px_#DCEAFF] + duration-300 +`,p7=b.div` + flex + flex-col + items-start + p-5 +`,h7=b.div` + flex + justify-between + font-semibold + w-[510px] + mt-[90px] +`,m7=b.div` + flex + mt-[5px] +`;function g7(e){return et({tag:"svg",attr:{fill:"currentColor",viewBox:"0 0 16 16"},child:[{tag:"path",attr:{d:"M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"}}]})(e)}function v7(e){return et({tag:"svg",attr:{fill:"currentColor",viewBox:"0 0 16 16"},child:[{tag:"path",attr:{d:"M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425a.247.247 0 0 1 .02-.022Z"}}]})(e)}function y7(e){return et({tag:"svg",attr:{viewBox:"0 0 256 256",fill:"currentColor"},child:[{tag:"path",attr:{d:"M240,94c0,70-103.79,126.66-108.21,129a8,8,0,0,1-7.58,0C119.79,220.66,16,164,16,94A62.07,62.07,0,0,1,78,32c20.65,0,38.73,8.88,50,23.89C139.27,40.88,157.35,32,178,32A62.07,62.07,0,0,1,240,94Z"}}]})(e)}function x7(e){return et({tag:"svg",attr:{viewBox:"0 0 256 256",fill:"currentColor"},child:[{tag:"path",attr:{d:"M178,32c-20.65,0-38.73,8.88-50,23.89C116.73,40.88,98.65,32,78,32A62.07,62.07,0,0,0,16,94c0,70,103.79,126.66,108.21,129a8,8,0,0,0,7.58,0C136.21,220.66,240,164,240,94A62.07,62.07,0,0,0,178,32ZM128,206.8C109.74,196.16,32,147.69,32,94A46.06,46.06,0,0,1,78,48c19.45,0,35.78,10.36,42.6,27a8,8,0,0,0,14.8,0c6.82-16.67,23.15-27,42.6-27a46.06,46.06,0,0,1,46,46C224,147.61,146.24,196.15,128,206.8Z"}}]})(e)}function uS({data:e}){const{storeId:t,img:n,title:r,reviewCount:o,address:s,rating:i,price:a,isLike:l}=e,c="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",d=qe(),[f,p]=w.useState(!1),[h,v]=w.useState(l),x=ze(mr),C=async m=>{m.stopPropagation(),p(!0),!f&&(x?f||(await fetch(`${c}/stores/favorites/${t}`,{method:"POST",headers:{Authorization:sessionStorage.getItem("Authorization")}})).ok&&(v(!0),pe("โค๏ธ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")):alert("๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."),setTimeout(()=>{p(!1)},5e3))},g=async m=>{m.stopPropagation(),p(!0),!f&&(f||(await fetch(`${c}/stores/favorites/${t}`,{method:"DELETE",headers:{Authorization:sessionStorage.getItem("Authorization")}})).ok&&(v(!1),pe("๐Ÿ–ค ์œ„์‹œ๋ฆฌ์ŠคํŠธ์—์„œ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")),setTimeout(()=>{p(!1)},5e3))};return u.jsxs(f7,{onClick:()=>d(`/category/${t}`),children:[u.jsx("img",{className:"w-[250px] h-[198px] object-cover",src:n,loading:"lazy"}),u.jsxs(p7,{children:[u.jsx(Ie,{to:`/category/${t}`,className:"font-semibold",children:r}),u.jsxs(m7,{children:[u.jsx("span",{className:"w-[20px] mr-[5px] mt-[2px]",children:u.jsx(g7,{size:"18",color:"#4771B7"})}),u.jsx("span",{className:"mr-[2px]",children:i.toFixed(1)}),u.jsxs("span",{className:"mr-[12px]",children:["(",o,")"]}),u.jsx("span",{children:s})]}),u.jsxs(h7,{children:[u.jsxs("span",{children:[a.toLocaleString("ko-KR"),"์› ~"]}),h?u.jsx(y7,{className:"hover:cursor-pointer",onClick:g,size:"24",color:"#4771B7"}):u.jsx(x7,{className:"hover:cursor-pointer",onClick:C,size:"24",color:"#4771B7"})]})]})]})}const w7=b.div` + flex + flex-col + min-h-[80vh] + mb-[70px] +`,S7=b.section` + flex + items-start + justify-center + my-[20px] + mt-[50px] + mx-[100px] +`,C7=b.div` + flex + w-[500px] + mt-[10px] + ml-[200px] + justify-center + text-sm +`,b7=b.div` + flex + flex-col + items-center + relative +`,A7=b.div` + fixed + right-[30px] + bottom-[40px] + w-[50px] + h-[50px] + rounded-full + text-white + bg-[#4771B7] + animate-topbounce +`,k7=b.div` + flex + flex-col + items-center +`,{persistAtom:E7}=fc(),R7=Be({key:"categoryData",default:{pageInfo:[{storeCount:0}],data:[]}});Be({key:"Heart",default:!1,effects_UNSTABLE:[E7]});function T7(){return u.jsxs("div",{role:"status",className:"fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center",children:[u.jsxs("svg",{"aria-hidden":"true",className:"w-12 h-12 text-gray-200 dark:text-gray-600 animate-spin fill-[#4771B7]",viewBox:"0 0 100 101",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[u.jsx("path",{d:"M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z",fill:"currentColor"}),u.jsx("path",{d:"M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z",fill:"currentFill"})]}),u.jsx("span",{className:"sr-only",children:"Loading..."})]})}function j7(){const[e]=dr(),t=e.get("keyword");return u.jsx("div",{className:"mx-0 my-auto w-[1060px] h-[500px] relative ml-[300px] mt-[30px]",children:u.jsx("div",{className:"pt-[40px] pb-[120px] px-0 relative",children:u.jsx("div",{className:"flex mt-[100px] justify-center items-center",children:u.jsxs("div",{className:"flex flex-col text-center items-center",children:[u.jsx("img",{src:yl,className:"w-[100px] h-[100px] mb-[30px] mr-[5px]"}),u.jsxs("div",{className:"ml-[15px]",children:[u.jsxs("p",{className:"mb-[3px]",children:[u.jsx("span",{className:"text-[#4771B7] font-medium",children:t})," ","์˜ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."]}),u.jsx("p",{children:"์ง€์—ญ/์—…์ฒด๋ช…์„ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”."})]})]})})})})}function Yg(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t]=dr(),n=tn(),r=t.get("category_name"),o=t.get("sort"),s=t.get("keyword"),[i,a]=Re(Hp),[l,c]=Re(aS),[d,f]=Re(R7);return w.useEffect(()=>{(async()=>{let h;if(s){a(!0),c(!0);const v=await fetch(`${e}/search?keyword=${encodeURIComponent(s)}`,{headers:{Authorization:sessionStorage.getItem("Authorization")}});if(h=await v.json(),v.status!==200)throw v}else{const v=await fetch(`${e}/stores?category=${r}&sort_field=${o}`,{headers:{Authorization:sessionStorage.getItem("Authorization")}});if(h=await v.json(),a(!1),v.status!==200)throw v}setTimeout(()=>{c(!1)},500),f(h)})()},[r,o,s]),u.jsxs(w7,{children:[u.jsx(Vo,{toastClassName:"h-[20px] rounded-md text-sm font-medium bg-[#EDF1F8] text-[#4771B7] text-center shadow-sm",position:"top-center",limit:10,closeButton:!1,autoClose:2e3,hideProgressBar:!0}),u.jsxs(S7,{style:{display:l?"none":"flex"},children:[u.jsxs("span",{className:"font-semibold text-2xl",children:["์ „์ฒด์ƒํ’ˆ ",d.pageInfo[0].storeCount]}),u.jsx(C7,{children:!i&&u.jsxs(u.Fragment,{children:[u.jsx(ns,{to:`/category?category_name=${r}&sort=likeCount`,className:()=>{const h=new URLSearchParams(n.search).get("sort");let v="mr-[25px]";return h==="likeCount"&&(v+=" text-[#4771B7] font-medium"),v},children:"โ€ข ๊ด€์‹ฌ์ˆœ"}),u.jsx(ns,{to:`/category?category_name=${r}&sort=rating`,className:()=>{const h=new URLSearchParams(n.search).get("sort");let v="mr-[25px]";return h==="rating"&&(v+=" text-[#4771B7] font-medium"),v},children:"โ€ข ๋†’์€ ํ‰์ ์ˆœ"}),u.jsx(ns,{to:`/category?category_name=${r}&sort=lowPrice`,className:()=>{const h=new URLSearchParams(n.search).get("sort");let v="mr-[25px]";return h==="lowPrice"&&(v+=" text-[#4771B7] font-medium"),v},children:"โ€ข ๋‚ฎ์€ ๊ฐ€๊ฒฉ์ˆœ"}),u.jsx(ns,{to:`/category?category_name=${r}&sort=highPrice`,className:()=>{const h=new URLSearchParams(n.search).get("sort");let v="mr-[25px]";return h==="highPrice"&&(v+=" text-[#4771B7] font-medium"),v},children:"โ€ข ๋†’์€ ๊ฐ€๊ฒฉ์ˆœ"}),u.jsx(ns,{to:`/category?category_name=${r}&sort=reviewCount`,className:()=>{const h=new URLSearchParams(n.search).get("sort");let v="mr-[25px]";return h==="reviewCount"&&(v+=" text-[#4771B7] font-medium"),v},children:"โ€ข ๋ฆฌ๋ทฐ ๋งŽ์€์ˆœ"})]})})]}),l?u.jsx(T7,{}):d.data.length>0?u.jsx(b7,{children:d.data.map(p=>u.jsx(uS,{data:p},p.storeId))}):i?u.jsx(j7,{}):null,u.jsx(k7,{children:u.jsx(A7,{onClick:()=>window.scrollTo({top:0,behavior:"smooth"}),children:u.jsx("img",{src:Bp,className:"w-[50px] cursor-pointer duration-500 ease-in-out "})})})]})}function P7(e){return et({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M12 20.8995L16.9497 15.9497C19.6834 13.2161 19.6834 8.78392 16.9497 6.05025C14.2161 3.31658 9.78392 3.31658 7.05025 6.05025C4.31658 8.78392 4.31658 13.2161 7.05025 15.9497L12 20.8995ZM12 23.7279L5.63604 17.364C2.12132 13.8492 2.12132 8.15076 5.63604 4.63604C9.15076 1.12132 14.8492 1.12132 18.364 4.63604C21.8787 8.15076 21.8787 13.8492 18.364 17.364L12 23.7279ZM12 13C13.1046 13 14 12.1046 14 11C14 9.89543 13.1046 9 12 9C10.8954 9 10 9.89543 10 11C10 12.1046 10.8954 13 12 13ZM12 15C9.79086 15 8 13.2091 8 11C8 8.79086 9.79086 7 12 7C14.2091 7 16 8.79086 16 11C16 13.2091 14.2091 15 12 15Z"}}]})(e)}function N7(e){return et({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"circle",attr:{cx:"12",cy:"12",r:"10"}},{tag:"polyline",attr:{points:"12 6 12 12 16 14"}}]})(e)}function L7(e){return et({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"path",attr:{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}}]})(e)}var dS={exports:{}},_7="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED",I7=_7,M7=I7;function fS(){}function pS(){}pS.resetWarningCache=fS;var D7=function(){function e(r,o,s,i,a,l){if(l!==M7){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}e.isRequired=e;function t(){return e}var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:pS,resetWarningCache:fS};return n.PropTypes=n,n};dS.exports=D7();var O7=dS.exports;const vr=ci(O7);var B7=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;r"u"){n&&console.warn("unable to use e.clipboardData"),n&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var f=Zg[t.format]||Zg.default;window.clipboardData.setData(f,e)}else d.clipboardData.clearData(),d.clipboardData.setData(t.format,e);t.onCopy&&(d.preventDefault(),t.onCopy(d.clipboardData))}),document.body.appendChild(a),s.selectNodeContents(a),i.addRange(s);var c=document.execCommand("copy");if(!c)throw new Error("copy command was unsuccessful");l=!0}catch(d){n&&console.error("unable to copy using execCommand: ",d),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),l=!0}catch(f){n&&console.error("unable to copy using clipboardData: ",f),n&&console.error("falling back to prompt"),r=F7("message"in t?t.message:z7),window.prompt(r,e)}}finally{i&&(typeof i.removeRange=="function"?i.removeRange(s):i.removeAllRanges()),a&&document.body.removeChild(a),o()}return l}var $7=U7;const W7=ci($7);var da;let H7=(da=class extends V.PureComponent{constructor(){super(...arguments);_i(this,"onClick",n=>{const{text:r,onCopy:o,children:s,options:i}=this.props,a=V.Children.only(s),l=W7(r,i);o&&o(r,l),a&&a.props&&typeof a.props.onClick=="function"&&a.props.onClick(n)})}render(){const{text:n,onCopy:r,options:o,children:s,...i}=this.props,a=V.Children.only(s);return V.cloneElement(a,{...i,onClick:this.onClick})}},_i(da,"propTypes",{text:vr.string.isRequired,children:vr.element.isRequired,onCopy:vr.func,options:vr.shape({debug:vr.bool,message:vr.string,format:vr.string})}),_i(da,"defaultProps",{onCopy:void 0,options:void 0}),da);const G7=Object.freeze(Object.defineProperty({__proto__:null,CopyToClipboard:H7},Symbol.toStringTag,{value:"Module"})),K7=VS(G7),{CopyToClipboard:Xd}=K7;Xd.CopyToClipboard=Xd;var J7=Xd;const Y7=b.div` + text-xl text-[#787878] font-medium + mb-1 +`,Z7=b.div` + text-3xl font-bold + border-b-[1px] border-[#4771B7] + pb-3 mb-5 +`,Q7=b.div` + flex flex-wrap justify-between + w-[600px] + mx-auto +`,X7=b.img` + w-[600px] h-[400px] + object-cover + rounded-[5px] + duration-1000 +`;b.img` + w-[570px] h-[400px] + mb-2 + mx-auto + object-cover +`;b.img` + w-[280px] h-[200px] + object-cover +`;const q7=b.div` + mt-10 p-5 + font-medium + border-[1px] border-[#4771B7] + rounded-[5px] +`,ji=Be({key:"CategoryDetailState",default:{storeName:"",category:"",body:"",latitude:0,longitude:0,kakao:"",contact:"",address:"",isLike:!1,profileImg:"",createdAt:"",items:[],storeImages:[]}}),zr=Be({key:"ReserFormState",default:{reservationName:"",reservationPhone:"",reservationEmail:"",reservationDate:"",reservationItems:[],totalPrice:0}}),hS=Be({key:"itemsState",default:[]}),vc=Be({key:"totalPrice",default:0}),eM=Be({key:"ReviewsState",default:{}}),mS=Be({key:"ReserDateState",default:new Date().toISOString().substring(0,10)});function tM(){const[e,t]=w.useState(0),n=ze(ji),r=()=>{t(e===0?n.storeImages.length-1:e-1)},o=()=>{e===n.storeImages.length-1?t(0):t(e+1)};return u.jsxs("section",{className:"w-[600px] mb-14",children:[u.jsx(Vo,{toastClassName:"h-[20px] rounded-md text-sm font-medium bg-[#EDF1F8] text-[#4771B7] text-center shadow-sm",position:"top-center",limit:10,closeButton:!1,autoClose:2e3,hideProgressBar:!0}),u.jsx(Y7,{children:n.category}),u.jsx(Z7,{children:n.storeName}),u.jsx(Q7,{children:n.storeImages&&u.jsxs("div",{className:"overflow-x-hidden",children:[u.jsx("div",{className:"flex duration-500 min-w-[1200px] overflow-hidden ease-in-out",style:{transform:`translateX(${e*-600}px)`,width:`${n.storeImages.length*600}px`},children:n.storeImages.map((s,i)=>u.jsx(X7,{src:s,alt:"์—…์ฒด์‚ฌ์ง„"},i))}),u.jsxs("div",{className:"flex justify-center items-center mt-3",children:[u.jsx("div",{className:"cursor-pointer my-auto arrow-left",onClick:r,children:u.jsx(Ww,{className:"hover:fill-[#9dacc5] duration-500",size:"40",color:"#4771B7"})}),u.jsxs("div",{className:"mx-5 text-center text-xl font-bold text-[#4771B7]",children:[e+1," / ",n.storeImages.length]}),u.jsx("div",{className:"cursor-pointer my-auto arrow-right",onClick:o,children:u.jsx(Hw,{className:"hover:fill-[#9dacc5] duration-500",size:"40",color:"#4771B7"})})]})]})}),u.jsxs(q7,{children:[u.jsxs("div",{className:"flex mb-2",children:[u.jsx(P7,{color:"#4771B7",size:"25"}),u.jsx("div",{className:"ml-2 mr-5",children:n.address}),u.jsx(J7.CopyToClipboard,{text:n.address,onCopy:()=>pe("ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."),children:u.jsx("button",{className:"bg-[#4771B7] rounded-[5px] text-white text-xs px-3 py-1",children:"์ฃผ์†Œ๋ณต์‚ฌ"})})]}),u.jsxs("div",{className:"flex mb-2",children:[u.jsx(N7,{color:"#4771B7",size:"23"}),u.jsx("div",{className:"ml-2",children:"๋งค์ผ 10:00 ~ 18:00(18:00์— ์šด์˜ ์ข…๋ฃŒ)"})]}),u.jsxs("div",{className:"flex mb-2",children:[u.jsx(L7,{color:"#4771B7",size:"23"}),u.jsx("div",{className:"ml-2",children:n.contact})]}),u.jsx("div",{children:n.body})]})]})}function nM(){const e=ze(ji);return u.jsxs("section",{className:"w-[600px] mb-10",children:[u.jsx("div",{className:"text-2xl font-semibold mb-3",children:"์œ„์น˜ ์•ˆ๋‚ด"}),e.latitude&&u.jsxs(Yw,{center:{lat:e.latitude,lng:e.longitude},style:{width:"100%",height:"360px",borderRadius:"10px",border:"1px solid #4771B7"},children:[u.jsx(Xw,{position:kakao.maps.ControlPosition.TOPLEFT}),u.jsx(qw,{position:kakao.maps.ControlPosition.TOPRIGHT}),u.jsx(Qw,{position:{lat:e.latitude,lng:e.longitude}})]})]})}const rM=b.section` + sticky top-10 + w-[300px] h-[635px] + border-[1px] border-[#4771B7] rounded-[5px] + mt-10 ml-20 + font-medium +`,oM=b.div` + bg-[#E7EDF6] + text-[#4771B7] font-semibold + flex justify-between + px-7 py-5 +`,sM=b.div` + w-[250px] h-[170px] + bg-[#E7EDF6] + rounded-[5px] + mx-5 my-7 p-3 +`,iM=b.button` + bg-[#4771B7] + w-[250px] h-[50px] + block mx-auto p-2 + text-white + rounded-[10px] +`,aM=b.button` + w-[250px] h-[50px] + block + mx-auto mt-5 mb-7 p-2 + rounded-[10px] border-[1px] border-[#4771B7] + font-semibold +`,lM=b.div` + border-t-[1px] border-[#4771B7] + flex justify-center + text-sm + p-2 +`,cM=b.img` + w-[38px] h-[38px] + object-cover + rounded-full + mr-3 +`;function uM(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=Re(zr),r=ze(mr),o=ze(ji),s=ze(vc),i=tn(),a=qe(),l=i.pathname.substring(10),c=async()=>{if(r)if(t.reservationName)if(t.reservationPhone)if(s){if(t.reservationPhone.substring(0,3)!=="010")return alert("์—ฐ๋ฝ์ฒ˜๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.")}else return alert("ํ‹ฐ์ผ“์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.");else return alert("์—ฐ๋ฝ์ฒ˜๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.");else return alert("์˜ˆ์•ฝ์ž๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.");else return alert("๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ์˜ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."),a("/login");const f=t.reservationItems.filter(p=>p.ticketCount!==0);n(p=>({...p,reservationItems:f})),a(`/store/payment/${l}`)},d=async()=>{if(!r)return alert("๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.");if(o.isLike)return alert("์ด๋ฏธ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.");(await fetch(`${e}/stores/favorites/${l}`,{method:"POST",headers:{Authorization:sessionStorage.getItem("Authorization")}})).ok&&(alert("โค๏ธ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค."),window.location.reload())};return u.jsxs(rM,{children:[u.jsxs("div",{children:[u.jsx("div",{className:"m-5 pb-3 text-lg border-b-[1px] border-black",children:"๊ฒฐ์ œ์ •๋ณด"}),u.jsxs("div",{className:"m-7 flex justify-between",children:[u.jsx("div",{children:"์ฃผ๋ฌธ๊ธˆ์•ก"}),u.jsxs("div",{children:[s.toLocaleString("ko-KR"),"์›"]})]}),u.jsxs(oM,{children:[u.jsx("div",{children:"์ด ๊ฒฐ์ œ๊ธˆ์•ก"}),u.jsxs("div",{children:[s.toLocaleString("ko-KR"),"์›"]})]}),u.jsxs(sM,{children:[u.jsx("div",{className:"font-semibold",children:"์˜ˆ์•ฝ์ทจ์†Œ ๊ทœ์ •"}),u.jsxs("ul",{className:"text-xs list-disc mt-3 pl-5",children:[u.jsx("li",{children:"์ฒดํ—˜์ผ 4์ผ์ „ 18์‹œ์ด์ „ 100% ํ™˜๋ถˆ๊ฐ€๋Šฅ"}),u.jsx("li",{children:"์ฒดํ—˜์ผ 4์ผ์ „ 18์‹œ์ดํ›„~๋‹น์ผ : ํ™˜๋ถˆ๋ถˆ๊ฐ€, ๋‚ ์งœ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€"}),u.jsx("li",{children:"๋ถ€๋ถ„ ์‚ฌ์šฉ ๋ฐ ๋ถ€๋ถ„ ์ทจ์†Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."}),u.jsx("li",{className:"text-red-600",children:"๊ฐ€์ƒ์œผ๋กœ๋งŒ ๊ฒฐ์ œ๋˜๊ณ  ์‹ค์ œ๋กœ ๋ˆ์ด ๋น ์ ธ๋‚˜๊ฐ€์ง€ ์•Š์œผ๋‹ˆ ์•ˆ์‹ฌํ•˜๊ณ  ๋งˆ์Œ๊ป ํ…Œ์ŠคํŠธ ํ•ด๋ณด์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค."})]})]}),u.jsxs(iM,{type:"button",onClick:c,children:[s.toLocaleString("ko-KR"),"์› ๊ฒฐ์ œํ•˜๊ธฐ"]}),u.jsxs(aM,{type:"button",onClick:d,children:[u.jsx("span",{className:"text-[#4771B7]",children:"โ™ฅ "}),u.jsx("span",{children:"์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ธฐ"})]})]}),u.jsxs(lM,{children:[u.jsx(cM,{src:o.profileImg==="default image"?gc:o.profileImg,alt:"์—…์ฒด ํ”„๋กœํ•„"}),u.jsxs("div",{children:[u.jsx("div",{className:"font-semibold",children:o.storeName}),u.jsxs("div",{className:"text-xs",children:["[๋ฌธ์˜] ์นด์นด์˜คํ†ก ์•„์ด๋””: ",o.kakao]})]})]})]})}function dM(){const[e,t]=Re(zr),n=r=>{const o=r.target.name,s=r.target.value;switch(o){case"reservationName":return t({...e,reservationName:s});case"reservationPhone":const i=/(\d{3})(\d{3,4})(\d{4})/;let a=s.replace(/[^0-9]/g,"");return a.length>=11&&(a=a.replace(i,"$1-$2-$3")),a.length>=14?void 0:t({...e,reservationPhone:a});case"reservationEmail":return t({...e,reservationEmail:s})}};return u.jsxs("section",{className:"w-[600px] mb-10",children:[u.jsx(fM,{children:"์˜ˆ์•ฝ์ž ์ •๋ณด"}),u.jsxs("div",{className:"flex ml-7 mb-3 items-center",children:[u.jsx("div",{className:"mr-5 text-lg font-medium",children:"์˜ˆ์•ฝ์ž"}),u.jsxs("div",{className:"relative",children:[u.jsx(Su,{type:"text",name:"reservationName",value:e.reservationName,onChange:n}),u.jsx(Qg,{children:"ํ•„์ˆ˜"})]})]}),u.jsxs("div",{className:"flex ml-7 mb-3 items-center",children:[u.jsx("div",{className:"mr-5 text-lg font-medium",children:"์—ฐ๋ฝ์ฒ˜"}),u.jsxs("div",{className:"relative",children:[u.jsx(Su,{type:"text",name:"reservationPhone",value:e.reservationPhone,onChange:n,placeholder:"'-'๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"}),u.jsx(Qg,{children:"ํ•„์ˆ˜"})]})]}),u.jsxs("div",{className:"flex ml-7 mb-3 items-center",children:[u.jsx("div",{className:"mr-5 text-lg font-medium",children:"์ด๋ฉ”์ผ"}),u.jsx(Su,{type:"text",name:"reservationEmail",value:e.reservationEmail,onChange:n})]})]})}const fM=b.div` + text-2xl font-semibold + border-b-[1px] border-[#4771B7] + pb-3 mb-10 +`,Su=b.input` + border-[1px] border-[#CCCCCC] rounded-[5px] + w-[260px] h-[38px] + p-2 +`,Qg=b.div` + absolute top-2 right-2 + text-[#FF0000] font-medium +`,gS="/assets/emptyStar-c709dc52.svg",vS="/assets/fillStar-ef57f9e5.svg";function pM({review:e}){const t=String(e.rating*10*2),n=new Date(e.createdAt).toLocaleDateString();return u.jsxs("section",{className:"border-b-[1px] border-[#4771B7] my-5 p-3",children:[u.jsxs("div",{className:"relative w-[100px] top-1",children:[u.jsx("img",{className:"absolute w-[100px] max-w-[100px]",src:gS,alt:"๋นˆ๋ณ„"}),u.jsx("div",{className:"absolute overflow-hidden w-[50%]",style:{width:`${t}%`},children:u.jsx("img",{src:vS,className:"card-star",alt:"๊ฝ‰์ฐฌ๋ณ„"})})]}),u.jsxs("div",{className:"flex justify-between items-center mb-3",children:[u.jsx("div",{className:"ml-28 font-medium",children:e.nickname}),u.jsx("div",{className:"text-sm font-medium",children:n})]}),u.jsx("div",{className:"text-lg",children:e.content})]})}const hM=b.div` + w-[190px] h-[150px] + bg-[#EDF1F8] + mr-[10px] px-5 py-10 + rounded-[5px] +`,mM=b.div` + w-[400px] h-[150px] + bg-[#EDF1F8] + rounded-[5px] + p-5 +`,gM=b.button` + bg-[#4771B7] + px-3 py-1 + text-white + rounded-[5px] +`,vM=b.textarea` + mt-3 p-2 + w-full h-[70px] + border-[1px] border-[#4771B7] + rounded-[5px] + text-sm + font-medium +`,Xg=b.span` + text-[#4471B7] text-lg + cursor-pointer +`;function yM(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=w.useState([!1,!1,!1,!1,!1]),[r,o]=w.useState({rating:0,content:""}),[s,i]=Re(eM),a=f=>{const p=[!1,!1,!1,!1,!1].map((h,v)=>v<=f?!0:h);o(h=>({...h,rating:f+1})),n(p)},l=f=>{o(p=>({...p,content:f.target.value}))},c=async()=>{if(r.rating){if(!r.content)return alert("๋ฆฌ๋ทฐ ๊ธ€์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.")}else return alert("๋ณ„์ ์„ ํด๋ฆญํ•ด์ฃผ์„ธ์š”.");const f=location.pathname.substring(10),p=sessionStorage.getItem("Authorization");try{const h=await fetch(`${e}/reviews/${f}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:p},body:JSON.stringify(r)});if(h.status===422)return alert(`์ด์šฉ์™„๋ฃŒ ํ›„์— ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +(์ด์šฉ์™„๋ฃŒ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•: ๋งˆ์ดํŽ˜์ด์ง€ > ์˜ˆ์•ฝ๋‚ด์—ญ์กฐํšŒ > ์ƒ์„ธ๋ณด๊ธฐ > ์ด์šฉ์™„๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ)`);if(h.status===409)return alert("์ด๋ฏธ ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.");if(h.status===400)return alert("๋น„์†์–ด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.");if(!h.ok)return alert("๋ฆฌ๋ทฐ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");alert("๋ฆฌ๋ทฐ๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค."),window.location.reload()}catch(h){console.error(h)}},d=async()=>{const f=location.pathname.substring(10);try{const h=await(await fetch(`${e}/reviews/${f}`)).json();i(h)}catch(p){console.error(p)}};return w.useEffect(()=>{d()},[]),u.jsxs("section",{className:"w-[600px] mb-10",children:[u.jsxs("div",{className:"text-2xl font-semibold mb-3",children:[u.jsx("span",{children:"๋ฆฌ๋ทฐ"}),s&&u.jsxs("span",{className:"text-[#4771B7] font-bold",children:[" ",s.reviewCount]})]}),u.jsxs("div",{className:"flex",children:[u.jsxs(hM,{children:[s.ratingAvg?u.jsx("div",{className:"text-center text-3xl font-bold mb-2",children:s.ratingAvg.toFixed(1)}):u.jsx("div",{className:"text-center text-3xl font-bold mb-2",children:0 .toFixed(1)}),u.jsxs("div",{className:"relative",children:[u.jsx("img",{className:"absolute max-w-[150px]",src:gS,alt:"๋นˆ๋ณ„"}),u.jsx("div",{className:"absolute overflow-hidden",style:{width:`${s.ratingAvg*10*2}%`},children:u.jsx("img",{src:vS,className:"star",alt:"๊ฝ‰์ฐฌ๋ณ„"})})]})]}),u.jsxs(mM,{children:[u.jsxs("div",{className:"flex justify-between text-sm font-semibold",children:[u.jsx("div",{className:"pt-1",children:"๋ ˆ์ €๋Š” ๋งŒ์กฑ ํ•˜์…จ๋‚˜์š”?"}),u.jsx("div",{className:"mr-12",children:t.map((f,p)=>f?u.jsx(Xg,{onClick:()=>a(p),children:"โ˜…"},p):u.jsx(Xg,{onClick:()=>a(p),children:"โ˜†"},p))}),u.jsx(gM,{className:"font-normal",type:"button",onClick:c,children:"๋“ฑ๋กํ•˜๊ธฐ"})]}),u.jsx(vM,{onChange:l,placeholder:"์•กํ‹ฐ์˜จ์ด ๋” ํ›ˆํ›ˆํ•ด์ง€๋Š” ๋Œ“๊ธ€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค."})]})]}),s.reviews&&s.reviews.map((f,p)=>u.jsx(pM,{review:f},p))]})}function xM(e){return et({tag:"svg",attr:{viewBox:"0 0 1024 1024"},child:[{tag:"path",attr:{d:"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"}}]})(e)}function wM(e){return et({tag:"svg",attr:{viewBox:"0 0 1024 1024"},child:[{tag:"path",attr:{d:"M696 480H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h368c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"}},{tag:"path",attr:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]})(e)}function SM(e){return et({tag:"svg",attr:{viewBox:"0 0 1024 1024"},child:[{tag:"path",attr:{d:"M696 480H544V328c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v152H328c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h152v152c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V544h152c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"}},{tag:"path",attr:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]})(e)}function CM({item:e,itemIdx:t}){const[n,r]=Re(hS),[o,s]=w.useState({...n[t]}),i=Xe(zr),a=Xe(vc),l=ze(zr),c=d=>{const f=[...n],p={...n[t]};d==="plus"&&p.ticketCounth+e.price)):d==="minus"&&p.ticketCount>0&&(p.ticketCount-=1,a(h=>h-e.price)),f[t]=p,s(p),r(f),i(h=>({...h,reservationItems:f}))};return w.useEffect(()=>{s({...n[t],ticketCount:0})},[l.reservationDate]),u.jsxs(bM,{children:[u.jsxs("div",{className:"flex justify-between items-center mb-3",children:[u.jsx("div",{className:"font-semibold text-lg",children:e.itemName}),u.jsxs("div",{className:"flex items-center",children:[u.jsx(wM,{className:"cursor-pointer",onClick:()=>c("minus"),size:"25",color:"#4771B7"}),u.jsx("div",{className:"mx-3",children:o.ticketCount?o.ticketCount:0}),u.jsx(SM,{className:"cursor-pointer",onClick:()=>c("plus"),size:"25",color:"#4771B7"})]})]}),u.jsxs("div",{className:"flex justify-between items-center",children:[u.jsxs("div",{className:"font-bold text-[#4771B7]",children:["์ž”์—ฌ๋Ÿ‰: ",e.remainingTicket]}),u.jsxs("div",{children:[u.jsx("span",{className:"mr-3 text-xs font-medium",children:"1์ธ๊ธฐ์ค€"}),u.jsxs("span",{className:"text-lg font-bold text-[#4771B7]",children:[e.price.toLocaleString("ko-KR"),"์›"]})]})]})]})}const bM=b.section` + shadow-[0px_2px_4px_0px_rgba(0,0,0,0.25)] + rounded-[5px] + p-5 mb-5 + bg-white +`,AM=b.div` + border-[1px] border-[#4771B7] rounded-[5px] + px-10 py-5 +`,kM=b.div` + inline-block + p-5 + border-[1px] border-[#4771B7] rounded-[5px] +`,EM=b.input` + bg-[#4771B7] + rounded-[5px] + py-2 px-5 + text-center text-white +`,RM=b.div` + border-[1px] border-[#4771B7] rounded-[5px] + p-5 + bg-[#EDF1F8] +`;function TM(){const[e,t]=Re(mS),[n,r]=Re(vc),o=ze(ji),s=Xe(hS),i=Xe(zr),a=l=>{const c=new Date().toLocaleDateString();if(new Date(l.target.value).toLocaleDateString()({...f,reservationDate:l.target.value}))};return w.useEffect(()=>{i(l=>({...l,reservationDate:e})),o.items&&(i(l=>({...l,reservationItems:[]})),s([]),r(0),o.items.forEach(l=>{s(c=>[...c,{itemId:l.itemId,ticketCount:0}])}))},[o.items]),u.jsxs("section",{className:"w-[600px] mb-10",children:[u.jsx("div",{className:"text-2xl font-semibold mb-3",children:"ํ‹ฐ์ผ“์„ ํƒ"}),u.jsxs(AM,{children:[u.jsxs("div",{className:"mb-7",children:[u.jsx("div",{className:"font-medium mb-3",children:"1. ์›ํ•˜์‹œ๋Š” ๋‚ ์งœ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."}),u.jsx(kM,{children:u.jsx(EM,{onChange:a,type:"date",value:e})})]}),u.jsxs("div",{children:[u.jsx("div",{className:"font-medium mb-3",children:"2. ์›ํ•˜์‹œ๋Š” ์ƒํ’ˆ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”."}),u.jsxs(RM,{children:[u.jsx("div",{className:"border-b-[1px] border-[#4771B7] pb-3",children:o.items&&o.items.map((l,c)=>u.jsx(CM,{item:l,itemIdx:c},c))}),u.jsxs("div",{className:"text-right pt-3 mb-5",children:[u.jsx("span",{className:"mr-5 font-bold",children:"์ด ์ƒํ’ˆ ๊ธˆ์•ก"}),u.jsxs("span",{className:"font-bold text-[#4771B7] text-xl",children:[n.toLocaleString("ko-KR")," ์›"]})]})]})]})]})]})}function jM(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=Re(ji),[r,o]=Re(zr),s=ze(mS),i=tn(),a=async()=>{try{const c=i.pathname.substring(10),f=await(await fetch(`${e}/stores/${c}`,{method:"GET",headers:{Authorization:sessionStorage.getItem("Authorization")}})).json();delete f.items,n(f)}catch(c){console.error(c)}},l=async()=>{const c=i.pathname.substring(10);try{const d=s.split("-").join(""),p=await(await fetch(`${e}/items/${c}?date=${d}`,{method:"GET",headers:{Authorization:sessionStorage.getItem("Authorization")}})).json();n(h=>({...h,items:p}))}catch(d){console.error(d)}};return w.useEffect(()=>{window.scrollTo(0,0),o({reservationName:"",reservationPhone:"",reservationEmail:"",reservationDate:"",reservationItems:[],totalPrice:0}),a(),l()},[]),w.useEffect(()=>{l()},[r.reservationDate]),u.jsxs("section",{className:"flex justify-center my-[100px]",children:[t&&u.jsxs("section",{className:"flex flex-col items-center",children:[u.jsx(tM,{}),u.jsx(dM,{}),u.jsx(TM,{}),u.jsx(nM,{}),u.jsx(yM,{})]}),u.jsx(uM,{})]})}var ca;function PM(e,t){var n=document.querySelector('[src="'.concat(e,'"]'));if(n!=null&&ca!==void 0)return ca;if(n!=null&&ua(t)!==void 0)return Promise.resolve(ua(t));var r=document.createElement("script");return r.src=e,ca=new Promise(function(o,s){document.head.appendChild(r),window.addEventListener("TossPayments:initialize:".concat(t),function(){ua(t)!==void 0?o(ua(t)):s(new Error("[TossPayments SDK] Failed to load script: [".concat(e,"]")))})}),ca}function ua(e){return window[e]}var NM="https://js.tosspayments.com/v1/payment-widget";function LM(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},o=r.src,s=o===void 0?NM:o;return typeof window>"u"?Promise.resolve({}):PM(s,"PaymentWidget").then(function(i){return i(e,t,n)})}let _M=(e=21)=>crypto.getRandomValues(new Uint8Array(e)).reduce((t,n)=>(n&=63,n<36?t+=n.toString(36):n<62?t+=(n-26).toString(36).toUpperCase():n>62?t+="-":t+="_",t),"");const IM="#payment-widget",MM="test_ck_dP9BRQmyarY0eEomwzZVJ07KzLNk",DM="YbX2HuSlsC9uVJW6NMRMj";function OM(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",t=sessionStorage.getItem("Authorization"),n=tn(),r=qe(),o=n.pathname.substring(15),s=w.useRef(null),i=w.useRef(null),a=ze(zr),l=ze(vc);return w.useEffect(()=>{if(!l)return r("/home");(async()=>{const c=await LM(MM,DM),d=c.renderPaymentMethods(IM,{value:l});c.renderAgreement("#agreement"),s.current=c,i.current=d})()},[]),w.useEffect(()=>{const c=i.current;c!=null&&c.updateAmount(l,c.UPDATE_REASON.COUPON)},[l]),u.jsxs("section",{className:"w-[600px] mx-auto pt-[200px]",children:[u.jsxs("span",{className:"text-xl font-bold text-[#4771B7]",children:["์ด ๊ฒฐ์ œ๊ธˆ์•ก: ",`${l.toLocaleString()}์›`]}),u.jsx("div",{id:"payment-widget"}),u.jsx("div",{id:"agreement"}),u.jsx("button",{className:"border-2 border-[#4771B7] px-3 py-1 font-bold rounded-[10px] text-[#4771B7] mx-auto block hover:bg-[#d8ecfc] duration-500",onClick:async()=>{const c=s.current;try{const f=await(await fetch(`${e}/reservations/${o}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:t},body:JSON.stringify({...a,totalPrice:l})})).json();await(c==null?void 0:c.requestPayment({orderId:_M(),orderName:"ActiOn",successUrl:`${window.location.origin}/store/payment/success?storeId=${o}&reservationKey=${f.reservationKey}`,failUrl:`${window.location.origin}/category/${o}`}))}catch(d){console.error(d)}},children:"๊ฒฐ์ œํ•˜๊ธฐ"})]})}function BM(e){return et({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M313 80v48h18V80zm-78.5 29.2l-17 5.6 16 48 17-5.6zm175 0l-16 48 17 5.6 16-48zM322 167c-71.9 0-130.9 55.5-136.6 126h127.1c5.7-18 6.2-37.7 8.4-54.8 10.5 6.9 21.1 22.4 26 37.7 4.9-22.7 5.7-46.6 8.2-67.6 20.3 14.8 40.9 56.5 37 84.7h66.5c-5.7-70.5-64.7-126-136.6-126zM20 311v18h472v-18zm190 38v18h224v-18zm16 38v18h192v-18zm32 38v18h128v-18zm42 38v18h44v-18z"}}]})(e)}function VM(e){return et({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M256 21A235 235 0 0 0 21 256a235 235 0 0 0 235 235 235 235 0 0 0 235-235A235 235 0 0 0 256 21zm0 82c84.393 0 153 68.607 153 153s-68.607 153-153 153-153-68.607-153-153 68.607-153 153-153zm0 18c-20.417 0-39.757 4.52-57.09 12.602C210.457 166.482 230.218 208 256 208c25.823 0 44.926-41.65 56.752-74.555C295.505 125.462 276.284 121 256 121zm98.752 42.88c-27.714 21.143-61.142 52.79-53.17 77.327 7.981 24.564 53.508 29.858 88.459 30.936.628-5.294.959-10.678.959-16.143 0-35.642-13.755-68.012-36.248-92.12zm-197.729.243C134.663 188.204 121 220.477 121 256c0 5.55.34 11.018.988 16.39 34.833-.825 80.381-6.793 88.344-31.3 7.974-24.542-25.68-55.553-53.309-76.967zm70.188 43.643a9 9 0 0 0-5.035 1.714 9 9 0 0 0-1.99 12.57 9 9 0 0 0 12.57 1.993 9 9 0 0 0 1.992-12.572 9 9 0 0 0-7.537-3.705zm57.578 0a9 9 0 0 0-.637.004 9 9 0 0 0-6.9 3.7 9 9 0 0 0 1.992 12.573 9 9 0 0 0 12.57-1.992 9 9 0 0 0-1.99-12.57 9 9 0 0 0-5.035-1.715zM256 224a32 32 0 0 0-32 32 32 32 0 0 0 32 32 32 32 0 0 0 32-32 32 32 0 0 0-32-32zm-46.297 38.037a9 9 0 0 0-2.652.44 9 9 0 0 0-5.78 11.341 9 9 0 0 0 11.34 5.778 9 9 0 0 0 5.78-11.34 9 9 0 0 0-8.688-6.219zm92.856.008a9 9 0 0 0-8.95 6.21 9 9 0 0 0 5.78 11.34 9 9 0 0 0 11.34-5.777 9 9 0 0 0-5.78-11.341 9 9 0 0 0-2.39-.432zm-92.143 27.713c-21.59.104-50.24 16.832-72.424 31.928 19.029 34.168 52.46 59.164 92.143 66.837 9.99-33.39 18.42-78.618-2.446-93.777-4.854-3.527-10.737-5.02-17.273-4.988zm91.016.02c-6.58 0-12.492 1.516-17.346 5.042-20.895 15.181-11.863 60.106-2.088 93.678 39.687-7.715 73.108-32.76 92.1-66.973-22.006-15.224-50.935-31.747-72.666-31.748zM256 295.58a9 9 0 0 0-9 9 9 9 0 0 0 9 9 9 9 0 0 0 9-9 9 9 0 0 0-9-9z"}}]})(e)}const zM=b.section` + w-[600px] h-[77vh] + mx-auto + flex flex-col justify-center items-center +`,FM=b.div` + bg-[#4771B7] + w-[105px] h-[105px + pr-2 pt-1 + rounded-full +`,UM=b.div` + bg-[#4771B7] + w-[105px] h-[105px] + flex justify-center items-center + rounded-full +`,$M=b.div` + px-10 py-7 mt-10 + border-[1px] border-[#4771B7] rounded-[5px] + bg-[#E7EDF6] + font-medium +`,qg=b.button` + mt-10 px-5 py-2 + bg-[#4771B7] + text-white + rounded-[10px] + duration-500 + hover:bg-[#65a4d8] +`;function ev({isSuccess:e}){const[t]=dr(),n=t.get("orderId"),r=t.get("amount"),o=t.get("storeId");return u.jsxs(zM,{children:[e?u.jsx(FM,{children:u.jsx(v7,{size:"100",color:"white"})}):u.jsx(UM,{children:u.jsx(Gw,{size:"100",color:"white"})}),u.jsxs("div",{className:"pt-5 text-xl font-semibold",children:["์˜ˆ์•ฝ์— ",e?"์„ฑ๊ณต":"์‹คํŒจ","ํ•˜์˜€์Šต๋‹ˆ๋‹ค."]}),u.jsxs($M,{children:[u.jsxs("div",{className:"mb-2",children:["์˜ˆ์•ฝ๋ฒˆํ˜ธ: ",n]}),u.jsxs("div",{children:["๊ฒฐ์ œ๊ธˆ์•ก: ",Number(r).toLocaleString(),"์›"]})]}),e?u.jsx(Ie,{to:"/my/order",children:u.jsx(qg,{children:"๊ฒฐ์ œ์™„๋ฃŒ"})}):u.jsx(Ie,{to:`/category/${o}`,children:u.jsx(qg,{children:"ํ™•์ธ"})})]})}function WM(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=w.useState("loading"),[r]=dr(),o=qe(),s=r.get("reservationKey"),i=r.get("orderId"),a=sessionStorage.getItem("Authorization"),l=async()=>{try{const c=await fetch(`${e}/reservation/payments?reservationKey=${s}&orderId=${i}`,{method:"POST",headers:{Authorization:a}});c.ok?n("success"):c.ok||n("fail")}catch(c){console.error(c)}};switch(w.useEffect(()=>{(!s||!i||!a)&&o("/home"),l()},[]),t){case"loading":return u.jsxs("div",{className:"h-[77vh] py-[250px] text-center text-2xl font-bold",children:[u.jsx(VM,{className:"mx-auto wheel",size:"100",color:"#4771B7"}),u.jsx("div",{className:"mt-5 mb-2",children:"๊ฒฐ์ œ ์ค‘์ž…๋‹ˆ๋‹ค...."}),u.jsx("div",{children:"ํ™”๋ฉด์„ ๋ฒ—์–ด๋‚˜์ง€ ๋งˆ์„ธ์š”."})]});case"success":return u.jsx(ev,{isSuccess:!0});case"fail":return u.jsx(ev,{isSuccess:!1})}}function HM(){return u.jsx(Mp.div,{initial:{opacity:0,scale:.5},animate:{opacity:1,scale:1},transition:{duration:.8,delay:.5,ease:[0,.71,.2,1.01]},children:u.jsxs(Xf,{children:[u.jsx(xe,{element:u.jsx(Kp,{}),children:u.jsxs(xe,{element:u.jsx(Gp,{}),children:[u.jsxs(xe,{element:u.jsx(lS,{}),children:[u.jsx(xe,{path:"/category",element:u.jsx(Yg,{})}),u.jsx(xe,{path:"/category/:id",element:u.jsx(jM,{})})]}),u.jsx(xe,{path:"/search",element:u.jsx(Yg,{})}),u.jsx(xe,{path:"/store/payment/success",element:u.jsx(WM,{})})]})}),u.jsx(xe,{path:"/store/payment/:store_id",element:u.jsx(OM,{})})]})})}const GM="/assets/close-8ae4dc29.svg",KM=b.div` + fixed + top-0 + left-0 + right-0 + bottom-0 + flex + justify-center + items-center + bg-black + bg-opacity-40 + z-50 +`,JM=b.div` + flex + flex-col + w-[600px] + h-[500px] + space-y-[20px] + rounded-lg + bg-white + drop-shadow-lg +`,YM=b.div` + flex + justify-end + p-2 +`,ZM=b.img` + cursor-pointer +`,QM=b.div` + flex + justify-center + py-12 +`,XM=b.img` + ml-[40px] + w-[182px] +`,tv=b.div` + flex + flex-row + justify-center + space-x-[30px] +`,nv=b.input` + border-[2px] + border-[#CCCCCC] + rounded-[8px] + w-[255px] + py-1 + px-3 +`,qM=b.div` + flex + flex-row + justify-center + text-sm + pl-[80px] +`,e8=b.div` + flex + justify-center + pt-[30px] +`,t8=b.button` + bg-[#4771B7] + text-white + p-3 + rounded-lg +`;function n8({onClick:e,defaultNickname:t,defaultPhoneNumber:n,onEditComplete:r}){const o="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[s,i]=w.useState(t),[a,l]=w.useState(n),[c,d]=w.useState(!0),f=async()=>{try{const C=sessionStorage.getItem("Authorization"),g={};s!==t&&(g.nickname=s),a!==n&&(g.phoneNumber=a);const m=await fetch(`${o}/mypage`,{method:"PATCH",headers:{Authorization:C,"Content-Type":"application/json"},body:JSON.stringify(g)});m.ok?(pe.success("ํŽธ์ง‘์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."),e(),r({nickname:s,phoneNumber:a})):m.status===409?alert("์ค‘๋ณต๋œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค."):m.status===422&&alert("์ค‘๋ณต๋œ ์ „ํ™”๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.")}catch(C){console.error("ํŽธ์ง‘ ์‹คํŒจ",C)}},p=C=>{const g=C.target.value;i(g),d(h(g))},h=C=>/^[A-Za-z0-9]+$/.test(C),v=C=>{l(C.target.value)},x=C=>{C.target===C.currentTarget&&e()};return u.jsx(KM,{onClick:x,children:u.jsxs(JM,{children:[u.jsx(YM,{children:u.jsx(ZM,{src:GM,alt:"close button",onClick:e})}),u.jsx(QM,{children:u.jsx(XM,{src:Wp,alt:"logo"})}),u.jsxs(tv,{children:[u.jsx("p",{children:"๋‹‰๋„ค์ž„"}),u.jsx(nv,{type:"text",defaultValue:s,onChange:p})]}),!c&&u.jsx(qM,{children:u.jsx("p",{className:"text-red-500",children:"๋‹‰๋„ค์ž„ ํŽธ์ง‘์€ ์˜๋ฌธ ๋˜๋Š” ์ˆซ์ž๋กœ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."})}),u.jsxs(tv,{children:[u.jsx("p",{children:"์—ฐ๋ฝ์ฒ˜"}),u.jsx(nv,{type:"text",defaultValue:a,onChange:v})]}),u.jsx(e8,{children:u.jsx(t8,{type:"button",onClick:f,children:"ํŽธ์ง‘ ์™„๋ฃŒ"})})]})})}const r8=b.div` + flex + flex-row + space-x-16 + justify-center + pt-[24px] +`,Cu=b.div` + flex + flex-col + space-y-[24px] + text-lg +`,bu=b.span` + font-semibold + w-[120px] +`;function o8({partnerData:e,businessRegi:t}){var n,r,o;return e?u.jsxs(r8,{children:[u.jsxs(Cu,{children:[u.jsx(bu,{children:"์—…ํƒœ"}),(n=e.stores)==null?void 0:n.map((s,i)=>u.jsx("span",{children:t},i))]}),u.jsxs(Cu,{children:[u.jsx(bu,{children:"์—…์ข…"}),(r=e.stores)==null?void 0:r.map((s,i)=>u.jsx("span",{children:s.category},i))]}),u.jsxs(Cu,{children:[u.jsx(bu,{children:"์—…์ฒด๋ช…"}),(o=e.stores)==null?void 0:o.map((s,i)=>u.jsx("span",{children:s.storeName},i))]})]}):null}const Au=b.div` + space-x-10 + text-lg +`,ku=b.span` + font-medium +`,s8=b.div` + space-y-8 + px-[96px] + py-[24px] +`;function i8({nickname:e,email:t,phoneNumber:n}){return u.jsxs(s8,{children:[u.jsxs(Au,{children:[u.jsx(ku,{children:"๋‹‰๋„ค์ž„"}),u.jsx("span",{children:e})]}),u.jsxs(Au,{children:[u.jsx(ku,{children:"์ด๋ฉ”์ผ"}),u.jsx("span",{children:t})]}),u.jsxs(Au,{children:[u.jsx(ku,{children:"์—ฐ๋ฝ์ฒ˜"}),u.jsx("span",{children:n})]})]})}const a8=b.div` + flex + flex-row + justify-center + max-w-[902px] + min-h-[800px] +`,l8=b.div` + border-[1px] + border-[#4771B7] + w-[902px] +`,rv=b.div` + space-y-4 + pt-5 + pb-10 + px-10 +`,c8=b.div` + grid + justify-items-end + pt-5 +`,u8=b.div` + grid + justify-items-end +`,ov=b.button` + bg-[#4771B7] + text-white + px-4 + py-1 + rounded +`,d8=b.div` + flex + space-x-3 +`,sv=b.span` + text-[12px] + bg-[#EDF1F8] + border-[1px] + border-[#4771B7] + rounded + p-2 + cursor-pointer +`,iv=b.img` + w-[100px] + h-[100px] + rounded-full + object-cover +`,f8=b.div` + flex + flex-col + items-center + space-y-4 +`,p8=b.span` + font-medium + text-xl +`,h8=b.div` + border-[1px] + border-[#4771B7] + w-[902px] + h-[800px] + flex + flex-col + justify-center + items-center + text-3xl + font-semibold + space-y-5 +`;function m8({profileImageUrl:e,handlePhotoChange:t,handlePhotoRemove:n}){return u.jsxs(u.Fragment,{children:[e!=="default image"?u.jsx(iv,{src:e,alt:"profile img"}):u.jsx(iv,{src:gc,alt:"profile img"}),u.jsxs(d8,{children:[u.jsxs("label",{htmlFor:"photoInput",children:[u.jsx("input",{id:"photoInput",type:"file",accept:"image/*",style:{display:"none"},onChange:t}),u.jsx(sv,{children:"์‚ฌ์ง„ ๋ณ€๊ฒฝ"})]}),u.jsxs("label",{htmlFor:"photoRemoveInput",children:[u.jsx("input",{id:"photoRemoveInput",type:"button",style:{display:"none"},onClick:n}),u.jsx(sv,{children:"์‚ฌ์ง„ ์‚ญ์ œ"})]})]})]})}function Jp(){return u.jsx(u.Fragment,{children:u.jsx(xM,{className:"animate-spin text-[#4771B7] text-[50px]"})})}function g8(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",t="์Šคํฌ์ธ  ๋ฐ ์—ฌ๊ฐ€๊ด€๋ จ ์„œ๋น„์Šค์—…",n=ze(Ti),[r,o]=w.useState(!1),[s,i]=w.useState(!1),[a,l]=w.useState(null),[c,d]=w.useState(null),[f,p]=Re(pc);w.useEffect(()=>{h()},[]);const h=async()=>{try{const M=sessionStorage.getItem("Authorization"),I=await fetch(`${e}/mypage`,{method:"GET",headers:{Authorization:M}});if(I.ok){const T=await I.json();l(T)}}catch(M){console.error("Error fetching data",M)}},v=async()=>{try{const M=sessionStorage.getItem("Authorization"),I=await fetch(`${e}/mypage/partner`,{method:"GET",headers:{Authorization:M}});if(I.ok){const T=await I.json();d(T)}}catch(M){console.error("Error fetching data",M)}};if(!a)return u.jsx(h8,{children:u.jsx(Jp,{})});const{nickname:x,email:C,phoneNumber:g}=a,m=()=>{o(!r),r||v()},y=()=>{n!=="PARTNER"?alert("์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."):m()},S=()=>{i(!0)},A=()=>{i(!1)},L=async M=>{const I=M.target.files[0];try{const T=sessionStorage.getItem("Authorization"),O=new FormData;O.append("image",I);const N=await fetch(`${e}/mypage/profile`,{method:"PUT",headers:{Authorization:T},body:O});if(N.ok){const D=new FileReader;D.onloadend=()=>{const H=D.result;sessionStorage.setItem("selectedPhoto",JSON.stringify(H)),p(H)},D.readAsDataURL(I)}else console.error("ํ”„๋กœํ•„ ์—…๋ฐ์ดํŠธ ์‹คํŒจ",N.status)}catch(T){console.error("ํ”„๋กœํ•„ ์—…๋ฐ์ดํŠธ ์—๋Ÿฌ",T)}},_=async()=>{alert("์‚ฌ์ง„์„ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?");try{const M=sessionStorage.getItem("Authorization"),I=await fetch(`${e}/mypage/profile`,{method:"DELETE",headers:{Authorization:M}});if(I.ok){const T=gc;sessionStorage.setItem("selectedPhoto",JSON.stringify(T)),p(T),h(),alert("ํ”„๋กœํ•„ ์‚ฌ์ง„์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")}else console.error("ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ ์‹คํŒจ",I.status),alert("ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.")}catch(M){console.error("ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ ์—๋Ÿฌ",M)}},k=M=>{l({...M,email:a.email}),i(!1)};return u.jsxs(u.Fragment,{children:[u.jsx(a8,{children:u.jsxs(l8,{children:[u.jsxs(rv,{children:[u.jsx(c8,{children:u.jsx(ov,{type:"button",onClick:S,children:"ํŽธ์ง‘"})}),u.jsxs(f8,{children:[u.jsx(m8,{profileImageUrl:f,handlePhotoChange:L,handlePhotoRemove:_}),u.jsx(p8,{children:x})]}),u.jsx(i8,{nickname:x,email:C,phoneNumber:g})]}),u.jsxs(rv,{children:[u.jsx(u8,{children:u.jsx(ov,{type:"button",onClick:y,children:"๋“ฑ๋กํ•œ ์—…์ฒด๋ณด๊ธฐ"})}),r&&u.jsx(o8,{partnerData:c,businessRegi:t})]})]})}),s&&u.jsx(n8,{onClick:A,defaultNickname:x,defaultPhoneNumber:g,onEditComplete:k})]})}const v8=b.div` + w-[600px] + mt-[80px] + mr-16 + mb-[80px] +`,av=b.div` + font-medium pb-3 text-xl border-b-[1px] border-[#4771B7] +`,lv=b.div` + text-lg + font-medium + my-5 +`,y8=b.section` + w-[600px] + mt-[100px] +`,Eu=b.div` + mr-5 + text-base + font-medium +`,x8=b.div` + text-3xl font-medium + pb-3 mb-10 +`,Ru=b.input` + border-[1px] border-[#CCCCCC] rounded-[5px] + w-[260px] h-[38px] + p-2 +`,cv=b.div` + absolute top-2 right-2 + text-[#FF0000] font-medium +`,w8=b.section` + w-[300px] h-[530px] + border-[1px] border-[#4771B7] rounded-[5px] + mt-28 + font-medium +`,S8=b.div` + bg-[#E7EDF6] + text-[#4771B7] font-semibold + flex justify-between + px-7 py-5 +`,C8=b.div` + w-[250px] h-[135px] + bg-[#E7EDF6] + rounded-[5px] + mx-5 my-7 p-3 +`,b8=b.button` + bg-[#4771B7] + w-[250px] h-[50px] + block mx-auto mb-3 p-2 + text-white + rounded-[10px] +`,A8=b.button` + w-[250px] h-[50px] + block mx-auto mb-3 p-2 + text-[#4771B7] + border-[1px] border-[#4771B7] rounded-[10px] +`,Tu=b.div` + flex + ml-7 + mb-3 + items-center +`,k8=b.div` + relative + w-[75px] + left-[520px] + bottom-[50px] + bg-[#F3F5F7] + rounded-lg + font-semibold + text-[14px] + p-[10px] + cursor-pointer +`;function E8(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",t={storeName:"",reservationDate:"",totalPrice:0,reservationName:"",reservationPhone:"",reservationEmail:"",reservationItems:[]},n=qe(),[r]=dr(),o=r.get("reservationId"),[s,i]=w.useState(t),[a,l]=w.useState(""),[c,d]=w.useState(""),[f,p]=w.useState(""),h=y=>{l(y.currentTarget.value)},v=y=>{const S=y.target.value,A=/(\d{3})(\d{3,4})(\d{4})/;let L=S.replace(/[^0-9]/g,"");if(L.length>=11&&(L=L.replace(A,"$1-$2-$3")),!(L.length>=14))return d(L)},x=y=>{p(y.currentTarget.value)},C=()=>{try{fetch(`${e}/reservations/${o}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:sessionStorage.getItem("Authorization")},body:JSON.stringify({reservationName:a,reservationPhone:c,reservationEmail:f})}),alert("์ˆ˜์ •์ด ์™„๋ฃŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค"),location.reload()}catch(y){console.error(y)}},g=()=>{confirm("์ •๋ง๋กœ ์˜ˆ์•ฝ์„ ์ทจ์†Œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?")==!0&&n("/my/order");try{fetch(`${e}/reservations/${o}`,{method:"DELETE",headers:{Authorization:sessionStorage.getItem("Authorization")}}),n("/my/order"),window.location.reload()}catch(y){console.error(y)}},m=()=>{if(confirm("์ •๋ง ์ด์šฉ ์™„๋ฃŒ ์ฒ˜๋ฆฌํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?"))try{fetch(`${e}/reservationsUsed/${o}`,{method:"POST",headers:{Authorization:sessionStorage.getItem("Authorization")}}),window.location.href="/my/order"}catch(S){console.error(S)}};return w.useEffect(()=>{(()=>{fetch(`${e}/reservations/${o}`,{headers:{Authorization:sessionStorage.getItem("Authorization")}}).then(S=>S.json()).then(S=>{i(S),l(S.reservationName),d(S.reservationPhone),p(S.reservationEmail)})})()},[o]),u.jsxs("div",{className:"flex justify-center",children:[u.jsxs(v8,{children:[u.jsx(x8,{children:s.storeName}),u.jsx(av,{children:"์˜ˆ์•ฝ์ •๋ณด"}),u.jsx(lv,{children:"1. ๊ฒฐ์ œํ•œ ์ƒํ’ˆ"}),s.reservationItems.map(y=>u.jsxs("li",{className:"mb-3 list-none",children:[y.itemName," x ",u.jsx("span",{children:y.ticketCount})]},y.itemName)),u.jsx(lv,{children:"2. ์˜ˆ์•ฝ ๋‚ ์งœ"}),s.reservationDate,u.jsxs(y8,{children:[u.jsx(av,{children:"์˜ˆ์•ฝ์ž ์ •๋ณด"}),u.jsx(k8,{onClick:C,children:"์ˆ˜์ •ํ•˜๊ธฐ"}),u.jsxs(Tu,{children:[u.jsx(Eu,{children:"์˜ˆ์•ฝ์ž"}),u.jsxs("div",{className:"relative",children:[u.jsx(Ru,{type:"text",value:a,onChange:h}),u.jsx(cv,{children:"ํ•„์ˆ˜"})]})]}),u.jsxs(Tu,{children:[u.jsx(Eu,{children:"์—ฐ๋ฝ์ฒ˜"}),u.jsxs("div",{className:"relative",children:[u.jsx(Ru,{type:"tel",value:c,onChange:v,maxLength:13,placeholder:"'-'๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"}),u.jsx(cv,{children:"ํ•„์ˆ˜"})]})]}),u.jsxs(Tu,{children:[u.jsx(Eu,{children:"์ด๋ฉ”์ผ"}),u.jsx(Ru,{type:"email",value:f,onChange:x})]})]})]}),u.jsxs(w8,{children:[u.jsx("div",{className:"m-5 pb-3 text-lg border-b-[1px] border-black",children:"๊ฒฐ์ œ์ •๋ณด"}),u.jsxs("div",{className:"m-7 flex justify-between",children:[u.jsx("div",{children:"์ฃผ๋ฌธ๊ธˆ์•ก"}),u.jsxs("div",{children:[s.totalPrice.toLocaleString("ko-KR")," ์›"]})]}),u.jsxs(S8,{children:[u.jsx("div",{children:"์ด ๊ฒฐ์ œ๊ธˆ์•ก"}),u.jsxs("div",{children:[s.totalPrice.toLocaleString("ko-KR")," ์›"]})]}),u.jsxs(C8,{children:[u.jsx("div",{className:"font-semibold",children:"์˜ˆ์•ฝ์ทจ์†Œ ๊ทœ์ •"}),u.jsxs("ul",{className:"text-xs list-disc mt-3 pl-5",children:[u.jsx("li",{children:"์ฒดํ—˜์ผ 4์ผ์ „ 18์‹œ์ด์ „ 100% ํ™˜๋ถˆ๊ฐ€๋Šฅ"}),u.jsx("li",{children:"์ฒดํ—˜์ผ 4์ผ์ „ 18์‹œ์ดํ›„~๋‹น์ผ : ํ™˜๋ถˆ๋ถˆ๊ฐ€, ๋‚ ์งœ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€"}),u.jsx("li",{children:"๋ถ€๋ถ„ ์‚ฌ์šฉ ๋ฐ ๋ถ€๋ถ„ ์ทจ์†Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."})]})]}),u.jsx(b8,{type:"button",onClick:g,children:"์˜ˆ์•ฝ ์ทจ์†Œ"}),u.jsx(A8,{type:"button",onClick:m,children:"์ด์šฉ ์™„๋ฃŒ"})]})]})}const R8=b.div` + border-[1px] + border-[#4771B7] + py-16 + px-[35px] + h-[800px] + w-[902px] + overflow-y-auto +`,T8=b.div` + flex + flex-col + justify-center + items-center + space-y-5 + p-20 + h-[600px] +`,j8=b.img` + w-[100px] +`,P8=b.p` + text-2xl + font-semibold + pt-12 + pl-4 +`,N8=b.span` + font-semibold + text-2xl + pl-4 +`;function Yp({title:e,description:t}){return u.jsxs(u.Fragment,{children:[u.jsx(P8,{children:e}),u.jsx("p",{children:t})]})}const L8=b.div` + border-[1px] + border-[#4771B7] + px-[50px] + py-16 + space-y-5 + w-[902px] + h-[800px] + overflow-y-auto +`,_8=b.p` + font-medium + text-2xl + pl-4 +`,I8=b.div` + border-[1.5px] + border-[#4771B7] + w-[780px] + h-[200px] + rounded-lg + p-5 + flex + flex-row + justify-center + items-center + space-x-12 +`,M8=b.div` + relative + w-[146px] + h-[127px] +`,D8=b.div` + absolute + inset-0 + w-[146px] + h-[127px] +`,O8=b.img` + w-full + h-full + object-cover + rounded-md +`,B8=b.div` + flex + flex-col + w-[100%] + space-y-2 +`,V8=b.div` + flex + justify-end + w-[100%] +`,z8=b.div` + flex + flex-col + w-[100%] + space-y-2 +`,F8=b.span` + text-[20px] + font-semibold +`,U8=b.span` + text-[15px] + text-[#868686] + font-medium +`,$8=b.span` + text-[15px] + font-semibold +`,W8=b.div` + flex + justify-end + space-x-3 + font-medium + text-[15px] +`,uv=b.button` + bg-[#F3F5F7] + p-2 + rounded-lg +`,H8=b.button` + bg-[#4771B7] + p-2 + text-sm + rounded-lg + text-white +`,G8=b.p` + h-[38.5px] +`,K8=b.div` + flex + flex-col + justify-center + items-center + space-y-5 + p-20 + h-[600px] +`;function J8(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=w.useState([]),[r,o]=w.useState(!0),s=sessionStorage.getItem("Authorization"),i=async l=>{(confirm("์ •๋ง ์˜ˆ์•ฝ์„ ์ทจ์†Œํ•˜๊ฒ ์Šต๋‹ˆ๊นŒ?")&&await fetch(`${e}/reservations/${l}`,{method:"DELETE",headers:{Authorization:s}})).status===204&&window.location.reload()},a=async()=>{const c=await(await fetch(`${e}/mypage/reservations`,{method:"GET",headers:{Authorization:s}})).json();n(c.data),o(!1)};return w.useEffect(()=>{a()},[]),u.jsxs(L8,{children:[u.jsx(_8,{children:"์˜ˆ์•ฝ ๋‚ด์—ญ ์กฐํšŒ"}),r?u.jsx("div",{className:"flex flex-col justify-center items-center h-[800px] w-[902px]",children:u.jsx(Jp,{})}):t.length===0?u.jsxs(K8,{children:[u.jsx(BM,{style:{fontSize:"100px",color:"#4771B7"}}),u.jsx(Yp,{title:"์•„์ง ๋“ฑ๋ก๋œ ์˜ˆ์•ฝ์ด ์—†๋„ค์š”!",description:"๊ด€์‹ฌ๊ฐ€๋Š” ์ƒํ’ˆ์„ ์ฐพ์•„ ์˜ˆ์•ฝ์„ ํ•ด๋ณผ๊นŒ์š”?"})]}):t&&t.map((l,c)=>u.jsxs(I8,{children:[u.jsx(M8,{children:u.jsx(D8,{children:u.jsx(O8,{src:l.storeImg,alt:"reservation image"})})}),u.jsxs(B8,{children:[u.jsx(V8,{children:u.jsx("div",{className:` + font-medium + text-[15px] + pt-[1px] + ${l.reservationStatus==="์˜ˆ์•ฝ ํ™•์ •"?"bg-[#4771B7] text-white":l.reservationStatus==="์ด์šฉ ์™„๋ฃŒ"?"bg-white text-[#4771B7] border-[1px] border-[#4771B7]":"bg-[#DD3535] text-white"} + w-[77px] + h-[27px] + flex + justify-center + items-center + `,children:u.jsx("span",{children:l.reservationStatus})})}),u.jsxs(z8,{children:[u.jsx("div",{children:u.jsx("span",{className:"text-[16px]",children:l.reservationDate})}),u.jsxs("div",{className:"space-x-3",children:[u.jsx(Ie,{to:`/category/${l.storeId}`,children:u.jsx(F8,{children:l.storeName})}),u.jsxs(U8,{children:["์ด ",l.itemCount,"๊ฐœ ์ƒํ’ˆ ๊ฒฐ์ œ"]})]}),u.jsx("div",{children:u.jsxs($8,{children:["๊ฒฐ์ œ๊ธˆ์•ก: ",Number(l.totalPrice).toLocaleString(),"์›"]})})]}),u.jsxs(W8,{children:[l.reservationStatus==="์˜ˆ์•ฝ ํ™•์ •"&&u.jsxs("div",{className:"space-x-3",children:[u.jsx(Ie,{to:`/my/order/edit?reservationId=${l.reservationId}`,children:u.jsx(uv,{type:"button",children:"์ƒ์„ธ ํ™•์ธ"})}),u.jsx(uv,{type:"button",onClick:()=>{i(l.reservationId)},children:"์˜ˆ์•ฝ ์ทจ์†Œ"})]}),l.reservationStatus==="์˜ˆ์•ฝ ์ทจ์†Œ"&&u.jsx("div",{children:u.jsx(G8,{})}),l.reservationStatus==="์ด์šฉ ์™„๋ฃŒ"&&u.jsx(Ie,{to:`/category/${l.storeId}`,children:u.jsx(H8,{children:"๋ฆฌ๋ทฐ ์ž‘์„ฑ"})})]})]})]},c))]})}function Y8(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=w.useState([]),[r,o]=w.useState(!0);w.useEffect(()=>{s()},[]);const s=async()=>{try{const i=sessionStorage.getItem("Authorization"),a=await fetch(`${e}/mypage/wishlist`,{method:"GET",headers:{Authorization:i}});if(a.ok){const l=await a.json();n(l.stores)}else console.error("์œ„์‹œ๋ฆฌ์ŠคํŠธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.",a.status)}catch(i){console.error("์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.",i)}finally{o(!1)}};return u.jsx(R8,{children:r?u.jsx("div",{className:"flex flex-col justify-center items-center h-[800px] w-[902px]",children:u.jsx(Jp,{})}):t.length===0?u.jsxs(T8,{children:[u.jsx(j8,{src:yl,alt:"nothingimg"}),u.jsx(Yp,{title:"์•„์ง ๋‹ด๊ธด ์œ„์‹œ๋ฆฌ์ŠคํŠธ๊ฐ€ ์—†๋„ค์š”!",description:"๊ด€์‹ฌ๊ฐ€๋Š” ์ƒํ’ˆ์„ ์ฐพ์•„ โ™ก๋ฅผ ๋ˆŒ๋Ÿฌ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์ฐจ๊ณก์ฐจ๊ณก ์Œ“์•„๋ณผ๊นŒ์š”?"})]}):u.jsxs("div",{className:"flex flex-col space-y-5 h-[100%]",children:[u.jsx("div",{children:u.jsxs(N8,{children:["์œ„์‹œ ์ƒํ’ˆ ",t.length,"๊ฐœ"]})}),t.filter(i=>i.isLike).map(i=>u.jsx(uS,{data:i},i.storeId))]})})}function Z8(e){return et({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",d:"M0 0h24v24H0z"}},{tag:"path",attr:{d:"M12 5.5l6 4.5v1c.7 0 1.37.1 2 .29V9l-8-6-8 6v12h7.68c-.3-.62-.5-1.29-.6-2H6v-9l6-4.5z"}},{tag:"path",attr:{d:"M18 13c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm3 5.5h-2.5V21h-1v-2.5H15v-1h2.5V15h1v2.5H21v1z"}}]})(e)}const Q8=b.div` + border-[1px] + border-[#4771B7] + px-[50px] + py-16 + space-y-5 + w-[902px] + h-[800px] + overflow-y-auto +`,X8=b.span` + font-medium + text-2xl + pl-4 +`,q8=b.div` + border-[1.5px] + border-[#4771B7] + w-[780px] + h-[200px] + rounded-lg + p-5 + flex + flex-row + justify-center + items-center + space-x-12 +`,e6=b.div` + relative + w-[146px] + h-[127px] +`,t6=b.div` + absolute + inset-0 + w-[146px] + h-[127px] +`,n6=b.img` + w-full + h-full + object-cover + rounded-md +`,r6=b.div` + flex + flex-col + w-[100%] + space-y-20 +`,o6=b.span` + text-[20px] + font-semibold + cursor-pointer +`,s6=b.div` + flex + justify-end + space-x-3 + font-medium + text-[15px] +`,dv=b.button` + bg-[#F3F5F7] + p-2 + rounded-lg +`,i6=b.div` + flex + flex-col + justify-center + items-center + space-y-5 + p-20 + h-[600px] +`;function a6(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=w.useState([]),[r,o]=w.useState(!0);w.useEffect(()=>{s()},[]);const s=async()=>{try{const f=sessionStorage.getItem("Authorization"),p=await fetch(`${e}/mystores`,{method:"GET",headers:{Authorization:f}});if(p.ok){const h=await p.json();n(h.stores)}}catch(f){console.error("์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.",f)}finally{o(!1)}},i=qe(),a=f=>{i(`/store/edit?store_id=${f}`)},l=()=>{i("/store/add")},c=f=>{i(`/category/${f}`)},d=()=>{alert("์—…์ฒด ์‚ญ์ œ๋Š” ํŒŒํŠธ๋„ˆ ์„ผํ„ฐ์— ๋ฌธ์˜์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.")};return u.jsxs(Q8,{children:[u.jsxs("div",{className:"flex flex-row justify-between",children:[u.jsx(X8,{children:"ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ"}),u.jsx("button",{className:"mr-6 text-[18px] font-semibold bg-[#4771B7] text-white p-[7px] rounded-lg",type:"button",onClick:l,children:"์—…์ฒด ๋“ฑ๋ก"})]}),r?u.jsx("div",{children:"๋กœ๋”ฉ์ค‘์ž…๋‹ˆ๋‹ค...."}):t.length===0?u.jsxs(i6,{children:[u.jsx(Z8,{style:{fontSize:"100px",color:"#4771B7"}}),u.jsx(Yp,{title:"์•„์ง ๋“ฑ๋ก๋œ ์—…์ฒด๊ฐ€ ์—†๋„ค์š”!",description:"์—…์ฒด๋ฅผ ์ฐจ๊ณก์ฐจ๊ณก ์Œ“์•„๋ณผ๊นŒ์š”?"})]}):t.map(f=>u.jsxs(q8,{children:[u.jsx(e6,{children:u.jsx(t6,{children:u.jsx(n6,{src:f.storeImage,alt:"store image"})})}),u.jsxs(r6,{children:[u.jsx("div",{className:"pt-5",children:u.jsx(o6,{onClick:()=>c(f.storeId),children:f.storeName})}),u.jsxs(s6,{children:[u.jsx(dv,{type:"button",onClick:()=>a(f.storeId),children:"์—…์ฒด ์ˆ˜์ •"}),u.jsx(dv,{type:"button",onClick:()=>d(),children:"์—…์ฒด ์‚ญ์ œ"})]})]})]},f.storeId))]})}const l6=b.section` + w-[900px] min-h-[55vh] + mx-auto my-20 + font-medium text-lg +`,Nr=b.input` + border-[1px] border-[#9A9A9A] rounded-[5px] + flex-auto + ml-5 p-3 + h-[45px] +`,c6=b.select` + border-[1px] border-[#9A9A9A] rounded-[5px] + flex-auto + ml-5 px-3 py-2 + h-[45px] +`,u6=b.textarea` + border-[1px] border-[#9A9A9A] rounded-[5px] + flex-auto + ml-5 p-3 + h-[120px] +`,xn=b.div` + w-[130px] text-right +`,d6=b.button` + px-5 py-2 ml-3 + bg-[#4771B7] + rounded-[10px] + text-white text-sm +`,f6=b.div` + w-[830px] + pl-8 pr-10 py-7 ml-5 + bg-[#EDF1F8] + flex-1 + rounded-[5px] +`,ju=b.div` + w-[80px] text-right +`,p6=b.button` + px-5 py-2 + bg-[#4771B7] + rounded-[10px] + text-white text-sm + block + ml-auto +`,h6=b.div` + ml-40 mb-5 + font-bold text-[#4771B7] + flex +`,m6=b.button` + px-3 py-1 ml-5 + border-[1px] border-black rounded-[5px] + bg-[#EDF1F8] + text-sm text-black +`,g6=b.button` + bg-[#4771B7] + px-7 py-3 mx-auto mt-20 + block + text-white text-lg + rounded-[10px] +`,Pi=Be({key:"formState",default:{storeName:"",body:"",address:"",kakao:"",contact:"",category:"",items:[]}}),yS=Be({key:"pageTitleState",default:"์—…์ฒด ๋“ฑ๋กํ•˜๊ธฐ"}),v6=Be({key:"ProductsState",default:{itemName:"",price:0,totalTicket:0}}),xS=Be({key:"SendFirstImgState",default:null}),wS=Be({key:"SendDetailImgsState",default:[]}),SS=Be({key:"FirstImgState",default:null}),CS=Be({key:"DetailImgsState",default:[]});function y6(){const[e,t]=Re(v6),[n,r]=Re(Pi),o=a=>{const l=a.target.value,c=Number(l.replace(/[^0-9]/g,""));a.target.name==="itemName"?t({...e,itemName:l}):a.target.name==="price"?t({...e,price:c}):a.target.name==="totalTicket"&&t({...e,totalTicket:c})},s=()=>{if(e.itemName===""||!e.price||!e.totalTicket)return alert("์ƒํ’ˆ ์ •๋ณด๋“ค์„ ์ œ๋Œ€๋กœ ๊ธฐ์ž…ํ•ด์ฃผ์„ธ์š”.");r(a=>({...a,items:[...a.items,{...e}]})),t({itemName:"",price:0,totalTicket:0})},i=a=>{const l=n.items.filter((c,d)=>d!==a);r(c=>({...c,items:[...l]}))};return u.jsxs("div",{children:[u.jsxs("div",{className:"flex mb-6",children:[u.jsx(xn,{children:"์ƒํ’ˆ๋“ฑ๋ก"}),u.jsxs(f6,{children:[u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(ju,{children:"์ƒํ’ˆ๋ช…"}),u.jsx(Nr,{type:"text",name:"itemName",value:e.itemName,onChange:o})]}),u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(ju,{children:"๊ฐ€๊ฒฉ"}),u.jsx(Nr,{type:"text",name:"price",value:e.price,onChange:o})]}),u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(ju,{children:"ํ‹ฐ์ผ“ ๊ฐœ์ˆ˜"}),u.jsx(Nr,{type:"text",name:"totalTicket",value:e.totalTicket,onChange:o})]}),u.jsx(p6,{type:"button",onClick:s,children:"๋“ฑ๋กํ•˜๊ธฐ"})]})]}),n.items&&n.items.map((a,l)=>u.jsxs(h6,{children:[u.jsxs("div",{children:[a.itemName," ",a.price.toLocaleString("ko-KR")," X ",a.totalTicket]}),u.jsx(m6,{onClick:()=>i(l),children:"์ง€์šฐ๊ธฐ"})]},l))]})}const fv=b.label` + bg-[#4771B7] + px-6 py-2 + text-sm text-white + rounded-[10px] +`,x6=b.div` + w-[230px] h-[230px] + border-[1px] border-[#4771B7] + mt-5 py-24 + text-center +`,pv=b.img` + w-[230px] h-[230px] + object-cover + mt-3 mb-3 + border-[1px] border-[#4771B7] +`,w6=b.button` + mx-auto px-4 py-1 + block + bg-[#EDF1F8] + border-[1px] border-black rounded-[5px] + text-sm +`;function S6({fetchImgsCount:e}){const t="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[n,r]=Re(SS),[o,s]=Re(CS),i=Xe(xS),[a,l]=Re(wS),[c]=dr(),d=c.get("store_id"),f=sessionStorage.getItem("Authorization"),p=x=>{const C=x.target.files[0],g=new FileReader;g.readAsDataURL(C),g.onloadend=()=>{r(String(g.result))},i(C)},h=x=>{const C=x.target.files;if(o.length+C.length>9)return alert("์ƒ์„ธ ์ด๋ฏธ์ง€๋Š” ์ตœ๋Œ€ 9์žฅ๊นŒ์ง€ ์—…๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.");for(let g=0;g{s(y=>[...y,m.result]),l(y=>[...y,C[g]])}}},v=x=>{if(location.pathname.substring(6)==="/edit"){if(o.length<=3)return alert("์ƒ์„ธ ์ด๋ฏธ์ง€๋Š” ์ตœ์†Œ 3์žฅ ์ด์ƒ ๋“ฑ๋กํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.");o[x][0]==="h"&&fetch(`${t}/storeImages/${d}?link=${o[x]}`,{method:"DELETE",headers:{Authorization:f}})}const g=[...o].filter((y,S)=>S!==x),m=[...a].filter((y,S)=>S!==x-e);s(g),l(m)};return u.jsxs("section",{children:[u.jsxs("div",{className:"flex mb-6 ",children:[u.jsx(xn,{children:"๋Œ€ํ‘œ ์ด๋ฏธ์ง€ ๋“ฑ๋ก"}),u.jsxs("div",{className:"ml-5",children:[u.jsxs(fv,{children:[u.jsx("span",{children:"ํŒŒ์ผ์„ ํƒ"}),u.jsx("input",{className:"hidden text-black",type:"file",accept:"image/*",onChange:p})]}),n?u.jsx(pv,{src:n,alt:"์—…์ฒด์‚ฌ์ง„"}):u.jsx(x6,{children:"๋Œ€ํ‘œ ์ด๋ฏธ์ง€"})]})]}),u.jsxs("div",{className:"flex mb-6 ",children:[u.jsx(xn,{children:"์ƒ์„ธ ์ด๋ฏธ์ง€ ๋“ฑ๋ก"}),u.jsxs("div",{className:"ml-5",children:[u.jsxs(fv,{children:[u.jsx("span",{children:"ํŒŒ์ผ์„ ํƒ"}),u.jsx("input",{className:"hidden text-black",type:"file",accept:"image/*",onChange:h,multiple:!0})]}),u.jsx("div",{className:"w-[750px] flex flex-wrap",children:o?o.map((x,C)=>u.jsxs("div",{className:"mr-5 mb-3",children:[u.jsx(pv,{src:x,alt:"์—…์ฒด์‚ฌ์ง„"}),u.jsx(w6,{onClick:()=>v(C),children:"์‚ญ์ œ"})]},C)):null})]})]})]})}var bS={},AS={},yc={};(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.postcodeScriptUrl=void 0;var t="https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js";e.postcodeScriptUrl="https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js";var n=function(){var o=null;return function(){var s=0"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function S(T){return S=Object.setPrototypeOf?Object.getPrototypeOf:function(O){return O.__proto__||Object.getPrototypeOf(O)},S(T)}function A(T,O,N){return O in T?Object.defineProperty(T,O,{value:N,enumerable:!0,configurable:!0,writable:!0}):T[O]=N,T}var L=n.default.createElement("p",null,"ํ˜„์žฌ Daum ์šฐํŽธ๋ฒˆํ˜ธ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”."),_={width:"100%",height:400},k={scriptUrl:r.postcodeScriptUrl,errorMessage:L,autoClose:!0},M=function(T){function O(){var D;f(this,O);for(var H=arguments.length,Z=Array(H),ne=0;ne{t(i=>!i)},s=i=>{r(a=>({...a,address:i.address})),t(a=>!a)};return u.jsxs("div",{className:"flex mb-6 items-center relative",children:[u.jsx(xn,{children:"์ฃผ์†Œ"}),u.jsx(Nr,{type:"text",name:"address",value:n.address,placeholder:"์ฃผ์†Œ์ฐพ๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์ฃผ์„ธ์š”.",readOnly:!0}),u.jsx(d6,{type:"button",onClick:o,children:"์ฃผ์†Œ์ฐพ๊ธฐ"}),e&&u.jsx(C6,{className:"absolute top-12 border-[1px] border-black",onComplete:s,autoClose:!1})]})}function A6({formChangeHandler:e}){const t=ze(Pi);return u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(xn,{children:"์นดํ…Œ๊ณ ๋ฆฌ"}),u.jsxs(c6,{name:"category",value:t.category,onChange:e,children:[u.jsx("option",{children:"์„ ํƒํ•ด์ฃผ์„ธ์š”"}),u.jsx("option",{children:"์Šค๋…ธํด๋ง/๋‹ค์ด๋น™"}),u.jsx("option",{children:"์ˆ˜์ƒ๋ ˆ์ €"}),u.jsx("option",{children:"์„œํ•‘"}),u.jsx("option",{children:"์Šน๋งˆ"}),u.jsx("option",{children:"ATV"})]})]})}function k6({formChangeHandler:e}){const t=ze(yS),n=ze(Pi);return u.jsxs(u.Fragment,{children:[u.jsx("div",{className:"text-2xl font-semibold mb-10 ml-10",children:t}),u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(xn,{children:"์—…์ฒด๋ช…"}),u.jsx(Nr,{type:"text",name:"storeName",value:n.storeName,onChange:e,placeholder:"์—…์ฒด๋ช…์„ ๊ธฐ์ค€์œผ๋กœ ๊ฒ€์ƒ‰์— ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค."})]}),u.jsxs("div",{className:"flex mb-6",children:[u.jsx(xn,{className:"pt-3",children:"์†Œ๊ฐœ๊ธ€"}),u.jsx(u6,{name:"body",value:n.body,onChange:e})]}),u.jsx(b6,{}),u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(xn,{children:"์นด์นด์˜คํ†ก ID"}),u.jsx(Nr,{type:"text",name:"kakao",value:n.kakao,onChange:e,placeholder:"์˜๋ฌธ๊ณผ ์ˆซ์ž ์กฐํ•ฉ์œผ๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."})]}),u.jsxs("div",{className:"flex mb-6 items-center",children:[u.jsx(xn,{children:"์—…์ฒด ์ „ํ™”๋ฒˆํ˜ธ"}),u.jsx(Nr,{type:"text",name:"contact",value:n.contact,onChange:e,placeholder:"'-'๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"})]}),u.jsx(A6,{formChangeHandler:e})]})}function hv(){const e="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",[t,n]=Re(Pi),[r,o]=w.useState(0),[s,i]=w.useState(!0),[a,l]=w.useState(!1),[c,d]=Re(xS),[f,p]=Re(wS),h=Xe(SS),v=Xe(CS),x=Xe(yS),C=tn(),[g]=dr(),m=g.get("store_id"),y=sessionStorage.getItem("Authorization"),S=k=>{const M=k.target.name,I=k.target.value;switch(M){case"storeName":return n({...t,storeName:I});case"body":return n({...t,body:I});case"kakao":const T=I.replace(/[^a-zA-Z0-9]/g,"");return n({...t,kakao:T});case"contact":const O=/(\d{3})(\d{3,4})(\d{4})/;let N=I.replace(/[^0-9]/g,"");return N.length>=11&&(N=N.replace(O,"$1-$2-$3")),N.length>=14?void 0:n({...t,contact:N});case"category":return n({...t,category:I})}},A=async()=>{if(!mv(t))return;if(!c)return alert("๋Œ€ํ‘œ์‚ฌ์ง„์„ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”.");if(f.length<3)return alert("์ƒ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ตœ์†Œ 3์žฅ ์ด์ƒ ๋“ฑ๋กํ•ด ์ฃผ์„ธ์š”.");const M=new FormData;f.forEach(I=>M.append("images",I)),M.append("thumbnailImage",c);try{l(N=>!N);const I=await fetch(`${e}/stores`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:y},body:JSON.stringify(t)});if(!I.ok)return l(N=>!N),alert("์—…์ฒด ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.");const T=await I.json();if(!(await fetch(`${e}/storeImages/${T.storeId}`,{method:"POST",headers:{Authorization:y},body:M})).ok)return l(N=>!N),alert("์—…์ฒด ์ด๋ฏธ์ง€ ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.");l(N=>!N),window.location.href=`/category/${T.storeId}`}catch(I){console.error(I)}},L=async k=>{try{const I=await(await fetch(`${e}/stores/${k}`)).json();n({storeName:I.storeName,body:I.body,address:I.address,kakao:I.kakao,contact:I.contact,category:I.category,items:I.items}),h(I.storeImages[0]),v(I.storeImages.slice(1)),o(I.storeImages.slice(1).length)}catch(M){console.error(M)}},_=async k=>{if(!mv(t))return;const I=new FormData;f.forEach(T=>I.append("images",T)),I.append("thumbnailImage",c);try{if(l(N=>!N),!(await fetch(`${e}/stores/${k}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:y},body:JSON.stringify(t)})).ok)return l(N=>!N),alert("์—…์ฒด ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.");if(!(await fetch(`${e}/storeImages/${k}`,{method:"PATCH",headers:{Authorization:y},body:I})).ok)return l(N=>!N),alert("์—…์ฒด ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.");l(N=>!N),window.location.href=`/category/${k}`}catch(T){console.error(T)}};return w.useEffect(()=>{n({storeName:"",body:"",address:"",kakao:"",contact:"",category:"",items:[]}),h(null),v([]),d(null),p([]),C.pathname.substring(6)==="/edit"&&(x("์—…์ฒด ์ˆ˜์ •ํ•˜๊ธฐ"),i(M=>!M),L(m))},[]),u.jsx(l6,{children:a?u.jsx("div",{className:"text-center text-2xl font-bold",children:"์—…์ฒด ๋“ฑ๋ก/์ˆ˜์ • ์ค‘์ž…๋‹ˆ๋‹ค..."}):u.jsxs(u.Fragment,{children:[u.jsx(k6,{formChangeHandler:S}),u.jsx(y6,{}),u.jsx(S6,{fetchImgsCount:r}),u.jsx(g6,{type:"button",onClick:()=>{s?A():_(m)},children:s?"๋“ฑ๋กํ•˜๊ธฐ":"์ˆ˜์ •ํ•˜๊ธฐ"})]})})}const mv=e=>{if(e.storeName)if(e.body)if(e.address)if(e.kakao){if(!e.contact||e.contact.length!==13)return alert("์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."),!1;if(e.category){if(!e.items.length)return alert("์ƒํ’ˆ์„ 1๊ฐœ ์ด์ƒ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”."),!1}else return alert("์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."),!1}else return alert("์นด์นด์˜คํ†ก ID๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."),!1;else return alert("์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."),!1;else return alert("์†Œ๊ฐœ๊ธ€์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."),!1;else return alert("์—…์ฒด๋ช…์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."),!1;return!0},E6=b.div` + border-[1px] + border-[#4771B7] + h-[500px] + w-[270px] + px-10 + py-16 + space-y-20 + mr-10 +`,gv=b.div` + flex + flex-col + space-y-8 +`,vv=b.span` + text-xl + font-semibold +`,yv=b.div` + text-lg + flex + flex-col + space-y-8 + pl-5 +`;b.a` + text-base + text-black + hover:text-[#3366BB] + cursor-pointer +`;function R6(){const e=ze(mr),t=ze(Ti),n=r=>{t!=="PARTNER"&&(r.preventDefault(),alert("์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."))};return u.jsxs(E6,{children:[u.jsxs(gv,{children:[u.jsx(vv,{children:"๋งˆ์ดํŽ˜์ด์ง€"}),u.jsxs(yv,{children:[u.jsx(Ie,{to:"/my",children:"๋‚ด ์ •๋ณด ๊ด€๋ฆฌ"}),u.jsx(Ie,{to:"/my/wish",children:"์œ„์‹œ๋ฆฌ์ŠคํŠธ"}),u.jsx(Ie,{to:"/my/order",children:"์˜ˆ์•ฝ ๋‚ด์—ญ ์กฐํšŒ"})]})]}),u.jsxs(gv,{children:[u.jsx(vv,{children:"ํŒŒํŠธ๋„ˆ์‰ฝ"}),u.jsx(yv,{children:e&&u.jsx(Ie,{to:"/my/stores",onClick:n,children:"ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ"})})]})]})}function T6(){return u.jsx(u.Fragment,{children:u.jsxs(j6,{children:[u.jsx(R6,{}),u.jsx(Ol,{})]})})}const j6=b.div` + flex + flex-row + justify-center + py-12 +`;function P6(){return u.jsx(Mp.div,{initial:{opacity:0,scale:.5},animate:{opacity:1,scale:1},transition:{duration:.8,delay:.5,ease:[0,.71,.2,1.01]},children:u.jsx(Xf,{children:u.jsx(xe,{element:u.jsx(Kp,{}),children:u.jsxs(xe,{element:u.jsx(Gp,{}),children:[u.jsxs(xe,{element:u.jsx(T6,{}),children:[u.jsx(xe,{path:"/my",element:u.jsx(g8,{})}),u.jsx(xe,{path:"/my/wish",element:u.jsx(Y8,{})}),u.jsx(xe,{path:"/my/order",element:u.jsx(J8,{})}),u.jsx(xe,{path:"/my/stores",element:u.jsx(a6,{})})]}),u.jsx(xe,{path:"/my/order/edit",element:u.jsx(E8,{})}),u.jsx(xe,{path:"/store/add",element:u.jsx(hv,{})}),u.jsx(xe,{path:"/store/edit",element:u.jsx(hv,{})})]})})})})}function N6(){const e=qe(),[t]=dr(),n=Xe(mr),r=Xe(pc),o=Xe(Ti),s="http://ec2-43-201-0-197.ap-northeast-2.compute.amazonaws.com:8080",i=async()=>{const a=t.get("access_token");if(a){try{const l=await fetch(`${s}/google/login`,{headers:{Authorization:`Bearer ${a}`}}),c=await l.json();if(l.status!==200)throw l;const d=c.nickname,f=c.profileImage,p=c.role;r(f),o(p),sessionStorage.setItem("Authorization",`Bearer ${a}`),n(!0),d&&(alert(`${d}๋‹˜ ๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค !`),e("/home"))}catch(l){console.error("๋กœ๊ทธ์ธ ์š”์ฒญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค",l)}e("/home")}};return w.useEffect(()=>{i()},[]),u.jsxs(u.Fragment,{children:[u.jsx(d7,{}),u.jsx(HM,{}),u.jsx(P6,{})]})}const L6={key:"recoil-persist",storage:localStorage};Pu.createRoot(document.getElementById("root")).render(u.jsx(sA,{children:u.jsx(mL,{children:u.jsx(V.Suspense,{fallback:u.jsx("div",{children:"Loading..."}),children:u.jsx(q3,{...L6,children:u.jsx(N6,{})})})})})); diff --git a/client/dist/assets/index-8d22ccae.css b/client/dist/assets/index-8d22ccae.css new file mode 100644 index 00000000..fcbcd4a0 --- /dev/null +++ b/client/dist/assets/index-8d22ccae.css @@ -0,0 +1 @@ +html{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}.object-cover{object-fit:cover}:root{--toastify-color-light: #fff;--toastify-color-dark: #121212;--toastify-color-info: #3498db;--toastify-color-success: #07bc0c;--toastify-color-warning: #f1c40f;--toastify-color-error: #e74c3c;--toastify-color-transparent: rgba(255, 255, 255, .7);--toastify-icon-color-info: var(--toastify-color-info);--toastify-icon-color-success: var(--toastify-color-success);--toastify-icon-color-warning: var(--toastify-color-warning);--toastify-icon-color-error: var(--toastify-color-error);--toastify-toast-width: 320px;--toastify-toast-background: #fff;--toastify-toast-min-height: 64px;--toastify-toast-max-height: 800px;--toastify-font-family: sans-serif;--toastify-z-index: 9999;--toastify-text-color-light: #757575;--toastify-text-color-dark: #fff;--toastify-text-color-info: #fff;--toastify-text-color-success: #fff;--toastify-text-color-warning: #fff;--toastify-text-color-error: #fff;--toastify-spinner-color: #616161;--toastify-spinner-color-empty-area: #e0e0e0;--toastify-color-progress-light: linear-gradient( to right, #4cd964, #5ac8fa, #007aff, #34aadc, #5856d6, #ff2d55 );--toastify-color-progress-dark: #bb86fc;--toastify-color-progress-info: var(--toastify-color-info);--toastify-color-progress-success: var(--toastify-color-success);--toastify-color-progress-warning: var(--toastify-color-warning);--toastify-color-progress-error: var(--toastify-color-error)}.Toastify__toast-container{z-index:var(--toastify-z-index);-webkit-transform:translate3d(0,0,var(--toastify-z-index));position:fixed;padding:4px;width:var(--toastify-toast-width);box-sizing:border-box;color:#fff}.Toastify__toast-container--top-left{top:1em;left:1em}.Toastify__toast-container--top-center{top:1em;left:50%;transform:translate(-50%)}.Toastify__toast-container--top-right{top:1em;right:1em}.Toastify__toast-container--bottom-left{bottom:1em;left:1em}.Toastify__toast-container--bottom-center{bottom:1em;left:50%;transform:translate(-50%)}.Toastify__toast-container--bottom-right{bottom:1em;right:1em}@media only screen and (max-width : 480px){.Toastify__toast-container{width:100vw;padding:0;left:0;margin:0}.Toastify__toast-container--top-left,.Toastify__toast-container--top-center,.Toastify__toast-container--top-right{top:0;transform:translate(0)}.Toastify__toast-container--bottom-left,.Toastify__toast-container--bottom-center,.Toastify__toast-container--bottom-right{bottom:0;transform:translate(0)}.Toastify__toast-container--rtl{right:0;left:initial}}.Toastify__toast{position:relative;min-height:var(--toastify-toast-min-height);box-sizing:border-box;margin-bottom:1rem;padding:8px;border-radius:4px;box-shadow:0 1px 10px #0000001a,0 2px 15px #0000000d;display:flex;justify-content:space-between;max-height:var(--toastify-toast-max-height);overflow:hidden;font-family:var(--toastify-font-family);cursor:default;direction:ltr;z-index:0}.Toastify__toast--rtl{direction:rtl}.Toastify__toast--close-on-click{cursor:pointer}.Toastify__toast-body{margin:auto 0;flex:1 1 auto;padding:6px;display:flex;align-items:center}.Toastify__toast-body>div:last-child{word-break:break-word;flex:1}.Toastify__toast-icon{-webkit-margin-end:10px;margin-inline-end:10px;width:20px;flex-shrink:0;display:flex}.Toastify--animate{animation-fill-mode:both;animation-duration:.7s}.Toastify--animate-icon{animation-fill-mode:both;animation-duration:.3s}@media only screen and (max-width : 480px){.Toastify__toast{margin-bottom:0;border-radius:0}}.Toastify__toast-theme--dark{background:var(--toastify-color-dark);color:var(--toastify-text-color-dark)}.Toastify__toast-theme--light,.Toastify__toast-theme--colored.Toastify__toast--default{background:var(--toastify-color-light);color:var(--toastify-text-color-light)}.Toastify__toast-theme--colored.Toastify__toast--info{color:var(--toastify-text-color-info);background:var(--toastify-color-info)}.Toastify__toast-theme--colored.Toastify__toast--success{color:var(--toastify-text-color-success);background:var(--toastify-color-success)}.Toastify__toast-theme--colored.Toastify__toast--warning{color:var(--toastify-text-color-warning);background:var(--toastify-color-warning)}.Toastify__toast-theme--colored.Toastify__toast--error{color:var(--toastify-text-color-error);background:var(--toastify-color-error)}.Toastify__progress-bar-theme--light{background:var(--toastify-color-progress-light)}.Toastify__progress-bar-theme--dark{background:var(--toastify-color-progress-dark)}.Toastify__progress-bar--info{background:var(--toastify-color-progress-info)}.Toastify__progress-bar--success{background:var(--toastify-color-progress-success)}.Toastify__progress-bar--warning{background:var(--toastify-color-progress-warning)}.Toastify__progress-bar--error{background:var(--toastify-color-progress-error)}.Toastify__progress-bar-theme--colored.Toastify__progress-bar--info,.Toastify__progress-bar-theme--colored.Toastify__progress-bar--success,.Toastify__progress-bar-theme--colored.Toastify__progress-bar--warning,.Toastify__progress-bar-theme--colored.Toastify__progress-bar--error{background:var(--toastify-color-transparent)}.Toastify__close-button{color:#fff;background:transparent;outline:none;border:none;padding:0;cursor:pointer;opacity:.7;transition:.3s ease;align-self:flex-start}.Toastify__close-button--light{color:#000;opacity:.3}.Toastify__close-button>svg{fill:currentColor;height:16px;width:14px}.Toastify__close-button:hover,.Toastify__close-button:focus{opacity:1}@keyframes Toastify__trackProgress{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.Toastify__progress-bar{position:absolute;bottom:0;left:0;width:100%;height:5px;z-index:var(--toastify-z-index);opacity:.7;transform-origin:left}.Toastify__progress-bar--animated{animation:Toastify__trackProgress linear 1 forwards}.Toastify__progress-bar--controlled{transition:transform .2s}.Toastify__progress-bar--rtl{right:0;left:initial;transform-origin:right}.Toastify__spinner{width:20px;height:20px;box-sizing:border-box;border:2px solid;border-radius:100%;border-color:var(--toastify-spinner-color-empty-area);border-right-color:var(--toastify-spinner-color);animation:Toastify__spin .65s linear infinite}@keyframes Toastify__bounceInRight{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}@keyframes Toastify__bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}@keyframes Toastify__bounceInLeft{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}@keyframes Toastify__bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes Toastify__bounceInUp{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}@keyframes Toastify__bounceOutUp{20%{transform:translate3d(0,-10px,0)}40%,45%{opacity:1;transform:translate3d(0,20px,0)}to{opacity:0;transform:translate3d(0,-2000px,0)}}@keyframes Toastify__bounceInDown{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}@keyframes Toastify__bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}.Toastify__bounce-enter--top-left,.Toastify__bounce-enter--bottom-left{animation-name:Toastify__bounceInLeft}.Toastify__bounce-enter--top-right,.Toastify__bounce-enter--bottom-right{animation-name:Toastify__bounceInRight}.Toastify__bounce-enter--top-center{animation-name:Toastify__bounceInDown}.Toastify__bounce-enter--bottom-center{animation-name:Toastify__bounceInUp}.Toastify__bounce-exit--top-left,.Toastify__bounce-exit--bottom-left{animation-name:Toastify__bounceOutLeft}.Toastify__bounce-exit--top-right,.Toastify__bounce-exit--bottom-right{animation-name:Toastify__bounceOutRight}.Toastify__bounce-exit--top-center{animation-name:Toastify__bounceOutUp}.Toastify__bounce-exit--bottom-center{animation-name:Toastify__bounceOutDown}@keyframes Toastify__zoomIn{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes Toastify__zoomOut{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.Toastify__zoom-enter{animation-name:Toastify__zoomIn}.Toastify__zoom-exit{animation-name:Toastify__zoomOut}@keyframes Toastify__flipIn{0%{transform:perspective(400px) rotateX(90deg);animation-timing-function:ease-in;opacity:0}40%{transform:perspective(400px) rotateX(-20deg);animation-timing-function:ease-in}60%{transform:perspective(400px) rotateX(10deg);opacity:1}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}@keyframes Toastify__flipOut{0%{transform:perspective(400px)}30%{transform:perspective(400px) rotateX(-20deg);opacity:1}to{transform:perspective(400px) rotateX(90deg);opacity:0}}.Toastify__flip-enter{animation-name:Toastify__flipIn}.Toastify__flip-exit{animation-name:Toastify__flipOut}@keyframes Toastify__slideInRight{0%{transform:translate3d(110%,0,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInLeft{0%{transform:translate3d(-110%,0,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInUp{0%{transform:translate3d(0,110%,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInDown{0%{transform:translate3d(0,-110%,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideOutRight{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(110%,0,0)}}@keyframes Toastify__slideOutLeft{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(-110%,0,0)}}@keyframes Toastify__slideOutDown{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,500px,0)}}@keyframes Toastify__slideOutUp{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,-500px,0)}}.Toastify__slide-enter--top-left,.Toastify__slide-enter--bottom-left{animation-name:Toastify__slideInLeft}.Toastify__slide-enter--top-right,.Toastify__slide-enter--bottom-right{animation-name:Toastify__slideInRight}.Toastify__slide-enter--top-center{animation-name:Toastify__slideInDown}.Toastify__slide-enter--bottom-center{animation-name:Toastify__slideInUp}.Toastify__slide-exit--top-left,.Toastify__slide-exit--bottom-left{animation-name:Toastify__slideOutLeft}.Toastify__slide-exit--top-right,.Toastify__slide-exit--bottom-right{animation-name:Toastify__slideOutRight}.Toastify__slide-exit--top-center{animation-name:Toastify__slideOutUp}.Toastify__slide-exit--bottom-center{animation-name:Toastify__slideOutDown}@keyframes Toastify__spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}[data-aos][data-aos][data-aos-duration="50"],body[data-aos-duration="50"] [data-aos]{transition-duration:50ms}[data-aos][data-aos][data-aos-delay="50"],body[data-aos-delay="50"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="50"].aos-animate,body[data-aos-delay="50"] [data-aos].aos-animate{transition-delay:50ms}[data-aos][data-aos][data-aos-duration="100"],body[data-aos-duration="100"] [data-aos]{transition-duration:.1s}[data-aos][data-aos][data-aos-delay="100"],body[data-aos-delay="100"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="100"].aos-animate,body[data-aos-delay="100"] [data-aos].aos-animate{transition-delay:.1s}[data-aos][data-aos][data-aos-duration="150"],body[data-aos-duration="150"] [data-aos]{transition-duration:.15s}[data-aos][data-aos][data-aos-delay="150"],body[data-aos-delay="150"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="150"].aos-animate,body[data-aos-delay="150"] [data-aos].aos-animate{transition-delay:.15s}[data-aos][data-aos][data-aos-duration="200"],body[data-aos-duration="200"] [data-aos]{transition-duration:.2s}[data-aos][data-aos][data-aos-delay="200"],body[data-aos-delay="200"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="200"].aos-animate,body[data-aos-delay="200"] [data-aos].aos-animate{transition-delay:.2s}[data-aos][data-aos][data-aos-duration="250"],body[data-aos-duration="250"] [data-aos]{transition-duration:.25s}[data-aos][data-aos][data-aos-delay="250"],body[data-aos-delay="250"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="250"].aos-animate,body[data-aos-delay="250"] [data-aos].aos-animate{transition-delay:.25s}[data-aos][data-aos][data-aos-duration="300"],body[data-aos-duration="300"] [data-aos]{transition-duration:.3s}[data-aos][data-aos][data-aos-delay="300"],body[data-aos-delay="300"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="300"].aos-animate,body[data-aos-delay="300"] [data-aos].aos-animate{transition-delay:.3s}[data-aos][data-aos][data-aos-duration="350"],body[data-aos-duration="350"] [data-aos]{transition-duration:.35s}[data-aos][data-aos][data-aos-delay="350"],body[data-aos-delay="350"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="350"].aos-animate,body[data-aos-delay="350"] [data-aos].aos-animate{transition-delay:.35s}[data-aos][data-aos][data-aos-duration="400"],body[data-aos-duration="400"] [data-aos]{transition-duration:.4s}[data-aos][data-aos][data-aos-delay="400"],body[data-aos-delay="400"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="400"].aos-animate,body[data-aos-delay="400"] [data-aos].aos-animate{transition-delay:.4s}[data-aos][data-aos][data-aos-duration="450"],body[data-aos-duration="450"] [data-aos]{transition-duration:.45s}[data-aos][data-aos][data-aos-delay="450"],body[data-aos-delay="450"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="450"].aos-animate,body[data-aos-delay="450"] [data-aos].aos-animate{transition-delay:.45s}[data-aos][data-aos][data-aos-duration="500"],body[data-aos-duration="500"] [data-aos]{transition-duration:.5s}[data-aos][data-aos][data-aos-delay="500"],body[data-aos-delay="500"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="500"].aos-animate,body[data-aos-delay="500"] [data-aos].aos-animate{transition-delay:.5s}[data-aos][data-aos][data-aos-duration="550"],body[data-aos-duration="550"] [data-aos]{transition-duration:.55s}[data-aos][data-aos][data-aos-delay="550"],body[data-aos-delay="550"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="550"].aos-animate,body[data-aos-delay="550"] [data-aos].aos-animate{transition-delay:.55s}[data-aos][data-aos][data-aos-duration="600"],body[data-aos-duration="600"] [data-aos]{transition-duration:.6s}[data-aos][data-aos][data-aos-delay="600"],body[data-aos-delay="600"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="600"].aos-animate,body[data-aos-delay="600"] [data-aos].aos-animate{transition-delay:.6s}[data-aos][data-aos][data-aos-duration="650"],body[data-aos-duration="650"] [data-aos]{transition-duration:.65s}[data-aos][data-aos][data-aos-delay="650"],body[data-aos-delay="650"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="650"].aos-animate,body[data-aos-delay="650"] [data-aos].aos-animate{transition-delay:.65s}[data-aos][data-aos][data-aos-duration="700"],body[data-aos-duration="700"] [data-aos]{transition-duration:.7s}[data-aos][data-aos][data-aos-delay="700"],body[data-aos-delay="700"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="700"].aos-animate,body[data-aos-delay="700"] [data-aos].aos-animate{transition-delay:.7s}[data-aos][data-aos][data-aos-duration="750"],body[data-aos-duration="750"] [data-aos]{transition-duration:.75s}[data-aos][data-aos][data-aos-delay="750"],body[data-aos-delay="750"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="750"].aos-animate,body[data-aos-delay="750"] [data-aos].aos-animate{transition-delay:.75s}[data-aos][data-aos][data-aos-duration="800"],body[data-aos-duration="800"] [data-aos]{transition-duration:.8s}[data-aos][data-aos][data-aos-delay="800"],body[data-aos-delay="800"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="800"].aos-animate,body[data-aos-delay="800"] [data-aos].aos-animate{transition-delay:.8s}[data-aos][data-aos][data-aos-duration="850"],body[data-aos-duration="850"] [data-aos]{transition-duration:.85s}[data-aos][data-aos][data-aos-delay="850"],body[data-aos-delay="850"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="850"].aos-animate,body[data-aos-delay="850"] [data-aos].aos-animate{transition-delay:.85s}[data-aos][data-aos][data-aos-duration="900"],body[data-aos-duration="900"] [data-aos]{transition-duration:.9s}[data-aos][data-aos][data-aos-delay="900"],body[data-aos-delay="900"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="900"].aos-animate,body[data-aos-delay="900"] [data-aos].aos-animate{transition-delay:.9s}[data-aos][data-aos][data-aos-duration="950"],body[data-aos-duration="950"] [data-aos]{transition-duration:.95s}[data-aos][data-aos][data-aos-delay="950"],body[data-aos-delay="950"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="950"].aos-animate,body[data-aos-delay="950"] [data-aos].aos-animate{transition-delay:.95s}[data-aos][data-aos][data-aos-duration="1000"],body[data-aos-duration="1000"] [data-aos]{transition-duration:1s}[data-aos][data-aos][data-aos-delay="1000"],body[data-aos-delay="1000"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1000"].aos-animate,body[data-aos-delay="1000"] [data-aos].aos-animate{transition-delay:1s}[data-aos][data-aos][data-aos-duration="1050"],body[data-aos-duration="1050"] [data-aos]{transition-duration:1.05s}[data-aos][data-aos][data-aos-delay="1050"],body[data-aos-delay="1050"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1050"].aos-animate,body[data-aos-delay="1050"] [data-aos].aos-animate{transition-delay:1.05s}[data-aos][data-aos][data-aos-duration="1100"],body[data-aos-duration="1100"] [data-aos]{transition-duration:1.1s}[data-aos][data-aos][data-aos-delay="1100"],body[data-aos-delay="1100"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1100"].aos-animate,body[data-aos-delay="1100"] [data-aos].aos-animate{transition-delay:1.1s}[data-aos][data-aos][data-aos-duration="1150"],body[data-aos-duration="1150"] [data-aos]{transition-duration:1.15s}[data-aos][data-aos][data-aos-delay="1150"],body[data-aos-delay="1150"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1150"].aos-animate,body[data-aos-delay="1150"] [data-aos].aos-animate{transition-delay:1.15s}[data-aos][data-aos][data-aos-duration="1200"],body[data-aos-duration="1200"] [data-aos]{transition-duration:1.2s}[data-aos][data-aos][data-aos-delay="1200"],body[data-aos-delay="1200"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1200"].aos-animate,body[data-aos-delay="1200"] [data-aos].aos-animate{transition-delay:1.2s}[data-aos][data-aos][data-aos-duration="1250"],body[data-aos-duration="1250"] [data-aos]{transition-duration:1.25s}[data-aos][data-aos][data-aos-delay="1250"],body[data-aos-delay="1250"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1250"].aos-animate,body[data-aos-delay="1250"] [data-aos].aos-animate{transition-delay:1.25s}[data-aos][data-aos][data-aos-duration="1300"],body[data-aos-duration="1300"] [data-aos]{transition-duration:1.3s}[data-aos][data-aos][data-aos-delay="1300"],body[data-aos-delay="1300"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1300"].aos-animate,body[data-aos-delay="1300"] [data-aos].aos-animate{transition-delay:1.3s}[data-aos][data-aos][data-aos-duration="1350"],body[data-aos-duration="1350"] [data-aos]{transition-duration:1.35s}[data-aos][data-aos][data-aos-delay="1350"],body[data-aos-delay="1350"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1350"].aos-animate,body[data-aos-delay="1350"] [data-aos].aos-animate{transition-delay:1.35s}[data-aos][data-aos][data-aos-duration="1400"],body[data-aos-duration="1400"] [data-aos]{transition-duration:1.4s}[data-aos][data-aos][data-aos-delay="1400"],body[data-aos-delay="1400"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1400"].aos-animate,body[data-aos-delay="1400"] [data-aos].aos-animate{transition-delay:1.4s}[data-aos][data-aos][data-aos-duration="1450"],body[data-aos-duration="1450"] [data-aos]{transition-duration:1.45s}[data-aos][data-aos][data-aos-delay="1450"],body[data-aos-delay="1450"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1450"].aos-animate,body[data-aos-delay="1450"] [data-aos].aos-animate{transition-delay:1.45s}[data-aos][data-aos][data-aos-duration="1500"],body[data-aos-duration="1500"] [data-aos]{transition-duration:1.5s}[data-aos][data-aos][data-aos-delay="1500"],body[data-aos-delay="1500"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1500"].aos-animate,body[data-aos-delay="1500"] [data-aos].aos-animate{transition-delay:1.5s}[data-aos][data-aos][data-aos-duration="1550"],body[data-aos-duration="1550"] [data-aos]{transition-duration:1.55s}[data-aos][data-aos][data-aos-delay="1550"],body[data-aos-delay="1550"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1550"].aos-animate,body[data-aos-delay="1550"] [data-aos].aos-animate{transition-delay:1.55s}[data-aos][data-aos][data-aos-duration="1600"],body[data-aos-duration="1600"] [data-aos]{transition-duration:1.6s}[data-aos][data-aos][data-aos-delay="1600"],body[data-aos-delay="1600"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1600"].aos-animate,body[data-aos-delay="1600"] [data-aos].aos-animate{transition-delay:1.6s}[data-aos][data-aos][data-aos-duration="1650"],body[data-aos-duration="1650"] [data-aos]{transition-duration:1.65s}[data-aos][data-aos][data-aos-delay="1650"],body[data-aos-delay="1650"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1650"].aos-animate,body[data-aos-delay="1650"] [data-aos].aos-animate{transition-delay:1.65s}[data-aos][data-aos][data-aos-duration="1700"],body[data-aos-duration="1700"] [data-aos]{transition-duration:1.7s}[data-aos][data-aos][data-aos-delay="1700"],body[data-aos-delay="1700"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1700"].aos-animate,body[data-aos-delay="1700"] [data-aos].aos-animate{transition-delay:1.7s}[data-aos][data-aos][data-aos-duration="1750"],body[data-aos-duration="1750"] [data-aos]{transition-duration:1.75s}[data-aos][data-aos][data-aos-delay="1750"],body[data-aos-delay="1750"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1750"].aos-animate,body[data-aos-delay="1750"] [data-aos].aos-animate{transition-delay:1.75s}[data-aos][data-aos][data-aos-duration="1800"],body[data-aos-duration="1800"] [data-aos]{transition-duration:1.8s}[data-aos][data-aos][data-aos-delay="1800"],body[data-aos-delay="1800"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1800"].aos-animate,body[data-aos-delay="1800"] [data-aos].aos-animate{transition-delay:1.8s}[data-aos][data-aos][data-aos-duration="1850"],body[data-aos-duration="1850"] [data-aos]{transition-duration:1.85s}[data-aos][data-aos][data-aos-delay="1850"],body[data-aos-delay="1850"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1850"].aos-animate,body[data-aos-delay="1850"] [data-aos].aos-animate{transition-delay:1.85s}[data-aos][data-aos][data-aos-duration="1900"],body[data-aos-duration="1900"] [data-aos]{transition-duration:1.9s}[data-aos][data-aos][data-aos-delay="1900"],body[data-aos-delay="1900"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1900"].aos-animate,body[data-aos-delay="1900"] [data-aos].aos-animate{transition-delay:1.9s}[data-aos][data-aos][data-aos-duration="1950"],body[data-aos-duration="1950"] [data-aos]{transition-duration:1.95s}[data-aos][data-aos][data-aos-delay="1950"],body[data-aos-delay="1950"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="1950"].aos-animate,body[data-aos-delay="1950"] [data-aos].aos-animate{transition-delay:1.95s}[data-aos][data-aos][data-aos-duration="2000"],body[data-aos-duration="2000"] [data-aos]{transition-duration:2s}[data-aos][data-aos][data-aos-delay="2000"],body[data-aos-delay="2000"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2000"].aos-animate,body[data-aos-delay="2000"] [data-aos].aos-animate{transition-delay:2s}[data-aos][data-aos][data-aos-duration="2050"],body[data-aos-duration="2050"] [data-aos]{transition-duration:2.05s}[data-aos][data-aos][data-aos-delay="2050"],body[data-aos-delay="2050"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2050"].aos-animate,body[data-aos-delay="2050"] [data-aos].aos-animate{transition-delay:2.05s}[data-aos][data-aos][data-aos-duration="2100"],body[data-aos-duration="2100"] [data-aos]{transition-duration:2.1s}[data-aos][data-aos][data-aos-delay="2100"],body[data-aos-delay="2100"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2100"].aos-animate,body[data-aos-delay="2100"] [data-aos].aos-animate{transition-delay:2.1s}[data-aos][data-aos][data-aos-duration="2150"],body[data-aos-duration="2150"] [data-aos]{transition-duration:2.15s}[data-aos][data-aos][data-aos-delay="2150"],body[data-aos-delay="2150"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2150"].aos-animate,body[data-aos-delay="2150"] [data-aos].aos-animate{transition-delay:2.15s}[data-aos][data-aos][data-aos-duration="2200"],body[data-aos-duration="2200"] [data-aos]{transition-duration:2.2s}[data-aos][data-aos][data-aos-delay="2200"],body[data-aos-delay="2200"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2200"].aos-animate,body[data-aos-delay="2200"] [data-aos].aos-animate{transition-delay:2.2s}[data-aos][data-aos][data-aos-duration="2250"],body[data-aos-duration="2250"] [data-aos]{transition-duration:2.25s}[data-aos][data-aos][data-aos-delay="2250"],body[data-aos-delay="2250"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2250"].aos-animate,body[data-aos-delay="2250"] [data-aos].aos-animate{transition-delay:2.25s}[data-aos][data-aos][data-aos-duration="2300"],body[data-aos-duration="2300"] [data-aos]{transition-duration:2.3s}[data-aos][data-aos][data-aos-delay="2300"],body[data-aos-delay="2300"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2300"].aos-animate,body[data-aos-delay="2300"] [data-aos].aos-animate{transition-delay:2.3s}[data-aos][data-aos][data-aos-duration="2350"],body[data-aos-duration="2350"] [data-aos]{transition-duration:2.35s}[data-aos][data-aos][data-aos-delay="2350"],body[data-aos-delay="2350"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2350"].aos-animate,body[data-aos-delay="2350"] [data-aos].aos-animate{transition-delay:2.35s}[data-aos][data-aos][data-aos-duration="2400"],body[data-aos-duration="2400"] [data-aos]{transition-duration:2.4s}[data-aos][data-aos][data-aos-delay="2400"],body[data-aos-delay="2400"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2400"].aos-animate,body[data-aos-delay="2400"] [data-aos].aos-animate{transition-delay:2.4s}[data-aos][data-aos][data-aos-duration="2450"],body[data-aos-duration="2450"] [data-aos]{transition-duration:2.45s}[data-aos][data-aos][data-aos-delay="2450"],body[data-aos-delay="2450"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2450"].aos-animate,body[data-aos-delay="2450"] [data-aos].aos-animate{transition-delay:2.45s}[data-aos][data-aos][data-aos-duration="2500"],body[data-aos-duration="2500"] [data-aos]{transition-duration:2.5s}[data-aos][data-aos][data-aos-delay="2500"],body[data-aos-delay="2500"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2500"].aos-animate,body[data-aos-delay="2500"] [data-aos].aos-animate{transition-delay:2.5s}[data-aos][data-aos][data-aos-duration="2550"],body[data-aos-duration="2550"] [data-aos]{transition-duration:2.55s}[data-aos][data-aos][data-aos-delay="2550"],body[data-aos-delay="2550"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2550"].aos-animate,body[data-aos-delay="2550"] [data-aos].aos-animate{transition-delay:2.55s}[data-aos][data-aos][data-aos-duration="2600"],body[data-aos-duration="2600"] [data-aos]{transition-duration:2.6s}[data-aos][data-aos][data-aos-delay="2600"],body[data-aos-delay="2600"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2600"].aos-animate,body[data-aos-delay="2600"] [data-aos].aos-animate{transition-delay:2.6s}[data-aos][data-aos][data-aos-duration="2650"],body[data-aos-duration="2650"] [data-aos]{transition-duration:2.65s}[data-aos][data-aos][data-aos-delay="2650"],body[data-aos-delay="2650"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2650"].aos-animate,body[data-aos-delay="2650"] [data-aos].aos-animate{transition-delay:2.65s}[data-aos][data-aos][data-aos-duration="2700"],body[data-aos-duration="2700"] [data-aos]{transition-duration:2.7s}[data-aos][data-aos][data-aos-delay="2700"],body[data-aos-delay="2700"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2700"].aos-animate,body[data-aos-delay="2700"] [data-aos].aos-animate{transition-delay:2.7s}[data-aos][data-aos][data-aos-duration="2750"],body[data-aos-duration="2750"] [data-aos]{transition-duration:2.75s}[data-aos][data-aos][data-aos-delay="2750"],body[data-aos-delay="2750"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2750"].aos-animate,body[data-aos-delay="2750"] [data-aos].aos-animate{transition-delay:2.75s}[data-aos][data-aos][data-aos-duration="2800"],body[data-aos-duration="2800"] [data-aos]{transition-duration:2.8s}[data-aos][data-aos][data-aos-delay="2800"],body[data-aos-delay="2800"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2800"].aos-animate,body[data-aos-delay="2800"] [data-aos].aos-animate{transition-delay:2.8s}[data-aos][data-aos][data-aos-duration="2850"],body[data-aos-duration="2850"] [data-aos]{transition-duration:2.85s}[data-aos][data-aos][data-aos-delay="2850"],body[data-aos-delay="2850"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2850"].aos-animate,body[data-aos-delay="2850"] [data-aos].aos-animate{transition-delay:2.85s}[data-aos][data-aos][data-aos-duration="2900"],body[data-aos-duration="2900"] [data-aos]{transition-duration:2.9s}[data-aos][data-aos][data-aos-delay="2900"],body[data-aos-delay="2900"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2900"].aos-animate,body[data-aos-delay="2900"] [data-aos].aos-animate{transition-delay:2.9s}[data-aos][data-aos][data-aos-duration="2950"],body[data-aos-duration="2950"] [data-aos]{transition-duration:2.95s}[data-aos][data-aos][data-aos-delay="2950"],body[data-aos-delay="2950"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="2950"].aos-animate,body[data-aos-delay="2950"] [data-aos].aos-animate{transition-delay:2.95s}[data-aos][data-aos][data-aos-duration="3000"],body[data-aos-duration="3000"] [data-aos]{transition-duration:3s}[data-aos][data-aos][data-aos-delay="3000"],body[data-aos-delay="3000"] [data-aos]{transition-delay:0}[data-aos][data-aos][data-aos-delay="3000"].aos-animate,body[data-aos-delay="3000"] [data-aos].aos-animate{transition-delay:3s}[data-aos][data-aos][data-aos-easing=linear],body[data-aos-easing=linear] [data-aos]{transition-timing-function:cubic-bezier(.25,.25,.75,.75)}[data-aos][data-aos][data-aos-easing=ease],body[data-aos-easing=ease] [data-aos]{transition-timing-function:ease}[data-aos][data-aos][data-aos-easing=ease-in],body[data-aos-easing=ease-in] [data-aos]{transition-timing-function:ease-in}[data-aos][data-aos][data-aos-easing=ease-out],body[data-aos-easing=ease-out] [data-aos]{transition-timing-function:ease-out}[data-aos][data-aos][data-aos-easing=ease-in-out],body[data-aos-easing=ease-in-out] [data-aos]{transition-timing-function:ease-in-out}[data-aos][data-aos][data-aos-easing=ease-in-back],body[data-aos-easing=ease-in-back] [data-aos]{transition-timing-function:cubic-bezier(.6,-.28,.735,.045)}[data-aos][data-aos][data-aos-easing=ease-out-back],body[data-aos-easing=ease-out-back] [data-aos]{transition-timing-function:cubic-bezier(.175,.885,.32,1.275)}[data-aos][data-aos][data-aos-easing=ease-in-out-back],body[data-aos-easing=ease-in-out-back] [data-aos]{transition-timing-function:cubic-bezier(.68,-.55,.265,1.55)}[data-aos][data-aos][data-aos-easing=ease-in-sine],body[data-aos-easing=ease-in-sine] [data-aos]{transition-timing-function:cubic-bezier(.47,0,.745,.715)}[data-aos][data-aos][data-aos-easing=ease-out-sine],body[data-aos-easing=ease-out-sine] [data-aos]{transition-timing-function:cubic-bezier(.39,.575,.565,1)}[data-aos][data-aos][data-aos-easing=ease-in-out-sine],body[data-aos-easing=ease-in-out-sine] [data-aos]{transition-timing-function:cubic-bezier(.445,.05,.55,.95)}[data-aos][data-aos][data-aos-easing=ease-in-quad],body[data-aos-easing=ease-in-quad] [data-aos]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-aos][data-aos][data-aos-easing=ease-out-quad],body[data-aos-easing=ease-out-quad] [data-aos]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-aos][data-aos][data-aos-easing=ease-in-out-quad],body[data-aos-easing=ease-in-out-quad] [data-aos]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-aos][data-aos][data-aos-easing=ease-in-cubic],body[data-aos-easing=ease-in-cubic] [data-aos]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-aos][data-aos][data-aos-easing=ease-out-cubic],body[data-aos-easing=ease-out-cubic] [data-aos]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-aos][data-aos][data-aos-easing=ease-in-out-cubic],body[data-aos-easing=ease-in-out-cubic] [data-aos]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-aos][data-aos][data-aos-easing=ease-in-quart],body[data-aos-easing=ease-in-quart] [data-aos]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-aos][data-aos][data-aos-easing=ease-out-quart],body[data-aos-easing=ease-out-quart] [data-aos]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-aos][data-aos][data-aos-easing=ease-in-out-quart],body[data-aos-easing=ease-in-out-quart] [data-aos]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-aos^=fade][data-aos^=fade]{opacity:0;transition-property:opacity,transform}[data-aos^=fade][data-aos^=fade].aos-animate{opacity:1;transform:translateZ(0)}[data-aos=fade-up]{transform:translate3d(0,100px,0)}[data-aos=fade-down]{transform:translate3d(0,-100px,0)}[data-aos=fade-right]{transform:translate3d(-100px,0,0)}[data-aos=fade-left]{transform:translate3d(100px,0,0)}[data-aos=fade-up-right]{transform:translate3d(-100px,100px,0)}[data-aos=fade-up-left]{transform:translate3d(100px,100px,0)}[data-aos=fade-down-right]{transform:translate3d(-100px,-100px,0)}[data-aos=fade-down-left]{transform:translate3d(100px,-100px,0)}[data-aos^=zoom][data-aos^=zoom]{opacity:0;transition-property:opacity,transform}[data-aos^=zoom][data-aos^=zoom].aos-animate{opacity:1;transform:translateZ(0) scale(1)}[data-aos=zoom-in]{transform:scale(.6)}[data-aos=zoom-in-up]{transform:translate3d(0,100px,0) scale(.6)}[data-aos=zoom-in-down]{transform:translate3d(0,-100px,0) scale(.6)}[data-aos=zoom-in-right]{transform:translate3d(-100px,0,0) scale(.6)}[data-aos=zoom-in-left]{transform:translate3d(100px,0,0) scale(.6)}[data-aos=zoom-out]{transform:scale(1.2)}[data-aos=zoom-out-up]{transform:translate3d(0,100px,0) scale(1.2)}[data-aos=zoom-out-down]{transform:translate3d(0,-100px,0) scale(1.2)}[data-aos=zoom-out-right]{transform:translate3d(-100px,0,0) scale(1.2)}[data-aos=zoom-out-left]{transform:translate3d(100px,0,0) scale(1.2)}[data-aos^=slide][data-aos^=slide]{transition-property:transform}[data-aos^=slide][data-aos^=slide].aos-animate{transform:translateZ(0)}[data-aos=slide-up]{transform:translate3d(0,100%,0)}[data-aos=slide-down]{transform:translate3d(0,-100%,0)}[data-aos=slide-right]{transform:translate3d(-100%,0,0)}[data-aos=slide-left]{transform:translate3d(100%,0,0)}[data-aos^=flip][data-aos^=flip]{backface-visibility:hidden;transition-property:transform}[data-aos=flip-left]{transform:perspective(2500px) rotateY(-100deg)}[data-aos=flip-left].aos-animate{transform:perspective(2500px) rotateY(0)}[data-aos=flip-right]{transform:perspective(2500px) rotateY(100deg)}[data-aos=flip-right].aos-animate{transform:perspective(2500px) rotateY(0)}[data-aos=flip-up]{transform:perspective(2500px) rotateX(-100deg)}[data-aos=flip-up].aos-animate{transform:perspective(2500px) rotateX(0)}[data-aos=flip-down]{transform:perspective(2500px) rotateX(100deg)}[data-aos=flip-down].aos-animate{transform:perspective(2500px) rotateX(0)}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0px}.bottom-0{bottom:0px}.bottom-5{bottom:1.25rem}.bottom-\[40px\]{bottom:40px}.bottom-\[50px\]{bottom:50px}.left-0{left:0px}.left-7{left:1.75rem}.left-\[3\%\]{left:3%}.left-\[452px\]{left:452px}.left-\[50\%\]{left:50%}.left-\[520px\]{left:520px}.right-0{right:0px}.right-2{right:.5rem}.right-\[10px\]{right:10px}.right-\[3\%\]{right:3%}.right-\[30px\]{right:30px}.right-\[5px\]{right:5px}.top-0{top:0px}.top-1{top:.25rem}.top-1\.5{top:.375rem}.top-10{top:2.5rem}.top-12{top:3rem}.top-2{top:.5rem}.top-5{top:1.25rem}.top-\[16px\]{top:16px}.top-\[25px\]{top:25px}.top-\[50\%\]{top:50%}.top-\[5px\]{top:5px}.z-0{z-index:0}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.m-5{margin:1.25rem}.m-7{margin:1.75rem}.mx-0{margin-left:0;margin-right:0}.mx-3{margin-left:.75rem;margin-right:.75rem}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.mx-\[100px\]{margin-left:100px;margin-right:100px}.mx-auto{margin-left:auto;margin-right:auto}.my-20{margin-top:5rem;margin-bottom:5rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.my-6{margin-top:1.5rem;margin-bottom:1.5rem}.my-7{margin-top:1.75rem;margin-bottom:1.75rem}.my-\[100px\]{margin-top:100px;margin-bottom:100px}.my-\[20px\]{margin-top:20px;margin-bottom:20px}.my-\[30px\]{margin-top:30px;margin-bottom:30px}.my-\[4px\]{margin-top:4px;margin-bottom:4px}.my-\[8px\]{margin-top:8px;margin-bottom:8px}.my-auto{margin-top:auto;margin-bottom:auto}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-14{margin-bottom:3.5rem}.mb-2{margin-bottom:.5rem}.mb-20{margin-bottom:5rem}.mb-3{margin-bottom:.75rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-7{margin-bottom:1.75rem}.mb-\[10px\]{margin-bottom:10px}.mb-\[15px\]{margin-bottom:15px}.mb-\[20px\]{margin-bottom:20px}.mb-\[30px\]{margin-bottom:30px}.mb-\[3px\]{margin-bottom:3px}.mb-\[40px\]{margin-bottom:40px}.mb-\[50px\]{margin-bottom:50px}.mb-\[67px\]{margin-bottom:67px}.mb-\[70px\]{margin-bottom:70px}.mb-\[80px\]{margin-bottom:80px}.ml-1{margin-left:.25rem}.ml-10{margin-left:2.5rem}.ml-2{margin-left:.5rem}.ml-20{margin-left:5rem}.ml-28{margin-left:7rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-40{margin-left:10rem}.ml-5{margin-left:1.25rem}.ml-7{margin-left:1.75rem}.ml-\[12px\]{margin-left:12px}.ml-\[150px\]{margin-left:150px}.ml-\[15px\]{margin-left:15px}.ml-\[200px\]{margin-left:200px}.ml-\[2px\]{margin-left:2px}.ml-\[300px\]{margin-left:300px}.ml-\[30px\]{margin-left:30px}.ml-\[40px\]{margin-left:40px}.ml-auto{margin-left:auto}.mr-10{margin-right:2.5rem}.mr-12{margin-right:3rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-20{margin-right:5rem}.mr-3{margin-right:.75rem}.mr-5{margin-right:1.25rem}.mr-6{margin-right:1.5rem}.mr-\[10px\]{margin-right:10px}.mr-\[12px\]{margin-right:12px}.mr-\[15px\]{margin-right:15px}.mr-\[25px\]{margin-right:25px}.mr-\[2px\]{margin-right:2px}.mr-\[40px\]{margin-right:40px}.mr-\[50px\]{margin-right:50px}.mr-\[5px\]{margin-right:5px}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-20{margin-top:5rem}.mt-28{margin-top:7rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-\[100px\]{margin-top:100px}.mt-\[10px\]{margin-top:10px}.mt-\[15px\]{margin-top:15px}.mt-\[2px\]{margin-top:2px}.mt-\[30px\]{margin-top:30px}.mt-\[50px\]{margin-top:50px}.mt-\[5px\]{margin-top:5px}.mt-\[70px\]{margin-top:70px}.mt-\[80px\]{margin-top:80px}.mt-\[90px\]{margin-top:90px}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-12{height:3rem}.h-7{height:1.75rem}.h-\[100\%\]{height:100%}.h-\[100px\]{height:100px}.h-\[100vh\]{height:100vh}.h-\[105px\]{height:105px}.h-\[120px\]{height:120px}.h-\[127px\]{height:127px}.h-\[135px\]{height:135px}.h-\[150px\]{height:150px}.h-\[15vh\]{height:15vh}.h-\[170px\]{height:170px}.h-\[198px\]{height:198px}.h-\[200px\]{height:200px}.h-\[20px\]{height:20px}.h-\[230px\]{height:230px}.h-\[25px\]{height:25px}.h-\[27px\]{height:27px}.h-\[300px\]{height:300px}.h-\[30px\]{height:30px}.h-\[35px\]{height:35px}.h-\[38\.5px\]{height:38.5px}.h-\[38px\]{height:38px}.h-\[400px\]{height:400px}.h-\[40px\]{height:40px}.h-\[45px\]{height:45px}.h-\[500px\]{height:500px}.h-\[50px\]{height:50px}.h-\[530px\]{height:530px}.h-\[550px\]{height:550px}.h-\[600px\]{height:600px}.h-\[635px\]{height:635px}.h-\[650px\]{height:650px}.h-\[65px\]{height:65px}.h-\[700px\]{height:700px}.h-\[70px\]{height:70px}.h-\[77vh\]{height:77vh}.h-\[800px\]{height:800px}.h-\[85px\]{height:85px}.h-\[8vh\]{height:8vh}.h-auto{height:auto}.h-full{height:100%}.min-h-\[55vh\]{min-height:55vh}.min-h-\[60vh\]{min-height:60vh}.min-h-\[77vh\]{min-height:77vh}.min-h-\[800px\]{min-height:800px}.min-h-\[80vh\]{min-height:80vh}.w-12{width:3rem}.w-28{width:7rem}.w-\[100\%\]{width:100%}.w-\[100px\]{width:100px}.w-\[100vw\]{width:100vw}.w-\[105px\]{width:105px}.w-\[1060px\]{width:1060px}.w-\[120px\]{width:120px}.w-\[130px\]{width:130px}.w-\[140px\]{width:140px}.w-\[146px\]{width:146px}.w-\[16px\]{width:16px}.w-\[182px\]{width:182px}.w-\[190px\]{width:190px}.w-\[200px\]{width:200px}.w-\[20px\]{width:20px}.w-\[220px\]{width:220px}.w-\[230px\]{width:230px}.w-\[250px\]{width:250px}.w-\[255px\]{width:255px}.w-\[25px\]{width:25px}.w-\[260px\]{width:260px}.w-\[270px\]{width:270px}.w-\[280px\]{width:280px}.w-\[300px\]{width:300px}.w-\[30px\]{width:30px}.w-\[330px\]{width:330px}.w-\[38px\]{width:38px}.w-\[400px\]{width:400px}.w-\[400vw\]{width:400vw}.w-\[40vw\]{width:40vw}.w-\[420px\]{width:420px}.w-\[45\%\]{width:45%}.w-\[50\%\]{width:50%}.w-\[500px\]{width:500px}.w-\[50px\]{width:50px}.w-\[510px\]{width:510px}.w-\[540px\]{width:540px}.w-\[55\%\]{width:55%}.w-\[570px\]{width:570px}.w-\[60\%\]{width:60%}.w-\[600px\]{width:600px}.w-\[70\%\]{width:70%}.w-\[700px\]{width:700px}.w-\[750px\]{width:750px}.w-\[75px\]{width:75px}.w-\[77px\]{width:77px}.w-\[78\%\]{width:78%}.w-\[780px\]{width:780px}.w-\[800px\]{width:800px}.w-\[80px\]{width:80px}.w-\[830px\]{width:830px}.w-\[9\%\]{width:9%}.w-\[900px\]{width:900px}.w-\[902px\]{width:902px}.w-full{width:100%}.min-w-\[1200px\]{min-width:1200px}.min-w-\[150px\]{min-width:150px}.max-w-\[100px\]{max-width:100px}.max-w-\[150px\]{max-width:150px}.max-w-\[902px\]{max-width:902px}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-\[-100vw\]{--tw-translate-x: -100vw;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-\[-200vw\]{--tw-translate-x: -200vw;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-\[-300vw\]{--tw-translate-x: -300vw;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-\[-50\%\]{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-\[-50\%\]{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-items-end{justify-items:end}.space-x-10>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(2.5rem * var(--tw-space-x-reverse));margin-left:calc(2.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-12>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(3rem * var(--tw-space-x-reverse));margin-left:calc(3rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-16>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(4rem * var(--tw-space-x-reverse));margin-left:calc(4rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.75rem * var(--tw-space-x-reverse));margin-left:calc(.75rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1.25rem * var(--tw-space-x-reverse));margin-left:calc(1.25rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-\[30px\]>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(30px * var(--tw-space-x-reverse));margin-left:calc(30px * calc(1 - var(--tw-space-x-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-20>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(5rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.space-y-\[20px\]>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(20px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(20px * var(--tw-space-y-reverse))}.space-y-\[24px\]>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(24px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(24px * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-\[10px\]{border-radius:10px}.rounded-\[20px\]{border-radius:20px}.rounded-\[30px\]{border-radius:30px}.rounded-\[5px\]{border-radius:5px}.rounded-\[8px\]{border-radius:8px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-l-full{border-top-left-radius:9999px;border-bottom-left-radius:9999px}.border{border-width:1px}.border-2{border-width:2px}.border-\[0\.5px\]{border-width:.5px}.border-\[1\.5px\]{border-width:1.5px}.border-\[1px\]{border-width:1px}.border-\[2px\]{border-width:2px}.border-b-\[0\.5px\]{border-bottom-width:.5px}.border-b-\[1px\]{border-bottom-width:1px}.border-t-\[1px\]{border-top-width:1px}.border-\[\#4771B7\]{--tw-border-opacity: 1;border-color:rgb(71 113 183 / var(--tw-border-opacity))}.border-\[\#9A9A9A\]{--tw-border-opacity: 1;border-color:rgb(154 154 154 / var(--tw-border-opacity))}.border-\[\#AEC1DF\]{--tw-border-opacity: 1;border-color:rgb(174 193 223 / var(--tw-border-opacity))}.border-\[\#CCCCCC\]{--tw-border-opacity: 1;border-color:rgb(204 204 204 / var(--tw-border-opacity))}.border-\[\#D8D8D8\]{--tw-border-opacity: 1;border-color:rgb(216 216 216 / var(--tw-border-opacity))}.border-black{--tw-border-opacity: 1;border-color:rgb(0 0 0 / var(--tw-border-opacity))}.bg-\[\#4770b755\]{background-color:#4770b755}.bg-\[\#4771B7\]{--tw-bg-opacity: 1;background-color:rgb(71 113 183 / var(--tw-bg-opacity))}.bg-\[\#678fe4\]{--tw-bg-opacity: 1;background-color:rgb(103 143 228 / var(--tw-bg-opacity))}.bg-\[\#879fa8\]{--tw-bg-opacity: 1;background-color:rgb(135 159 168 / var(--tw-bg-opacity))}.bg-\[\#D6DFEF\]{--tw-bg-opacity: 1;background-color:rgb(214 223 239 / var(--tw-bg-opacity))}.bg-\[\#DD3535\]{--tw-bg-opacity: 1;background-color:rgb(221 53 53 / var(--tw-bg-opacity))}.bg-\[\#E7EDF6\]{--tw-bg-opacity: 1;background-color:rgb(231 237 246 / var(--tw-bg-opacity))}.bg-\[\#ECF1F8\]{--tw-bg-opacity: 1;background-color:rgb(236 241 248 / var(--tw-bg-opacity))}.bg-\[\#EDF1F8\]{--tw-bg-opacity: 1;background-color:rgb(237 241 248 / var(--tw-bg-opacity))}.bg-\[\#F3F5F7\]{--tw-bg-opacity: 1;background-color:rgb(243 245 247 / var(--tw-bg-opacity))}.bg-\[\#e4c767\]{--tw-bg-opacity: 1;background-color:rgb(228 199 103 / var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/60{background-color:#fff9}.bg-opacity-40{--tw-bg-opacity: .4}.bg-cover{background-size:cover}.fill-\[\#4771B7\]{fill:#4771b7}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:.25rem}.p-10{padding:2.5rem}.p-2{padding:.5rem}.p-20{padding:5rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.p-\[10px\]{padding:10px}.p-\[7px\]{padding:7px}.p-\[8px\]{padding:8px}.px-0{padding-left:0;padding-right:0}.px-10{padding-left:2.5rem;padding-right:2.5rem}.px-14{padding-left:3.5rem;padding-right:3.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-7{padding-left:1.75rem;padding-right:1.75rem}.px-\[10px\]{padding-left:10px;padding-right:10px}.px-\[25px\]{padding-left:25px;padding-right:25px}.px-\[30px\]{padding-left:30px;padding-right:30px}.px-\[35px\]{padding-left:35px;padding-right:35px}.px-\[50px\]{padding-left:50px;padding-right:50px}.px-\[8px\]{padding-left:8px;padding-right:8px}.px-\[96px\]{padding-left:96px;padding-right:96px}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-24{padding-top:6rem;padding-bottom:6rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-7{padding-top:1.75rem;padding-bottom:1.75rem}.py-\[10px\]{padding-top:10px;padding-bottom:10px}.py-\[24px\]{padding-top:24px;padding-bottom:24px}.py-\[250px\]{padding-top:250px;padding-bottom:250px}.py-\[2px\]{padding-top:2px;padding-bottom:2px}.py-\[4px\]{padding-top:4px;padding-bottom:4px}.py-\[5px\]{padding-top:5px;padding-bottom:5px}.py-\[8px\]{padding-top:8px;padding-bottom:8px}.pb-10{padding-bottom:2.5rem}.pb-3{padding-bottom:.75rem}.pb-\[120px\]{padding-bottom:120px}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pl-8{padding-left:2rem}.pl-\[30px\]{padding-left:30px}.pl-\[80px\]{padding-left:80px}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pr-\[12px\]{padding-right:12px}.pr-\[15px\]{padding-right:15px}.pr-\[50px\]{padding-right:50px}.pt-1{padding-top:.25rem}.pt-12{padding-top:3rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.pt-\[1px\]{padding-top:1px}.pt-\[200px\]{padding-top:200px}.pt-\[20px\]{padding-top:20px}.pt-\[24px\]{padding-top:24px}.pt-\[30px\]{padding-top:30px}.pt-\[40px\]{padding-top:40px}.text-center{text-align:center}.text-right{text-align:right}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[18px\]{font-size:18px}.text-\[20px\]{font-size:20px}.text-\[25px\]{font-size:25px}.text-\[30px\]{font-size:30px}.text-\[32px\]{font-size:32px}.text-\[3rem\]{font-size:3rem}.text-\[40px\]{font-size:40px}.text-\[48px\]{font-size:48px}.text-\[50px\]{font-size:50px}.text-\[64px\]{font-size:64px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.tracking-\[0\.5px\]{letter-spacing:.5px}.text-\[\#21C55D\]{--tw-text-opacity: 1;color:rgb(33 197 93 / var(--tw-text-opacity))}.text-\[\#4471B7\]{--tw-text-opacity: 1;color:rgb(68 113 183 / var(--tw-text-opacity))}.text-\[\#4771B7\]{--tw-text-opacity: 1;color:rgb(71 113 183 / var(--tw-text-opacity))}.text-\[\#787878\]{--tw-text-opacity: 1;color:rgb(120 120 120 / var(--tw-text-opacity))}.text-\[\#868686\]{--tw-text-opacity: 1;color:rgb(134 134 134 / var(--tw-text-opacity))}.text-\[\#9b9b9b\]{--tw-text-opacity: 1;color:rgb(155 155 155 / var(--tw-text-opacity))}.text-\[\#FF0000\]{--tw-text-opacity: 1;color:rgb(255 0 0 / var(--tw-text-opacity))}.text-\[\#FFFFFF\]{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-950{--tw-text-opacity: 1;color:rgb(3 7 18 / var(--tw-text-opacity))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.opacity-50{opacity:.5}.shadow-\[0px_2px_4px_0px_rgba\(0\,0\,0\,0\.25\)\]{--tw-shadow: 0px 2px 4px 0px rgba(0,0,0,.25);--tw-shadow-colored: 0px 2px 4px 0px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[2px_3px_4px_3px_rgba\(0\,0\,0\,0\.4\)\]{--tw-shadow: 2px 3px 4px 3px rgba(0,0,0,.4);--tw-shadow-colored: 2px 3px 4px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[\#8F9296\]{--tw-shadow-color: #8F9296;--tw-shadow: var(--tw-shadow-colored)}.shadow-\[\#cdd2d8\]{--tw-shadow-color: #cdd2d8;--tw-shadow: var(--tw-shadow-colored)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-lg{--tw-drop-shadow: drop-shadow(0 10px 8px rgb(0 0 0 / .04)) drop-shadow(0 4px 3px rgb(0 0 0 / .1));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-1000{transition-duration:1s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@font-face{font-family:nanum;font-weight:300;src:url(/assets/NanumSquareNeo-aLt-1b9af8b2.ttf)}@font-face{font-family:nanum;font-weight:400;src:url(/assets/NanumSquareNeo-bRg-864de849.ttf)}@font-face{font-family:nanum;font-weight:500;src:url(/assets/NanumSquareNeo-cBd-4749fa56.ttf)}@font-face{font-family:nanum;font-weight:600;src:url(/assets/NanumSquareNeo-dEb-3cedb3ee.ttf)}@font-face{font-family:nanum;font-weight:700;src:url(/assets/NanumSquareNeo-eHv-a2850a33.ttf)}*{margin:0;padding:0;box-sizing:border-box;font-family:nanum}html,body,#root{width:100%;height:100%}body{-webkit-user-select:none;-moz-user-select:none;user-select:none;overflow-x:hidden}html::-webkit-scrollbar{width:15px;background-color:#fff}html::-webkit-scrollbar-track{width:10px}html::-webkit-scrollbar-thumb{background-color:#a8a8a8;border-radius:10px;border:2px solid white}html{scroll-behavior:smooth}.carousel-title{font-size:xx-large;font-weight:700;-webkit-text-stroke:.5px white}.arrow-left{animation:arrowLeft 1.5s ease-in-out infinite}.arrow-right{animation:arrowRight 1.5s ease-in-out infinite}.star{width:150px;max-width:initial}.card-star{width:100px;max-width:initial}.wheel{animation:wheelRotate 1.5s infinite linear}.intro-text{animation:fadeInRight .75s ease-in-out}.animate-topbounce{animation:topbounce 1s infinite}.animate-bounce{animation:bounce 1s infinite}@keyframes topbounce{0%,to{transform:none;animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:translateY(-10%);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-10%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes wheelRotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes fadeInRight{0%{opacity:0;transform:translate(-500px)}to{opacity:1;transform:translate(0)}}@keyframes arrowLeft{0%{transform:translate(0)}50%{transform:translate(-10px)}to{transform:translate(0)}}@keyframes arrowRight{0%{transform:translate(0)}50%{transform:translate(10px)}to{transform:translate(0)}}.hover\:w-\[100px\]:hover{width:100px}.hover\:scale-110:hover{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:cursor-pointer:hover{cursor:pointer}.hover\:bg-\[\#65a4d8\]:hover{--tw-bg-opacity: 1;background-color:rgb(101 164 216 / var(--tw-bg-opacity))}.hover\:bg-\[\#6787BC\]:hover{--tw-bg-opacity: 1;background-color:rgb(103 135 188 / var(--tw-bg-opacity))}.hover\:bg-\[\#EDF1F8\]:hover{--tw-bg-opacity: 1;background-color:rgb(237 241 248 / var(--tw-bg-opacity))}.hover\:bg-\[\#d8ecfc\]:hover{--tw-bg-opacity: 1;background-color:rgb(216 236 252 / var(--tw-bg-opacity))}.hover\:fill-\[\#9dacc5\]:hover{fill:#9dacc5}.hover\:text-\[\#3366BB\]:hover{--tw-text-opacity: 1;color:rgb(51 102 187 / var(--tw-text-opacity))}.hover\:text-\[\#4771B7\]:hover{--tw-text-opacity: 1;color:rgb(71 113 183 / var(--tw-text-opacity))}.hover\:shadow-\[0_0_20px_5px_\#DCEAFF\]:hover{--tw-shadow: 0 0 20px 5px #DCEAFF;--tw-shadow-colored: 0 0 20px 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:translate-y-6:focus{--tw-translate-y: 1.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}@media (prefers-color-scheme: dark){.dark\:text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}} diff --git a/client/dist/assets/logo-f382c619.svg b/client/dist/assets/logo-f382c619.svg new file mode 100644 index 00000000..b32cfbef --- /dev/null +++ b/client/dist/assets/logo-f382c619.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/page3-7ff6dd6c.svg b/client/dist/assets/page3-7ff6dd6c.svg new file mode 100644 index 00000000..10d248a8 --- /dev/null +++ b/client/dist/assets/page3-7ff6dd6c.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/page4(2)-7dac419e.svg b/client/dist/assets/page4(2)-7dac419e.svg new file mode 100644 index 00000000..93ca4289 --- /dev/null +++ b/client/dist/assets/page4(2)-7dac419e.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/page5-abd4f884.svg b/client/dist/assets/page5-abd4f884.svg new file mode 100644 index 00000000..1e87413d --- /dev/null +++ b/client/dist/assets/page5-abd4f884.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/dist/assets/profile-087f0ee3.svg b/client/dist/assets/profile-087f0ee3.svg new file mode 100644 index 00000000..aa0945d3 --- /dev/null +++ b/client/dist/assets/profile-087f0ee3.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/dist/assets/riding-bae27c4c.svg b/client/dist/assets/riding-bae27c4c.svg new file mode 100644 index 00000000..eb7ccfec --- /dev/null +++ b/client/dist/assets/riding-bae27c4c.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/search-03c9f968.svg b/client/dist/assets/search-03c9f968.svg new file mode 100644 index 00000000..176ce4d0 --- /dev/null +++ b/client/dist/assets/search-03c9f968.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/surf-91428e94.svg b/client/dist/assets/surf-91428e94.svg new file mode 100644 index 00000000..5db05bba --- /dev/null +++ b/client/dist/assets/surf-91428e94.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/assets/top-4895b10f.svg b/client/dist/assets/top-4895b10f.svg new file mode 100644 index 00000000..d6d50f22 --- /dev/null +++ b/client/dist/assets/top-4895b10f.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/dist/assets/w_bottom-545fa504.svg b/client/dist/assets/w_bottom-545fa504.svg new file mode 100644 index 00000000..eecc0bb8 --- /dev/null +++ b/client/dist/assets/w_bottom-545fa504.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/dist/assets/w_top-70b5cea1.svg b/client/dist/assets/w_top-70b5cea1.svg new file mode 100644 index 00000000..30685cd2 --- /dev/null +++ b/client/dist/assets/w_top-70b5cea1.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/dist/assets/waterleisure-6804039d.svg b/client/dist/assets/waterleisure-6804039d.svg new file mode 100644 index 00000000..77c530a9 --- /dev/null +++ b/client/dist/assets/waterleisure-6804039d.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/dist/index.html b/client/dist/index.html new file mode 100644 index 00000000..629bb67f --- /dev/null +++ b/client/dist/index.html @@ -0,0 +1,21 @@ + + + + + + + + ActiOn + + + + +
+ + + + + + diff --git a/client/index.html b/client/index.html index dac98c22..59aa38f1 100644 --- a/client/index.html +++ b/client/index.html @@ -4,11 +4,16 @@ + ActiOn
+ + diff --git a/client/package-lock.json b/client/package-lock.json index f23f0404..b1dd586d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,13 +9,17 @@ "version": "0.0.0", "dependencies": { "@tosspayments/payment-widget-sdk": "^0.9.1", + "aos": "^2.3.4", + "framer-motion": "^10.13.0", "nanoid": "^4.0.2", "react": "^18.2.0", + "react-copy-to-clipboard": "^5.1.0", "react-daum-postcode": "^3.1.3", "react-dom": "^18.2.0", "react-icons": "^4.10.1", "react-kakao-maps-sdk": "^1.1.9", "react-router-dom": "^6.14.1", + "react-toastify": "^9.1.3", "recoil": "^0.7.7", "recoil-persist": "^5.1.0" }, @@ -59,6 +63,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@esbuild/android-arm": { "version": "0.17.19", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", @@ -1206,6 +1225,16 @@ "node": ">= 8" } }, + "node_modules/aos": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/aos/-/aos-2.3.4.tgz", + "integrity": "sha512-zh/ahtR2yME4I51z8IttIt4lC1Nw0ktsFtmeDzID1m9naJnWXhCoARaCgNOGXb5CLy3zm+wqmRAEgMYB5E2HUw==", + "dependencies": { + "classlist-polyfill": "^1.0.3", + "lodash.debounce": "^4.0.6", + "lodash.throttle": "^4.0.1" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -1422,6 +1451,19 @@ "node": ">= 6" } }, + "node_modules/classlist-polyfill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz", + "integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ==" + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1455,6 +1497,14 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1941,6 +1991,34 @@ "url": "https://www.patreon.com/infusion" } }, + "node_modules/framer-motion": { + "version": "10.13.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.13.0.tgz", + "integrity": "sha512-xKhw9VCizmwEHbopOfluaoVunGHSZyMztGbTvsgOYqCjaKu6qtlwWY1J+6GhL41NY1P157JgEikjDm67XCFnvQ==", + "dependencies": { + "tslib": "^2.4.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/framer-motion/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2271,12 +2349,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, "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 }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2408,7 +2496,6 @@ "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, "engines": { "node": ">=0.10.0" } @@ -2726,6 +2813,16 @@ "node": ">= 0.8.0" } }, + "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==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -2766,6 +2863,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, "node_modules/react-daum-postcode": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/react-daum-postcode/-/react-daum-postcode-3.1.3.tgz", @@ -2794,6 +2903,11 @@ "react": "*" } }, + "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==" + }, "node_modules/react-kakao-maps-sdk": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/react-kakao-maps-sdk/-/react-kakao-maps-sdk-1.1.9.tgz", @@ -2836,6 +2950,18 @@ "react-dom": ">=16.8" } }, + "node_modules/react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -3226,6 +3352,11 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", diff --git a/client/package.json b/client/package.json index dd935229..2371a1e2 100644 --- a/client/package.json +++ b/client/package.json @@ -11,13 +11,17 @@ }, "dependencies": { "@tosspayments/payment-widget-sdk": "^0.9.1", + "aos": "^2.3.4", + "framer-motion": "^10.13.0", "nanoid": "^4.0.2", "react": "^18.2.0", + "react-copy-to-clipboard": "^5.1.0", "react-daum-postcode": "^3.1.3", "react-dom": "^18.2.0", "react-icons": "^4.10.1", "react-kakao-maps-sdk": "^1.1.9", "react-router-dom": "^6.14.1", + "react-toastify": "^9.1.3", "recoil": "^0.7.7", "recoil-persist": "^5.1.0" }, @@ -38,5 +42,6 @@ "tailwindcss": "^3.3.2", "typescript": "^5.0.2", "vite": "^4.3.9" - } + }, + "proxy": "http://ac-ti-on.s3-website.ap-northeast-2.amazonaws.com" } diff --git a/client/src/App.tsx b/client/src/App.tsx index e8d7998d..b72773bd 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,53 +1,50 @@ import { useEffect } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { useSetRecoilState } from 'recoil'; + import MainRouter from './router/MainRouter'; import CategoryRouter from './router/CategoryRouter'; import MyRouter from './router/MyRouter'; -import { useNavigate } from 'react-router-dom'; -// import { useSetRecoilState } from 'recoil'; -// import { isLoginState } from './store/userInfoAtom'; +import { Role, isLoginState, isProfile } from './store/userInfoAtom'; function App() { const navigate = useNavigate(); - // const url = import.meta.env.VITE_APP_API_URL; - - // const setIsLoginState = useSetRecoilState(isLoginState); - - // const getAccessToken = async (accessToken) => { - // console.log('1'); - // try { - // const parsedHash = new URLSearchParams(window.location.hash.substring(1)); - // console.log('2'); - // const accessToken = parsedHash.get('access_token'); - // sessionStorage.setItem('access_token', accessToken); + const [searchParams] = useSearchParams(); - // navigate('/home'); - // // await fetch(`${url}/oauth2/authorization/google`, { - // // method: 'POST', - // // headers: { - // // 'Content-Type': 'application/json', - // // // eslint-disable-next-line prettier/prettier - // // Authorization: "Bearer " + accessToken - // // }, - // // }); - // // const { accessToken } = result.data; - - // setIsLoginState(true); - // // setAccessToken(accessToken); - // } catch (err) { - // alert(err); - // } - // }; + const setIsLoginState = useSetRecoilState(isLoginState); + const setIsProfile = useSetRecoilState(isProfile); + const setIsRole = useSetRecoilState(Role); + const url = import.meta.env.VITE_APP_API_URL; const handleAccessToken = async () => { - const parsedHash = new URLSearchParams(window.location.href); - // console.log('2'); - const accessToken = parsedHash.get('access_token'); - // console.log(accessToken); + const accessToken = searchParams.get('access_token'); if (accessToken) { + try { + const res = await fetch(`${url}/google/login`, { + headers: { Authorization: `Bearer ${accessToken}` }, + }); + const result1 = await res.json(); + if (res.status !== 200) throw res; + + //ํ—ค๋”์—์„œ ๋ฉค๋ฒ„์•„์ด๋””์™€ ๋‹‰๋„ค์ž„์„ ๋ฐ›์•„์˜ด + const name = result1.nickname; + const profile = result1.profileImage; + const role = result1.role; + setIsProfile(profile); + setIsRole(role); + // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— memberId,ํ† ํฐ ์ €์žฅ + sessionStorage.setItem('Authorization', `Bearer ${accessToken}`); + setIsLoginState(true); + + // ํ—ค๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•˜์œผ๋ฉด ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ + if (name) { + alert(`${name}๋‹˜ ๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค !`); + navigate('/home'); + } + } catch (error) { + console.error('๋กœ๊ทธ์ธ ์š”์ฒญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค', error); + } navigate('/home'); - // await getAccessToken(accessToken); - // console.log(accessToken); - // navigate('/home'); } }; diff --git a/client/src/assets/activity.svg b/client/src/assets/activity.svg new file mode 100644 index 00000000..36335df4 --- /dev/null +++ b/client/src/assets/activity.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/bg.svg b/client/src/assets/bg.svg new file mode 100644 index 00000000..4f2a8824 --- /dev/null +++ b/client/src/assets/bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/assets/bg2.svg b/client/src/assets/bg2.svg new file mode 100644 index 00000000..910f73e2 --- /dev/null +++ b/client/src/assets/bg2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/assets/bg3.svg b/client/src/assets/bg3.svg new file mode 100644 index 00000000..748a396e --- /dev/null +++ b/client/src/assets/bg3.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/assets/bottom.svg b/client/src/assets/bottom.svg new file mode 100644 index 00000000..c9324bf0 --- /dev/null +++ b/client/src/assets/bottom.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/src/assets/marker/marker-blue.png b/client/src/assets/marker/marker-blue.png new file mode 100644 index 00000000..bf99282d Binary files /dev/null and b/client/src/assets/marker/marker-blue.png differ diff --git a/client/src/assets/marker/marker-green.png b/client/src/assets/marker/marker-green.png new file mode 100644 index 00000000..0fb42503 Binary files /dev/null and b/client/src/assets/marker/marker-green.png differ diff --git a/client/src/assets/marker/marker-orange.png b/client/src/assets/marker/marker-orange.png new file mode 100644 index 00000000..a2ff1992 Binary files /dev/null and b/client/src/assets/marker/marker-orange.png differ diff --git a/client/src/assets/marker/marker-red.png b/client/src/assets/marker/marker-red.png new file mode 100644 index 00000000..8f23b63e Binary files /dev/null and b/client/src/assets/marker/marker-red.png differ diff --git a/client/src/assets/marker/marker-yellow.png b/client/src/assets/marker/marker-yellow.png new file mode 100644 index 00000000..8d3f894f Binary files /dev/null and b/client/src/assets/marker/marker-yellow.png differ diff --git a/client/src/assets/page3.svg b/client/src/assets/page3.svg new file mode 100644 index 00000000..10d248a8 --- /dev/null +++ b/client/src/assets/page3.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/page4(2).svg b/client/src/assets/page4(2).svg new file mode 100644 index 00000000..93ca4289 --- /dev/null +++ b/client/src/assets/page4(2).svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/page5.svg b/client/src/assets/page5.svg new file mode 100644 index 00000000..1e87413d --- /dev/null +++ b/client/src/assets/page5.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/top.svg b/client/src/assets/top.svg new file mode 100644 index 00000000..d6d50f22 --- /dev/null +++ b/client/src/assets/top.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/src/assets/w_bottom.svg b/client/src/assets/w_bottom.svg new file mode 100644 index 00000000..eecc0bb8 --- /dev/null +++ b/client/src/assets/w_bottom.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/src/assets/w_top.svg b/client/src/assets/w_top.svg new file mode 100644 index 00000000..30685cd2 --- /dev/null +++ b/client/src/assets/w_top.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/src/components/CategoryDetail/DetailContent.tsx b/client/src/components/CategoryDetail/DetailContent.tsx index 4582b8b1..c4ca3755 100644 --- a/client/src/components/CategoryDetail/DetailContent.tsx +++ b/client/src/components/CategoryDetail/DetailContent.tsx @@ -2,9 +2,12 @@ import { useState } from 'react'; import { FaChevronLeft, FaChevronRight } from 'react-icons/fa6'; import { RiMapPinLine } from 'react-icons/ri'; import { FiClock, FiPhone } from 'react-icons/fi'; +import { ToastContainer, toast } from 'react-toastify'; +import { CopyToClipboard } from "react-copy-to-clipboard/src"; import { DetailCategoryName, + DetailImg, DetailTitle, ImgBox, StoreInfoBox, @@ -34,28 +37,69 @@ function DetailContent() { return (
+ {data.category} {data.storeName} -
- -
-
- {data.storeImages && ( - <> - ์—…์ฒด์‚ฌ์ง„ -
{current + 1} / {data.storeImages.length}
- - )} -
-
- -
+ {data.storeImages && ( +
+
+ {data.storeImages.map((src, idx) => ( + + ))} +
+
+
+ +
+
+ {current + 1} / {data.storeImages.length} +
+
+ +
+
+
+ )}
-
{data.address}
+
{data.address}
+ toast("ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")}> + +
diff --git a/client/src/components/CategoryDetail/LocationInfo.tsx b/client/src/components/CategoryDetail/LocationInfo.tsx index 4699562b..5b38fc71 100644 --- a/client/src/components/CategoryDetail/LocationInfo.tsx +++ b/client/src/components/CategoryDetail/LocationInfo.tsx @@ -1,4 +1,4 @@ -import { Map, MapMarker } from 'react-kakao-maps-sdk'; +import { Map, MapMarker, MapTypeControl, ZoomControl } from 'react-kakao-maps-sdk'; import { useRecoilValue } from 'recoil'; import { CategoryDetailState } from '../../store/categoryDetailAtom'; @@ -19,8 +19,10 @@ function LocationInfo() { border: "1px solid #4771B7" }} > - - + + + + )}
); diff --git a/client/src/components/CategoryDetail/PaymentInfo.tsx b/client/src/components/CategoryDetail/PaymentInfo.tsx index 0e55fb7a..8f4da0d3 100644 --- a/client/src/components/CategoryDetail/PaymentInfo.tsx +++ b/client/src/components/CategoryDetail/PaymentInfo.tsx @@ -1,6 +1,7 @@ -import { useRecoilValue } from 'recoil'; -import { useLocation } from 'react-router-dom'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import { useLocation, useNavigate } from 'react-router-dom'; +import defaultImg from '../../assets/profile.svg'; import { CategoryDetailState, ReserFormState, totalPrice } from '../../store/categoryDetailAtom'; import { AmountBox, @@ -11,31 +12,56 @@ import { StoreProfile, WishButton } from '../../styles/CategoryDetail/PaymentInfo'; +import { isLoginState } from '../../store/userInfoAtom'; function PaymentInfo() { const API_URL = import.meta.env.VITE_APP_API_URL; + const [form, setForm] = useRecoilState(ReserFormState); + const isLogin = useRecoilValue(isLoginState); const data = useRecoilValue(CategoryDetailState); - const form = useRecoilValue(ReserFormState); const total = useRecoilValue(totalPrice); const location = useLocation(); + const navigate = useNavigate(); + const storeId = location.pathname.substring(10); - const reservationPost = async () => { - const storeId = location.pathname.substring(10); - const accessToken = sessionStorage.getItem('Authorization'); - try { - await fetch(`${API_URL}/reservations/${storeId}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': accessToken - }, - body: JSON.stringify({...form, totalPrice: total}) - }) + const movePayment = async () => { + if (!isLogin) { + alert(`๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ์˜ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.`); + return navigate('/login'); } - catch(error) { - console.log(error); + else if (!form.reservationName) { + return alert('์˜ˆ์•ฝ์ž๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); } + else if (!form.reservationPhone) { + return alert('์—ฐ๋ฝ์ฒ˜๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + } + else if (!total) { + return alert('ํ‹ฐ์ผ“์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.'); + } + else if (form.reservationPhone.substring(0, 3) !== '010') { + return alert('์—ฐ๋ฝ์ฒ˜๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.'); + } + const items = form.reservationItems.filter((item) => item.ticketCount !== 0); + setForm((prev) => ({...prev, reservationItems: items})); + navigate(`/store/payment/${storeId}`); } + + const onClickHeart = async () => { + if (!isLogin) { + return alert(`๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.`); + } + if (data.isLike) { + return alert('์ด๋ฏธ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.'); + } + const res = await fetch(`${API_URL}/stores/favorites/${storeId}`, { + method: 'POST', + headers: { Authorization: sessionStorage.getItem('Authorization') }, + }); + if (res.ok) { + alert('โค๏ธ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); + window.location.reload(); + } + } return ( @@ -57,16 +83,17 @@ function PaymentInfo() {
  • ์ฒดํ—˜์ผ 4์ผ์ „ 18์‹œ์ด์ „ 100% ํ™˜๋ถˆ๊ฐ€๋Šฅ
  • ์ฒดํ—˜์ผ 4์ผ์ „ 18์‹œ์ดํ›„~๋‹น์ผ : ํ™˜๋ถˆ๋ถˆ๊ฐ€, ๋‚ ์งœ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€
  • ๋ถ€๋ถ„ ์‚ฌ์šฉ ๋ฐ ๋ถ€๋ถ„ ์ทจ์†Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • +
  • ๊ฐ€์ƒ์œผ๋กœ๋งŒ ๊ฒฐ์ œ๋˜๊ณ  ์‹ค์ œ๋กœ ๋ˆ์ด ๋น ์ ธ๋‚˜๊ฐ€์ง€ ์•Š์œผ๋‹ˆ ์•ˆ์‹ฌํ•˜๊ณ  ๋งˆ์Œ๊ป ํ…Œ์ŠคํŠธ ํ•ด๋ณด์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.
  • - {total.toLocaleString('ko-KR')}์› ๊ฒฐ์ œํ•˜๊ธฐ - + {total.toLocaleString('ko-KR')}์› ๊ฒฐ์ œํ•˜๊ธฐ + โ™ฅ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ธฐ - +
    {data.storeName}
    [๋ฌธ์˜] ์นด์นด์˜คํ†ก ์•„์ด๋””: {data.kakao}
    diff --git a/client/src/components/CategoryDetail/ReservationInfo.tsx b/client/src/components/CategoryDetail/ReservationInfo.tsx index 6a772577..732c22c1 100644 --- a/client/src/components/CategoryDetail/ReservationInfo.tsx +++ b/client/src/components/CategoryDetail/ReservationInfo.tsx @@ -7,14 +7,23 @@ function ReservationInfo() { const [form, setForm] = useRecoilState(ReserFormState); const reserChangeHandler = (e) => { - if (e.target.name === "reservationName") { - setForm({...form, reservationName: e.target.value}) - } - else if (e.target.name === "reservationPhone") { - setForm({...form, reservationPhone: e.target.value}) - } - else if (e.target.name === "reservationEmail") { - setForm({...form, reservationEmail: e.target.value}) + const name = e.target.name; + const value = e.target.value; + switch(name) { + case 'reservationName': + return setForm({...form, reservationName: value}) + case 'reservationPhone': + const phoneNumberPattern = /(\d{3})(\d{3,4})(\d{4})/; + let contactVerify = value.replace(/[^0-9]/g, ''); + if (contactVerify.length >= 11) { + contactVerify = contactVerify.replace(phoneNumberPattern, '$1-$2-$3'); + } + if (contactVerify.length >= 14) { + return; + } + return setForm({...form, reservationPhone: contactVerify}); + case 'reservationEmail': + return setForm({...form, reservationEmail: value}) } } @@ -25,9 +34,10 @@ function ReservationInfo() {
    ์˜ˆ์•ฝ์ž
    ํ•„์ˆ˜
    @@ -36,10 +46,11 @@ function ReservationInfo() {
    ์—ฐ๋ฝ์ฒ˜
    ํ•„์ˆ˜
    @@ -47,9 +58,10 @@ function ReservationInfo() {
    ์ด๋ฉ”์ผ
    @@ -66,7 +78,7 @@ const ReservationTitle = tw.div` const ReservationInput = tw.input` border-[1px] border-[#CCCCCC] rounded-[5px] - w-[240px] h-[38px] + w-[260px] h-[38px] p-2 `; diff --git a/client/src/components/CategoryDetail/Review.tsx b/client/src/components/CategoryDetail/Review.tsx index 52da50ad..d77b52e6 100644 --- a/client/src/components/CategoryDetail/Review.tsx +++ b/client/src/components/CategoryDetail/Review.tsx @@ -16,10 +16,10 @@ import { function Review() { const API_URL = import.meta.env.VITE_APP_API_URL; const [stars, setStars] = useState([false, false, false, false, false]); - const [form, setForm] = useState({}); + const [form, setForm] = useState({ rating: 0, content: '' }); const [data, setData] = useRecoilState(ReviewsState); - const starClickHandler = (idx) => { + const starClickHandler = (idx: number) => { const result = [false, false, false, false, false].map((star, starIdx) => { if (starIdx <= idx) { return true; @@ -35,10 +35,16 @@ function Review() { }; const reviewPost = async () => { + if (!form.rating) { + return alert('๋ณ„์ ์„ ํด๋ฆญํ•ด์ฃผ์„ธ์š”.'); + } + else if (!form.content) { + return alert('๋ฆฌ๋ทฐ ๊ธ€์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.'); + } const storeId = location.pathname.substring(10); const accessToken = sessionStorage.getItem('Authorization'); try { - await fetch(`${API_URL}/reviews/${storeId}`, { + const res = await fetch(`${API_URL}/reviews/${storeId}`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -46,9 +52,23 @@ function Review() { }, body: JSON.stringify(form) }) + if (res.status === 422) { + return alert ('์ด์šฉ์™„๋ฃŒ ํ›„์— ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n\n(์ด์šฉ์™„๋ฃŒ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•: ๋งˆ์ดํŽ˜์ด์ง€ > ์˜ˆ์•ฝ๋‚ด์—ญ์กฐํšŒ > ์ƒ์„ธ๋ณด๊ธฐ > ์ด์šฉ์™„๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ)'); + } + if (res.status === 409) { + return alert ('์ด๋ฏธ ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.'); + } + else if (res.status === 400) { + return alert ('๋น„์†์–ด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.'); + } + else if (!res.ok) { + return alert('๋ฆฌ๋ทฐ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); + } + alert('๋ฆฌ๋ทฐ๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); + window.location.reload(); } catch(error) { - console.log(error); + console.error(error); } } @@ -60,7 +80,7 @@ function Review() { setData(json); } catch(error) { - console.log(error); + console.error(error); } }; @@ -76,7 +96,8 @@ function Review() {
    - {data.ratingAvg &&
    {data.ratingAvg.toFixed(1)}
    } + {data.ratingAvg ?
    {data.ratingAvg.toFixed(1)}
    : +
    {Number(0).toFixed(1)}
    }
    ๋นˆ๋ณ„
    diff --git a/client/src/components/CategoryDetail/ReviewCard.tsx b/client/src/components/CategoryDetail/ReviewCard.tsx index 35c590ba..6ac54634 100644 --- a/client/src/components/CategoryDetail/ReviewCard.tsx +++ b/client/src/components/CategoryDetail/ReviewCard.tsx @@ -13,8 +13,10 @@ function ReviewCard({ review }) { ๊ฝ‰์ฐฌ๋ณ„
    -
    {review.nickname}
    -
    {date}
    +
    +
    {review.nickname}
    +
    {date}
    +
    {review.content}
    ); diff --git a/client/src/components/CategoryDetail/TicketCard.tsx b/client/src/components/CategoryDetail/TicketCard.tsx index 57241062..e21c82cc 100644 --- a/client/src/components/CategoryDetail/TicketCard.tsx +++ b/client/src/components/CategoryDetail/TicketCard.tsx @@ -12,18 +12,16 @@ function TicketCard({ item, itemIdx }) { const setTotal = useSetRecoilState(totalPrice); const form = useRecoilValue(ReserFormState); - const countClickHandler = (keyword) => { + const countClickHandler = (keyword: string) => { const result = [...items]; const updateItem = {...items[itemIdx]}; - if (keyword === "plus") { + if (keyword === "plus" && updateItem.ticketCount < item.remainingTicket) { updateItem.ticketCount += 1; setTotal((prev) => prev + item.price); - console.log(form); } else if (keyword === "minus" && updateItem.ticketCount > 0) { updateItem.ticketCount -= 1; setTotal((prev) => prev - item.price); - console.log(form); } result[itemIdx] = updateItem; setUpdate(updateItem) @@ -40,9 +38,19 @@ function TicketCard({ item, itemIdx }) {
    {item.itemName}
    - countClickHandler('minus')} size="25" color="#4771B7" /> + countClickHandler('minus')} + size="25" + color="#4771B7" + />
    {update.ticketCount ? update.ticketCount : 0}
    - countClickHandler('plus')} size="25" color="#4771B7" /> + countClickHandler('plus')} + size="25" + color="#4771B7" + />
    diff --git a/client/src/components/CategoryDetail/TicketSelect.tsx b/client/src/components/CategoryDetail/TicketSelect.tsx index e7b1b5cf..0719a065 100644 --- a/client/src/components/CategoryDetail/TicketSelect.tsx +++ b/client/src/components/CategoryDetail/TicketSelect.tsx @@ -23,6 +23,11 @@ function TicketSelect() { const setForm = useSetRecoilState(ReserFormState); const dateChangeHandler = (e) => { + const today = new Date().toLocaleDateString(); + const selectDate = new Date(e.target.value).toLocaleDateString(); + if (selectDate < today) { + return alert('์ง€๋‚œ ๋‚ ์งœ๋Š” ์„ ํƒํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); + } setDate(e.target.value); setForm((prev) => ({...prev, reservationDate: e.target.value})); } diff --git a/client/src/components/Categorybar/CategoryCard.tsx b/client/src/components/Categorybar/CategoryCard.tsx index 98cc1df9..1d2ba186 100644 --- a/client/src/components/Categorybar/CategoryCard.tsx +++ b/client/src/components/Categorybar/CategoryCard.tsx @@ -1,5 +1,6 @@ -// import { useState } from 'react'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; +import { toast } from 'react-toastify'; +import 'aos/dist/aos.css'; import { CardContainer, @@ -32,53 +33,63 @@ function CategoryCard({ data }: CProps) { const { storeId, img, title, reviewCount, address, rating, price, isLike } = data; const url = import.meta.env.VITE_APP_API_URL; + const navigate = useNavigate(); const [isHeartClicked, setIsHeartClicked] = useState(false); - // const [isHeart, setIsHeart] = useState(isLike); + const [isHeart, setIsHeart] = useState(isLike); const isLogin = useRecoilValue(isLoginState); - // ํƒ€์ด๋จธ ๋ณ€์ˆ˜ - let clickTimer; - console.log(clickTimer); // ์ƒํƒœ์ฝ”๋“œ ๋ณด๊ณ  UI ๋ณ€๊ฒฝ์‹œํ‚ค๊ธฐ .. - const onClickHeart = async () => { + const onClickHeart = async (e) => { + e.stopPropagation(); + setIsHeartClicked(true); + if (isHeartClicked) { + return; + } if (!isLogin) { alert(`๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.`); - } - if (!isHeartClicked) { - setIsHeartClicked(true); - await fetch(`${url}/stores/favorites/${storeId}`, { + } else if (!isHeartClicked) { + const res = await fetch(`${url}/stores/favorites/${storeId}`, { method: 'POST', headers: { Authorization: sessionStorage.getItem('Authorization') }, }); - // console.log(isLike); - - clickTimer = setTimeout(() => { - setIsHeartClicked(false); - }, 5000); + if (res.ok) { + setIsHeart(true); + toast('โค๏ธ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); + } } + + setTimeout(() => { + setIsHeartClicked(false); + }, 5000); }; - const onClickNonHeart = async () => { - if (!isLogin) { - alert(`๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.`); + const onClickNonHeart = async (e) => { + e.stopPropagation(); + setIsHeartClicked(true); + if (isHeartClicked) { + return; } if (!isHeartClicked) { - setIsHeartClicked(true); - - await fetch(`${url}/stores/favorites/${storeId}`, { + const res = await fetch(`${url}/stores/favorites/${storeId}`, { method: 'DELETE', headers: { Authorization: sessionStorage.getItem('Authorization') }, }); - // console.log(isLike); - clickTimer = setTimeout(() => { - setIsHeartClicked(false); - }, 5000); + if (res.ok) { + setIsHeart(false); + toast('๐Ÿ–ค ์œ„์‹œ๋ฆฌ์ŠคํŠธ์—์„œ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); + } } + setTimeout(() => { + setIsHeartClicked(false); + }, 5000); }; - // console.log(isLike); return ( - - + navigate(`/category/${storeId}`)}> + {title} @@ -87,22 +98,22 @@ function CategoryCard({ data }: CProps) { - {rating} + {rating.toFixed(1)} ({reviewCount}) {address} {price.toLocaleString('ko-KR')}์› ~ - {isLike ? ( + {isHeart ? ( ) : (
    - ๋กœ๊ณ  -
    ๊ฐœ์ธ์ •๋ณด์ฒ˜๋ฆฌ๋ฐฉ์นจ
    -
    ํŒ€์žฅ: ๊น€ํƒœ์šฐ
    -
    ๋ถ€ํŒ€์žฅ: ๊ฐ•๋™์šฐ
    -
    ํŒ€์›: ๊น€๋ฏผ์ง€, ํ˜„์ฑ„์€, ์‹ ์ด์ˆ˜, ์ด์šฉ๋งŒ
    +
    + ๋กœ๊ณ  +
    ํŒ€์žฅ: ๊น€ํƒœ์šฐ | ๋ถ€ํŒ€์žฅ: ๊ฐ•๋™์šฐ | ํŒ€์›: ๊น€๋ฏผ์ง€, ํ˜„์ฑ„์€, ์‹ ์ด์ˆ˜
    +
    +
    Copyright @ 2023 ActiOn
    +
    + ์ƒํ˜ธ๋ช… (์ฃผ)์•กํ‹ฐ์˜จ | ๋Œ€ํ‘œ ๊น€ํƒœ์šฐ | + ๊ฐœ์ธ์ •๋ณด๋ณดํ˜ธ์ฑ…์ž„์ž ๊ฐ•๋™์šฐ | ์ด๋ฉ”์ผ zop1234@hanmail.net | + ๋งˆ์ผ€ํŒ…/์ œํœด ๋ฌธ์˜ zop1234@hanmail.net | ๊ด‘๊ณ  ๋งค์ฒด ๋ฌธ์˜ zop1234@hanmail.net +
    diff --git a/client/src/components/Header/Dropdown.tsx b/client/src/components/Header/Dropdown.tsx index 43b25850..93173486 100644 --- a/client/src/components/Header/Dropdown.tsx +++ b/client/src/components/Header/Dropdown.tsx @@ -1,31 +1,54 @@ import { Link } from 'react-router-dom'; -import { StyledContainer, Menu } from '../../styles/Header/Dropdown'; +import { + StyledContainer, + Menu, + DropDownContainer, +} from '../../styles/Header/Dropdown'; import { useSetRecoilState } from 'recoil'; import { isLoginState } from '../../store/userInfoAtom'; +import { open } from '../../store/dropdownAtom'; function Dropdown() { const setIsLoginState = useSetRecoilState(isLoginState); + // const url = import.meta.env.VITE_APP_API_URL; + const setIsOpen = useSetRecoilState(open); - const handleLogout = () => { - setIsLoginState(false); - - sessionStorage.removeItem('Authorization'); - sessionStorage.removeItem('memberId'); - sessionStorage.removeItem('access_token'); - window.location.href = '/home'; + const handleLogout = async () => { + if (confirm('์ •๋ง๋กœ ๋กœ๊ทธ์•„์›ƒ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ ?') == true) { + //true๋Š” ํ™•์ธ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์ฝ”๋“œ ์ž‘์„ฑ + await fetch(`/logout`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: sessionStorage.getItem('Authorization'), + 'Access-Control-Allow-Origin': '*', + }, + credentials: 'include', + }); + setIsOpen(false); + setIsLoginState(false); + localStorage.removeItem('recoil-persist'); + sessionStorage.removeItem('Authorization'); + sessionStorage.removeItem('memberId'); + sessionStorage.removeItem('access_token'); + window.location.href = '/home'; + } }; + return ( -
    + - ๋งˆ์ดํŽ˜์ด์ง€ + setIsOpen(false)}> + ๋งˆ์ดํŽ˜์ด์ง€ +
    ๋กœ๊ทธ์•„์›ƒ
    -
    + ); } diff --git a/client/src/components/Header/Header.tsx b/client/src/components/Header/Header.tsx index 89242c63..55c470f8 100644 --- a/client/src/components/Header/Header.tsx +++ b/client/src/components/Header/Header.tsx @@ -1,18 +1,20 @@ -import { useState } from 'react'; +import { open } from '../../store/dropdownAtom'; import { Link, useNavigate } from 'react-router-dom'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; +import { toast } from 'react-toastify'; import { Role, isLoginState, isProfile } from '../../store/userInfoAtom'; import headerlogo from '../../assets/headerlogo.svg'; import profile from '../../assets/profile.svg'; import Searchbar from './Searchbar'; +import 'react-toastify/dist/ReactToastify.css'; import { HaederContainer, LogoContainer, LoginContainer, UnLoginContainer, - DropdownContainer, + ProfileIcon, } from '../../styles/Header/Haeder'; import Dropdown from './Dropdown'; import { search, searchKeyword } from '../../store/searchbarAtom'; @@ -21,7 +23,7 @@ function Header() { //๋น„๋กœ๊ทธ์ธ ์ƒํƒœ์ผ๋•Œ //๋กœ๊ทธ์ธ ๋œ ์ƒํƒœ์ผ๋•Œ -> 1. ํŒŒํŠธ๋„ˆ ๋กœ๊ทธ์ธ์„ ํ•œ ์ƒํƒœ์ผ๋•Œ 2. ํŒŒํŠธ๋„ˆ ๋กœ๊ทธ์ธ์„ ํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ผ ๋•Œ //UseContainer ์•ˆ ์š”์†Œ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•ด์ค„ ๊ฒƒ - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useRecoilState(open); const setKeyword = useSetRecoilState(searchKeyword); const profileImg = useRecoilValue(isProfile); @@ -31,23 +33,25 @@ function Header() { const navigate = useNavigate(); - const handleClick = () => { - navigate('/home'); - setIsSearch(false); - setKeyword(''); - }; - const onClickPartner = () => { + const handlePartner = () => { if (!isLogin) { - alert(`๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.`); + toast('๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.'); navigate('/login'); } else { navigate('/partner'); } }; + const handleClick = () => { + navigate('/home'); + setIsSearch(false); + setKeyword(''); + }; + const handleDropdownClick = () => { setIsOpen(!isOpen); }; + return ( @@ -61,7 +65,7 @@ function Header() { {!isLogin ? ( -
    +
    ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก
    @@ -76,50 +80,18 @@ function Header() { ) : ( - {role === 'PARTNER' ? ( //&& - <> - - ์—…์ฒด ๋“ฑ๋ก - - - {} - {profileImg !== 'default image' ? ( - - ) : ( - - )} - {isOpen && } - - + + {role === 'PARTNER' ? '์—…์ฒด ๋“ฑ๋ก' : 'ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก'} + + {profileImg !== 'default image' ? ( + ) : ( - <> - - ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก - - {profileImg !== 'default image' ? ( // ๋กœ์ง์„ ํ•˜๋‚˜๋กœ ๋นผ๋‘๊ธฐ ? - - ) : ( - - )} - {isOpen && } - + )} + {isOpen && } )} diff --git a/client/src/components/Header/Searchbar.tsx b/client/src/components/Header/Searchbar.tsx index 7675b5b5..09c66939 100644 --- a/client/src/components/Header/Searchbar.tsx +++ b/client/src/components/Header/Searchbar.tsx @@ -1,45 +1,121 @@ import { useRecoilState } from 'recoil'; import { useNavigate } from 'react-router-dom'; +import { useEffect, useRef, useState } from 'react'; import { searchKeyword } from '../../store/searchbarAtom'; import search from '../../assets/search.svg'; import { SearchbarContainer, SearchbarInput, + AutoSearchContainer, + AutoSearchData, + SearchIcon, } from '../../styles/Header/Searchbar'; +interface AutoData { + storeId: number; + category: string; + title: string; + content: string; + address: string; + rating: number; + reviewCount: string; + price: number; + isLike: boolean; + img: string; +} + function Searchbar() { const [keyword, setKeyword] = useRecoilState(searchKeyword); + const [keyItems, setKeyItems] = useState([]); + const [open, setOpen] = useState(false); + const inputRef = useRef(null); const navigate = useNavigate(); + const url = import.meta.env.VITE_APP_API_URL; + + const autoData = async () => { + try { + const res = await fetch( + `${url}/search?keyword=${encodeURIComponent(keyword)}`, + { + headers: { Authorization: sessionStorage.getItem('Authorization') }, + } + ); + if (!res.ok) { + throw new Error('Failed to fetch data'); + } + const data = await res.json(); + setKeyItems(data.data); + } catch (error) { + console.error(error); + } + }; const searchFetch = async () => { try { - await navigate(`/search?keyword=${keyword}`); + await navigate(`/search?keyword=${encodeURIComponent(keyword)}`); + setKeyword(keyword); } catch (error) { console.error(error); } }; - const handleKeyDown = (event) => { - if (event.key === 'Enter') { + const handleKeyDown = (e) => { + if (e.key === 'Enter') { + inputRef.current.blur(); searchFetch(); + setOpen(false); } }; + useEffect(() => { + const debounce = setTimeout(() => { + if (keyword) autoData(); + }, 100); + return () => { + clearTimeout(debounce); + }; + }, [keyword]); + return ( setKeyword(e.currentTarget.value)} - onKeyDown={handleKeyDown} + onKeyUp={handleKeyDown} placeholder="์ƒํ’ˆ์„ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”" + onFocus={() => setOpen(true)} + onBlur={() => setOpen(false)} /> + {open && keyItems.length > 0 && ( + +
      + {keyItems.map((item) => ( + { + e.stopPropagation(); + setKeyword(item.title); + navigate(`/search?keyword=${encodeURIComponent(item.title)}`); + }} + > + setOpen(false)} /> + + {item.title} + + + ))} +
    +
    + )}
    ); } diff --git a/client/src/components/Home/KakaoMap.tsx b/client/src/components/Home/KakaoMap.tsx index d25bed8b..56d6b5e4 100644 --- a/client/src/components/Home/KakaoMap.tsx +++ b/client/src/components/Home/KakaoMap.tsx @@ -1,9 +1,21 @@ -import { useState } from 'react'; -import { Map, MapMarker, CustomOverlayMap } from 'react-kakao-maps-sdk'; +import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import tw from 'tailwind-styled-components'; +import { IoClose } from 'react-icons/io5'; +import { + Map, + MapMarker, + CustomOverlayMap, + ZoomControl, + MapTypeControl +} from 'react-kakao-maps-sdk'; import { homeMapPropsType } from '../../intefaces/Home'; +import markerYellow from '../../assets/marker/marker-yellow.png'; +import markerOrange from '../../assets/marker/marker-orange.png'; +import markerGreen from '../../assets/marker/marker-green.png'; +import markerBlue from '../../assets/marker/marker-blue.png'; +import markerRed from '../../assets/marker/marker-red.png'; function KakaoMap({ marker }: homeMapPropsType) { return ( @@ -13,21 +25,19 @@ function KakaoMap({ marker }: homeMapPropsType) { width: "100%", height: "600px", borderRadius: "10px", - border: "1px solid #4771B7" + border: "1px solid #4771B7", }} level={10} > - { - marker.map((el) => { - return ( - - ); - }) - } + + + {marker.map((el) => ( + + ))} ); } @@ -35,19 +45,45 @@ function KakaoMap({ marker }: homeMapPropsType) { export default KakaoMap; const EventMarkerContainer = ({ position, content }) => { - const [isVisible, setIsVisible] = useState(false) + const [isVisible, setIsVisible] = useState(false); + const [imgSrc, setImgSrc] = useState(''); + + useEffect(() => { + switch(content.category) { + case '์Šค๋…ธํด๋ง/๋‹ค์ด๋น™': + return setImgSrc(markerBlue); + case '์ˆ˜์ƒ๋ ˆ์ €': + return setImgSrc(markerYellow); + case '์„œํ•‘': + return setImgSrc(markerRed); + case '์Šน๋งˆ': + return setImgSrc(markerGreen); + case 'ATV': + return setImgSrc(markerOrange); + } + }, []) return ( <> setIsVisible(true)} + onClick={() => setIsVisible((prev) => !prev)} + image={{ + src: imgSrc && imgSrc, // ๋งˆ์ปค์ด๋ฏธ์ง€์˜ ์ฃผ์†Œ์ž…๋‹ˆ๋‹ค + size: { + width: 40, + height: 43, + }, // ๋งˆ์ปค์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ์ž…๋‹ˆ๋‹ค + }} /> {isVisible && ( - - {content.storeName} +
    +
    {content.category}
    + {content.storeName} +
    +
    )} @@ -56,10 +92,10 @@ const EventMarkerContainer = ({ position, content }) => { } const OverlaySection = tw.section` - bg-white - p-2 - rounded-[10px] - border-2 - border-black - flex flex-col + relative + min-w-[150px] + bg-white/60 + backdrop-blur-sm + px-3 py-2 + border-[1px] border-black rounded-[10px] `; \ No newline at end of file diff --git a/client/src/components/IntroPage/Page1.tsx b/client/src/components/IntroPage/Page1.tsx new file mode 100644 index 00000000..255a832a --- /dev/null +++ b/client/src/components/IntroPage/Page1.tsx @@ -0,0 +1,50 @@ +import { useNavigate } from 'react-router-dom'; + +import logo from '../../assets/logo.svg'; +import bg3 from '../../assets/bg3.svg'; +import bottom from '../../assets/bottom.svg'; +import { Button, Blue, Inrto } from '../../styles/Welcome/Welcome'; +import { + PageContainer, + IntroText, + ClickContainer, + HomeBtn, +} from '../../styles/Welcome/IntroPage/Page1'; + +function page1() { + // eslint-disable-next-line react-hooks/rules-of-hooks + const navigate = useNavigate(); + + const handleButton = () => { + navigate('/home'); + }; + + return ( + + + + + + ๋‹ค์–‘ํ•œ ๋ ˆ์ € ์„œ๋น„์Šค๋ฅผ
    + ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” +
    ์•กํ‹ฐ์˜จ์ž…๋‹ˆ๋‹ค. +
    + +
    + + ์—‘ํ‹ฐ์˜จ ์•Œ์•„๋ณด๊ธฐ + + + + +
    + ); +} + +export default page1; diff --git a/client/src/components/IntroPage/Page2.tsx b/client/src/components/IntroPage/Page2.tsx new file mode 100644 index 00000000..35ef4096 --- /dev/null +++ b/client/src/components/IntroPage/Page2.tsx @@ -0,0 +1,61 @@ +import activity from '../../assets/activity.svg'; +import bottom from '../../assets/bottom.svg'; +import top from '../../assets/top.svg'; + +import { + PageContainer, + MainText, + SubText, +} from '../../styles/Welcome/IntroPage/Page2'; + +function Page2() { + return ( + + + + + + ์ œ์ฃผ๋„ ์ˆ˜์ƒ๋ ˆ์ €๋Š” ๋ชจ๋‘ ์—‘ํ‹ฐ์˜จ์œผ๋กœ + + + ๋ฌด๋”์šด ์—ฌ๋ฆ„ ์นœ๊ตฌ๋“ค๊ณผ ํ•จ๊ป˜ ์งœ๋ฆฟํ•œ ์ถ”์–ต์„ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”. + + + + + + + ); +} + +export default Page2; diff --git a/client/src/components/IntroPage/Page3.tsx b/client/src/components/IntroPage/Page3.tsx new file mode 100644 index 00000000..776b7751 --- /dev/null +++ b/client/src/components/IntroPage/Page3.tsx @@ -0,0 +1,73 @@ +import { useNavigate } from 'react-router-dom'; +import page3 from '../../assets/page3.svg'; +import w_top from '../../assets/w_top.svg'; +import w_bottom from '../../assets/w_bottom.svg'; + +import { + Wrapper, + PageContainer, + TextContainer, + MainText, + SubText, + HomeBtn, +} from '../../styles/Welcome/IntroPage/Page3'; +1867; +function Page3() { + const navigate = useNavigate(); + + return ( + + + + + + + + + ์ œ์ฃผ๋„์˜ ๋ชจ๋“  ๋ ˆ์ €๋ฅผ +
    ์ง€๋„๋กœ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ™•์ธํ•ด ๋ณด์„ธ์š” ! +
    + + ์ถ”์ฒœ์ƒํ’ˆ๋„ ๋†“์น˜์ง€ ๋ง๊ณ  ํ™•์ธํ•ด ๋ณด์„ธ์š” . + + navigate('/home')} + > + ํ™ˆ์œผ๋กœ ์ด๋™ํ•˜๊ธฐ + +
    +
    + + + +
    + ); +} + +export default Page3; diff --git a/client/src/components/IntroPage/Page4.tsx b/client/src/components/IntroPage/Page4.tsx new file mode 100644 index 00000000..11384199 --- /dev/null +++ b/client/src/components/IntroPage/Page4.tsx @@ -0,0 +1,59 @@ +import { useNavigate } from 'react-router-dom'; +import page4 from '../../assets/page4(2).svg'; +import top from '../../assets/top.svg'; +import bottom from '../../assets/bottom.svg'; + +import { + Wrapper, + PageContainer, + TextContainer, + MainText, + SubText, + HomeBtn, +} from '../../styles/Welcome/IntroPage/Page4'; + +function Page4() { + const navigate = useNavigate(); + + return ( + + + + + + + + ์ฆ๊ธฐ๊ณ  ์‹ถ์€ ๋ ˆ์ €๋ฅผ ๊ณ ๋ฅด๊ณ  +
    + ์˜ˆ์•ฝํ•˜๊ณ  ๊ฒฐ์ œ๊นŒ์ง€ ์ง„ํ–‰ํ•ด ๋ณด์„ธ์š” ! +
    + + ๋งˆ์Œ์— ๋“œ๋Š” ์—…์ฒด๋Š” ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ๋‹ด์•„๋‘๊ณ  +
    + ํ•œ๋ˆˆ์— ๋น„๊ตํ•ด ๋ณด์„ธ์š” ! +
    + navigate('/home')}>์—…์ฒด ๋ณด๋Ÿฌ๊ฐ€๊ธฐ +
    + +
    + + + +
    + ); +} + +export default Page4; diff --git a/client/src/components/IntroPage/Page5.tsx b/client/src/components/IntroPage/Page5.tsx new file mode 100644 index 00000000..33f88a58 --- /dev/null +++ b/client/src/components/IntroPage/Page5.tsx @@ -0,0 +1,78 @@ +import { useNavigate } from 'react-router-dom'; +import page5 from '../../assets/page5.svg'; +import w_top from '../../assets/w_top.svg'; +import w_bottom from '../../assets/w_bottom.svg'; + +import { + Wrapper, + PageContainer, + TextContainer, + MainText, + SubText, + HomeBtn, +} from '../../styles/Welcome/IntroPage/Page3'; +1867; +function Page3() { + const navigate = useNavigate(); + + return ( + + + + + + + + + ๋‹ค์–‘ํ•œ ๊ฒฐ์ œ ๋ฐฉ์‹์œผ๋กœ +
    ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ฒฐ์ œ๋ฅผ ์ง„ํ–‰ํ•ด ๋ณด์„ธ์š” ! +
    + + ๊ฒฐ์ œ ์™„๋ฃŒ ํ›„ ์˜ˆ์•ฝ๋‚ด์—ญ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”. + + navigate('/home')} + > + ์—‘ํ‹ฐ์˜จ ์‹œ์ž‘ํ•˜๊ธฐ + +
    +
    +
    +
    + ๋‹ค์‹œ ๊ฐ์ƒํ•˜๋ ค๋ฉด ๋ˆ„๋ฅด์„ธ์š”! +
    + + + +
    +
    + ); +} + +export default Page3; diff --git a/client/src/components/Layout/SideBarLayout.tsx b/client/src/components/Layout/SideBarLayout.tsx index 1f5e713a..00c7937b 100644 --- a/client/src/components/Layout/SideBarLayout.tsx +++ b/client/src/components/Layout/SideBarLayout.tsx @@ -19,5 +19,5 @@ const Style = tw.div` flex flex-row justify-center - pt-20 -`; + py-12 +`; \ No newline at end of file diff --git a/client/src/components/Layout/WelcomeLayout.tsx b/client/src/components/Layout/WelcomeLayout.tsx new file mode 100644 index 00000000..5cd954de --- /dev/null +++ b/client/src/components/Layout/WelcomeLayout.tsx @@ -0,0 +1,10 @@ +// eslint-disable-next-line react/prop-types +const WelcomeLayout = ({ child }) => { + return ( + <> +
    {child}
    + + ); +}; + +export default WelcomeLayout; diff --git a/client/src/components/Loading/LoadingComponent.tsx b/client/src/components/Loading/LoadingComponent.tsx new file mode 100644 index 00000000..a954b894 --- /dev/null +++ b/client/src/components/Loading/LoadingComponent.tsx @@ -0,0 +1,11 @@ +import { AiOutlineLoading } from 'react-icons/ai'; + +function LoadingComponent() { + return ( + <> + + + ); +} + +export default LoadingComponent; diff --git a/client/src/components/MyPage/BusinessSpaceSection.tsx b/client/src/components/MyPage/BusinessSpaceSection.tsx new file mode 100644 index 00000000..fe93724f --- /dev/null +++ b/client/src/components/MyPage/BusinessSpaceSection.tsx @@ -0,0 +1,36 @@ +import { + BusinessCategory, + BusinessSpace, + BusinessCategoryTitle +} from '../../styles/MyPage/BusinessSpaceSection'; + +function BusinessSpaceSection({ partnerData, businessRegi }) { + if(!partnerData) { + return null; + } + + return ( + + + ์—…ํƒœ + {partnerData.stores?.map((_, index) => ( + {businessRegi} + ))} + + + ์—…์ข… + {partnerData.stores?.map((store, index) => ( + {store.category} + ))} + + + ์—…์ฒด๋ช… + {partnerData.stores?.map((store, index) => ( + {store.storeName} + ))} + + + ); +} + +export default BusinessSpaceSection; diff --git a/client/src/components/MyPage/ConfirmationModal.tsx b/client/src/components/MyPage/ConfirmationModal.tsx new file mode 100644 index 00000000..77ed2665 --- /dev/null +++ b/client/src/components/MyPage/ConfirmationModal.tsx @@ -0,0 +1,26 @@ +import { + BioConfirmContainer, + CheckMessage, + CheckButtonContainer, + ConfirmButton +} from "../../styles/MyPage/ConfirmationModal"; + +type ConfirmationModal = { + message: string; + onConfirm: () => void; + onCancel: () => void; +} + +function ConfirmationModal({ message, onConfirm, onCancel }) { + return ( + + {message} + + ์‚ฌ์ง„ ์‚ญ์ œ + ์‚ญ์ œ ์ทจ์†Œ + + + ); +}; + +export default ConfirmationModal; \ No newline at end of file diff --git a/client/src/components/MyPage/Modal.tsx b/client/src/components/MyPage/Modal.tsx index ce9d95c2..2c76ca63 100644 --- a/client/src/components/MyPage/Modal.tsx +++ b/client/src/components/MyPage/Modal.tsx @@ -1,30 +1,128 @@ +import { useState } from 'react'; +import { toast } from 'react-toastify'; import headerlogo from '../../assets/headerlogo.svg'; import close from '../../assets/close.svg'; +import { + CloseButtonContainer, + ModalAllContainer, + ModalBoxContainer , + CloseButton, + LogoContainer, + Logo, + EditContainer, + EditInput, + EditMessage, + EditComplete, + EditConfirmButton +} from '../../styles/MyPage/Modal'; -function Modal({ onClick, defaultNickname, defaultPhoneNumber }) { - return ( -
    -
    -
    - close button -
    -
    - logo -
    -
    -

    ๋‹‰๋„ค์ž„

    - -
    -
    -

    ์—ฐ๋ฝ์ฒ˜

    - -
    -
    - -
    -
    -
    - ); -}; - -export default Modal; \ No newline at end of file +function Modal({ onClick, defaultNickname, defaultPhoneNumber, onEditComplete }) { + const APIURL = import.meta.env.VITE_APP_API_URL; + const [updatedNickname, setUpdatedNickname] = useState(defaultNickname); + const [updatedPhoneNumber, setUpdatedPhoneNumber] = useState(defaultPhoneNumber); + const [isNicknameValid, setNicknameValid] = useState(true); + + const handleEditComplete = async () => { + try { + const EDIT_ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const requestBody: { nickname?: string, phoneNumber?: string } = {}; + + if (updatedNickname !== defaultNickname) { + requestBody.nickname = updatedNickname; + } + + if (updatedPhoneNumber !== defaultPhoneNumber) { + requestBody.phoneNumber = updatedPhoneNumber; + } + + const res = await fetch(`${APIURL}/mypage`, { + method: 'PATCH', + headers: { + 'Authorization': EDIT_ACCESS_TOKEN, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(requestBody) + }); + + if (res.ok) { + toast.success('ํŽธ์ง‘์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); + onClick(); + onEditComplete({ + nickname: updatedNickname, + phoneNumber: updatedPhoneNumber + }); + } else if(res.status === 409) { + alert('์ค‘๋ณต๋œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค.'); + } else if(res.status === 422) { + alert('์ค‘๋ณต๋œ ์ „ํ™”๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.'); + } + } catch (error) { + console.error('ํŽธ์ง‘ ์‹คํŒจ', error); + } + }; + + const handleNicknameChange = (e) => { + const nickname = e.target.value; + setUpdatedNickname(nickname); + setNicknameValid(isValidNickname(nickname)); + }; + + const isValidNickname = (nickname) => { + const regex = /^[A-Za-z0-9]+$/; + return regex.test(nickname); + } + + const handlePhoneNumberChange = (e) => { + setUpdatedPhoneNumber(e.target.value); + }; + + const handleOutsideClick = (e) => { + if (e.target === e.currentTarget) { + onClick(); + } + } + + return ( + + + + + + + + + +

    ๋‹‰๋„ค์ž„

    + +
    + {!isNicknameValid && ( + +

    ๋‹‰๋„ค์ž„ ํŽธ์ง‘์€ ์˜๋ฌธ ๋˜๋Š” ์ˆซ์ž๋กœ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

    +
    + )} + +

    ์—ฐ๋ฝ์ฒ˜

    + +
    + + + ํŽธ์ง‘ ์™„๋ฃŒ + + +
    +
    + ); +} + +export default Modal; diff --git a/client/src/components/MyPage/NothingComponent.tsx b/client/src/components/MyPage/NothingComponent.tsx new file mode 100644 index 00000000..226ba09a --- /dev/null +++ b/client/src/components/MyPage/NothingComponent.tsx @@ -0,0 +1,14 @@ +import { + NoWishTitle +} from "../../styles/MyPage/WishList"; + +function NothingComponent({ title, description}) { + return ( + <> + {title} +

    {description}

    + + ); +}; + +export default NothingComponent; \ No newline at end of file diff --git a/client/src/components/MyPage/ProfileImageSection.tsx b/client/src/components/MyPage/ProfileImageSection.tsx new file mode 100644 index 00000000..ebbfbf6d --- /dev/null +++ b/client/src/components/MyPage/ProfileImageSection.tsx @@ -0,0 +1,43 @@ +import { ImgStyle, MiniButtonGrid, PhotoInputStyle } from '../../styles/MyPage/MyPage'; +import defaultProfileImg from '../../assets/profile.svg'; + +function ProfileImageSection({ profileImageUrl, handlePhotoChange, handlePhotoRemove }) { + return ( + <> + {profileImageUrl !== 'default image' ? ( + + ) : ( + + )} + + + + + + ); +} + +export default ProfileImageSection; diff --git a/client/src/components/MyPage/SideBar.tsx b/client/src/components/MyPage/SideBar.tsx index 4d65035e..f08e89d3 100644 --- a/client/src/components/MyPage/SideBar.tsx +++ b/client/src/components/MyPage/SideBar.tsx @@ -1,4 +1,7 @@ import { Link } from 'react-router-dom'; +import { useRecoilValue } from 'recoil'; +import { isLoginState, Role } from '../../store/userInfoAtom'; + import { SideContainer, SideSpace, @@ -7,6 +10,16 @@ import { } from '../../styles/MyPage/SideBar'; function SideBar() { + const isLogin = useRecoilValue(isLoginState); + const userRole = useRecoilValue(Role); + + const handleLinkClick = (e) => { + if (userRole !== 'PARTNER') { + e.preventDefault(); + alert('์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.'); + } + }; + return ( @@ -20,7 +33,9 @@ function SideBar() { ํŒŒํŠธ๋„ˆ์‰ฝ - ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ + {isLogin && ( + ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ + )} diff --git a/client/src/components/MyPage/UserInfoSection.tsx b/client/src/components/MyPage/UserInfoSection.tsx new file mode 100644 index 00000000..2cda19ea --- /dev/null +++ b/client/src/components/MyPage/UserInfoSection.tsx @@ -0,0 +1,22 @@ +import { UserInfo, UserInfoTitle, MySpace } from '../../styles/MyPage/UserInfo'; + +function UserInfoSection({ nickname, email, phoneNumber }) { + return ( + + + ๋‹‰๋„ค์ž„ + {nickname} + + + ์ด๋ฉ”์ผ + {email} + + + ์—ฐ๋ฝ์ฒ˜ + {phoneNumber} + + + ); +}; + +export default UserInfoSection; diff --git a/client/src/components/NoResult/NoResult.tsx b/client/src/components/NoResult/NoResult.tsx index f0c4c4e7..55db0e3b 100644 --- a/client/src/components/NoResult/NoResult.tsx +++ b/client/src/components/NoResult/NoResult.tsx @@ -1,9 +1,9 @@ -import { useRecoilValue } from 'recoil'; import search from '../../assets/search.svg'; -import { searchKeyword } from '../../store/searchbarAtom'; +import { useSearchParams } from 'react-router-dom'; function NoResult() { - const keyword = useRecoilValue(searchKeyword); + const [searchParams] = useSearchParams(); + const keywords = searchParams.get('keyword'); return (
    @@ -15,8 +15,8 @@ function NoResult() { />

    - {keyword} ์˜ - ๊ฒ€์ƒ‰๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. + {keywords}{' '} + ์˜ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

    ์ง€์—ญ/์—…์ฒด๋ช…์„ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”.

    diff --git a/client/src/components/Partner/FormRegistration.tsx b/client/src/components/Partner/FormRegistration.tsx index 2f7049f7..53e09ed1 100644 --- a/client/src/components/Partner/FormRegistration.tsx +++ b/client/src/components/Partner/FormRegistration.tsx @@ -1,15 +1,25 @@ -import { FormRegiContainer, FormRegiButton } from '../../styles/Partner/Partner'; +import { FormRegiContainer, FormRegiButton, DisableFormRegiButton } from '../../styles/Partner/Partner'; + +function FormRegistration ({ isFormValid, handleSubmit, businessSector, isDuplicateChecked }) { + const isSelectedOptionSelected = businessSector === 'select'; + const formIsValid = isFormValid && !isSelectedOptionSelected && isDuplicateChecked; -function FormRegistration ({ isFormValid, handleSubmit }) { return ( - - ๋“ฑ๋กํ•˜๊ธฐ - + {!formIsValid ? ( + + ๋“ฑ๋กํ•˜๊ธฐ + + ) : ( + + ๋“ฑ๋กํ•˜๊ธฐ + + )} ); } diff --git a/client/src/components/Partner/RegistrationNumber.tsx b/client/src/components/Partner/RegistrationNumber.tsx index 5c93d77a..a30710d4 100644 --- a/client/src/components/Partner/RegistrationNumber.tsx +++ b/client/src/components/Partner/RegistrationNumber.tsx @@ -1,55 +1,101 @@ -import { - RegiNumberContainer, - RegiNumberInput, - RegiNumberNoWrite, - RegiNumberCorrect, - RegiNumberWrong - } from "../../styles/Partner/Partner"; +import { useEffect, useState } from "react"; +import { + RegiNumberContainer, + RegiNumberInput, + RegiNumberNoWrite, + RegiNumberCorrect, + RegiNumberWrong, + RegiNumberConfirm +} from "../../styles/Partner/Partner"; -function RegistrationNumber({ - regiNumber, - handleRegiNumberChange, - isInputTouched, - isRegiNumberIncomplete, - isRegiNumberValid, - setIsInputTouched, - isCheckingDuplicate - }) { - return ( - - -
    -
    - setIsInputTouched(true)} - /> - {isInputTouched && !regiNumber && ( - ์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”. - )} - {isRegiNumberValid && ( - ์˜ฌ๋ฐ”๋ฅธ ์ž…๋ ฅ์ž…๋‹ˆ๋‹ค. - )} - {isRegiNumberIncomplete && ( - ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ๋Š” 10์ž๋ฆฌ๋กœ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - )} -
    - -
    -
    - ); -}; +function RegistrationNumber({ + regiNumber, + handleRegiNumberChange, + isInputTouched, + isRegiNumberIncomplete, + isRegiNumberValid, + setIsInputTouched, + isDuplicateChecked, + setIsDuplicateChecked +}) { + const APIURL = import.meta.env.VITE_APP_API_URL; + const [isDuplicate, setIsDuplicate] = useState(false); + const [duplicateMessage, setDuplicateMessage] = useState(''); -export default RegistrationNumber; \ No newline at end of file + const handleDuplicateCheck = async () => { + try { + const ACCESS_TOKEN = sessionStorage.getItem('Authorization') + const res = await fetch(`${APIURL}/partners/verify?number=${regiNumber}`, { + method: 'GET', + headers: { + 'Authorization': ACCESS_TOKEN, + }, + }); + if (res.ok) { + if(res.status === 200) { + setIsDuplicate(false); + setDuplicateMessage('์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.'); + setIsDuplicateChecked(true); + alert('์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‚ฌ์—…์ž๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.'); + }; + } else { + setIsDuplicate(true); + setDuplicateMessage('์ค‘๋ณต๋œ ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.') + setIsDuplicateChecked(true); + alert('์ค‘๋ณต๋œ ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.'); + } + } catch (error) { + console.error('์ค‘๋ณตํ™•์ธ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', error); + } + }; + + useEffect(() => { + setIsDuplicateChecked(false); + }, [regiNumber]); + + return ( + + +
    +
    + setIsInputTouched(true)} + /> + {isInputTouched && !regiNumber && ( + ์ˆซ์ž๋งŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”. + )} + {!isDuplicateChecked && isRegiNumberValid && ( + ์ค‘๋ณตํ™•์ธ์„ ์ง„ํ–‰ํ•ด์ฃผ์„ธ์š”. + )} + {isRegiNumberValid && isDuplicateChecked && ( + {duplicateMessage} + )} + {isRegiNumberIncomplete && ( + ์‚ฌ์—…์ž ๋“ฑ๋ก๋ฒˆํ˜ธ๋Š” 10์ž๋ฆฌ๋กœ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + )} + {isDuplicate && isDuplicateChecked && ( + {duplicateMessage} + )} + +
    + +
    +
    + ); +} + +export default RegistrationNumber; diff --git a/client/src/components/Partner/SelectBox.tsx b/client/src/components/Partner/SelectBox.tsx index b3336252..2f9609d7 100644 --- a/client/src/components/Partner/SelectBox.tsx +++ b/client/src/components/Partner/SelectBox.tsx @@ -1,20 +1,12 @@ -import { useState } from 'react'; import { SelectContainer } from '../../styles/Partner/SelectBox'; function SelectBox({ value, onChange }) { - const [isSelectDisabled, setIsSelectDisabled] = useState(false); - - const handleSelectFocus = () => { - setIsSelectDisabled(true); - }; - - return ( + return ( -
    @@ -37,6 +38,7 @@ function StoreAddTop({ formChangeHandler }) { name="kakao" value={form.kakao} onChange={formChangeHandler} + placeholder="์˜๋ฌธ๊ณผ ์ˆซ์ž ์กฐํ•ฉ์œผ๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”." />
    @@ -46,6 +48,7 @@ function StoreAddTop({ formChangeHandler }) { name="contact" value={form.contact} onChange={formChangeHandler} + placeholder="'-'๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”" />
    diff --git a/client/src/index.css b/client/src/index.css index a6763dc5..1705cc88 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -44,12 +44,48 @@ html, body, #root { height: 100%; } +body { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + overflow-x: hidden; +} + +html::-webkit-scrollbar { + width: 15px; + background-color: rgb(255, 255, 255); +} + +html::-webkit-scrollbar-track { + width: 10px; +} + +html::-webkit-scrollbar-thumb { + background-color: rgb(168, 168, 168); + border-radius: 10px; + border: 2px solid white; +} + +html { + scroll-behavior: smooth; +} + + .carousel-title { font-size: xx-large; font-weight: 700; -webkit-text-stroke: 0.5px white; } +.arrow-left { + animation: arrowLeft 1.5s ease-in-out infinite +} + +.arrow-right { + animation: arrowRight 1.5s ease-in-out infinite +} + .star { width: 150px; max-width: initial; @@ -58,4 +94,94 @@ html, body, #root { .card-star { width: 100px; max-width: initial; +} + +.wheel { + animation: wheelRotate 1.5s infinite linear; +} + +.intro-text { + animation: fadeInRight 0.75s ease-in-out ; +} + +.animate-topbounce { + animation: topbounce 1s infinite; +} + +.animate-bounce { + animation: bounce 1s infinite; +} + +@keyframes topbounce { + + 0%, + 100% { + transform: none; + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + + 50% { + transform: translateY(-10%); + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } +} + +@keyframes bounce { + + 0%, + 100% { + transform: translateY(-10%); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + + 50% { + transform: none; + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } +} + + +@keyframes wheelRotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +@keyframes fadeInRight { + from { + opacity: 0; + transform: translateX(-500px); + } + + to { + opacity: 1; + transform: translateX(0px); + } +} + +@keyframes arrowLeft { + 0% { + transform: translateX(0); + } + 50% { + transform: translateX(-10px); + } + 100% { + transform: translateX(0); + } +} + +@keyframes arrowRight { + 0% { + transform: translateX(0); + } + 50% { + transform: translateX(10px); + } + 100% { + transform: translateX(0); + } } \ No newline at end of file diff --git a/client/src/main.tsx b/client/src/main.tsx index 590d8eca..5e18b55f 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -4,6 +4,7 @@ import App from './App.tsx'; import './index.css'; import { RecoilRoot } from 'recoil'; import { BrowserRouter } from 'react-router-dom'; +import { AnimatePresence } from 'framer-motion'; const recoilPersistConfig = { key: 'recoil-persist', // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ๋  ํ‚ค @@ -12,10 +13,12 @@ const recoilPersistConfig = { ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - Loading...
    }> - - - - + + Loading...
    }> + + + + + ); diff --git a/client/src/pages/CategoryDetail.tsx b/client/src/pages/CategoryDetail.tsx index 90c12b8a..cf2b105f 100644 --- a/client/src/pages/CategoryDetail.tsx +++ b/client/src/pages/CategoryDetail.tsx @@ -17,49 +17,62 @@ import { reserFormType } from '../intefaces/CategoryDetail'; function CategoryDetail() { const API_URL = import.meta.env.VITE_APP_API_URL; - const location = useLocation(); const [data, setData] = useRecoilState(CategoryDetailState); const [form, setForm] = useRecoilState(ReserFormState); const date = useRecoilValue(ReserDateState); + const location = useLocation(); - const CategoryDetailFetch = async () => { + const categoryDetailFetch = async () => { try { const storeId = location.pathname.substring(10); - const res = await fetch(`${API_URL}/stores/${storeId}`); + const res = await fetch(`${API_URL}/stores/${storeId}`, { + method: 'GET', + headers: { Authorization: sessionStorage.getItem('Authorization') }, + }); const json = await res.json(); delete json.items; setData(json); } catch (error) { - console.log(error); + console.error(error); } }; - const dateFetch = async () => { + const itemsFetch = async () => { const storeId = location.pathname.substring(10); try { const dateValue = date.split('-').join(''); - const res = await fetch(`${API_URL}/items/${storeId}?date=${dateValue}`); + const res = await fetch(`${API_URL}/items/${storeId}?date=${dateValue}`, { + method: 'GET', + headers: { Authorization: sessionStorage.getItem('Authorization') }, + }); const json = await res.json(); setData((prev) => ({ ...prev, items: json })); } catch (error) { - console.log(error); + console.error(error); } }; useEffect(() => { window.scrollTo(0, 0); - setForm({} as reserFormType); - CategoryDetailFetch(); - dateFetch(); + setForm({ + reservationName: '', + reservationPhone: '', + reservationEmail: '', + reservationDate: '', + reservationItems: [], + totalPrice: 0 + } as reserFormType); + categoryDetailFetch(); + itemsFetch(); }, []); useEffect(() => { - dateFetch(); + itemsFetch(); }, [form.reservationDate]); return ( -
    - {data && ( +
    + {data &&
    diff --git a/client/src/pages/CategoryPage.tsx b/client/src/pages/CategoryPage.tsx index e463ca0e..ae5c4a75 100644 --- a/client/src/pages/CategoryPage.tsx +++ b/client/src/pages/CategoryPage.tsx @@ -1,5 +1,8 @@ -import { Link, useSearchParams } from 'react-router-dom'; +import { useSearchParams, NavLink, useLocation } from 'react-router-dom'; import { useEffect } from 'react'; +import { useRecoilState } from 'recoil'; +import 'aos/dist/aos.css'; +import { ToastContainer } from 'react-toastify'; import CategoryCard from '../components/Categorybar/CategoryCard'; import { @@ -7,29 +10,28 @@ import { CategoryContainer, Option, Category, + TopBtn, + BtnWrapper, } from '../styles/Category/CategoryPage'; -import { useRecoilState } from 'recoil'; - import { categoryData } from '../store/categoryAtom'; import { loading, search } from '../store/searchbarAtom'; import Loading from '../components/Loading/Loading'; import NoResult from '../components/NoResult/NoResult'; +import top from '../assets/w_top.svg'; function CategoryPage() { const url = import.meta.env.VITE_APP_API_URL; const [searchParams] = useSearchParams(); + const location = useLocation(); const categoryName = searchParams.get('category_name'); const sort = searchParams.get('sort'); const keywords = searchParams.get('keyword'); - // const keyword = useRecoilValue(searchKeyword); // ์ „์—ญ ์ƒํƒœ ๋ณ€์ˆ˜ const [isSearch, setIsSearch] = useRecoilState(search); const [isLoading, setIsLoading] = useRecoilState(loading); const [category, setCategory] = useRecoilState(categoryData); - // console.log(keywords); // ์ถœ๋ ฅ: 'ํ•จ๋•' - useEffect(() => { const fetchData = async () => { let data; @@ -37,20 +39,28 @@ function CategoryPage() { if (keywords) { setIsSearch(true); setIsLoading(true); - const res = await fetch(`${url}/search?keyword=${keywords}`); + const res = await fetch( + `${url}/search?keyword=${encodeURIComponent(keywords)}`, + { + headers: { Authorization: sessionStorage.getItem('Authorization') }, + } + ); data = await res.json(); if (res.status !== 200) throw res; } else { // ๊ฒ€์ƒ‰ ์กฐ๊ฑด์ด ์—†์„ ๋•Œ const res = await fetch( - `${url}/stores?category=${categoryName}&sort_field=${sort}` + `${url}/stores?category=${categoryName}&sort_field=${sort}`, + { + headers: { Authorization: sessionStorage.getItem('Authorization') }, + } ); data = await res.json(); setIsSearch(false); // ์—๋Ÿฌ ์ฒ˜๋ฆฌ if (res.status !== 200) throw res; } - // 2์ดˆ ๋™์•ˆ ๋กœ๋”ฉ ํ‘œ์‹œ + // 0.5์ดˆ ๋™์•ˆ ๋กœ๋”ฉ ํ‘œ์‹œ setTimeout(() => { setIsLoading(false); @@ -63,6 +73,16 @@ function CategoryPage() { return ( ); } diff --git a/client/src/pages/Home.tsx b/client/src/pages/Home.tsx index 302822b1..be85f337 100644 --- a/client/src/pages/Home.tsx +++ b/client/src/pages/Home.tsx @@ -39,9 +39,9 @@ function Home() { const res = await fetch(`${API_URL}/main`); const json = await res.json(); setHomeData(json); - } + }; - useEffect(() => { + useEffect(() => { // ๋ฐ”๊นฅ์œผ๋กœ ๋กœ์ง ๋ถ„๋ฆฌ์‹œ์ผœ๋ณด๊ธฐ if (homeData.recommend) { const interval = setInterval(() => { if (current === homeData.recommend.length - 1) { @@ -57,33 +57,34 @@ function Home() { }, [current, homeData]); useEffect(() => { + window.scrollTo(0, 0); try { homeDataFetch(); - } - catch (error) { + } catch (error) { console.error(error); } - }, []) + }, []); return (
    - - {homeData.recommend && homeData.recommend.map((el) => { - return ; - })} + + {homeData.recommend && + homeData.recommend.map((el) => { + return ; + })} - + - +
    -
    +
    ๋ชจ๋“  ๋ ˆ์ € ํ•œ๋ˆˆ์— ๋ณด๊ธฐ
    -
    - {homeData.data && } +
    + {homeData.data && }
    diff --git a/client/src/pages/Login.tsx b/client/src/pages/Login.tsx index 1d5e06ca..849315a6 100644 --- a/client/src/pages/Login.tsx +++ b/client/src/pages/Login.tsx @@ -1,6 +1,8 @@ import { useState } from 'react'; import { useSetRecoilState } from 'recoil'; import { Role, isLoginState, isProfile } from '../store/userInfoAtom'; +import { ToastContainer, toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; import { InputContainer, @@ -16,142 +18,99 @@ import { useNavigate } from 'react-router-dom'; function Login() { const navigate = useNavigate(); const url = import.meta.env.VITE_APP_API_URL; - // const CLIENT_ID = import.meta.env.VITE_APP_CLIENT_ID; - // const GOOGLE_REDIRECT_URI = import.meta.env.VITE_APP_REDIRECT_URI; - const [email, setEmail] = useState(''); - const [password, setPassWord] = useState(''); - // const [accessToken, setAccessToken] = useState(''); + const [isClicked, setIClicked] = useState(false); + const [form, setForm] = useState({ email: '', password: '' }); //recoil ์ „์—ญ์ƒํƒœ const setIsLoginState = useSetRecoilState(isLoginState); const setIsProfile = useSetRecoilState(isProfile); const setIsRole = useSetRecoilState(Role); - const onEmailHandler = (event) => { - setEmail(event.currentTarget.value); + const handleChange = (e) => { + const { name, value } = e.target; + setForm({ ...form, [name]: value }); }; - const onPwHandler = (event) => { - setPassWord(event.currentTarget.value); - }; - - //๊ตฌ๊ธ€๋กœ๊ทธ์ธ - // const getAccessToken = async (authorizationCode) => { - // // console.log('3'); - // // await fetch(`${url}/oauth2/authorization/google`, { - // // method: 'POST', - // // body: JSON.stringify({ - // // accesstoken: authorizationCode, - // // }), - // // }); - // // setIsLoginState(true); - // const parsedHash = new URLSearchParams(window.location.hash.substring(1)); - // const accessToken = parsedHash.get('access_token'); - - // // await url.post('oauth/google', { accessToken }); - // await fetch(`${url}/oauth2/authorization/google/success`, { - // method: 'POST', - // body: JSON.stringify({ - // accesstoken: accessToken, - // }), - // }); - // // setIsLoginState(true); - // setIsLoginState(true); - // navigate('/home'); - // }; - // useEffect(() => { - // // Authorization Server๋กœ๋ถ€ํ„ฐ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋œ ๊ฒฝ์šฐ, Authorization Code๊ฐ€ ํ•จ๊ป˜ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. - // // ex) http://localhost:3000/mypage?code=5e52fb85d6a1ed46a51f - // // 4. [Github Auth ์„œ๋ฒ„ ->ํด๋ผ์ด์–ธํŠธ] Redirect + Authorization code ํ™•์ธ - // console.log('3'); - // const url = new URL(window.location.href); - // const authorizationCode = url.searchParams.get('code'); - // if (authorizationCode) { - // getAccessToken(authorizationCode); - // } - // }, []); - // const getAccessToken = async (accessToken) => { - // console.log('1'); - // try { - // await fetch(`${url}/oauth2/authorization/google`, { - // method: 'POST', - // headers: { - // 'Content-Type': 'application/json', - // }, - // body: JSON.stringify({ - // accessToken: accessToken, - // }), - // }); - // // const { accessToken } = result.data; - // setIsLoginState(true); - // setAccessToken(accessToken); - // navigate('/home'); - // } catch (err) { - // alert(err); - // } - // }; - - // const handleAccessToken = async () => { - // const parsedHash = new URLSearchParams(window.location.hash.substring(1)); - // console.log('2'); - // const accessToken = parsedHash.get('access_token'); - // if (accessToken) { - // await getAccessToken(accessToken); - // } - // }; - - const handleGoogleLogin = async (e) => { - e.preventDefault(); - window.location.href = `${url}/oauth2/authorization/google`; - // 'https://accounts.google.com/o/oauth2/auth?' + - // `client_id=${CLIENT_ID}&` + - // `redirect_uri=${GOOGLE_REDIRECT_URI}&` + - // 'response_type=token&' + - // 'scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'; - }; - - // useEffect(() => { - // handleAccessToken(); - // }, []); - //์ผ๋ฐ˜๋กœ๊ทธ์ธ -> ๊ณตํ†ต์œผ๋กœ ๋บ„ ๊ฒƒ.....axios const handleLogin = async (e) => { + setIClicked(true); + if (isClicked) { + return; + } e.preventDefault(); try { const res = await fetch(`${url}/auth/login`, { method: 'POST', + headers: { 'Access-Control-Allow-Origin': '*' }, body: JSON.stringify({ - username: email, - password: password, + username: form.email, + password: form.password, }), + credentials: 'include', }); const result1 = await res.json(); - if (res.status !== 200) throw res; //ํ—ค๋”์—์„œ ๋ฉค๋ฒ„์•„์ด๋””์™€ ๋‹‰๋„ค์ž„์„ ๋ฐ›์•„์˜ด const Authorization = res.headers.get('Authorization'); const name = result1.nickname; const profile = result1.profileImage; const role = result1.role; - setIsProfile(profile); - setIsRole(role); - // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— memberId,ํ† ํฐ ์ €์žฅ - sessionStorage.setItem('Authorization', Authorization); - setIsLoginState(true); - - // ํ—ค๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•˜์œผ๋ฉด ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ - if (name) { - alert(`${name}๋‹˜ ๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค !`); - navigate('/home'); + if (res.ok) { + setIsLoginState(true); + toast(`๐ŸŒŠ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ! ${name}๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค `); + setTimeout(() => { + navigate('/home'); + setIsLoginState(true); + }, 2000); + + // ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ ์ „์—ญ์— ์ €์žฅ + setIsProfile(profile); + setIsRole(role); + // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— memberId,ํ† ํฐ ์ €์žฅ + sessionStorage.setItem('Authorization', Authorization); + } else if (res.status === 401) { + toast('๐Ÿšจ ์ด๋ฉ”์ผ๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”'); + setTimeout(() => { + setIClicked(false); + }, 3000); } } catch (error) { - console.error('๋กœ๊ทธ์ธ ์š”์ฒญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค', error); + console.error(error); + toast(`๐Ÿšจ ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค!`); + setTimeout(() => { + setIClicked(false); + }, 3000); + } + }; + + const handleKeyDown = (e) => { + if (e.key === 'Enter') { + setIClicked(true); + if (isClicked) { + return; + } + handleLogin(e); } }; + const handleGoogleLogin = async (e) => { + e.preventDefault(); + window.location.href = `${url}/oauth2/authorization/google`; + }; + return ( + @@ -161,21 +120,31 @@ function Login() {
    - +
    - +
    @@ -189,7 +158,12 @@ function Login() { ๊ตฌ๊ธ€๋กœ ๋กœ๊ทธ์ธํ•˜๊ธฐ
    - diff --git a/client/src/pages/MyPage.tsx b/client/src/pages/MyPage.tsx index e8a053ae..57ca299e 100644 --- a/client/src/pages/MyPage.tsx +++ b/client/src/pages/MyPage.tsx @@ -1,171 +1,214 @@ -import { useState } from 'react'; -import { dummyBio } from '../dummy/mypagedummy'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import { isProfile, Role } from '../store/userInfoAtom'; +import { useEffect, useState } from 'react'; import Modal from '../components/MyPage/Modal'; -import profile from '../assets/profile.svg'; - +import BusinessSpaceSection from '../components/MyPage/BusinessSpaceSection'; +import UserInfoSection from '../components/MyPage/UserInfoSection'; +import ProfileImageSection from '../components/MyPage/ProfileImageSection'; +import LoadingComponent from '../components/Loading/LoadingComponent'; +import defaultProfileImg from '../assets/profile.svg'; +import 'react-toastify/dist/ReactToastify.css'; import { - BusinessCategory, - BusinessSpace, ButtonGrid, ButtonStyle, - ImgStyle, - MiniButtonGrid, MySpace, NicknameAccent, TopSpace, - UserInfo, - UserInfoTitle, - BusinessCategoryTitle, MyPageContainer, MyBioContainer, - PhotoInputStyle, + ButtonGridEdit, + LoadingContainer, } from '../styles/MyPage/MyPage'; - function MyPage() { - // const APIURL = import.meta.env.VITE_APP_API_URL - const user = dummyBio[0]; - const businessCategory = user.stores[0].businessCategory; + const APIURL = import.meta.env.VITE_APP_API_URL; const businessRegi = `์Šคํฌ์ธ  ๋ฐ ์—ฌ๊ฐ€๊ด€๋ จ ์„œ๋น„์Šค์—…`; - + const role = useRecoilValue(Role); const [showBusinessSpace, setShowBusinessSpace] = useState(false); const [showModal, setShowModal] = useState(false); - const [selectedPhoto, setSelectedPhoto] = useState(null); - // const [userData, setUserData] = useState(null); - - // useEffect(() => { - // fetchData(); - // }, []); - - // const fetchData = async () => { - // try { - // const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); - // const res = await fetch(`${APIURL}/mypage`, { - // method: 'GET', - // headers: { - // 'Authorization': ACCESS_TOKEN - // } - // }) - // .then(res => res.json()) - // .then(data => { - // //์‘๋‹ต ๋ฐ์ดํ„ฐ์ฒ˜๋ฆฌ - // }) - // } catch (error) { - // console.error('Error fetching data', error); - // } - // }; - - // if(!userData) { - // return

    Loading...

    ; - // } + const [userData, setUserData] = useState(null); + const [partnerData, setPartnerData] = useState(null); + const [profileImageUrl, setProfileImageUrl] = useRecoilState(isProfile); + useEffect(() => { + fetchData(); + }, []); + const fetchData = async () => { + try { + const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const res = await fetch(`${APIURL}/mypage`, { + method: 'GET', + headers: { + Authorization: ACCESS_TOKEN, + }, + }); + if (res.ok) { + const data = await res.json(); + setUserData(data); // userData ์—…๋ฐ์ดํŠธ + } + } catch (error) { + console.error('Error fetching data', error); + } + }; + const fetchPartnerData = async () => { + try { + const PARTNER_ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const res = await fetch(`${APIURL}/mypage/partner`, { + method: 'GET', + headers: { + Authorization: PARTNER_ACCESS_TOKEN, + }, + }); + if (res.ok) { + const data = await res.json(); + setPartnerData(data); + } + } catch (error) { + console.error('Error fetching data', error); + } + }; + if (!userData) { + return ( + + + + ); + } + const { nickname, email, phoneNumber } = userData; const handleBusinessSpaceToggle = () => { setShowBusinessSpace(!showBusinessSpace); + if (!showBusinessSpace) { + fetchPartnerData(); + } + }; + const handleButtonClick = () => { + if (role !== 'PARTNER') { + alert('์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.'); + } else { + handleBusinessSpaceToggle(); + } }; - const openModal = () => { setShowModal(true); }; - const closeModal = () => { setShowModal(false); }; - - const handlePhotoChange = (e) => { + const handlePhotoChange = async (e) => { const file = e.target.files[0]; - setSelectedPhoto(file); - }; + try { + const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const formData = new FormData(); + formData.append('image', file); + + const res = await fetch(`${APIURL}/mypage/profile`, { + method: 'PUT', + headers: { + Authorization: ACCESS_TOKEN, + }, + body: formData, + }); - const handlePhotoRemove = () => { - setSelectedPhoto(null); - const input = document.getElementById('photoInput') as HTMLInputElement; - if (input) { - input.value=''; + if (res.ok) { + const reader = new FileReader(); + reader.onloadend = () => { + const imageUrl = reader.result; + sessionStorage.setItem('selectedPhoto', JSON.stringify(imageUrl)); + setProfileImageUrl(imageUrl); + } + reader.readAsDataURL(file) + // if (res.ok) { + // const data = await res.json(); + // if(data && data.imageUrl) { + // sessionStorage.setItem('selectedPhoto', JSON.stringify(data.imageUrl)); + // setProfileImageUrl(data.imageUrl); + // } + } else { + console.error('ํ”„๋กœํ•„ ์—…๋ฐ์ดํŠธ ์‹คํŒจ', res.status); + } + } catch (error) { + console.error('ํ”„๋กœํ•„ ์—…๋ฐ์ดํŠธ ์—๋Ÿฌ', error); } }; - + + const handlePhotoRemove = async () => { + alert('์‚ฌ์ง„์„ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?'); + try { + const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const res = await fetch(`${APIURL}/mypage/profile`, { + method: 'DELETE', + headers: { + Authorization: ACCESS_TOKEN, + }, + }); + if (res.ok) { + const imageUrl = defaultProfileImg; + sessionStorage.setItem('selectedPhoto', JSON.stringify(imageUrl)); + setProfileImageUrl(imageUrl); + fetchData(); + alert('ํ”„๋กœํ•„ ์‚ฌ์ง„์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.') + } else { + console.error('ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ ์‹คํŒจ', res.status); + alert('ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'); + } + } catch (error) { + console.error('ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ ์—๋Ÿฌ', error); + } + }; + const handleEditComplete = (updatedUserData) => { + setUserData({ + ...updatedUserData, + email: userData.email, + }); + setShowModal(false); + }; return ( <> - - ํŽธ์ง‘ - + + + ํŽธ์ง‘ + + - - - - - - {user.nickname} + {nickname} - - - ๋‹‰๋„ค์ž„ - {user.nickname} - - - ์ด๋ฉ”์ผ - {user.email} - - - ์—ฐ๋ฝ์ฒ˜ - {user.phoneNumber} - - + - ๋“ฑ๋กํ•œ ์—…์ฒด๋ณด๊ธฐ + + ๋“ฑ๋กํ•œ ์—…์ฒด๋ณด๊ธฐ + {showBusinessSpace && ( - - - ์—…ํƒœ - {user.stores.map((_, index) => ( - {businessRegi} - ))} - - - ์—…์ข… - {user.stores.map((_, index) => ( - {businessCategory} - ))} - - - ์—…์ฒด๋ช… - {user.stores.map((store, index) => ( - {store.storeName} - ))} - - + )} - {showModal && } + {showModal && ( + + )} ); } - -export default MyPage; +export default MyPage; \ No newline at end of file diff --git a/client/src/pages/Partner.tsx b/client/src/pages/Partner.tsx index 80a38b45..a3ce6df7 100644 --- a/client/src/pages/Partner.tsx +++ b/client/src/pages/Partner.tsx @@ -1,10 +1,12 @@ import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { - RepresentativeName, - RegistrationNumber, - BusinessComponents, - FormRegistration +import { useRecoilState } from 'recoil'; +import { isLoginState } from '../store/userInfoAtom'; +import { + RepresentativeName, + RegistrationNumber, + BusinessComponents, + FormRegistration, } from '../components/Partner'; import { @@ -14,44 +16,47 @@ import { FormContainer, CompanyName, CommonInput, - OpeningContainer + OpeningContainer, } from '../styles/Partner/Partner'; function Partner() { - const APIURL = import.meta.env.VITE_APP_API_URL + const APIURL = import.meta.env.VITE_APP_API_URL; const navigate = useNavigate(); - + const [_, setIsLogin] = useRecoilState(isLoginState); const [regiNumber, setRegiNumber] = useState(''); const [repreName, setRepreName] = useState(''); const [companyName, setCompanyName] = useState(''); const [openingDate, setOpeningDate] = useState(''); - const [businessSector, setBusinessSector] = useState(''); - + const [selectedBusinessSector, setSelectedBusinessSector] = + useState('select'); const [isInputTouched, setIsInputTouched] = useState(false); - const [isCheckingDuplicate, _] = useState(false); + const [isDuplicateChecked, setIsDuplicateChecked] = useState(false); const handleRegiNumberChange = (e) => { const input = e.target.value.replace(/\D/g, ''); const formattedInput = input.slice(0, 10); - const formattedRegiNumber = formattedInput.replace(/(\d{3})(\d{2})(\d{5})/, '$1-$2-$3'); + const formattedRegiNumber = formattedInput.replace( + /(\d{3})(\d{2})(\d{5})/, + '$1-$2-$3' + ); setRegiNumber(formattedRegiNumber); }; const isRegiNumberValid = regiNumber.match(/^\d{3}-\d{2}-\d{5}$/); const isRegiNumberIncomplete = regiNumber.length > 0 && !isRegiNumberValid; + const currentDate = new Date().toISOString().split('T')[0]; useEffect(() => { setIsInputTouched(true); }, []); - const isFormValid = ( + const isFormValid = regiNumber && isRegiNumberValid && repreName.length > 0 && companyName.length > 0 && openingDate.length > 0 && - businessSector.length > 0 - ); + selectedBusinessSector !== 'select'; const handleSubmit = async (e) => { e.preventDefault(); @@ -60,48 +65,46 @@ function Partner() { owner: repreName, businessName: companyName, registrationNumber: regiNumber, - businessCategory: businessSector + businessCategory: selectedBusinessSector, }; try { - const ACCESS_TOKEN = sessionStorage.getItem('Authorization') + const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); const response = await fetch(`${APIURL}/partners`, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': ACCESS_TOKEN + Authorization: ACCESS_TOKEN, }, - body: JSON.stringify(formData) + body: JSON.stringify(formData), + credentials: 'include', }); if (response.ok) { // ์„ฑ๊ณต์ ์œผ๋กœ ๋“ฑ๋ก๋œ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ - console.log('Status', response.status); - if(response.status === 201) { - console.log('201 Created'); - navigate('/home'); + if (response.status === 201) { + alert('ํŒŒํŠธ๋„ˆ๋“ฑ๋ก์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํ•ด์ฃผ์„ธ์š”.'); + setIsLogin(false); + sessionStorage.removeItem('Authorization'); + navigate('/login'); } } else { // ๋“ฑ๋ก ์‹คํŒจํ•œ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ - console.log('Status', response.status); alert('ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'); } } catch (error) { // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ - console.log('๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜: ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.'); + console.error('๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜: ํŒŒํŠธ๋„ˆ ๋“ฑ๋ก์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.', error); } }; - return (
    - - ํŒŒํŠธ๋„ˆ ๋“ฑ๋กํ•˜๊ธฐ - + ํŒŒํŠธ๋„ˆ ๋“ฑ๋กํ•˜๊ธฐ - setRepreName(e.target.value)} /> @@ -112,7 +115,8 @@ function Partner() { isRegiNumberValid={isRegiNumberValid} isRegiNumberIncomplete={isRegiNumberIncomplete} setIsInputTouched={setIsInputTouched} - isCheckingDuplicate={isCheckingDuplicate} + isDuplicateChecked={isDuplicateChecked} + setIsDuplicateChecked={setIsDuplicateChecked} /> @@ -129,16 +133,19 @@ function Partner() { placeholder="2023-00-00" type="date" value={openingDate} + max={currentDate} onChange={(e) => setOpeningDate(e.target.value)} /> - diff --git a/client/src/pages/PaymentSuccess.tsx b/client/src/pages/PaymentSuccess.tsx new file mode 100644 index 00000000..12c04f6b --- /dev/null +++ b/client/src/pages/PaymentSuccess.tsx @@ -0,0 +1,60 @@ +import { useState, useEffect } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { GiCarWheel } from 'react-icons/gi'; + +import AfterPayment from '../components/PaymentSuccess/AfterPayment'; + +function PaymentSuccess() { + // /reservations/verify + const API_URL = import.meta.env.VITE_APP_API_URL; + const [status, setStatus] = useState('loading'); + const [searchParams] = useSearchParams(); + const navigate = useNavigate(); + const reservationKey = searchParams.get('reservationKey'); + const orderId = searchParams.get('orderId'); + const accessToken = sessionStorage.getItem('Authorization'); + + const verifyFetch = async () => { + try { + const res = await fetch(`${API_URL}/reservation/payments?reservationKey=${reservationKey}&orderId=${orderId}`, { + method: 'POST', + headers: { + 'Authorization': accessToken + } + }) + if (res.ok) { + setStatus('success'); + } + else if (!res.ok) { + setStatus('fail'); + } + } + catch(error) { + console.error(error); + } + }; + + useEffect(() => { + if (!reservationKey || !orderId || !accessToken) { + navigate('/home'); + } + verifyFetch(); + }, []); + + switch(status) { + case 'loading': + return ( +
    + +
    ๊ฒฐ์ œ ์ค‘์ž…๋‹ˆ๋‹ค....
    +
    ํ™”๋ฉด์„ ๋ฒ—์–ด๋‚˜์ง€ ๋งˆ์„ธ์š”.
    +
    + ); + case 'success': + return + case 'fail' : + return + } +} + +export default PaymentSuccess; diff --git a/client/src/pages/Payments.tsx b/client/src/pages/Payments.tsx index d9a03a5c..f57667b0 100644 --- a/client/src/pages/Payments.tsx +++ b/client/src/pages/Payments.tsx @@ -1,25 +1,34 @@ import { useEffect, useRef } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; +import { useRecoilValue } from "recoil"; import { PaymentWidgetInstance, loadPaymentWidget, } from "@tosspayments/payment-widget-sdk"; import { nanoid } from "nanoid"; -import { useRecoilValue } from "recoil"; -import { totalPrice } from "../store/categoryDetailAtom"; +import { ReserFormState, totalPrice } from "../store/categoryDetailAtom"; const selector = "#payment-widget"; const clientKey = 'test_ck_dP9BRQmyarY0eEomwzZVJ07KzLNk'; -// const secretKey = 'test_sk_7DLJOpm5Qrl0eEYvlG0rPNdxbWnY'; const customerKey = "YbX2HuSlsC9uVJW6NMRMj"; function Payments() { + const API_URL = import.meta.env.VITE_APP_API_URL; + const accessToken = sessionStorage.getItem('Authorization'); + const location = useLocation(); + const navigate = useNavigate(); + const storeId = location.pathname.substring(15); const paymentWidgetRef = useRef(null); const paymentMethodsWidgetRef = useRef | null>(null); + PaymentWidgetInstance["renderPaymentMethods"] + > | null>(null); + const form = useRecoilValue(ReserFormState); const price = useRecoilValue(totalPrice); useEffect(() => { + if (!price) { + return navigate('/home'); + } (async () => { // ------ ๊ฒฐ์ œ์œ„์ ฏ ์ดˆ๊ธฐํ™” ------ // ๋น„ํšŒ์› ๊ฒฐ์ œ์—๋Š” customerKey ๋Œ€์‹  ANONYMOUS๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. @@ -30,7 +39,7 @@ function Payments() { // https://docs.tosspayments.com/reference/widget-sdk#renderpaymentmethods์„ ํƒ์ž-๊ฒฐ์ œ-๊ธˆ์•ก-์˜ต์…˜ const paymentMethodsWidget = paymentWidget.renderPaymentMethods( selector, - { value: 200 } + { value: price } ); // ------ ์ด์šฉ์•ฝ๊ด€ ๋ Œ๋”๋ง ------ @@ -58,7 +67,7 @@ function Payments() { }, [price]); return ( -
    +
    ์ด ๊ฒฐ์ œ๊ธˆ์•ก: {`${price.toLocaleString()}์›`}
    @@ -67,15 +76,24 @@ function Payments() { onClick={async () => { const paymentWidget = paymentWidgetRef.current; try { + const res = await fetch(`${API_URL}/reservations/${storeId}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': accessToken + }, + body: JSON.stringify({...form, totalPrice: price}) + }) + const json = await res.json(); // ------ '๊ฒฐ์ œํ•˜๊ธฐ' ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ๊ฒฐ์ œ์ฐฝ ๋„์šฐ๊ธฐ ------ // https://docs.tosspayments.com/reference/widget-sdk#requestpayment๊ฒฐ์ œ-์ •๋ณด await paymentWidget?.requestPayment({ orderId: nanoid(), - orderName: "ํ† ์Šค ํ‹ฐ์…”์ธ  ์™ธ 2๊ฑด", - customerName: "๊น€ํ† ์Šค", - customerEmail: "customer123@gmail.com", - successUrl: `${window.location.origin}/home`, - failUrl: `${window.location.origin}/fail`, + orderName: 'ActiOn', + // customerName: "๊น€ํ† ์Šค", + // customerEmail: "customer123@gmail.com", + successUrl: `${window.location.origin}/store/payment/success?storeId=${storeId}&reservationKey=${json.reservationKey}`, + failUrl: `${window.location.origin}/category/${storeId}`, }); } catch (error) { // ์—๋Ÿฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ diff --git a/client/src/pages/Register.tsx b/client/src/pages/Register.tsx index ad047ccc..264a64c5 100644 --- a/client/src/pages/Register.tsx +++ b/client/src/pages/Register.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import { ToastContainer, toast } from 'react-toastify'; import { StyleContainer, @@ -14,155 +15,251 @@ import { useNavigate } from 'react-router-dom'; function Register() { const url = import.meta.env.VITE_APP_API_URL; - // const CLIENT_ID = import.meta.env.VITE_APP_CLIENT_ID; - // const GOOGLE_REDIRECT_URI = import.meta.env.VITE_APP_REDIRECT_URI; const navigate = useNavigate(); // ์ดˆ๊ธฐ๊ฐ’ ์„ธํŒ… - ์•„์ด๋””, ๋‹‰๋„ค์ž„, ๋น„๋ฐ€๋ฒˆํ˜ธ, ๋น„๋ฐ€๋ฒˆํ˜ธํ™•์ธ, ์ด๋ฉ”์ผ, ์ „ํ™”๋ฒˆํ˜ธ, ์ƒ๋…„์›”์ผ //useRef ->๊ฐ์ฒด๊ด€๋ฆฌ.... - const [name, setName] = useState(''); - const [password, setPassword] = useState(''); - const [email, setEmail] = useState(''); - const [phone, setPhone] = useState(''); + const [isClicked, setIClicked] = useState(false); + const [formattedPhoneNumber, setFormattedPhoneNumber] = useState(''); + const [form, setForm] = useState({ + name: '', + password: '', + email: '', + phone: '', + }); // ์˜ค๋ฅ˜๋ฉ”์„ธ์ง€ ์ƒํƒœ ์ €์žฅ - const [emailMessage, setEmailMessage] = - useState('์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค.'); - const [nameMessage, setNameMessage] = useState('์˜๋ฌธ ์ˆซ์ž๋กœ๋งŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); - const [passwordMessage, setPasswordMessage] = useState( - '์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์—ฌ 8์ž ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.' - ); - const [passwordConfirmMessage, setPasswordConfirmMessage] = - useState('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค'); + const [emailMessage, setEmailMessage] = useState(''); + const [nameMessage, setNameMessage] = useState(''); + const [passwordMessage, setPasswordMessage] = useState(''); + const [passwordConfirmMessage, setPasswordConfirmMessage] = useState(''); + const [phoneMessage, setPhoneMessage] = useState(''); const [isSubmitDisabled, setIsSubmitDisabled] = useState(true); - // const setIsLoginState = useSetRecoilState(isLoginState); - - //์ด๋ฉ”์ผ ์œ ํšจ์„ฑ - const onChangeEmail = (e) => { - const currentEmail = e.target.value; - setEmail(currentEmail); - const emailRegExp = - /^[A-Za-z0-9_]+[A-Za-z0-9]*[@]{1}[A-Za-z0-9]+[A-Za-z0-9]*[.]{1}[A-Za-z]{1,3}$/; - if (emailRegExp.test(currentEmail)) { - setEmailMessage('์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค.'); - } else { - setEmailMessage('์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค.'); - } - }; + // onChange ํ•จ์ˆ˜ + const handleChange = (e) => { + const { name, value } = e.target; + if (name === 'name') { + const nameRegExp = /^[a-zA-Z0-9]{4,}$/; + if (!value) { + setNameMessage(''); + } else if (nameRegExp.test(value)) { + setNameMessage('์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค.'); + } else { + setNameMessage('์˜๋ฌธ, ์ˆซ์ž๋กœ๋งŒ 4์ž ์ด์ƒ์œผ๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + } + } else if (name === 'email') { + const emailRegExp = + /^[A-Za-z0-9_]+[A-Za-z0-9]*[@]{1}[A-Za-z0-9]+[A-Za-z0-9]*[.]{1}[A-Za-z]{1,3}$/; + if (!value) { + setEmailMessage(''); + } else if (value && emailRegExp.test(value)) { + setEmailMessage('์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค.'); + } else { + setEmailMessage('์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค.'); + } + } else if (name === 'password') { + const passwordRegExp = + /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/; + if (!value) { + setPasswordMessage(''); + } else if (passwordRegExp.test(value)) { + setPasswordMessage('์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค.'); + } else { + setPasswordMessage( + '์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์—ฌ 8์ž ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.' + ); + } + } else if (name === 'passwordConfirm') { + if (!value) { + setPasswordConfirmMessage(''); + return; + } else if (form.password === value) { + setPasswordConfirmMessage('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค.'); + } else { + setPasswordConfirmMessage('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.'); + } + } else if (name === 'phone') { + const phoneRegExp = /^(010)-[0-9]{4}-[0-9]{4}$/; + let formattedNumber = ''; - const onChangeName = (e) => { - const currentName = e.target.value; - setName(currentName); - const nameRegExp = /^(?=.*[a-zA-Z])(?=.*[0-9]).{4,25}$/; + formattedNumber = value.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'); + setFormattedPhoneNumber(formattedNumber); - if (nameRegExp.test(currentName)) { - setNameMessage('์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค.'); - } else { - setNameMessage('์˜๋ฌธ ์ˆซ์ž๋กœ๋งŒ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + if (!value) { + setPhoneMessage(''); + } else if (phoneRegExp.test(formattedNumber)) { + setPhoneMessage('์˜ฌ๋ฐ”๋ฅธ ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์ž…๋‹ˆ๋‹ค.'); + } else { + setPhoneMessage('์ „ํ™”๋ฒˆํ˜ธ์— -๋ฅผ ์ œ์™ธํ•˜๊ณ  ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.'); + } } + setForm({ ...form, [name]: value }); }; - const onChangePassword = (e) => { - const currentPassword = e.target.value; - setPassword(currentPassword); - const passwordRegExp = - /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/; - if (passwordRegExp.test(currentPassword)) { - setPasswordMessage('์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค.'); - } else { - setPasswordMessage( - '์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์—ฌ 8์ž ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.' - ); - } - }; - - const onChangePasswordConfirm = (e) => { - const currentPasswordConfirm = e.target.value; - if (password === currentPasswordConfirm) { - setPasswordConfirmMessage('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค'); + useEffect(() => { + // ๋ชจ๋“  ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ํ†ต๊ณผํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€์ž… ์ง„ํ–‰ํ•˜๊ธฐ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” + if ( + emailMessage === '์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค.' && + nameMessage === '์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค.' && + passwordMessage === '์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค.' && + passwordConfirmMessage === '๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค.' && + phoneMessage === '์˜ฌ๋ฐ”๋ฅธ ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹์ž…๋‹ˆ๋‹ค.' + ) { + setIsSubmitDisabled(false); } else { - setPasswordConfirmMessage('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค'); + setIsSubmitDisabled(true); } - }; - - const onChangePhone = (e) => { - const currentPhone = e.target.value; - setPhone(currentPhone); - }; + }, [ + emailMessage, + nameMessage, + passwordMessage, + passwordConfirmMessage, + phoneMessage, + ]); const handleSubmit = async (e) => { e.preventDefault(); + setIClicked(true); + if (isClicked) { + return; + } if (!isSubmitDisabled) { - await fetch(`${url}/signup`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - email: email, - password: password, - phoneNumber: phone, - nickname: name, - }), - }).then(() => navigate('/login')); + try { + const res = await fetch(`${url}/signup`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: form.email, + password: form.password, + phoneNumber: form.phone, + nickname: form.name, + }), + }); + if (res.ok) { + toast('ํšŒ์›๊ฐ€์ž…์„ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค !'); + setTimeout(() => { + navigate('/login'); + }, 2000); + } else if (res.status === 403) { + toast('๐Ÿšจ ์ค‘๋ณต๋œ ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค.'); + setTimeout(() => { + setIClicked(false); + }, 3000); + } else if (res.status === 409) { + toast('๐Ÿšจ ์ค‘๋ณต๋œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค.'); + setTimeout(() => { + setIClicked(false); + }, 3000); + } else if (res.status === 422) { + toast('๐Ÿšจ ์ค‘๋ณต๋œ ์ „ํ™”๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.'); + setTimeout(() => { + setIClicked(false); + }, 3000); + } + } catch (error) { + console.error('ํšŒ์›๊ฐ€์ž… ์š”์ฒญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค', error); + setTimeout(() => { + setIClicked(false); + }, 3000); + } } else { - alert('์กฐ๊ฑด์— ๋งž๊ฒŒ ํšŒ์›์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + alert('๐Ÿšจ ๊ฐ€์ž…์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•ด์ฃผ์„ธ์š” !'); + setTimeout(() => { + setIClicked(false); + }, 3000); } }; const handleGoogleSignup = async (e) => { e.preventDefault(); window.location.href = `${url}/oauth2/authorization/google`; - // 'https://accounts.google.com/o/oauth2/auth?' + - // `client_id=${CLIENT_ID}&` + - // `redirect_uri=${GOOGLE_REDIRECT_URI}&` + - // 'response_type=token&' + - // 'scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'; - // const parsedHash = new URLSearchParams(window.location.hash); - // console.log('2'); - // const accessToken = parsedHash.get('access_token'); - // sessionStorage.setItem('access_token', accessToken); - - // setIsLoginState(true); - // navigate('/home'); }; - useEffect(() => { - // ๋ชจ๋“  ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ํ†ต๊ณผํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€์ž… ์ง„ํ–‰ํ•˜๊ธฐ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” - if ( - emailMessage === '์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ์ž…๋‹ˆ๋‹ค.' && - nameMessage === '์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹‰๋„ค์ž„ ์ž…๋‹ˆ๋‹ค.' && - passwordMessage === '์•ˆ์ „ํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋‹ˆ๋‹ค.' && - passwordConfirmMessage === '๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค' - ) { - setIsSubmitDisabled(false); - } else { - setIsSubmitDisabled(true); + const handleKeyDown = (e) => { + if (e.key === 'Enter') { + handleSubmit(e); } - }, [emailMessage, nameMessage, passwordMessage, passwordConfirmMessage]); + }; return ( +
    - - {emailMessage} + + + {emailMessage} +
    - - {nameMessage} + + + {nameMessage} +
    - - {passwordMessage} + + + {passwordMessage} +
    @@ -170,10 +267,20 @@ function Register() { - {passwordConfirmMessage} + + {passwordConfirmMessage} +
    @@ -181,11 +288,22 @@ function Register() { - ์ „ํ™”๋ฒˆํ˜ธ๋Š” - ๋ฅผ ๋„ฃ๊ณ  ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”. + + {phoneMessage} +
    diff --git a/client/src/pages/ReservationCheck.tsx b/client/src/pages/ReservationCheck.tsx index b232bc3b..1980fd80 100644 --- a/client/src/pages/ReservationCheck.tsx +++ b/client/src/pages/ReservationCheck.tsx @@ -1,4 +1,7 @@ -import { reservationCheckdummy } from "../dummy/reservationcheckdummy"; +import { useEffect, useState } from "react"; +import{ GiBoatHorizon } from 'react-icons/gi'; +import NothingComponent from "../components/MyPage/NothingComponent"; +import LoadingComponent from '../components/Loading/LoadingComponent'; import { ResCheckContainer, ResCheckTitle, @@ -15,73 +18,132 @@ import { ResButtonsContainer, ButtonStyle, NoButtons, + NoReservation, + ButtonReview, } from '../styles/MyPage/ReservationCheck'; +import { Link } from "react-router-dom"; function ReservationCheck() { - const { data } = reservationCheckdummy; + const API_URL = import.meta.env.VITE_APP_API_URL; + const [data, setData] = useState([]); + const [loading, setLoading] = useState(true); + const accessToken = sessionStorage.getItem('Authorization'); + const reservationDelete = async (reservationId: number) => { + const confirmDelete = confirm("์ •๋ง ์˜ˆ์•ฝ์„ ์ทจ์†Œํ•˜๊ฒ ์Šต๋‹ˆ๊นŒ?"); + const res = confirmDelete && await fetch(`${API_URL}/reservations/${reservationId}`, { + method: 'DELETE', + headers: { + 'Authorization': accessToken + } + }); + if (res.status === 204) { + window.location.reload(); + } + } + + const reservationListFetch = async () => { + const res = await fetch(`${API_URL}/mypage/reservations`, { + method: 'GET', + headers: { + 'Authorization': accessToken + } + }); + const json = await res.json(); + setData(json.data); + setLoading(false); + } + + useEffect(() => { + reservationListFetch(); + }, []) return ( ์˜ˆ์•ฝ ๋‚ด์—ญ ์กฐํšŒ - {data.map((reservation) => ( - - - - - - - - -
    - {reservation.reservationStatus} -
    -
    - -
    - {reservation.reservationDate} -
    -
    - {reservation.storeName} - ์ด {reservation.itemCount}๊ฐœ ์ƒํ’ˆ ๊ฒฐ์ œ -
    -
    - ๊ฒฐ์ œ๊ธˆ์•ก: {reservation.totalPrice}์› -
    -
    - - {reservation.reservationStatus === "์˜ˆ์•ฝ ์™„๋ฃŒ" && ( + {loading ? ( +
    + +
    + ) : data.length === 0 ? ( + + + + + ) : ( + data && data.map((reservation, idx) => ( + + + + + + + + +
    + {reservation.reservationStatus} +
    +
    + +
    + {reservation.reservationDate} +
    - ์˜ˆ์•ฝ ์ˆ˜์ • - ์˜ˆ์•ฝ ์‚ญ์ œ + {reservation.storeName} + ์ด {reservation.itemCount}๊ฐœ ์ƒํ’ˆ ๊ฒฐ์ œ
    - )} - {(reservation.reservationStatus === "์˜ˆ์•ฝ ์ทจ์†Œ" || reservation.reservationStatus === "์ด์šฉ ์™„๋ฃŒ") && (
    - + ๊ฒฐ์ œ๊ธˆ์•ก: {Number(reservation.totalPrice).toLocaleString()}์›
    - )} -
    -
    -
    - ))} + + + {reservation.reservationStatus === "์˜ˆ์•ฝ ํ™•์ •" && ( +
    + + ์ƒ์„ธ ํ™•์ธ + + {reservationDelete(reservation.reservationId)}} + >์˜ˆ์•ฝ ์ทจ์†Œ +
    + )} + {reservation.reservationStatus === "์˜ˆ์•ฝ ์ทจ์†Œ" && ( +
    + +
    + )} + {reservation.reservationStatus === "์ด์šฉ ์™„๋ฃŒ" && ( + + ๋ฆฌ๋ทฐ ์ž‘์„ฑ + + )} +
    + + + )) + )}
    ); } diff --git a/client/src/pages/ReservationModify.tsx b/client/src/pages/ReservationModify.tsx index f3e2ba8d..a2925b3a 100644 --- a/client/src/pages/ReservationModify.tsx +++ b/client/src/pages/ReservationModify.tsx @@ -1,4 +1,5 @@ -import { reservation } from '../dummy/reservation'; +import { useEffect, useState } from 'react'; + import { ReservationContainer, ReservationTitle, @@ -12,59 +13,187 @@ import { AmountBox, RuleBox, PaymentButton, + InputContainer, + ModifyButton, + UseCompleteButton, } from '../styles/Reservation/ReservationModify'; +import { useNavigate, useSearchParams } from 'react-router-dom'; + +type CProps = { + storeName: string; + reservationDate: string; + totalPrice: number; + reservationName: string; + reservationPhone: string; + reservationEmail: string; + reservationItems: any[]; +}; function ReservationModify() { + const url = import.meta.env.VITE_APP_API_URL; + const initialReservation = { + storeName: '', + reservationDate: '', + totalPrice: 0, + reservationName: '', + reservationPhone: '', + reservationEmail: '', + reservationItems: [], + }; + + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const reservationId = searchParams.get('reservationId'); + + const [data, setData] = useState(initialReservation); + const [name, setName] = useState(''); + const [phone, setPhone] = useState(''); + const [email, setEmail] = useState(''); + + const HandlerName = (e) => { + setName(e.currentTarget.value); + }; + const HandlerPhone = (e) => { + const value = e.target.value; + const phoneNumberPattern = /(\d{3})(\d{3,4})(\d{4})/; + let contactVerify = value.replace(/[^0-9]/g, ''); + if (contactVerify.length >= 11) { + contactVerify = contactVerify.replace(phoneNumberPattern, '$1-$2-$3'); + } + if (contactVerify.length >= 14) { + return; + } + return setPhone(contactVerify); + }; + const HandlerEmail = (e) => { + setEmail(e.currentTarget.value); + }; + + //์˜ˆ์•ฝ์ž ์ •๋ณด๋ณ€๊ฒฝ + const handleModify = () => { + try { + fetch(`${url}/reservations/${reservationId}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + Authorization: sessionStorage.getItem('Authorization'), + }, + body: JSON.stringify({ + reservationName: name, + reservationPhone: phone, + reservationEmail: email, + }), + }); + alert('์ˆ˜์ •์ด ์™„๋ฃŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค'); + location.reload(); + } catch (error) { + console.error(error); + } + }; + + //์˜ˆ์•ฝ ์ทจ์†Œ + const handleCancel = () => { + if (confirm('์ •๋ง๋กœ ์˜ˆ์•ฝ์„ ์ทจ์†Œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?') == true) { + //true๋Š” ํ™•์ธ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์ฝ”๋“œ ์ž‘์„ฑ + navigate('/my/order'); + } + try { + fetch(`${url}/reservations/${reservationId}`, { + method: 'DELETE', + headers: { Authorization: sessionStorage.getItem('Authorization') }, + }); + navigate('/my/order'); // ์˜ˆ์•ฝ๋‚ด์—ญ ์กฐํšŒ ํŽ˜์ด์ง€๋กœ ์ด๋™ + window.location.reload(); + } catch (error) { + console.error(error); + } + }; + + //์ด์šฉ ์™„๋ฃŒ + const useCompleteHandler = () => { + const useConfirm = confirm('์ •๋ง ์ด์šฉ ์™„๋ฃŒ ์ฒ˜๋ฆฌํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?'); + if (!useConfirm) { + return; + } + try { + fetch(`${url}/reservationsUsed/${reservationId}`, { + method: 'POST', + headers: { Authorization: sessionStorage.getItem('Authorization') }, + }); + window.location.href = '/my/order'; + } catch (error) { + console.error(error); + } + }; + + //Get + useEffect(() => { + const fetchData = () => { + fetch(`${url}/reservations/${reservationId}`, { + headers: { Authorization: sessionStorage.getItem('Authorization') }, + }) + .then((res) => res.json()) + .then((data) => { + setData(data); + setName(data.reservationName); + setPhone(data.reservationPhone); + setEmail(data.reservationEmail); + }); + }; + fetchData(); + }, [reservationId]); + return ( -
    +
    - {reservation.storeName} + {data.storeName} ์˜ˆ์•ฝ์ •๋ณด -
    - 1. ๊ฒฐ์ œํ•œ ์ƒํ’ˆ - {reservation.reservationItems.map((el) => { - return ( -
    - {el.item} x {el.ticketCount} -
    - ); - })} - 2. ์˜ˆ์•ฝ ๋‚ ์งœ - {reservation.reservationDate} - - ์˜ˆ์•ฝ์ž ์ •๋ณด - -
    - ์˜ˆ์•ฝ์ž -
    - - ํ•„์ˆ˜ -
    -
    -
    - ์—ฐ๋ฝ์ฒ˜ -
    - - ํ•„์ˆ˜ -
    -
    -
    - ์ด๋ฉ”์ผ + 1. ๊ฒฐ์ œํ•œ ์ƒํ’ˆ + {data.reservationItems.map((el) => { + return ( +
  • + {el.itemName} x {el.ticketCount} +
  • + ); + })} + 2. ์˜ˆ์•ฝ ๋‚ ์งœ + {data.reservationDate} + + ์˜ˆ์•ฝ์ž ์ •๋ณด + ์ˆ˜์ •ํ•˜๊ธฐ + + ์˜ˆ์•ฝ์ž +
    + ํ•„์ˆ˜
    -
    -
    + + + ์—ฐ๋ฝ์ฒ˜ +
    + + ํ•„์ˆ˜ +
    +
    + + ์ด๋ฉ”์ผ + + +
    @@ -72,11 +201,11 @@ function ReservationModify() {
    ์ฃผ๋ฌธ๊ธˆ์•ก
    -
    {reservation.totalPrice.toLocaleString('ko-KR')} ์›
    +
    {data.totalPrice.toLocaleString('ko-KR')} ์›
    ์ด ๊ฒฐ์ œ๊ธˆ์•ก
    -
    {reservation.totalPrice.toLocaleString('ko-KR')} ์›
    +
    {data.totalPrice.toLocaleString('ko-KR')} ์›
    ์˜ˆ์•ฝ์ทจ์†Œ ๊ทœ์ •
    @@ -86,7 +215,12 @@ function ReservationModify() {
  • ๋ถ€๋ถ„ ์‚ฌ์šฉ ๋ฐ ๋ถ€๋ถ„ ์ทจ์†Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • - ์˜ˆ์•ฝ์ทจ์†Œ + + ์˜ˆ์•ฝ ์ทจ์†Œ + + + ์ด์šฉ ์™„๋ฃŒ +
    ); diff --git a/client/src/pages/StoreAdd.tsx b/client/src/pages/StoreAdd.tsx index 69b8f9f5..4068276e 100644 --- a/client/src/pages/StoreAdd.tsx +++ b/client/src/pages/StoreAdd.tsx @@ -1,55 +1,75 @@ import { useEffect, useState } from 'react'; -import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; -import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil"; +import { useLocation, useSearchParams } from 'react-router-dom'; +import { useRecoilState, useSetRecoilState } from 'recoil'; -import { AddBtn, StoreAddSection } from "../styles/StoreAdd/StoreAdd"; -import AddProduct from "../components/StoreAdd/AddProduct"; -import AddImages from "../components/StoreAdd/AddImages"; -import StoreAddTop from "../components/StoreAdd/StoreAddTop"; +import { AddBtn, StoreAddSection } from '../styles/StoreAdd/StoreAdd'; +import AddProduct from '../components/StoreAdd/AddProduct'; +import AddImages from '../components/StoreAdd/AddImages'; +import StoreAddTop from '../components/StoreAdd/StoreAddTop'; import { DetailImgsState, FirstImgState, SendDetailImgsState, SendFirstImgState, StoreformState, - pageTitleState + pageTitleState, } from '../store/storeAddAtom'; +import { StoreAddFormType } from '../intefaces/StoreAdd'; function StoreAdd() { const API_URL = import.meta.env.VITE_APP_API_URL; const [form, setForm] = useRecoilState(StoreformState); + const [fetchImgsCount, setFetchImgsCount] = useState(0); const [btnText, setBtnText] = useState(true); const [isLoading, setIsLoading] = useState(false); - const sendFirstImg = useRecoilValue(SendFirstImgState); - const sendDetailImgs = useRecoilValue(SendDetailImgsState); - const setPageTitle = useSetRecoilState(pageTitleState); + const [sendFirstImg, setSendFirstImg] = useRecoilState(SendFirstImgState); + const [sendDetailImgs, setSendDetailImgs] = useRecoilState(SendDetailImgsState); const setFirstImg = useSetRecoilState(FirstImgState); const setDetailImgs = useSetRecoilState(DetailImgsState); + const setPageTitle = useSetRecoilState(pageTitleState); const location = useLocation(); - const navigate = useNavigate(); const [searchParams] = useSearchParams(); const storeId = searchParams.get('store_id'); const accessToken = sessionStorage.getItem('Authorization'); - const formChangeHandler = (e) => { // ์Šค์œ„์น˜๋ฌธ์œผ๋กœ ์ถ”์ฒœ - if (e.target.name === "storeName") { - setForm({...form, storeName: e.target.value}); - } - else if (e.target.name === "body") { - setForm({...form, body: e.target.value}); - } - else if (e.target.name === "kakao") { - setForm({...form, kakao: e.target.value}); - } - else if (e.target.name === "contact") { - setForm({...form, contact: e.target.value}); - } - else if (e.target.name === "category") { - setForm({...form, category: e.target.value}); + const formChangeHandler = (e: React.ChangeEvent) => { + // ์Šค์œ„์น˜๋ฌธ์œผ๋กœ ์ถ”์ฒœ + const name = e.target.name; + const value = e.target.value; + switch (name) { + case 'storeName': + return setForm({ ...form, storeName: value }); + case 'body': + return setForm({ ...form, body: value }); + case 'kakao': + const kakaoVerify = value.replace(/[^a-zA-Z0-9]/g, ''); + return setForm({ ...form, kakao: kakaoVerify }); + case 'contact': + const phoneNumberPattern = /(\d{3})(\d{3,4})(\d{4})/; + let contactVerify = value.replace(/[^0-9]/g, ''); + if (contactVerify.length >= 11) { + contactVerify = contactVerify.replace(phoneNumberPattern, '$1-$2-$3'); + } + if (contactVerify.length >= 14) { + return; + } + return setForm({ ...form, contact: contactVerify }); + case 'category': + return setForm({ ...form, category: value }); } }; const storeAddPost = async () => { + const inputVerify = formVerify(form); + if (!inputVerify) { + return; + } + if (!sendFirstImg) { + return alert('๋Œ€ํ‘œ์‚ฌ์ง„์„ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”.'); + } + if (sendDetailImgs.length < 3) { + return alert('์ƒ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ตœ์†Œ 3์žฅ ์ด์ƒ ๋“ฑ๋กํ•ด ์ฃผ์„ธ์š”.'); + } const imgForm = new FormData(); sendDetailImgs.forEach((img) => imgForm.append(`images`, img)); imgForm.append('thumbnailImage', sendFirstImg); @@ -59,9 +79,9 @@ function StoreAdd() { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': accessToken + Authorization: accessToken, }, - body: JSON.stringify(form) + body: JSON.stringify(form), }); if (!res.ok) { setIsLoading((prev) => !prev); @@ -71,21 +91,20 @@ function StoreAdd() { const imgRes = await fetch(`${API_URL}/storeImages/${json.storeId}`, { method: 'POST', headers: { - 'Authorization': accessToken + Authorization: accessToken, }, - body: imgForm + body: imgForm, }); if (!imgRes.ok) { setIsLoading((prev) => !prev); return alert('์—…์ฒด ์ด๋ฏธ์ง€ ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'); } setIsLoading((prev) => !prev); - navigate(`/category/${json.storeId}`); + window.location.href = `/category/${json.storeId}`; + } catch (error) { + console.error(error); } - catch(error) { - console.log(error); - } - } + }; const storeEditFetch = async (storeId: string) => { try { @@ -98,29 +117,34 @@ function StoreAdd() { kakao: json.kakao, contact: json.contact, category: json.category, - items: json.items - }) + items: json.items, + }); setFirstImg(json.storeImages[0]); setDetailImgs(json.storeImages.slice(1)); + setFetchImgsCount(json.storeImages.slice(1).length); + } catch (error) { + console.error(error); } - catch(error) { - console.log(error); - } - } + }; const storeEditPatch = async (storeId: string) => { + const inputVerify = formVerify(form); + if (!inputVerify) { + return; + } const imgForm = new FormData(); sendDetailImgs.forEach((img) => imgForm.append(`images`, img)); imgForm.append('thumbnailImage', sendFirstImg); try { setIsLoading((prev) => !prev); - const res = await fetch(`${API_URL}/stores/${storeId}`, { // ๋™๊ธฐ ํ•„์š”์—†์Œ + const res = await fetch(`${API_URL}/stores/${storeId}`, { + // ๋™๊ธฐ ํ•„์š”์—†์Œ method: 'PATCH', headers: { 'Content-Type': 'application/json', - 'Authorization': accessToken + Authorization: accessToken, }, - body: JSON.stringify(form) + body: JSON.stringify(form), }); if (!res.ok) { setIsLoading((prev) => !prev); @@ -129,22 +153,35 @@ function StoreAdd() { const imgRes = await fetch(`${API_URL}/storeImages/${storeId}`, { method: 'PATCH', headers: { - 'Authorization': accessToken + Authorization: accessToken, }, - body: imgForm + body: imgForm, }); if (!imgRes.ok) { setIsLoading((prev) => !prev); return alert('์—…์ฒด ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'); } - navigate(`/category/${storeId}`); - } - catch(error) { - console.log(error); + setIsLoading((prev) => !prev); + window.location.href = `/category/${storeId}`; + } catch (error) { + console.error(error); } - } + }; useEffect(() => { + setForm({ + storeName: '', + body: '', + address: '', + kakao: '', + contact: '', + category: '', + items: [], + }); + setFirstImg(null); + setDetailImgs([]); + setSendFirstImg(null); + setSendDetailImgs([]); const path = location.pathname.substring(6); if (path === '/edit') { setPageTitle('์—…์ฒด ์ˆ˜์ •ํ•˜๊ธฐ'); @@ -155,24 +192,57 @@ function StoreAdd() { return ( - {isLoading ? -
    ์—…์ฒด ๋“ฑ๋ก/์ˆ˜์ • ์ค‘์ž…๋‹ˆ๋‹ค...
    : + {isLoading ? ( +
    + ์—…์ฒด ๋“ฑ๋ก/์ˆ˜์ • ์ค‘์ž…๋‹ˆ๋‹ค... +
    + ) : ( <> - - { - if (btnText) { - storeAddPost(); - } - else { - storeEditPatch(storeId); - } - }}>{btnText ? '๋“ฑ๋กํ•˜๊ธฐ' : '์ˆ˜์ •ํ•˜๊ธฐ'} + + { + if (btnText) { + storeAddPost(); + } else { + storeEditPatch(storeId); + } + }} + > + {btnText ? '๋“ฑ๋กํ•˜๊ธฐ' : '์ˆ˜์ •ํ•˜๊ธฐ'} + - } + )}
    ); } export default StoreAdd; + +const formVerify = (form: StoreAddFormType) => { + if (!form.storeName) { + alert('์—…์ฒด๋ช…์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + return false; + } else if (!form.body) { + alert('์†Œ๊ฐœ๊ธ€์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + return false; + } else if (!form.address) { + alert('์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”.'); + return false; + } else if (!form.kakao) { + alert('์นด์นด์˜คํ†ก ID๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + return false; + } else if (!form.contact || form.contact.length !== 13) { + alert('์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.'); + return false; + } else if (!form.category) { + alert('์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”.'); + return false; + } else if (!form.items.length) { + alert('์ƒํ’ˆ์„ 1๊ฐœ ์ด์ƒ ๋“ฑ๋กํ•ด์ฃผ์„ธ์š”.'); + return false; + } + return true; +}; diff --git a/client/src/pages/StoreCheck.tsx b/client/src/pages/StoreCheck.tsx index c51b1646..d4e0312c 100644 --- a/client/src/pages/StoreCheck.tsx +++ b/client/src/pages/StoreCheck.tsx @@ -1,4 +1,6 @@ -import { storecheckdummy } from '../dummy/storecheckdummy'; +import { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { MdOutlineAddHome } from 'react-icons/md'; import { StoreButtonStyle, ButtonsContainer, @@ -10,38 +12,123 @@ import { StoreCheckTitle, StoreInfoContainer, StoreName, + NoStores, } from '../styles/MyPage/StoreCheck'; +import NothingComponent from '../components/MyPage/NothingComponent'; +// import Loading from '../components/Loading/Loading'; function StoreCheck() { - const { stores } = storecheckdummy; + const APIURL = import.meta.env.VITE_APP_API_URL; + const [storesData, setStoresData] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetchStores(); + },[]); + + const fetchStores = async () => { + try { + const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const res = await fetch(`${APIURL}/mystores`, { + method: 'GET', + headers: { + 'Authorization': ACCESS_TOKEN + } + }); + + if(res.ok) { + const data = await res.json(); + setStoresData(data.stores); + } + } catch (error) { + console.error('์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', error); + } finally { + setLoading(false); + } + }; + + // const deleteStore = async (storeId) => { + // try { + // const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + // const res = await fetch(`${APIURL}/stores/${storeId}`, { + // method: 'DELETE', + // headers: { + // 'Authorization': ACCESS_TOKEN + // } + // }); + + // if(res.ok) { + // console.log('์—…์ฒด ์‚ญ์ œ ์™„๋ฃŒ'); + // setStoresData((prevStoresData) => + // prevStoresData.filter((store) => store.storeId !== storeId) + // ); + // } else { + // console.error('์—…์ฒด ์‚ญ์ œ ์‹คํŒจ', res.status); + // } + // } catch (error) { + // console.error('์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', error); + // } + // }; + + const navigate = useNavigate(); + + const handleEditClick = (storeId) => { + navigate(`/store/edit?store_id=${storeId}`); + }; + + const handleAddClick = () => { + navigate(`/store/add`); + }; + + const handleStoreNameClick = (storeId) => { + navigate(`/category/${storeId}`); + }; const handleDeleteClick = () => { - alert('์ •๋ง ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊ฐ€?'); + alert('์—…์ฒด ์‚ญ์ œ๋Š” ํŒŒํŠธ๋„ˆ ์„ผํ„ฐ์— ๋ฌธ์˜์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.'); + // if (window.confirm('์ •๋ง ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?')) { + // deleteStore(storeId); + // } }; return ( - ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ - {stores.map((store) => ( - - - - - - - -
    - {store.storeName} -
    - - ์—…์ฒด ์ˆ˜์ • - - ์—…์ฒด ์‚ญ์ œ - - -
    -
    - ))} +
    + ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ + +
    + {loading ? ( +
    ๋กœ๋”ฉ์ค‘์ž…๋‹ˆ๋‹ค....
    + ) : storesData.length === 0 ? ( + + + + + ) : ( + storesData.map((store) => ( + + + + + + + +
    + handleStoreNameClick(store.storeId)}>{store.storeName} +
    + + handleEditClick(store.storeId)}>์—…์ฒด ์ˆ˜์ • + handleDeleteClick()}> + ์—…์ฒด ์‚ญ์ œ + + +
    +
    + )) + )}
    ); } diff --git a/client/src/pages/Welcome.tsx b/client/src/pages/Welcome.tsx index ec7d7091..2e55a2f7 100644 --- a/client/src/pages/Welcome.tsx +++ b/client/src/pages/Welcome.tsx @@ -1,40 +1,31 @@ -import { useNavigate } from 'react-router-dom'; - -import logo from '../assets/logo.svg'; -import welcome from '../assets/welcome.svg'; -import { Button, Blue, Inrto } from '../styles/Welcome/Welcome'; - -function Welcome() { - const navigate = useNavigate(); - - const handleButton = () => { - setTimeout(() => { - navigate('/home'); - }, 300); - }; +import tw from 'tailwind-styled-components'; +import 'tailwindcss/tailwind.css'; +import Page1 from '../components/IntroPage/Page1'; +import WelcomeLayout from '../components/Layout/WelcomeLayout'; +import Page2 from '../components/IntroPage/Page2'; +import Page3 from '../components/IntroPage/Page3'; +import Page4 from '../components/IntroPage/Page4'; +import Page5 from '../components/IntroPage/Page5'; +const Welcome = () => { return ( -
    -
    - -
    -
    -
    - - ๋‹ค์–‘ํ•œ ๋ ˆ์ € ์„œ๋น„์Šค๋ฅผ
    - ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” -
    ์•กํ‹ฐ์˜จ์ž…๋‹ˆ๋‹ค. -
    - -
    -
    -
    + + + + + + + + } + /> ); -} +}; + +const WelcomeContainer = tw.div` + pt-60px + overflow-hidden +`; export default Welcome; diff --git a/client/src/pages/WishList.tsx b/client/src/pages/WishList.tsx index 0062a38d..80adc592 100644 --- a/client/src/pages/WishList.tsx +++ b/client/src/pages/WishList.tsx @@ -1,67 +1,76 @@ - -// import { useSearchParams } from 'react-router-dom'; -// import { useEffect } from 'react'; -// import { useRecoilState } from 'recoil'; -// import { CategoryData } from '../store/categoryAtom'; - -// import CategoryCard from '../components/Categorybar/CategoryCard'; -// import search from '../assets/search.svg'; +//wishlist +import { useEffect, useState } from 'react'; +import CategoryCard from '../components/Categorybar/CategoryCard'; +import NothingComponent from '../components/MyPage/NothingComponent'; +import LoadingComponent from '../components/Loading/LoadingComponent'; +import search from '../assets/search.svg'; import { - // NoWishList, - // NoWishImgSize, - // NoWishTitle, + NoWishList, WishContainer, - // WishCountTitle, + WishCountTitle, + NoWishImgSize, } from '../styles/MyPage/WishList'; function WishList() { - // const [searchParams] = useSearchParams(); - // const categoryName = searchParams.get('category_name'); - // const sort = searchParams.get('sort'); - - // const [category, setCategory] = useRecoilState(CategoryData); + const APIURL = import.meta.env.VITE_APP_API_URL; + const [wishlist, setWishList] = useState([]); + const [loading, setLoading] = useState(true); - // const getLikedCards = () => { - // return category.data.filter((el) => el.isLike); - // }; + useEffect(() => { + fetchWishList(); + }, []); - // const storesFetch = async () => { - // const res = await fetch( - // `/stores?category=${categoryName}&sort_field=${sort}` - // ); - // const data = await res.json(); - // setCategory(data); - // }; + const fetchWishList = async () => { + try { + const ACCESS_TOKEN = sessionStorage.getItem('Authorization'); + const res = await fetch(`${APIURL}/mypage/wishlist`, { + method: 'GET', + headers: { + 'Authorization': ACCESS_TOKEN + } + }); - // useEffect(() => { - // storesFetch(); - // }, [categoryName, sort]); + if (res.ok) { + const data = await res.json(); + setWishList(data.stores); + } else { + console.error('์œ„์‹œ๋ฆฌ์ŠคํŠธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.', res.status); + } + } catch (error) { + console.error('์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', error); + } finally { + setLoading(false); + } + }; return ( - {/* {getLikedCards().length === 0 ? ( + {loading ? ( +
    + +
    + ) : wishlist.length === 0 ? ( - - ์•„์ง ๋‹ด๊ธด ์œ„์‹œ๋ฆฌ์ŠคํŠธ๊ฐ€ ์—†๋„ค์š”! - -

    ๊ด€์‹ฌ๊ฐ€๋Š” ์ƒํ’ˆ์„ ์ฐพ์•„ โ™ก๋ฅผ ๋ˆŒ๋Ÿฌ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์ฐจ๊ณก์ฐจ๊ณก ์Œ“์•„๋ณผ๊นŒ์š”?

    + +
    ) : ( -
    +
    - ์œ„์‹œ ์ƒํ’ˆ {getLikedCards().length}๊ฐœ + ์œ„์‹œ ์ƒํ’ˆ {wishlist.length}๊ฐœ
    -
    - {getLikedCards().map((el) => { - return ; - })} -
    + {wishlist + .filter((item) => item.isLike) // Filter out items with isLike: false + .map((item) => ( + + ))}
    - - )} */} - + )} ); } diff --git a/client/src/router/CategoryRouter.tsx b/client/src/router/CategoryRouter.tsx index 09fe886b..f67f63ba 100644 --- a/client/src/router/CategoryRouter.tsx +++ b/client/src/router/CategoryRouter.tsx @@ -1,4 +1,5 @@ import { Route, Routes } from 'react-router-dom'; +import { motion } from 'framer-motion'; import CategoryPage from '../pages/CategoryPage'; import CategoryDetail from '../pages/CategoryDetail'; @@ -6,21 +7,33 @@ import CategoryLayout from '../components/Layout/CategoryLayout'; import FooterLayout from '../components/Layout/FooterLayout'; import HeaderLayout from '../components/Layout/HeaderLayout'; import Payments from '../pages/Payments'; +import PaymentSuccess from '../pages/PaymentSuccess'; function CategoryRouter() { return ( - - }> - }> - }> - } /> - } /> + + + }> + }> + }> + } /> + } /> + + } /> + } /> - } /> - - } /> - + } /> + + ); } diff --git a/client/src/router/MainRouter.tsx b/client/src/router/MainRouter.tsx index 23c69ddd..29e30599 100644 --- a/client/src/router/MainRouter.tsx +++ b/client/src/router/MainRouter.tsx @@ -1,4 +1,6 @@ import { Routes, Route } from 'react-router-dom'; +import { motion } from 'framer-motion'; + import Welcome from '../pages/Welcome'; import Home from '../pages/Home'; import Login from '../pages/Login'; @@ -10,19 +12,29 @@ import HeaderLayout from '../components/Layout/HeaderLayout'; function MainRouter() { return ( - - } /> - }> - }> - } /> - }> - } /> - } /> - } /> + + + } /> + }> + }> + } /> + }> + } /> + } /> + } /> + - - + + ); } diff --git a/client/src/router/MyRouter.tsx b/client/src/router/MyRouter.tsx index 68078ad2..ae56e8f4 100644 --- a/client/src/router/MyRouter.tsx +++ b/client/src/router/MyRouter.tsx @@ -1,4 +1,5 @@ import { Route, Routes } from 'react-router-dom'; +import { motion } from 'framer-motion'; import MyPage from '../pages/MyPage'; import ReservationModify from '../pages/ReservationModify'; @@ -12,21 +13,31 @@ import SideBarLayout from '../components/Layout/SideBarLayout'; function MyRouter() { return ( - - }> - }> - }> - } /> - } /> - } /> - } /> + + + }> + }> + }> + } /> + } /> + } /> + } /> + + } /> + } /> + } /> - } /> - } /> - } /> - - + + ); } diff --git a/client/src/store/categoryAtom.ts b/client/src/store/categoryAtom.ts index 89d5c720..d2dbdbac 100644 --- a/client/src/store/categoryAtom.ts +++ b/client/src/store/categoryAtom.ts @@ -1,9 +1,13 @@ import { atom } from 'recoil'; +import { recoilPersist } from 'recoil-persist'; export interface CategoryData { pageInfo: { storeCount: number }[]; data: any[]; } + +const { persistAtom } = recoilPersist(); + export const categoryData = atom({ key: 'categoryData', default: { @@ -15,4 +19,5 @@ export const categoryData = atom({ export const Heart = atom({ key: 'Heart', default: false, + effects_UNSTABLE: [persistAtom], }); diff --git a/client/src/store/categoryDetailAtom.ts b/client/src/store/categoryDetailAtom.ts index 9cdee5ce..c12aa94c 100644 --- a/client/src/store/categoryDetailAtom.ts +++ b/client/src/store/categoryDetailAtom.ts @@ -26,8 +26,15 @@ export const CategoryDetailState = atom({ }) export const ReserFormState = atom({ - key: 'ReservationFormState', - default: {} as reserFormType, + key: 'ReserFormState', + default: { + reservationName: '', + reservationPhone: '', + reservationEmail: '', + reservationDate: '', + reservationItems: [], + totalPrice: 0 + } as reserFormType, }); export const itemsState = atom({ diff --git a/client/src/store/dropdownAtom.ts b/client/src/store/dropdownAtom.ts new file mode 100644 index 00000000..b2b4cdb3 --- /dev/null +++ b/client/src/store/dropdownAtom.ts @@ -0,0 +1,10 @@ +import { atom } from 'recoil'; +import { recoilPersist } from 'recoil-persist'; + +const { persistAtom } = recoilPersist(); + +export const open = atom({ + key: 'open', + default: false, + effects_UNSTABLE: [persistAtom], +}); diff --git a/client/src/styles/Category/CategoryPage.ts b/client/src/styles/Category/CategoryPage.ts index 7080f336..497b2c18 100644 --- a/client/src/styles/Category/CategoryPage.ts +++ b/client/src/styles/Category/CategoryPage.ts @@ -4,6 +4,7 @@ export const Style = tw.div` flex flex-col min-h-[80vh] + mb-[70px] `; export const CategoryContainer = tw.section` flex @@ -29,3 +30,21 @@ export const Category = tw.div` items-center relative `; + +export const TopBtn = tw.div` + fixed + right-[30px] + bottom-[40px] + w-[50px] + h-[50px] + rounded-full + text-white + bg-[#4771B7] + animate-topbounce +`; + +export const BtnWrapper = tw.div` + flex + flex-col + items-center +`; diff --git a/client/src/styles/CategoryDetail/DetailContent.ts b/client/src/styles/CategoryDetail/DetailContent.ts index 60fb89ac..79fd5ec5 100644 --- a/client/src/styles/CategoryDetail/DetailContent.ts +++ b/client/src/styles/CategoryDetail/DetailContent.ts @@ -8,15 +8,22 @@ export const DetailCategoryName = tw.div` export const DetailTitle = tw.div` text-3xl font-bold border-b-[1px] border-[#4771B7] - pb-3 mb-10 + pb-3 mb-5 `; export const ImgBox = tw.div` flex flex-wrap justify-between - w-[570px] + w-[600px] mx-auto `; +export const DetailImg = tw.img` + w-[600px] h-[400px] + object-cover + rounded-[5px] + duration-1000 +`; + export const ThumbnailImg = tw.img` w-[570px] h-[400px] mb-2 diff --git a/client/src/styles/CategoryDetail/PaymentInfo.ts b/client/src/styles/CategoryDetail/PaymentInfo.ts index 70730f70..92bc515e 100644 --- a/client/src/styles/CategoryDetail/PaymentInfo.ts +++ b/client/src/styles/CategoryDetail/PaymentInfo.ts @@ -2,7 +2,7 @@ import tw from "tailwind-styled-components"; export const PaymentInfoBox = tw.section` sticky top-10 - w-[300px] h-[600px] + w-[300px] h-[635px] border-[1px] border-[#4771B7] rounded-[5px] mt-10 ml-20 font-medium @@ -16,7 +16,7 @@ export const AmountBox = tw.div` `; export const RuleBox = tw.div` - w-[250px] h-[135px] + w-[250px] h-[170px] bg-[#E7EDF6] rounded-[5px] mx-5 my-7 p-3 diff --git a/client/src/styles/Categorybar/CategoryCard.ts b/client/src/styles/Categorybar/CategoryCard.ts index b3ee5037..1bbdfedb 100644 --- a/client/src/styles/Categorybar/CategoryCard.ts +++ b/client/src/styles/Categorybar/CategoryCard.ts @@ -7,6 +7,8 @@ export const CardContainer = tw.div` border my-6 border-[#AEC1DF] + hover:shadow-[0_0_20px_5px_#DCEAFF] + duration-300 `; export const CardText = tw.div` flex diff --git a/client/src/styles/Categorybar/Categorybar.ts b/client/src/styles/Categorybar/Categorybar.ts index cbd08ab3..d84614e8 100644 --- a/client/src/styles/Categorybar/Categorybar.ts +++ b/client/src/styles/Categorybar/Categorybar.ts @@ -5,7 +5,8 @@ export const Item = tw.div` flex-col justify-center items-center - + transition duration-500 ease-in-out + hover:scale-110 `; export const CategoryBarContainer = tw.div` diff --git a/client/src/styles/Footer/Footer.ts b/client/src/styles/Footer/Footer.ts index beb362d9..ebbc3022 100644 --- a/client/src/styles/Footer/Footer.ts +++ b/client/src/styles/Footer/Footer.ts @@ -1,9 +1,9 @@ import tw from "tailwind-styled-components"; export const FooterSection = tw.section` - text-[#6C6C6C] text-sm font-medium + text-[#9b9b9b] text-sm font-medium border-t-[1px] border-[#4771B7] - w-full h-[200px] - flex justify-around - mt-20 p-7 + w-full h-[15vh] + flex justify-center + py-5 `; \ No newline at end of file diff --git a/client/src/styles/Header/Dropdown.ts b/client/src/styles/Header/Dropdown.ts index f699ca29..80aac9f5 100644 --- a/client/src/styles/Header/Dropdown.ts +++ b/client/src/styles/Header/Dropdown.ts @@ -12,8 +12,13 @@ export const StyledContainer = tw.ul` bg-[#D6DFEF] `; -export const Menu = tw.li`s +export const Menu = tw.li` px-[25px] py-[10px] cursor-pointer + hover:text-[#4771B7] +`; + +export const DropDownContainer = tw.div` +relative `; diff --git a/client/src/styles/Header/Haeder.ts b/client/src/styles/Header/Haeder.ts index ecbbe546..e3b6459e 100644 --- a/client/src/styles/Header/Haeder.ts +++ b/client/src/styles/Header/Haeder.ts @@ -1,10 +1,9 @@ import tw from 'tailwind-styled-components'; export const HaederContainer = tw.header` + h-[8vh] flex - mt-5 justify-between - pb-[15px] border-b-[0.5px] border-[#4771B7] w-full @@ -32,6 +31,13 @@ export const UnLoginContainer = tw.div` leading-0 items-center `; -export const DropdownContainer = tw.div` - relative + +export const ProfileIcon = tw.img` + w-[30px] + h-[30px] + ml-[40px] + transition duration-500 ease-in-out + focus:translate-y-6 + rounded-full + object-cover `; diff --git a/client/src/styles/Header/Searchbar.ts b/client/src/styles/Header/Searchbar.ts index 3f49e710..1f38fe58 100644 --- a/client/src/styles/Header/Searchbar.ts +++ b/client/src/styles/Header/Searchbar.ts @@ -5,6 +5,8 @@ export const SearchbarContainer = tw.div` `; export const SearchbarInput = tw.input` + z-40 + relative border border-[#4771B7] rounded-[30px] @@ -12,4 +14,41 @@ export const SearchbarInput = tw.input` h-[40px] pl-5 text-sm + focus:outline-none +`; + +export const AutoSearchContainer = tw.div` + z-10 + border-[0.5px] + border-t-none + border-[#4771B7] + absolute + w-[500px] + h-auto + bg-white + p-[8px] + top-[16px] + rounded-b-lg +`; + +export const AutoSearchData = tw.li` + z-10 + relative + px-[8px] + py-[4px] + w-full + + text-[14px] + font-medium + hover:bg-[#EDF1F8] + hover:text-[#4771B7] + cursor-pointer + tracking-[0.5px] +`; + +export const SearchIcon = tw.img` + absolute + w-[16px] + right-[5px] + top-1.5 `; diff --git a/client/src/styles/Home/Carousel.tsx b/client/src/styles/Home/Carousel.ts similarity index 100% rename from client/src/styles/Home/Carousel.tsx rename to client/src/styles/Home/Carousel.ts diff --git a/client/src/styles/Login/Login.ts b/client/src/styles/Login/Login.ts index bc267cc7..0400751b 100644 --- a/client/src/styles/Login/Login.ts +++ b/client/src/styles/Login/Login.ts @@ -11,9 +11,11 @@ export const StyleContainer = tw.div` flex justify-center items-center + mb-[50px] + min-h-[60vh] `; -export const LoginContainer = tw.form` +export const LoginContainer = tw.div` flex flex-col items-center diff --git a/client/src/styles/MyPage/BusinessSpaceSection.ts b/client/src/styles/MyPage/BusinessSpaceSection.ts new file mode 100644 index 00000000..2efe5eff --- /dev/null +++ b/client/src/styles/MyPage/BusinessSpaceSection.ts @@ -0,0 +1,21 @@ +import tw from 'tailwind-styled-components'; + +export const BusinessSpace = tw.div` + flex + flex-row + space-x-16 + justify-center + pt-[24px] +`; + +export const BusinessCategory = tw.div` + flex + flex-col + space-y-[24px] + text-lg +`; + +export const BusinessCategoryTitle = tw.span` + font-semibold + w-[120px] +`; \ No newline at end of file diff --git a/client/src/styles/MyPage/ConfirmationModal.ts b/client/src/styles/MyPage/ConfirmationModal.ts new file mode 100644 index 00000000..738a5c14 --- /dev/null +++ b/client/src/styles/MyPage/ConfirmationModal.ts @@ -0,0 +1,21 @@ +import tw from 'tailwind-styled-components'; + +export const BioConfirmContainer = tw.div` + space-y-2 +`; + +export const CheckMessage = tw.p` + text-[16px] +`; + +export const CheckButtonContainer = tw.div` + space-x-3 +`; + +export const ConfirmButton = tw.button` + bg-white + border-[1px] + border-[#4771B7] + p-1 + rounded-lg +`; \ No newline at end of file diff --git a/client/src/styles/MyPage/Modal.ts b/client/src/styles/MyPage/Modal.ts new file mode 100644 index 00000000..afc61cdd --- /dev/null +++ b/client/src/styles/MyPage/Modal.ts @@ -0,0 +1,84 @@ +import tw from 'tailwind-styled-components'; + +export const ModalAllContainer = tw.div` + fixed + top-0 + left-0 + right-0 + bottom-0 + flex + justify-center + items-center + bg-black + bg-opacity-40 + z-50 +`; + +export const ModalBoxContainer = tw.div` + flex + flex-col + w-[600px] + h-[500px] + space-y-[20px] + rounded-lg + bg-white + drop-shadow-lg +`; + +export const CloseButtonContainer = tw.div` + flex + justify-end + p-2 +`; + +export const CloseButton = tw.img` + cursor-pointer +`; + +export const LogoContainer = tw.div` + flex + justify-center + py-12 +`; + +export const Logo = tw.img` + ml-[40px] + w-[182px] +`; + +export const EditContainer = tw.div` + flex + flex-row + justify-center + space-x-[30px] +`; + +export const EditInput = tw.input` + border-[2px] + border-[#CCCCCC] + rounded-[8px] + w-[255px] + py-1 + px-3 +`; + +export const EditMessage = tw.div` + flex + flex-row + justify-center + text-sm + pl-[80px] +`; + +export const EditComplete = tw.div` + flex + justify-center + pt-[30px] +`; + +export const EditConfirmButton = tw.button` + bg-[#4771B7] + text-white + p-3 + rounded-lg +`; \ No newline at end of file diff --git a/client/src/styles/MyPage/MyPage.ts b/client/src/styles/MyPage/MyPage.ts index f95805e3..e0e4ccf9 100644 --- a/client/src/styles/MyPage/MyPage.ts +++ b/client/src/styles/MyPage/MyPage.ts @@ -4,18 +4,27 @@ export const MyPageContainer = tw.div` flex flex-row justify-center - space-x-10 + max-w-[902px] + min-h-[800px] `; export const MyBioContainer = tw.div` border-[1px] border-[#4771B7] - w-[800px] + w-[902px] `; export const MySpace = tw.div` - space-y-8 - p-10 + space-y-4 + pt-5 + pb-10 + px-10 +`; + +export const ButtonGridEdit = tw.div` + grid + justify-items-end + pt-5 `; export const ButtonGrid = tw.div` @@ -43,11 +52,14 @@ export const PhotoInputStyle = tw.span` border-[#4771B7] rounded p-2 + cursor-pointer `; export const ImgStyle = tw.img` w-[100px] + h-[100px] rounded-full + object-cover `; export const TopSpace = tw.div` @@ -62,29 +74,16 @@ export const NicknameAccent = tw.span` text-xl `; -export const UserInfo = tw.div` - space-x-10 - text-lg -`; - -export const UserInfoTitle = tw.span` - font-medium -`; - -export const BusinessSpace = tw.div` - flex - flex-row - space-x-10 - justify-center -`; - -export const BusinessCategory = tw.div` - flex - flex-col - space-y-5 - text-lg -`; - -export const BusinessCategoryTitle = tw.span` - font-semibold +export const LoadingContainer = tw.div` + border-[1px] + border-[#4771B7] + w-[902px] + h-[800px] + flex + flex-col + justify-center + items-center + text-3xl + font-semibold + space-y-5 `; \ No newline at end of file diff --git a/client/src/styles/MyPage/ReservationCheck.ts b/client/src/styles/MyPage/ReservationCheck.ts index 9b1b27d6..91e66d69 100644 --- a/client/src/styles/MyPage/ReservationCheck.ts +++ b/client/src/styles/MyPage/ReservationCheck.ts @@ -6,6 +6,9 @@ export const ResCheckContainer = tw.div` px-[50px] py-16 space-y-5 + w-[902px] + h-[800px] + overflow-y-auto `; export const ResCheckTitle = tw.p` @@ -17,7 +20,7 @@ export const ResCheckTitle = tw.p` export const ResCheckCards = tw.div` border-[1.5px] border-[#4771B7] - w-[700px] + w-[780px] h-[200px] rounded-lg p-5 @@ -108,4 +111,14 @@ export const ButtonReview = tw.button` export const NoButtons = tw.p` h-[38.5px] +`; + +export const NoReservation = tw.div` + flex + flex-col + justify-center + items-center + space-y-5 + p-20 + h-[600px] `; \ No newline at end of file diff --git a/client/src/styles/MyPage/StoreCheck.ts b/client/src/styles/MyPage/StoreCheck.ts index 99712f72..8d4cdf51 100644 --- a/client/src/styles/MyPage/StoreCheck.ts +++ b/client/src/styles/MyPage/StoreCheck.ts @@ -6,7 +6,8 @@ export const StoreCheckContainer = tw.div` px-[50px] py-16 space-y-5 - max-h-[800px] + w-[902px] + h-[800px] overflow-y-auto `; @@ -19,7 +20,7 @@ export const StoreCheckTitle = tw.span` export const StoreCards = tw.div` border-[1.5px] border-[#4771B7] - w-[700px] + w-[780px] h-[200px] rounded-lg p-5 @@ -60,6 +61,7 @@ export const StoreInfoContainer = tw.div` export const StoreName = tw.span` text-[20px] font-semibold + cursor-pointer `; export const ButtonsContainer = tw.div` @@ -74,4 +76,14 @@ export const StoreButtonStyle = tw.button` bg-[#F3F5F7] p-2 rounded-lg +`; + +export const NoStores = tw.div` + flex + flex-col + justify-center + items-center + space-y-5 + p-20 + h-[600px] `; \ No newline at end of file diff --git a/client/src/styles/MyPage/UserInfo.ts b/client/src/styles/MyPage/UserInfo.ts new file mode 100644 index 00000000..4deca494 --- /dev/null +++ b/client/src/styles/MyPage/UserInfo.ts @@ -0,0 +1,16 @@ +import tw from 'tailwind-styled-components'; + +export const UserInfo = tw.div` + space-x-10 + text-lg +`; + +export const UserInfoTitle = tw.span` + font-medium +`; + +export const MySpace = tw.div` + space-y-8 + px-[96px] + py-[24px] +`; \ No newline at end of file diff --git a/client/src/styles/MyPage/WishList.ts b/client/src/styles/MyPage/WishList.ts index 23960204..ffc0a83a 100644 --- a/client/src/styles/MyPage/WishList.ts +++ b/client/src/styles/MyPage/WishList.ts @@ -3,8 +3,10 @@ import tw from 'tailwind-styled-components'; export const WishContainer = tw.div` border-[1px] border-[#4771B7] - p-10 - max-h-[800px] + py-16 + px-[35px] + h-[800px] + w-[902px] overflow-y-auto `; @@ -14,9 +16,8 @@ export const NoWishList = tw.div` justify-center items-center space-y-5 - border-[1px] - border-[#4771B7] p-20 + h-[600px] `; export const NoWishImgSize = tw.img` @@ -27,9 +28,11 @@ export const NoWishTitle = tw.p` text-2xl font-semibold pt-12 + pl-4 `; export const WishCountTitle = tw.span` font-semibold text-2xl + pl-4 `; \ No newline at end of file diff --git a/client/src/styles/Partner/Partner.ts b/client/src/styles/Partner/Partner.ts index 7fbbdd78..b6d9415e 100644 --- a/client/src/styles/Partner/Partner.ts +++ b/client/src/styles/Partner/Partner.ts @@ -4,7 +4,7 @@ export const PartnerContainer = tw.div` flex justify-center items-center - h-[80%] + min-h-[77vh] `; export const RegiContainer = tw.div` @@ -67,6 +67,11 @@ export const RegiNumberCorrect = tw.p` text-green-500 `; +export const RegiNumberConfirm = tw.p` + pt-1 + text-amber-600 +`; + export const RegiNumberWrong = tw.p` pt-1 text-red-500 @@ -130,6 +135,17 @@ export const FormRegiButton = tw.button` text-white `; +export const DisableFormRegiButton = tw.button` + font-semibold + text-xl + px-14 + py-3 + opacity-50 + bg-[#4771B7] + text-white + cursor-default +`; + export const FormRegiContainer = tw.div` flex justify-center diff --git a/client/src/styles/PaymentSuccess/AfterPayment.ts b/client/src/styles/PaymentSuccess/AfterPayment.ts new file mode 100644 index 00000000..c2193f28 --- /dev/null +++ b/client/src/styles/PaymentSuccess/AfterPayment.ts @@ -0,0 +1,37 @@ +import tw from "tailwind-styled-components" + +export const AfterPaymentSection = tw.section` + w-[600px] h-[77vh] + mx-auto + flex flex-col justify-center items-center +`; + +export const CheckIcon = tw.div` + bg-[#4771B7] + w-[105px] h-[105px + pr-2 pt-1 + rounded-full +`; + +export const CloseIcon = tw.div` + bg-[#4771B7] + w-[105px] h-[105px] + flex justify-center items-center + rounded-full +`; + +export const AfterPaymentContent = tw.div` + px-10 py-7 mt-10 + border-[1px] border-[#4771B7] rounded-[5px] + bg-[#E7EDF6] + font-medium +`; + +export const AfterPaymentBtn = tw.button` + mt-10 px-5 py-2 + bg-[#4771B7] + text-white + rounded-[10px] + duration-500 + hover:bg-[#65a4d8] +`; \ No newline at end of file diff --git a/client/src/styles/Register/Register.ts b/client/src/styles/Register/Register.ts index a5ddaf69..507f5843 100644 --- a/client/src/styles/Register/Register.ts +++ b/client/src/styles/Register/Register.ts @@ -4,6 +4,8 @@ export const StyleContainer = tw.div` flex justify-center items-center + mb-[50px] + min-h-[60vh] `; export const RegisterContainer = tw.div` diff --git a/client/src/styles/Reservation/ReservationModify.ts b/client/src/styles/Reservation/ReservationModify.ts index 56b90331..63d3f341 100644 --- a/client/src/styles/Reservation/ReservationModify.ts +++ b/client/src/styles/Reservation/ReservationModify.ts @@ -1,11 +1,10 @@ import tw from 'tailwind-styled-components'; export const ReservationContainer = tw.div` - h-[100vh] w-[600px] - text-start - ml-[300px] mt-[80px] + mr-16 + mb-[80px] `; export const Title = tw.div` @@ -36,7 +35,7 @@ export const ReservationTitle = tw.div` export const ReservationInput = tw.input` border-[1px] border-[#CCCCCC] rounded-[5px] - w-[240px] h-[38px] + w-[260px] h-[38px] p-2 `; @@ -46,10 +45,9 @@ export const InputRequire = tw.div` `; export const PaymentInfoBox = tw.section` - sticky top-10 - w-[300px] h-[500px] + w-[300px] h-[530px] border-[1px] border-[#4771B7] rounded-[5px] - mt-10 ml-20 + mt-28 font-medium `; @@ -70,7 +68,34 @@ export const RuleBox = tw.div` export const PaymentButton = tw.button` bg-[#4771B7] w-[250px] h-[50px] - block mx-auto p-2 + block mx-auto mb-3 p-2 text-white rounded-[10px] `; + +export const UseCompleteButton = tw.button` + w-[250px] h-[50px] + block mx-auto mb-3 p-2 + text-[#4771B7] + border-[1px] border-[#4771B7] rounded-[10px] +`; + +export const InputContainer = tw.div` + flex + ml-7 + mb-3 + items-center +`; + +export const ModifyButton = tw.div` + relative + w-[75px] + left-[520px] + bottom-[50px] + bg-[#F3F5F7] + rounded-lg + font-semibold + text-[14px] + p-[10px] + cursor-pointer +`; diff --git a/client/src/styles/StoreAdd/StoreAdd.ts b/client/src/styles/StoreAdd/StoreAdd.ts index 02f40207..82e4584c 100644 --- a/client/src/styles/StoreAdd/StoreAdd.ts +++ b/client/src/styles/StoreAdd/StoreAdd.ts @@ -2,7 +2,7 @@ import tw from "tailwind-styled-components"; export const StoreAddSection = tw.section` w-[900px] min-h-[55vh] - mx-auto mt-20 + mx-auto my-20 font-medium text-lg `; diff --git a/client/src/styles/Welcome/IntroPage/Page1.ts b/client/src/styles/Welcome/IntroPage/Page1.ts new file mode 100644 index 00000000..8ea6615a --- /dev/null +++ b/client/src/styles/Welcome/IntroPage/Page1.ts @@ -0,0 +1,30 @@ +import tw from 'tailwind-styled-components'; + +export const PageContainer = tw.div` + relative + w-[100vw] + h-[100vh] +`; + +export const IntroText = tw.div` + h-full + flex flex-col justify-center + ml-[150px] +`; + +export const ClickContainer = tw.div` + flex + flex-col + items-center + justify-center + absolute + left-[50%] + bottom-5 + translate-x-[-50%] +`; + +export const HomeBtn = tw.span` + font-semibold + text-[25px] + mb-[10px] +`; diff --git a/client/src/styles/Welcome/IntroPage/Page2.ts b/client/src/styles/Welcome/IntroPage/Page2.ts new file mode 100644 index 00000000..661288ef --- /dev/null +++ b/client/src/styles/Welcome/IntroPage/Page2.ts @@ -0,0 +1,24 @@ +import tw from 'tailwind-styled-components'; + +export const PageContainer = tw.div` + relative + bg-[#ECF1F8] + w-[100vw] + h-[100vh] + flex + flex-col + items-center + justify-center +`; + +export const MainText = tw.div` + font-semibold + text-[3rem] + text-[#4771B7] + my-[30px] +`; + +export const SubText = tw.p` + text-[30px] + mb-[30px] +`; diff --git a/client/src/styles/Welcome/IntroPage/Page3.ts b/client/src/styles/Welcome/IntroPage/Page3.ts new file mode 100644 index 00000000..54ad5036 --- /dev/null +++ b/client/src/styles/Welcome/IntroPage/Page3.ts @@ -0,0 +1,54 @@ +import tw from 'tailwind-styled-components'; + +export const Wrapper = tw.div` + relative + bg-[#4771B7] + w-[100vw] + h-[100vh] + flex + flex-col + items-center justify-center +`; +export const PageContainer = tw.div` + mb-10 + bg-[#4771B7] + w-full + h-full + flex + items-center + justify-around +`; + +export const TextContainer = tw.div` + flex + flex-col + items-center +`; + +export const MainText = tw.div` + text-[#FFFFFF] + text-[48px] + font-semibold + text-center + mb-[30px] +`; + +export const SubText = tw.p` + text-[#FFFFFF] + text-[32px] + mb-[30px] +`; + +export const HomeBtn = tw.button` + w-[330px] + h-[65px] + text-[25px] + font-medium + border + bg-white + text-center + rounded-[30px] + shadow-md + shadow-[#cdd2d8] + cursor-pointer +`; diff --git a/client/src/styles/Welcome/IntroPage/Page4.ts b/client/src/styles/Welcome/IntroPage/Page4.ts new file mode 100644 index 00000000..49ae4770 --- /dev/null +++ b/client/src/styles/Welcome/IntroPage/Page4.ts @@ -0,0 +1,54 @@ +import tw from 'tailwind-styled-components'; + +export const Wrapper = tw.div` + relative + bg-[#ECF1F8] + w-[100vw] + h-[100vh] + flex + flex-col + items-center +`; + +export const PageContainer = tw.div` + bg-[#ECF1F8] + w-full + h-[100vh] + flex + items-center + justify-around +`; + +export const TextContainer = tw.div` + flex + flex-col + items-center +`; + +export const MainText = tw.div` + text-[#4771B7] + text-[48px] + font-semibold + text-center + mb-[67px] +`; + +export const SubText = tw.p` + text-[32px] + mb-[67px] + text-center +`; + +export const HomeBtn = tw.button` + w-[330px] + h-[65px] + text-[25px] + font-medium + border + shadow-md + shadow-[#8F9296] + bg-white + text-center + rounded-[30px] + cursor-pointer +`; diff --git a/client/src/styles/Welcome/Welcome.ts b/client/src/styles/Welcome/Welcome.ts index c05b3ed4..b5872b39 100644 --- a/client/src/styles/Welcome/Welcome.ts +++ b/client/src/styles/Welcome/Welcome.ts @@ -5,9 +5,7 @@ export const Blue = tw.span` `; export const Button = tw.button` - relative - top-[320px] - left-[140px] + mt-10 rounded-[20px] text-[40px] font-semibold @@ -15,12 +13,11 @@ export const Button = tw.button` h-[85px] bg-[#4771B7] text-[#FFFFFF] + transition duration-500 ease-in-out + hover:bg-[#6787BC] `; export const Inrto = tw.div` - relative - top-[280px] - left-[150px] font-semibold text-[64px] `; diff --git a/client/tailwind.config.js b/client/tailwind.config.js index 108402e6..1e4fb8d1 100644 --- a/client/tailwind.config.js +++ b/client/tailwind.config.js @@ -2,7 +2,21 @@ export default { content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], theme: { - extend: {}, + safelist: [ + 'animate-[fade-in_1s_ease-in-out]', + 'animate-[fade-in-down_1s_ease-in-out]', + ], + extend: { + animation: { + wiggle: 'wiggle 1s ease-in-out infinite', + fade: 'fadeOut 5s ease-in-out', + }, + keyframes: { + wiggle: { + '0%, 100%': { transform: 'rotate(-3deg)' }, + '50%': { transform: 'rotate(3deg)' }, + }, + }, + }, }, - plugins: [], }; diff --git a/server/build.gradle b/server/build.gradle index cd2f08ba..e012ce59 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -2,7 +2,6 @@ plugins { id 'java' id 'org.springframework.boot' version '2.7.13' id 'io.spring.dependency-management' version '1.0.15.RELEASE' -// id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" // Querydsl ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฒ„์ „ ์ถ”๊ฐ€ } group = 'com.example' @@ -12,7 +11,7 @@ java { sourceCompatibility = '11' } -//apply plugin: "com.ewerk.gradle.plugins.querydsl" +apply plugin: 'io.spring.dependency-management' configurations { compileOnly { @@ -29,17 +28,21 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' - - // ํŒŒ๋ผ๋ฏธํ„ฐ ์Šคํ† ์–ด - implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' + runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' + //redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'it.ozimov:embedded-redis:0.7.2' + implementation 'redis.clients:jedis:3.6.1' + + // ํŒŒ๋ผ๋ฏธํ„ฐ ์Šคํ† ์–ด + implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config' + // OAuth2 implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' @@ -57,49 +60,16 @@ dependencies { //aws s3 ์˜์กด implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' - -// //Querydsl ๋ฒ„์ „์„ BOM์œผ๋กœ ์ผ์น˜์‹œํ‚ค๊ธฐ -// implementation platform("com.querydsl:querydsl-bom:4.4.2") // Spring Boot 2.7.13์— ๋งž๋Š” Querydsl ๋ฒ„์ „ ์‚ฌ์šฉ -// implementation 'com.querydsl:querydsl-jpa' -// annotationProcessor 'com.querydsl:querydsl-apt' } -//querydsl ์ถ”๊ฐ€ -//def querydslDir = "src/main/generated/querydsl" -// -//querydsl { -// library = "com.querydsl:querydsl-apt" -// jpa = true -// querydslSourcesDir = querydslDir -//} -// -//sourceSets { -// main { -// java { -// srcDirs = ['src/main/java', querydslDir] -// } -// } -//} -// -//compileQuerydsl { -// options.annotationProcessorPath = configurations.querydsl -//} -// -//configurations { -// querydsl.extendsFrom compileClasspath -//} - -dependencyManagement { // ๋ธ”๋ก ์ถ”๊ฐ€ +dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Hoxton.SR12" } } -jar { - enabled = false -} - tasks.named('test') { exclude "**/*" useJUnitPlatform() } + diff --git a/server/restart.sh b/server/restart.sh new file mode 100644 index 00000000..7fb8c849 --- /dev/null +++ b/server/restart.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# actiOn-0.0.1-SNAPSHOT.jar๊ฐ€ ์‹คํ–‰ ์ค‘์ด๋ผ๋ฉด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. +ps -ef | grep "actiOn-0.0.1-SNAPSHOT.jar" | grep -v grep | awk '{print $2}' | xargs kill -9 2> /dev/null + +# ์ข…๋ฃŒ ์ด๋ ฅ์„ ํŒŒ์•…ํ•˜์—ฌ ์ ์ ˆํ•œ ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. +if [ $? -eq 0 ];then + echo "my-application Stop Success" +else + echo "my-application Not Running" +fi + +# actiOn-0.0.1-SNAPSHOT.jar๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. +echo "my-application Restart!" +echo $1 + +# nohup ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ actiOn-0.0.1-SNAPSHOT.jar๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. +nohup java -jar build/libs/actiOn-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev > /dev/null 2>&1 & \ No newline at end of file diff --git a/server/src/main/java/actiOn/ActiOnApplication.java b/server/src/main/java/actiOn/ActiOnApplication.java index 8ea6f74c..6d82c869 100644 --- a/server/src/main/java/actiOn/ActiOnApplication.java +++ b/server/src/main/java/actiOn/ActiOnApplication.java @@ -8,7 +8,7 @@ @SpringBootApplication public class ActiOnApplication { - public static void main(String[] args) { - SpringApplication.run(ActiOnApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(ActiOnApplication.class, args); + } } \ No newline at end of file diff --git a/server/src/main/java/actiOn/Img/dto/ProfileImgDto.java b/server/src/main/java/actiOn/Img/dto/ProfileImgDto.java new file mode 100644 index 00000000..45664be7 --- /dev/null +++ b/server/src/main/java/actiOn/Img/dto/ProfileImgDto.java @@ -0,0 +1,13 @@ +package actiOn.Img.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class ProfileImgDto { + private String nickname; + private String profileImage; +} diff --git a/server/src/main/java/actiOn/Img/profileImg/ProfileImg.java b/server/src/main/java/actiOn/Img/profileImg/ProfileImg.java deleted file mode 100644 index e2329612..00000000 --- a/server/src/main/java/actiOn/Img/profileImg/ProfileImg.java +++ /dev/null @@ -1,36 +0,0 @@ -package actiOn.Img.profileImg; - -import actiOn.member.entity.Member; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import javax.persistence.*; - -@Entity -@Getter -@Setter -@NoArgsConstructor -public class ProfileImg { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private long imgId; - - @Column(nullable = false) - private String link = "default image"; - - @Enumerated(value = EnumType.STRING) - @Column(length = 20, nullable = false) - private ProfileImgStatus imgStatus = ProfileImgStatus.PROFILE_DEFAULT; - - @OneToOne - @JoinColumn(name = "MEMBER_ID") - private Member member; - - public enum ProfileImgStatus { - PROFILE_DEFAULT, - PROFILE_ACTIVE, - PROFILE_DELETED - } -} -//Todo ๋‚ด ์˜ˆ์•ฝ ์กฐํšŒ๋Š” memberController๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ๋ฐ›์ง€๋งŒ, ์ฒ˜๋ฆฌ ๋กœ์ง์€ reservationService์—์„œ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•จ \ No newline at end of file diff --git a/server/src/main/java/actiOn/Img/profileImg/ProfileImgRepository.java b/server/src/main/java/actiOn/Img/profileImg/ProfileImgRepository.java deleted file mode 100644 index 2eaec348..00000000 --- a/server/src/main/java/actiOn/Img/profileImg/ProfileImgRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package actiOn.Img.profileImg; - -import actiOn.member.entity.Member; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface ProfileImgRepository extends JpaRepository { - Optional findByMemberAndImgStatus(Member member, ProfileImg.ProfileImgStatus status); -} diff --git a/server/src/main/java/actiOn/Img/service/ImgService.java b/server/src/main/java/actiOn/Img/service/ImgService.java index 69d4af79..3930d7bf 100644 --- a/server/src/main/java/actiOn/Img/service/ImgService.java +++ b/server/src/main/java/actiOn/Img/service/ImgService.java @@ -1,17 +1,15 @@ package actiOn.Img.service; -import actiOn.Img.profileImg.ProfileImg; -import actiOn.Img.profileImg.ProfileImgRepository; import actiOn.Img.storeImg.StoreImg; import actiOn.Img.storeImg.StoreImgRepository; import actiOn.exception.BusinessLogicException; import actiOn.exception.ExceptionCode; import actiOn.member.entity.Member; import actiOn.store.entity.Store; -import actiOn.store.repository.StoreRepository; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -19,7 +17,10 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; @Service public class ImgService { @@ -29,174 +30,51 @@ public class ImgService { @Value("${cloud.aws.region.static}") private String REGION; - // private final String S3Repository = "https://test-main-005.s3.ap-northeast-2.amazonaws.com/"; - private final ProfileImgRepository profileImgRepository; private final StoreImgRepository storeImgRepository; - private final StoreRepository storeRepository; - - public ImgService(ProfileImgRepository profileImgRepository, StoreImgRepository storeImgRepository, StoreRepository storeRepository) { - this.profileImgRepository = profileImgRepository; - this.storeImgRepository = storeImgRepository; - this.storeRepository = storeRepository; - } - // ๊ธฐ๋ณธ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ ์ €์žฅํ•˜๋Š” ๋ฉ”์„œ๋“œ - public ProfileImg setDefaultProfileImg(Member member) { - ProfileImg profileImg = new ProfileImg(); - profileImg.setLink("default Link"); // TODO ๋ณ€๊ฒฝ ํ•ด์ฃผ์–ด์•ผ ํ•จ - profileImg.setMember(member); - - return profileImg; + public ImgService(StoreImgRepository storeImgRepository) { + this.storeImgRepository = storeImgRepository; } // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ๋ก - @Transactional - public ProfileImg uploadProfileImage(MultipartFile file, Member member) throws IOException { - // ๊ธฐ์กด ํ”„๋กœํ•„ ์‚ฌ์ง„์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ - if (existsCurrentProfileImage(member)) { - // ๊ธฐ์กด ํ”„๋กœํ•„ DELETED๋กœ ๋ณ€๊ฒฝ - updateProfileImageStatusDeleted(member); - } - - + public String uploadProfileImage(MultipartFile file, Member member) throws IOException { // S3์— ์ด๋ฏธ์ง€ ํŒŒ์ผ ์—…๋กœ๋“œ - String imageName = generateRandomName(); + String imageName = generateRandomName(member, Math.toIntExact(member.getMemberId())); String fileUrl = uploadImage(file, imageName); - // ์ƒˆ๋กœ์šด ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ƒ์„ฑ - ProfileImg profileImg = createNewProfileImage(member, fileUrl); - return profileImgRepository.save(profileImg); - } - - // ๊ธฐ๋ณธ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ํƒ์ƒ‰ - public ProfileImg getDefaultProfileImage(Member member) { - Optional defaultProfileImg = profileImgRepository.findByMemberAndImgStatus( - member, ProfileImg.ProfileImgStatus.PROFILE_DEFAULT); - - if (defaultProfileImg.isEmpty()) { - throw new BusinessLogicException(ExceptionCode.PROFILE_IMAGE_NOT_FOUND); - } - - return defaultProfileImg.get(); - } - - // ๊ธฐ์กด ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ status DELETED๋กœ ๋ณ€๊ฒฝ - public void updateProfileImageStatusDeleted(Member member) { - ProfileImg currentProfileImg = findProfileImgByMember(member); - currentProfileImg.setImgStatus(ProfileImg.ProfileImgStatus.PROFILE_DELETED); - - profileImgRepository.save(currentProfileImg); - } - - - public StoreImg StoreThumbnailImgIdGenerator(Store store, StoreImg storeImg) { - storeImg.setIsThumbnail(true); - StoreImg thumbnailImg = storeImgRepository.findByStoreAndIsThumbnail(store, true); - if (thumbnailImg != null) storeImg.setImgId(thumbnailImg.getImgId()); - return storeImg; - } - - public List uploadStoreImage(List files, long storeId, MultipartFile thumbnailImage) { - String randomString = generateRandomName(); - try { - List storeImgs = new ArrayList<>(); - if (thumbnailImage != null) { //thumbnailImage๊ฐ€ null์ด ์•„๋‹ˆ๋ฉด ํŒŒ์ผ๋ฆฌ์ŠคํŠธ 0๋ฒˆ์งธ ๋„ฃ์–ด์„œ ์ธ๋„ค์ผ๋กœ ๋งŒ๋“ค๊ธฐ - files.add(0, thumbnailImage); - } else { - files.add(0, null); - } - - Store findStore = storeRepository.findById(storeId).orElseThrow(() -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND)); - if (findStore == null) { - return null; - } - int index = 1; - for (MultipartFile file : files) { - if (file != null) { - String imageName = String.valueOf(storeId) + randomString + String.valueOf(index); - StoreImg storeImg = new StoreImg(); - String fileUrl = uploadImage(file, imageName); - storeImg.setLink(fileUrl); - if (file.equals(files.get(0))) { - storeImg.setIsThumbnail(true); - StoreImg findThumbnail = storeImgRepository.findByStoreAndIsThumbnail(findStore, true); - if (findThumbnail != null) { - storeImg.setImgId(findThumbnail.getImgId()); - } - } - storeImg.setStore(findStore); - storeImgs.add(storeImgRepository.save(storeImg)); - index++; - } - } - - return storeImgs; - //Todo url / ๋””๋น„์— ์ €์žฅ - } catch (Exception e) { - e.printStackTrace(); - - return null; - } - + return fileUrl; } + // ์—…์ฒด ์ด๋ฏธ์ง€ ๋“ฑ๋ก + @Transactional public void uploadStoreImage(List files, Store store, MultipartFile thumbnailImage) throws IOException { int storeImgListSize = storeImgRepository.countByStore(store); - if (files.size() > 12- storeImgListSize) { // ์‚ฌ์ง„๊ฐœ์ˆ˜ ์ œํ•œ + + if (files.size() > 12 - storeImgListSize) { // ์‚ฌ์ง„๊ฐœ์ˆ˜ ์ œํ•œ int remainingSize = 12 - storeImgListSize; if (remainingSize < 0) remainingSize = 0; files = files.subList(0, remainingSize); } - String randomStringForImageName = generateRandomName(); List storeImgs = new ArrayList<>(); + int index = 1; for (MultipartFile file : files) { - if (file == null) continue; - String imageName = String.valueOf(store.getStoreId()) + randomStringForImageName + String.valueOf(index); - String fileUrl = uploadImage(file, imageName); + if (file == null) { + continue; + } + + String fileName = generateRandomName(store.getMember(), index); + String fileUrl = uploadImage(file, fileName); StoreImg storeImg = new StoreImg(fileUrl, store); - if (file.equals(thumbnailImage)) storeImg = StoreThumbnailImgIdGenerator(store, storeImg); + + if (file.equals(thumbnailImage)) { + storeImg = StoreThumbnailImgIdGenerator(store, storeImg); + } storeImgs.add(storeImg); index++; } storeImgRepository.saveAll(storeImgs); - }//์ˆ˜์ •์™„๋ฃŒ - - // ๊ธฐ๋ณธ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์„ค์ • - public ProfileImg setDefaultProfileImage(Member member) { - ProfileImg profileImg = new ProfileImg(); - profileImg.setMember(member); - - return profileImgRepository.save(profileImg); - } - - // ์ƒˆ๋กœ์šด ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ƒ์„ฑ - private ProfileImg createNewProfileImage(Member member, String fileUrl) { - ProfileImg profileImg = new ProfileImg(); - profileImg.setLink(fileUrl); - profileImg.setImgStatus(ProfileImg.ProfileImgStatus.PROFILE_ACTIVE); - profileImg.setMember(member); - - return profileImg; - } - - // ๊ธฐ์กด ํ”„๋กœํ•„ ์‚ฌ์ง„ ํƒ์ƒ‰ - private ProfileImg findProfileImgByMember(Member member) { - Optional currentProfileImg = profileImgRepository - .findByMemberAndImgStatus(member, ProfileImg.ProfileImgStatus.PROFILE_ACTIVE); - - if (currentProfileImg.isEmpty()) { - throw new BusinessLogicException(ExceptionCode.PROFILE_IMAGE_NOT_FOUND); - } - return currentProfileImg.get(); - } - - // ๊ธฐ์กด ํ”„๋กœํ•„ ์‚ฌ์ง„์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ - private boolean existsCurrentProfileImage(Member member) { - return profileImgRepository - .findByMemberAndImgStatus(member, ProfileImg.ProfileImgStatus.PROFILE_ACTIVE) - .isPresent(); } private String uploadImage(MultipartFile file, String imageName) throws IOException { @@ -204,28 +82,38 @@ private String uploadImage(MultipartFile file, String imageName) throws IOExcept .withRegion(REGION) .build(); + // ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(file.getContentType()); + metadata.setContentLength(file.getInputStream().available()); + s3Client.putObject(new PutObjectRequest( - BUCKET_NAME, imageName, file.getInputStream(), null) + BUCKET_NAME, imageName, file.getInputStream(), metadata) ); - String fileUrl = s3Client.getUrl(BUCKET_NAME, imageName).toString(); - return fileUrl; + return s3Client.getUrl(BUCKET_NAME, imageName).toString(); } - private String generateRandomName() { + private String generateRandomName(Member member, int index) { String uuid = UUID.randomUUID().toString(); - int leftLimit = 97; // letter 'a' - int rightLimit = 122; // letter 'z' - int targetStringLength = 25; - Random random = new Random(); - String generatedString = random.ints(leftLimit, rightLimit + 1) - .limit(targetStringLength) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) - .toString(); - return uuid + generatedString; + + return uuid + "-" + index + "-" + member.getMemberId(); + } + + private StoreImg StoreThumbnailImgIdGenerator(Store store, StoreImg storeImg) { + storeImg.setIsThumbnail(true); + StoreImg thumbnailImg = storeImgRepository.findByStoreAndIsThumbnail(store, true); + if (thumbnailImg != null) storeImg.setImgId(thumbnailImg.getImgId()); + return storeImg; } public void deleteStoreImage(String link) { - storeImgRepository.deleteByLink(link.replace(" ", "")); + Optional storeImg = storeImgRepository.findByLink(link); + + if (storeImg.isEmpty()) { + throw new BusinessLogicException(ExceptionCode.STORE_IMAGE_NOT_FOUND); + } + + storeImgRepository.delete(storeImg.get()); } } diff --git a/server/src/main/java/actiOn/Img/storeImg/StoreImg.java b/server/src/main/java/actiOn/Img/storeImg/StoreImg.java index 85988a7b..ccbba7db 100644 --- a/server/src/main/java/actiOn/Img/storeImg/StoreImg.java +++ b/server/src/main/java/actiOn/Img/storeImg/StoreImg.java @@ -32,6 +32,4 @@ public StoreImg(String link, Store store) { this.link = link; this.store = store; } - - } diff --git a/server/src/main/java/actiOn/Img/storeImg/StoreImgRepository.java b/server/src/main/java/actiOn/Img/storeImg/StoreImgRepository.java index 8fa29049..c16badb4 100644 --- a/server/src/main/java/actiOn/Img/storeImg/StoreImgRepository.java +++ b/server/src/main/java/actiOn/Img/storeImg/StoreImgRepository.java @@ -2,20 +2,15 @@ import actiOn.store.entity.Store; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; import java.util.Optional; -public interface StoreImgRepository extends JpaRepository { - Optional findByStore(Store store); +public interface StoreImgRepository extends JpaRepository { Optional findByLink(String link); StoreImg findByStoreAndIsThumbnail(Store store, boolean isThumbnail); - void deleteByLink(String link); int countByStore(Store store); } diff --git a/server/src/main/java/actiOn/auth/dto/LoginResponseDto.java b/server/src/main/java/actiOn/auth/dto/LoginResponseDto.java index f0b8906b..c186e8c8 100644 --- a/server/src/main/java/actiOn/auth/dto/LoginResponseDto.java +++ b/server/src/main/java/actiOn/auth/dto/LoginResponseDto.java @@ -1,9 +1,11 @@ package actiOn.auth.dto; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; @Getter +@Builder @AllArgsConstructor public class LoginResponseDto { private String role; diff --git a/server/src/main/java/actiOn/auth/filter/JwtVerificationFilter.java b/server/src/main/java/actiOn/auth/filter/JwtVerificationFilter.java index 01eaf21c..05967936 100644 --- a/server/src/main/java/actiOn/auth/filter/JwtVerificationFilter.java +++ b/server/src/main/java/actiOn/auth/filter/JwtVerificationFilter.java @@ -2,8 +2,13 @@ import actiOn.auth.provider.TokenProvider; import actiOn.auth.utils.MemberAuthorityUtil; +import actiOn.member.entity.Member; +import actiOn.member.service.MemberService; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jws; import io.jsonwebtoken.security.SignatureException; +import lombok.AllArgsConstructor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -12,14 +17,15 @@ import javax.servlet.FilterChain; import javax.servlet.ServletException; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Arrays; import java.util.List; import java.util.Map; -import static actiOn.auth.utils.TokenPrefix.AUTHORIZATION; -import static actiOn.auth.utils.TokenPrefix.BEARER; +import static actiOn.auth.utils.TokenPrefix.*; /* ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ „์†ก๋œ request header์— ํฌํ•จ๋œ JWT ๊ฒ€์ฆ์„ ์œ„ํ•œ ํ•„ํ„ฐ @@ -27,14 +33,11 @@ ๊ฒ€์ฆ์ด ๋๋‚˜๋ฉด SecurityHolder๋ฅผ ์ด์šฉํ•ด SecurityContext์— ์ธ์ฆ๋œ Authentication์„ ์ €์žฅ */ +@AllArgsConstructor public class JwtVerificationFilter extends OncePerRequestFilter { private final TokenProvider tokenProvider; private final MemberAuthorityUtil authorityUtil; - - public JwtVerificationFilter(TokenProvider tokenProvider, MemberAuthorityUtil authorityUtil) { - this.tokenProvider = tokenProvider; - this.authorityUtil = authorityUtil; - } + private final MemberService memberService; // ์˜ˆ์™ธ ๋กœ์ง ์ถ”๊ฐ€ @Override @@ -47,7 +50,9 @@ protected void doFilterInternal(HttpServletRequest request, } catch (SignatureException se) { request.setAttribute("exception", se); } catch (ExpiredJwtException ee) { - request.setAttribute("exception", ee); + // ์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋œ ๊ฒฝ์šฐ + handleExpiredToken(request, response); + return; } catch (Exception e) { request.setAttribute("exception", e); } @@ -55,6 +60,61 @@ protected void doFilterInternal(HttpServletRequest request, filterChain.doFilter(request, response); } + // ์•ก์„ธ์Šค ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์žฌ๋ฐœ๊ธ‰ + private void handleExpiredToken(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + try { + String refreshToken = extractRefreshTokenFromCookie(request); + // ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ๊ฒ€์ฆ + Jws claims = verifyRefreshToken(refreshToken); + + String email = claims.getBody().getSubject(); + Member member = memberService.findMemberByEmail(email); + + // ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ ์žฌ๋ฐœ๊ธˆ + String accessToken = tokenProvider.delegateAccessToken(member); + response.setHeader(AUTHORIZATION.getType(), BEARER.getType() + accessToken); + + // ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ์ฟ ํ‚ค์— ์ €์žฅ + response.setHeader("Set-Cookie", REFRESH.getType() + "=" + refreshToken + + "; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=3600;"); + } catch (Exception e) { + // ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ๋„ ๋งŒ๋ฃŒ๋œ ๊ฒฝ์šฐ + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.getWriter().write("refresh token์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”."); + response.getWriter().flush(); + } + } + + private Jws verifyRefreshToken(String refreshToken) throws Exception { + // ํ† ํฐ ๊ฒ€์ฆ ํ›„ claims ๋ฐ˜ํ™˜ + String base64EncodedSecretKey = tokenProvider.encodedBase64SecretKey(); + Jws claims = tokenProvider.getClaims(refreshToken, base64EncodedSecretKey); + + // ํ† ํฐ ๋งŒ๋ฃŒ ๊ฒ€์ฆ + if (tokenProvider.isExpired(claims)) { + throw new Exception("๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."); + } + + return claims; + } + + // refresh Token ์ถ”์ถœ + private String extractRefreshTokenFromCookie(HttpServletRequest request) throws ServletException { + Cookie[] cookies = request.getCookies(); + + if (cookies == null) { + System.out.println("์ฟ ํ‚ค๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."); + throw new ServletException("์ฟ ํ‚ค๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."); + } + + return Arrays.stream(cookies) + .filter(cookie -> + cookie.getName().equals(REFRESH.getType())) + .findFirst() + .orElseThrow(() -> new ServletException("Refresh ํ† ํฐ์ด ์—†์Šต๋‹ˆ๋‹ค.")) + .getValue(); + } + // JWT๊ฐ€ ํ—ค๋”์— ํฌํ•จ๋˜์ง€ ์•Š๊ฑฐ๋‚˜, ํ—ค๋” ๊ฐ’์ด null์ธ ๊ฒฝ์šฐ ๋‹ค์Œ ํ•„ํ„ฐ๋กœ ๊ฑด๋„ˆ๋œ€ @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { @@ -64,9 +124,15 @@ protected boolean shouldNotFilter(HttpServletRequest request) throws ServletExce } // claims๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ๊ณผ์ •์„ ํ†ตํ•ด JWT ๊ฒ€์ฆ - private Map verifyJws(HttpServletRequest request) { - String jws = request.getHeader(AUTHORIZATION.getType()).replace(BEARER.getType(), ""); - String base64EncodedSecretKey = tokenProvider.encodedBase64SecretKey(tokenProvider.getSecretKey()); + private Map verifyJws(HttpServletRequest request) throws ServletException { + String authorizationHeader = request.getHeader(AUTHORIZATION.getType()); + + if (authorizationHeader.isEmpty()) { + throw new ServletException("ํ—ค๋”๊ฐ€ ๋น„์—ˆ์Šต๋‹ˆ๋‹ค."); + } + + String jws = authorizationHeader.replace(BEARER.getType(), ""); + String base64EncodedSecretKey = tokenProvider.encodedBase64SecretKey(); Map claims = tokenProvider.getClaims(jws, base64EncodedSecretKey).getBody(); return claims; @@ -75,7 +141,8 @@ private Map verifyJws(HttpServletRequest request) { // Authentication ๊ฐ์ฒด๋ฅผ SecurityContext์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ private void setAuthenticationToContext(Map claims) { String username = (String) claims.get("username"); - List authorities = authorityUtil.createAuthorities((List) claims.get("roles")); + List roles = (List) claims.get("roles"); + List authorities = authorityUtil.createAuthorities(roles); Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, authorities); SecurityContextHolder.getContext().setAuthentication(authentication); diff --git a/server/src/main/java/actiOn/auth/handler/MemberAuthenticationSuccessHandler.java b/server/src/main/java/actiOn/auth/handler/MemberAuthenticationSuccessHandler.java index 9bdba09d..bf76f40e 100644 --- a/server/src/main/java/actiOn/auth/handler/MemberAuthenticationSuccessHandler.java +++ b/server/src/main/java/actiOn/auth/handler/MemberAuthenticationSuccessHandler.java @@ -1,8 +1,6 @@ package actiOn.auth.handler; -import actiOn.auth.dto.LoginResponseDto; import actiOn.auth.provider.TokenProvider; -import actiOn.helper.util.JsonUtil; import actiOn.member.entity.Member; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,23 +29,20 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo String accessToken = tokenProvider.delegateAccessToken(member); String refreshToken = tokenProvider.delegateRefreshToken(member); - String loginResponse = getLoginResponseJson(member); + String loginResponse = tokenProvider.getLoginResponseJson(member); response.setContentType(MediaType.APPLICATION_JSON_VALUE); + // ์•ก์„ธ์Šค ํ† ํฐ ์ €์žฅ response.setHeader(AUTHORIZATION.getType(), BEARER.getType() + accessToken); - response.setHeader(REFRESH.getType(), refreshToken); - response.getWriter().write(loginResponse); - log.info("# Authenticated Successfully!"); - } + // ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ์ฟ ํ‚ค์— ์ €์žฅ + response.setHeader("Set-Cookie", REFRESH.getType() + "=" + refreshToken + + "; Path=/; Secure; SameSite=None; HttpOnly; Max-Age=3600;"); + response.setHeader("Access-Control-Allow-Origin", "http://ac-ti-on.s3-website.ap-northeast-2.amazonaws.com"); - // ๋กœ๊ทธ์ธ response๋ฅผ Json ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ - private String getLoginResponseJson(Member member) { - String role = member.getRoleName(); - String nickname = member.getNickname(); - String profileImage = member.getProfileImgLink(); - LoginResponseDto responseDto = new LoginResponseDto(role, nickname, profileImage); - return JsonUtil.toJson(responseDto, LoginResponseDto.class); + response.getWriter().write(loginResponse); + + log.info("# Authenticated Successfully!"); } } diff --git a/server/src/main/java/actiOn/auth/oauth2/OAuth2MemberSuccessHandler.java b/server/src/main/java/actiOn/auth/oauth2/OAuth2MemberSuccessHandler.java index 5f68f53d..4609cc4e 100644 --- a/server/src/main/java/actiOn/auth/oauth2/OAuth2MemberSuccessHandler.java +++ b/server/src/main/java/actiOn/auth/oauth2/OAuth2MemberSuccessHandler.java @@ -7,6 +7,8 @@ import actiOn.member.entity.Member; import actiOn.member.service.MemberService; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; @@ -21,7 +23,10 @@ import java.security.SecureRandom; import java.util.List; +import static actiOn.auth.utils.TokenPrefix.*; + // OAuth2 ์ธ์ฆ์— ์„ฑ๊ณตํ•˜๋ฉด ํ˜ธ์ถœ๋˜๋Š” ํ•ธ๋“ค๋Ÿฌ +@Slf4j @AllArgsConstructor public class OAuth2MemberSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private final MemberService memberService; @@ -32,6 +37,8 @@ public class OAuth2MemberSuccessHandler extends SimpleUrlAuthenticationSuccessHa public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { var oAuth2User = (OAuth2User) authentication.getPrincipal(); String email = String.valueOf(oAuth2User.getAttributes().get("email")); + String profileImgUrl = String.valueOf(oAuth2User.getAttributes().get("picture")); + Member member; // ๊ธฐ์กด ํšŒ์›์ธ์ง€ ํ™•์ธ @@ -40,11 +47,36 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo } else { // ์‹ ๊ทœ ํšŒ์›์ธ ๊ฒฝ์šฐ ํšŒ์› ์ƒ์„ฑ ๋ฐ ์ €์žฅ member = createNewMember(email); memberService.createMember(member); + // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ๋ก + memberService.registerGoogleProfileImage(profileImgUrl, email); } redirect(request, response, member); } + // ํ”„๋ก ํŠธ๋กœ JWT ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด redirectํ•˜๋Š” ๋ฉ”์„œ๋“œ + private void redirect(HttpServletRequest request, HttpServletResponse response, Member member) throws IOException { + + String accessToken = tokenProvider.delegateAccessToken(member); + String refreshToken = tokenProvider.delegateRefreshToken(member); + String loginResponse = tokenProvider.getLoginResponseJson(member); + + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + // ์•ก์„ธ์Šค ํ† ํฐ ์ €์žฅ + response.setHeader(AUTHORIZATION.getType(), BEARER.getType() + accessToken); + + // ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ์ฟ ํ‚ค์— ์ €์žฅ + response.setHeader("Set-Cookie", REFRESH.getType() + "=" + refreshToken + + "; Path=/; Secure; SameSite=None; HttpOnly; Max-Age=3600;"); + + response.getWriter().write(loginResponse); + + String uri = createURI(accessToken, member); + + log.info("# Google Authenticated Successfully!"); + getRedirectStrategy().sendRedirect(request, response, uri); + } + private Member createNewMember(String email) { Member member = new Member(); member.setEmail(email); @@ -79,29 +111,18 @@ private String generateNicknameFromEmail(String email) { return nickname; } - // ํ”„๋ก ํŠธ๋กœ JWT ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด redirectํ•˜๋Š” ๋ฉ”์„œ๋“œ - private void redirect(HttpServletRequest request, HttpServletResponse response, Member member) throws IOException { - String accessToken = tokenProvider.delegateAccessToken(member); -// String refreshToken = tokenProvider.delegateRefreshToken(member); - - String uri = createURI(accessToken, member); - getRedirectStrategy().sendRedirect(request, response, uri); - } - private String createURI(String accessToken, Member member) { MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("access_token", accessToken); -// queryParams.add("memberId", member.getMemberId().toString()); queryParams.add("nickname", member.getNickname()); // ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋ณด๋‚ธ ํ›„ ํ”„๋ก ํŠธ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‹œ๋„ return UriComponentsBuilder.newInstance() + // ํ”„๋ก ํŠธ ๋„๋ฉ”์ธ .scheme("http") - .host("localhost") -// .host("S3 ์—”๋“œํฌ์ธํŠธ") // TODO ์—”๋“œํฌ์ธํŠธ - .port(5173) + .host("ac-ti-on.s3-website.ap-northeast-2.amazonaws.com") // s3 ์—”๋“œํฌ์ธํŠธ +// .port(5173) .path("/oauth2/authorization/google/success") -// .path("/home") // TODO redirect ์–ด๋””๋กœ ํ•  ๊ฑด์ง€ .queryParams(queryParams) .build().toUri() .toString(); diff --git a/server/src/main/java/actiOn/auth/provider/TokenProvider.java b/server/src/main/java/actiOn/auth/provider/TokenProvider.java index 675d3fd1..d48adb24 100644 --- a/server/src/main/java/actiOn/auth/provider/TokenProvider.java +++ b/server/src/main/java/actiOn/auth/provider/TokenProvider.java @@ -1,5 +1,7 @@ package actiOn.auth.provider; +import actiOn.auth.dto.LoginResponseDto; +import actiOn.helper.util.JsonUtil; import actiOn.member.entity.Member; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; @@ -9,8 +11,11 @@ import io.jsonwebtoken.security.Keys; import lombok.Getter; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; import org.springframework.stereotype.Component; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.Key; import java.util.Calendar; @@ -18,6 +23,8 @@ import java.util.HashMap; import java.util.Map; +import static actiOn.auth.utils.TokenPrefix.*; + @Component public class TokenProvider { @Getter @@ -32,7 +39,7 @@ public class TokenProvider { @Value("${jwt.refresh-token-expiration-minutes}") private int refreshTokenExpirationMinutes; - public String encodedBase64SecretKey(String secretKey) { + public String encodedBase64SecretKey() { return Encoders.BASE64 .encode(secretKey.getBytes(StandardCharsets.UTF_8)); } @@ -47,16 +54,16 @@ public String delegateAccessToken(Member member) { claims.put("roles", member.getRoles()); String subject = member.getEmail(); - Date expiration = getTokenExpiration(getAccessTokenExpirationMinutes()); - String base64EncodedSecretKey = encodedBase64SecretKey(getSecretKey()); + Date expiration = getTokenExpiration(accessTokenExpirationMinutes); + String base64EncodedSecretKey = encodedBase64SecretKey(); return generateAccessToken(claims, subject, expiration, base64EncodedSecretKey); } public String delegateRefreshToken(Member member) { String subject = member.getEmail(); - Date expiration = getTokenExpiration(getRefreshTokenExpirationMinutes()); - String base64EncodedSecretKey = encodedBase64SecretKey(getSecretKey()); + Date expiration = getTokenExpiration(refreshTokenExpirationMinutes); + String base64EncodedSecretKey = encodedBase64SecretKey(); return generateRefreshToken(subject, expiration, base64EncodedSecretKey); } @@ -90,6 +97,22 @@ public String generateRefreshToken(String subject, Date expiration, .compact(); } + // ๋กœ๊ทธ์ธ response๋ฅผ Json ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ + public String getLoginResponseJson(Member member) { + String role = member.getRoleName(); + String nickname = member.getNickname(); + String profileImage = member.getProfileImg(); + + LoginResponseDto responseDto = new LoginResponseDto(role, nickname, profileImage); + return JsonUtil.toJson(responseDto, LoginResponseDto.class); + } + + // ํ† ํฐ ๋งŒ๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + public boolean isExpired(Jws claims) { + Date expiration = claims.getBody().getExpiration(); + return expiration.before(Calendar.getInstance().getTime()); + } + // ๊ฒ€์ฆ ํ›„, Claims๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์šฉ๋„ public Jws getClaims(String jws, String base64EncodedSecretKey) { Key key = getKeyFromBase64EncodedKey(base64EncodedSecretKey); diff --git a/server/src/main/java/actiOn/auth/role/Role.java b/server/src/main/java/actiOn/auth/role/Role.java index 83f495c6..86dcee72 100644 --- a/server/src/main/java/actiOn/auth/role/Role.java +++ b/server/src/main/java/actiOn/auth/role/Role.java @@ -1,6 +1,5 @@ package actiOn.auth.role; -import actiOn.helper.audit.BaseEntity; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -14,7 +13,7 @@ @Setter @Entity @Table(name = "ROLES") -public class Role extends BaseEntity { +public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long roleId; diff --git a/server/src/main/java/actiOn/auth/userdetails/MemberDetails.java b/server/src/main/java/actiOn/auth/userdetails/MemberDetails.java index f0a3ac37..34e1d663 100644 --- a/server/src/main/java/actiOn/auth/userdetails/MemberDetails.java +++ b/server/src/main/java/actiOn/auth/userdetails/MemberDetails.java @@ -16,6 +16,7 @@ public MemberDetails(Member member, MemberAuthorityUtil authorityUtil) { setMemberId(member.getMemberId()); setEmail(member.getEmail()); setPassword(member.getPassword()); + setProfileImg(member.getProfileImg()); setNickname(member.getNickname()); setPhoneNumber(member.getPhoneNumber()); setMemberRoles(member.getMemberRoles()); diff --git a/server/src/main/java/actiOn/auth/utils/MemberAuthorityUtil.java b/server/src/main/java/actiOn/auth/utils/MemberAuthorityUtil.java index 38b39f62..174a5b32 100644 --- a/server/src/main/java/actiOn/auth/utils/MemberAuthorityUtil.java +++ b/server/src/main/java/actiOn/auth/utils/MemberAuthorityUtil.java @@ -1,5 +1,6 @@ package actiOn.auth.utils; +import lombok.Getter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Component; @@ -11,8 +12,14 @@ // ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์„ ๋งคํ•‘, ์ƒ์„ฑํ•˜๋Š” util @Component public class MemberAuthorityUtil { - private final List USER_ROLES_STRING = List.of("USER"); - private final List PARTNER_ROLES_STRING = List.of("PARTNER", "USER"); + @Getter + private final String USER = "USER"; + + @Getter + private final String PARTNER = "PARTNER"; + + private final List USER_ROLES_STRING = List.of(USER); + private final List PARTNER_ROLES_STRING = List.of(PARTNER, USER); // DB์— ์ €์žฅ๋œ Role์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ถŒํ•œ ์ •๋ณด ์ƒ์„ฑ public List createAuthorities(List roles) { diff --git a/server/src/main/java/actiOn/auth/utils/StubDataLoader.java b/server/src/main/java/actiOn/auth/utils/StubDataLoader.java deleted file mode 100644 index 2b332637..00000000 --- a/server/src/main/java/actiOn/auth/utils/StubDataLoader.java +++ /dev/null @@ -1,298 +0,0 @@ -package actiOn.auth.utils; - -import actiOn.Img.storeImg.StoreImg; -import actiOn.Img.storeImg.StoreImgRepository; -import actiOn.item.entity.Item; -import actiOn.item.repository.ItemRepository; -import actiOn.store.entity.Store; -import actiOn.store.repository.StoreRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -@Component -public class StubDataLoader implements CommandLineRunner { - - private final StoreRepository storeRepository; - private final StoreImgRepository storeImgRepository; - private final ItemRepository itemRepository; - - public StubDataLoader(StoreRepository storeRepository, StoreImgRepository storeImgRepository, ItemRepository itemRepository) { - this.storeRepository = storeRepository; - this.storeImgRepository = storeImgRepository; - this.itemRepository = itemRepository; - } - - @Override - public void run(String... args) throws Exception { - - Store bestStore1 = new Store(); - bestStore1.setStoreId(1L); - bestStore1.setStoreName("์–ธ๋”์›Œํ„ฐํ”Œ๋ ˆ์ด ํ•จ๋•์ "); - bestStore1.setCategory("์Šค๋…ธํด๋ง/๋‹ค์ด๋น™"); - bestStore1.setBody("์ œ์ฃผ๋„ ์‹œ์›ํ•œ ๋ฐ”๋‹ท์†์—์„œ ๋‹ค์–‘ํ•œ ๋ฌผ๊ณ ๊ธฐ๋“ค์„..."); - bestStore1.setAddress("์ œ์ฃผ๋„ ์ œ์ฃผ์ ์ œ์ฃผ์‹œ"); - bestStore1.setLatitude(33.509565870437); - bestStore1.setLongitude(126.479180622209); - bestStore1.setKakao("kakaoHello"); - bestStore1.setContact("010-1111-1111"); - bestStore1.setLikeCount(100); - bestStore1.setReviewCount(100); - bestStore1.setRating(4.9); - bestStore1.setLowPrice(10000); - storeRepository.save(bestStore1); - - //-----------------------------------------------------------// - - Store bestStore2 = new Store(); - bestStore2.setStoreId(2L); - bestStore2.setStoreName("์ˆ˜์ƒ๋ ˆ์ € ๋‹ค์žˆ์–ด์ "); - bestStore2.setCategory("์ˆ˜์ƒ๋ ˆ์ €"); - bestStore2.setBody("์ˆ˜์ƒ๋ ˆ์ €๋กœ ํ•œ์—ฌ๋ฆ„์˜ ๋”์œ„ ๋‚ ๋ ค..."); - bestStore2.setAddress("์ œ์ฃผ๋„ ์ œ์ฃผ์ ์ œ์ฃผ์‹œ"); - bestStore2.setLatitude(33.509665870437); - bestStore2.setLongitude(126.479180622209); - bestStore2.setKakao("kakaoTalk"); - bestStore2.setContact("010-1112-1112"); - bestStore2.setLikeCount(99); - bestStore2.setReviewCount(100); - bestStore2.setRating(4.6); - bestStore2.setLowPrice(90000); - storeRepository.save(bestStore2); - - //------------------------------------------// - - Store bestStore3 = new Store(); - bestStore3.setStoreId(3L); - bestStore3.setStoreName("์›”์ •ํ€ต์„œํ”„"); - bestStore3.setCategory("์„œํ•‘"); - bestStore3.setBody("์—๋ฉ”๋ž„๋“œ ๋น› ํ•ด๋ณ€์—์„œ ์ด๋ฃจ์–ด์ง€๋Š” ์ „๋ฌธ ์„œํ•‘ ๊ฐ•์Šต..."); - bestStore3.setAddress("์ œ์ฃผ๋„ ์ œ์ฃผ์ ํ•จ๋•์‹œ"); - bestStore3.setLatitude(33.509535870437); - bestStore3.setLongitude(126.479180622209); - bestStore3.setKakao("kakaoSearch"); - bestStore3.setContact("010-1321-1211"); - bestStore3.setLikeCount(98); - bestStore3.setReviewCount(94); - bestStore3.setRating(3.6); - bestStore3.setLowPrice(1000900); - storeRepository.save(bestStore3); - - Store bestStore4 = new Store(); - bestStore4.setStoreId(4L); - bestStore4.setStoreName("์ œ์ฃผ๋„ ATV์ฒดํ—˜"); - bestStore4.setCategory("ATV"); - bestStore4.setBody("์ œ์ฃผ๋„์—์„œ ๋งŽ์ด ์ฆ๊ธฐ๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ์˜ ๊ฝƒ ATV..."); - bestStore4.setAddress("์ œ์ฃผ๋„ ์ œ์ฃผ์ ์ œ์ฃผ์‹œ"); - bestStore4.setLatitude(33.509525870437); - bestStore4.setLongitude(126.479180622209); - bestStore4.setKakao("kakaoMap"); - bestStore4.setContact("010-1321-1211"); - bestStore4.setLikeCount(0); - bestStore4.setReviewCount(91); - bestStore4.setRating(3.2); - bestStore4.setLowPrice(104300); - storeRepository.save(bestStore4); - - - //์ด๋ฏธ์ง€ set - List storeImgList1 = new ArrayList<>(); - StoreImg storeImg1 = new StoreImg(); - storeImg1.setImgId(1L); - storeImg1.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRV0IlkaymZEgDAQfVmTTMIrm4nRqawHOwMWA&usqp=CAU"); - storeImg1.setIsThumbnail(true); - storeImg1.setStore(bestStore1); - - StoreImg storeImg2 = new StoreImg(); - storeImg2.setImgId(2L); - storeImg2.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvTWeJ4zfReFrDCHaMnjZBGEmM-pLFNgd7oQ&usqp=CAU"); - storeImg2.setIsThumbnail(false); - storeImg2.setStore(bestStore1); - - storeImgRepository.save(storeImg1); - storeImgRepository.save(storeImg2); - - storeImgList1.add(storeImg1); - storeImgList1.add(storeImg2); - bestStore1.setStoreImgList(storeImgList1); - storeRepository.save(bestStore1); - - //--------------------------------------------------------------// - - List storeImgList2 = new ArrayList<>(); - StoreImg storeImg3 = new StoreImg(); - storeImg3.setImgId(3L); - storeImg3.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ2MU1T_daMAj_TCOxxS_WUMmLnYy57FBM8mw&usqp=CAU"); - storeImg3.setIsThumbnail(true); - storeImg3.setStore(bestStore2); - - StoreImg storeImg4 = new StoreImg(); - storeImg4.setImgId(4L); - storeImg4.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRi4Bo1grekwpSHrA7-IB0PZBIiCdTQTZlJWA&usqp=CAU"); - storeImg4.setIsThumbnail(false); - storeImg4.setStore(bestStore2); - - storeImgRepository.save(storeImg3); - storeImgRepository.save(storeImg4); - - storeImgList2.add(storeImg3); - storeImgList2.add(storeImg4); - bestStore2.setStoreImgList(storeImgList2); - storeRepository.save(bestStore2); - - //------------------------------------------------------------// - - List storeImgList3 = new ArrayList<>(); - StoreImg storeImg5 = new StoreImg(); - storeImg5.setImgId(5L); - storeImg5.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZYGC_IVAshC3is3qyNX8EmXvm5hX2f2T-UA&usqp=CAU"); - storeImg5.setIsThumbnail(true); - storeImg5.setStore(bestStore3); - - StoreImg storeImg6 = new StoreImg(); - storeImg6.setImgId(6L); - storeImg6.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQhNpcNEK2AnEQfGDDydlRg5tw-7bvd4XewNQ&usqp=CAU"); - storeImg6.setIsThumbnail(false); - storeImg6.setStore(bestStore3); - - storeImgRepository.save(storeImg5); - storeImgRepository.save(storeImg6); - - storeImgList3.add(storeImg5); - storeImgList3.add(storeImg6); - bestStore3.setStoreImgList(storeImgList3); - storeRepository.save(bestStore3); - - //--------------------------------------------------------// - - List storeImgList4 = new ArrayList<>(); - StoreImg storeImg7 = new StoreImg(); - storeImg7.setImgId(7L); - storeImg7.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTddjByXIAlIRGnr12e5EhH54T6_yUYvmrh-w&usqp=CAU"); - storeImg7.setIsThumbnail(true); - storeImg7.setStore(bestStore4); - - StoreImg storeImg8 = new StoreImg(); - storeImg8.setImgId(8L); - storeImg8.setLink("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSG3Q1-tfq7cV873Y4fvoppMrSMlUo1vG4Gwg&usqp=CAU"); - storeImg8.setIsThumbnail(false); - storeImg8.setStore(bestStore4); - - storeImgRepository.save(storeImg7); - storeImgRepository.save(storeImg8); - - storeImgList4.add(storeImg7); - storeImgList4.add(storeImg8); - bestStore3.setStoreImgList(storeImgList4); - storeRepository.save(bestStore3); - - //Item์„ ๋งŒ๋“ค์ž - List items1 = new ArrayList<>(); - - Item item1 = new Item(); - item1.setItemId(1L); - item1.setItemName("์ œ์ฃผ ์„œ๊ท€ํฌ ์ž ์ˆ˜ํ•จ"); - item1.setTotalTicket(10); - item1.setPrice(36270); - item1.setStore(bestStore1); - - Item item2 = new Item(); - item2.setItemId(2L); - item2.setItemName("๊ฐ€๋””์–ธ๋‹ค์ด๋ธŒ ์ฒดํ—˜ ์Šค์ฟ ๋ฒ„ ๋‹ค์ด๋น™"); - item2.setTotalTicket(10); - item2.setPrice(95000); - item2.setStore(bestStore1); - - itemRepository.save(item1); - itemRepository.save(item2); - - items1.add(item1); - items1.add(item2); - - bestStore1.setItems(items1); - storeRepository.save(bestStore1); - //----------------------------------// - - List items2 = new ArrayList<>(); - - Item item3 = new Item(); - item3.setItemId(3L); - item3.setItemName("๋Œ๊ณ ๋ž˜ ์—์ฝ”ํˆฌ์–ด ์„ ์…‹(์š”ํŠธํˆฌ์–ด)"); - item3.setTotalTicket(10); - item3.setPrice(39060); - item3.setStore(bestStore2); - - Item item4 = new Item(); - item4.setItemId(4L); - item4.setItemName("์ œ์ฃผ๋„ ์„œ๊ท€ํฌ ๊ทธ๋ž‘๋ธ”๋ฃจ์š”ํŠธ ์„ ์…‹"); - item4.setTotalTicket(10); - item4.setPrice(26040); - item4.setStore(bestStore2); - - itemRepository.save(item3); - itemRepository.save(item4); - - items1.add(item3); - items1.add(item4); - - bestStore2.setItems(items2); - storeRepository.save(bestStore2); - //----------------------------------// - - List items3 = new ArrayList<>(); - - Item item5 = new Item(); - item5.setItemId(5L); - item5.setItemName("์ค‘๋ฌธ์ƒ‰๋‹ฌํ•ด๋ณ€ ์„œํ•‘ ๊ฐ•์Šต"); - item5.setTotalTicket(10); - item5.setPrice(60000); - item5.setStore(bestStore3); - - Item item6 = new Item(); - item6.setItemId(6L); - item6.setItemName("๋ˆ„๋””๋‹ค์ด๋ธŒ ๋ฒ”์„ฌ ์ฒดํ—˜ ๋‹ค์ด๋น™"); - item6.setTotalTicket(10); - item6.setPrice(79000); - item6.setStore(bestStore3); - - itemRepository.save(item5); - itemRepository.save(item6); - - items1.add(item1); - items1.add(item2); - - bestStore3.setItems(items3); - storeRepository.save(bestStore3); - //----------------------------------// - - List items4 = new ArrayList<>(); - - Item item7 = new Item(); - item7.setItemId(7L); - item7.setItemName("์œจ๋žœ๋“œ ์Šค์ฟ ๋ฒ„ ๋‹ค์ด๋น™ ์ฒดํ—˜"); - item7.setTotalTicket(10); - item7.setPrice(100000); - item7.setStore(bestStore4); - - Item item8 = new Item(); - item8.setItemId(8L); - item8.setItemName("์ œ์ฃผ ํˆฌ๋ช…์นด์•ฝ/๋ฐ”๋‹ค์นด์•ฝ/์Šค๋…ธํด๋ง ์ฒดํ—˜"); - item8.setTotalTicket(10); - item8.setPrice(10000); - item8.setStore(bestStore4); - - itemRepository.save(item7); - itemRepository.save(item8); - - items1.add(item7); - items1.add(item8); - - bestStore1.setItems(items4); - storeRepository.save(bestStore4); - //----------------------------------// - } -} - diff --git a/server/src/main/java/actiOn/auth/utils/TokenPrefix.java b/server/src/main/java/actiOn/auth/utils/TokenPrefix.java index 61cefce6..f1c72744 100644 --- a/server/src/main/java/actiOn/auth/utils/TokenPrefix.java +++ b/server/src/main/java/actiOn/auth/utils/TokenPrefix.java @@ -7,7 +7,7 @@ public enum TokenPrefix { private final String type; - private TokenPrefix(String type) { + TokenPrefix(String type) { this.type = type; } diff --git a/server/src/main/java/actiOn/auth/utils/badword/BadWordFiltering.java b/server/src/main/java/actiOn/auth/utils/badword/BadWordFiltering.java index 5952dcca..cad9ca20 100644 --- a/server/src/main/java/actiOn/auth/utils/badword/BadWordFiltering.java +++ b/server/src/main/java/actiOn/auth/utils/badword/BadWordFiltering.java @@ -3,12 +3,14 @@ import actiOn.auth.utils.badword.method.ReadFile; import actiOn.auth.utils.badword.method.ReadURL; import actiOn.auth.utils.badword.words.BadWords; +import lombok.NoArgsConstructor; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; +@NoArgsConstructor public class BadWordFiltering implements BadWords, ReadFile, ReadURL { private final Set set = new HashSet<>(List.of(koreaWord1)); private String substituteValue = "*"; @@ -19,8 +21,6 @@ public BadWordFiltering(String substituteValue) { this.substituteValue = substituteValue; } - public BadWordFiltering() {} - //ํŠน์ • ๋ฌธ์ž ์ถ”๊ฐ€, ์‚ญ์ œ @Override public void add(String text) { diff --git a/server/src/main/java/actiOn/business/controller/BusinessController.java b/server/src/main/java/actiOn/business/controller/BusinessController.java deleted file mode 100644 index 52ad5be2..00000000 --- a/server/src/main/java/actiOn/business/controller/BusinessController.java +++ /dev/null @@ -1,4 +0,0 @@ -package actiOn.business.controller; - -public class BusinessController { -} diff --git a/server/src/main/java/actiOn/config/S3Configuration.java b/server/src/main/java/actiOn/config/S3Configuration.java new file mode 100644 index 00000000..90b3d60f --- /dev/null +++ b/server/src/main/java/actiOn/config/S3Configuration.java @@ -0,0 +1,29 @@ +package actiOn.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class S3Configuration { + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + public AmazonS3 amazonS3Client() { + BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } +} \ No newline at end of file diff --git a/server/src/main/java/actiOn/config/sercurity/SecurityConfiguration.java b/server/src/main/java/actiOn/config/SecurityConfiguration.java similarity index 61% rename from server/src/main/java/actiOn/config/sercurity/SecurityConfiguration.java rename to server/src/main/java/actiOn/config/SecurityConfiguration.java index 22508266..38e4f0b0 100644 --- a/server/src/main/java/actiOn/config/sercurity/SecurityConfiguration.java +++ b/server/src/main/java/actiOn/config/SecurityConfiguration.java @@ -1,4 +1,4 @@ -package actiOn.config.sercurity; +package actiOn.config; import actiOn.auth.filter.JwtAuthenticationFilter; import actiOn.auth.filter.JwtVerificationFilter; @@ -12,6 +12,8 @@ import actiOn.auth.utils.MemberAuthorityUtil; import actiOn.member.service.MemberService; import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -20,6 +22,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; @@ -30,17 +33,20 @@ import java.util.Arrays; +import static actiOn.auth.utils.TokenPrefix.REFRESH; +import static org.springframework.http.HttpMethod.*; + @Configuration @EnableWebSecurity -@AllArgsConstructor +@RequiredArgsConstructor public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private final TokenProvider tokenProvider; private final MemberAuthorityUtil authorityUtil; - private final MemberService memberService; - private final RoleService roleService; @Override protected void configure(HttpSecurity httpSecurity) throws Exception { + ApplicationContext context = getApplicationContext(); + httpSecurity .headers().frameOptions().sameOrigin() @@ -59,20 +65,58 @@ protected void configure(HttpSecurity httpSecurity) throws Exception { .accessDeniedHandler(new MemberAccessDeniedHandler()) .and() - .apply(new CustomFilterConfigurer()) + .apply(new CustomFilterConfigurer(context.getBean(MemberService.class))) .and() - .authorizeRequests(authorize -> authorize - .anyRequest().permitAll() /// Todo URI ๊ถŒํ•œ ๋ ˆ๋ฒจ ์„ค์ • - ) + .logout() + .logoutUrl("/logout") + .addLogoutHandler(((request, response, authentication) -> { + response.setHeader("Set-Cookie", REFRESH.getType() + + "=; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=0;"); + response.setHeader("Access-Control-Allow-Origin", "http://ac-ti-on.s3-website.ap-northeast-2.amazonaws.com"); + })) + .logoutSuccessUrl("http://ac-ti-on.s3-website.ap-northeast-2.amazonaws.com/home") + + .and() + .authorizeRequests(this::configureAuthorization) .oauth2Login(oAuth2 -> oAuth2 - .loginPage("/oauth2/authorization/google") - .successHandler(new OAuth2MemberSuccessHandler(memberService, roleService, tokenProvider)) + .successHandler(new OAuth2MemberSuccessHandler( + context.getBean(MemberService.class), context.getBean(RoleService.class), tokenProvider) + ) ); } + private void configureAuthorization + (ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry authorize) { + String USER = authorityUtil.getUSER(); + String PARTNER = authorityUtil.getPARTNER(); + + authorize + // PARTNER ๊ถŒํ•œ + .mvcMatchers(GET, "/mystores").hasRole(PARTNER) + .mvcMatchers(GET, "/mypage/partner").hasRole(PARTNER) + .mvcMatchers(POST, "/stores").hasRole(PARTNER) + .mvcMatchers(PATCH, "/stores/{store-id}").hasRole(PARTNER) + .mvcMatchers(DELETE, "/stores").hasRole(PARTNER) + .mvcMatchers(POST, "/storeImages/**").hasRole(PARTNER) + + // USER ๊ถŒํ•œ + .mvcMatchers(POST, "/stores/favorites/{store-id}").hasRole(USER) + .mvcMatchers(DELETE, "/stores/favorites/{store-id}").hasRole(USER) + .mvcMatchers("/payments/**").hasRole(USER) + .mvcMatchers("/partners/**").hasRole(USER) + .mvcMatchers("/reservations/**").hasRole(USER) + .mvcMatchers(POST, "/reviews").hasRole(USER) + .mvcMatchers(GET, "/mypage/**").hasRole(USER) + + .mvcMatchers("/").permitAll(); + } + // JwtAuthenticationFilter ๊ตฌ์„ฑํ•˜๋Š” ํด๋ž˜์Šค + @AllArgsConstructor public class CustomFilterConfigurer extends AbstractHttpConfigurer { + private final MemberService memberService; + @Override public void configure(HttpSecurity builder) throws Exception { AuthenticationManager authenticationManager = @@ -84,7 +128,7 @@ public void configure(HttpSecurity builder) throws Exception { jwtAuthenticationFilter.setAuthenticationSuccessHandler(new MemberAuthenticationSuccessHandler(tokenProvider)); jwtAuthenticationFilter.setAuthenticationFailureHandler(new MemberAuthenticationFailureHandler()); - JwtVerificationFilter jwtVerificationFilter = new JwtVerificationFilter(tokenProvider, authorityUtil); + JwtVerificationFilter jwtVerificationFilter = new JwtVerificationFilter(tokenProvider, authorityUtil, memberService); // Spring Security Filter Chain์— ์ถ”๊ฐ€ builder.addFilter(jwtAuthenticationFilter) @@ -102,18 +146,17 @@ CorsConfigurationSource corsConfigurationSource() { Arrays.asList( "http://localhost:3000", "https://acti-on.netlify.app", - "https://6f76-222-232-33-89.ngrok-free.app", "http://localhost:5173", - "http://ec2-52-78-205-102.ap-northeast-2.compute.amazonaws.com" - // TODO S3 ์—”๋“œํฌ์ธํŠธ ์ถ”๊ฐ€ "" + "http://ec2-52-78-205-102.ap-northeast-2.compute.amazonaws.com:8080", + "http://ac-ti-on.s3-website.ap-northeast-2.amazonaws.com" ) ); - configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE")); - configuration.setAllowCredentials(true); configuration.setMaxAge(2000L); - configuration.setAllowedHeaders(Arrays.asList("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization")); - configuration.setExposedHeaders(Arrays.asList("authorization", "refresh")); + configuration.setAllowedHeaders(Arrays.asList("*")); +// configuration.setAllowedHeaders(Arrays.asList("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization", "Refresh", "Set-Cookie")); + configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE")); + configuration.setExposedHeaders(Arrays.asList("Authorization", "Refresh")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); diff --git a/server/src/main/java/actiOn/config/payments/TossPaymentsConfiguration.java b/server/src/main/java/actiOn/config/payments/TossPaymentsConfiguration.java new file mode 100644 index 00000000..c57cd578 --- /dev/null +++ b/server/src/main/java/actiOn/config/payments/TossPaymentsConfiguration.java @@ -0,0 +1,18 @@ +package actiOn.config.payments; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Getter +public class TossPaymentsConfiguration { + @Value("${payment.toss.test-client-key}") + private String testClientKey; + + @Value("${payment.toss.test-secret-key}") + private String testSecretKey; + + @Value("${payment.toss.url}") + private String url; +} diff --git a/server/src/main/java/actiOn/exception/ExceptionCode.java b/server/src/main/java/actiOn/exception/ExceptionCode.java index b68ad07e..ad9c68e9 100644 --- a/server/src/main/java/actiOn/exception/ExceptionCode.java +++ b/server/src/main/java/actiOn/exception/ExceptionCode.java @@ -5,9 +5,9 @@ public enum ExceptionCode { // MEMBER MEMBER_NOT_FOUND(404, "Member not found"), - MEMBER_EXISTS(409, "Member exists"), + MEMBER_EXISTS(403, "Member exists"), NICKNAME_EXISTS(409, "member nickname exists"), - PHONE_NUMBER_EXISTS(409, "member phone number exists"), + PHONE_NUMBER_EXISTS(422, "member phone number exists"), MEMBER_NOT_AUTHORIZED(403, "Member not authorized"), PROFILE_IMAGE_NOT_FOUND(404, "Profile image not found"), @@ -18,17 +18,19 @@ public enum ExceptionCode { INVALID_MEMBER(400, "Invalid member access"), // BUSINESS - BUSINESS_EXISTS(409, "Registration number exists."), + BUSINESS_EXISTS(409, "Registration number exists"), INVALID_REGISTRATION_NUMBER(400, "Invalid registration number format"), // STORE STORE_NOT_FOUND(404, "Store not found"), + STORE_IMAGE_NOT_FOUND(404, "Store Image Not Found"), NOT_IMPLEMENTATION(501, "Not Implementation"), INVALID_SORT_PARAMETER(400, "Invalid parameter named 'sort'"), NULL_STORE_IMAGE(404, "Store image is null"), THUMBNAIL_NOT_FOUND(404, "Store thumbnail not found"), UNAUTHORIZED(401, "Unauthorized to update store"), INVALID_PARAMETER_VALUE(400, "INVALID_PARAMETER_VALUE"), + BAD_REQUEST(400, "Bad Request!"), // RESERVATION RESERVATION_NOT_FOUND(404, "Reservation not found"), @@ -41,13 +43,27 @@ public enum ExceptionCode { REQUEST_ITEM_ID_IS_REJECTED(400, "Request itemId is rejected!"), REVIEW_CREATE_REJECTED(400, "์‚ฌ์šฉ์™„๋ฃŒ ์˜ˆ์•ฝ๊ฑด์„ ์ดˆ๊ณผํ•˜์—ฌ ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), DATE_BAD_REQUEST(400, "๋‚ ์งœํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + //WISH WISH_EXIST(409, "Wish exists"), WISH_NOT_FOUND(404, "Wish not found"), // ITEM - ITEM_NOT_FOUND(404, "Item not found"); + ITEM_NOT_FOUND(404, "Item not found"), + + // PAYMENT + INVALID_PAYMENT_AMOUNT(400, "Invalid payment total amount"), + PAYMENT_NOT_FOUND(404, "Payment not found"), + NOT_FOUND_PAYMENT(404, "์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฐ์ œ ์ •๋ณด์ž…๋‹ˆ๋‹ค."), + PAYMENT_AMOUNT_MISMATCH(422, "Total amounts do not match"), + // REVIEW + BAD_WORD_NOT_ALLOWED(400, "๋ฐ”๋ฅธ๋ง์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."), + ONLY_RESERVED_MEMBER_REVIEW(404, "Only members using the store can review"), + BEFORE_STORE_USE_COMPLETE(422, "์ด์šฉ ์™„๋ฃŒ ์ „์ž…๋‹ˆ๋‹ค."), + ALREADY_WROTE_A_REVIEW(409, "์ด๋ฏธ ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•˜์…จ์Šต๋‹ˆ๋‹ค."), + REJECTED_UPDATE(400, "์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.") + ; @Getter private int status; diff --git a/server/src/main/java/actiOn/exception/advice/GlobalExceptionAdvice.java b/server/src/main/java/actiOn/exception/advice/GlobalExceptionAdvice.java index 65bd6a65..8656f177 100644 --- a/server/src/main/java/actiOn/exception/advice/GlobalExceptionAdvice.java +++ b/server/src/main/java/actiOn/exception/advice/GlobalExceptionAdvice.java @@ -43,8 +43,7 @@ public ErrorResponse handleConstraintViolationException(ConstraintViolationExcep public ResponseEntity handleBusinessLogicException(BusinessLogicException e) { final ErrorResponse response = ErrorResponse.of(e.getExceptionCode()); - return new ResponseEntity<>(response, - HttpStatus.valueOf(e.getExceptionCode().getStatus())); + return new ResponseEntity<>(response, HttpStatus.valueOf(e.getExceptionCode().getStatus())); } // ํŠน์ • URL์— HTTP ๋ฉ”์„œ๋“œ ์š”์ฒญ์ด ์ž˜๋ชป๋œ ๊ฒฝ์šฐ ๋“ฑ diff --git a/server/src/main/java/actiOn/helper/validator/NotSpaceValidator.java b/server/src/main/java/actiOn/helper/validator/NotSpaceValidator.java index 4c696ffc..aef0c084 100644 --- a/server/src/main/java/actiOn/helper/validator/NotSpaceValidator.java +++ b/server/src/main/java/actiOn/helper/validator/NotSpaceValidator.java @@ -5,7 +5,7 @@ import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; -public class NotSpaceValidator implements ConstraintValidator { +public class NotSpaceValidator implements ConstraintValidator { @Override public void initialize(NotSpace constraintAnnotation) { diff --git a/server/src/main/java/actiOn/item/controller/ItemController.java b/server/src/main/java/actiOn/item/controller/ItemController.java deleted file mode 100644 index 8e89ed1f..00000000 --- a/server/src/main/java/actiOn/item/controller/ItemController.java +++ /dev/null @@ -1,9 +0,0 @@ -package actiOn.item.controller; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - - -public class ItemController { - -} diff --git a/server/src/main/java/actiOn/item/dto/ItemDto.java b/server/src/main/java/actiOn/item/dto/ItemDto.java index 7c8ddd03..f0384fce 100644 --- a/server/src/main/java/actiOn/item/dto/ItemDto.java +++ b/server/src/main/java/actiOn/item/dto/ItemDto.java @@ -5,13 +5,22 @@ import lombok.Getter; import lombok.Setter; +import javax.validation.constraints.Min; + @Getter @Setter @AllArgsConstructor public class ItemDto { long itemId; + String itemName; + + @Min(0) int totalTicket; + + @Min(0) int price; + + @Min(0) int remainingTicket; } diff --git a/server/src/main/java/actiOn/item/entity/Item.java b/server/src/main/java/actiOn/item/entity/Item.java index 61defc93..45b9651a 100644 --- a/server/src/main/java/actiOn/item/entity/Item.java +++ b/server/src/main/java/actiOn/item/entity/Item.java @@ -12,9 +12,8 @@ @Setter @Entity public class Item { - - @GeneratedValue(strategy = GenerationType.IDENTITY) @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ITEM_ID") private Long itemId; @@ -35,12 +34,6 @@ public class Item { @JoinColumn(name = "STORE_ID") private Store store; - public void validateTicketCount(int ticketCount) { - if (ticketCount > this.totalTicket) { - throw new IllegalArgumentException("ํ‹ฐ์ผ“ ์ˆ˜๊ฐ€ ์ตœ๋Œ€ ํ—ˆ์šฉ๋Ÿ‰์„ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค."); - } - } - public enum ItemStatus { SAVED, DELETED } diff --git a/server/src/main/java/actiOn/item/mapper/ItemMapper.java b/server/src/main/java/actiOn/item/mapper/ItemMapper.java deleted file mode 100644 index 7742cfce..00000000 --- a/server/src/main/java/actiOn/item/mapper/ItemMapper.java +++ /dev/null @@ -1,4 +0,0 @@ -package actiOn.item.mapper; - -public class ItemMapper { -} diff --git a/server/src/main/java/actiOn/item/repository/ItemRepository.java b/server/src/main/java/actiOn/item/repository/ItemRepository.java index fdd81048..d6ceb71e 100644 --- a/server/src/main/java/actiOn/item/repository/ItemRepository.java +++ b/server/src/main/java/actiOn/item/repository/ItemRepository.java @@ -7,6 +7,4 @@ import java.util.Optional; public interface ItemRepository extends JpaRepository { - Optional findItemByItemId(Long itemId); - } diff --git a/server/src/main/java/actiOn/item/service/ItemService.java b/server/src/main/java/actiOn/item/service/ItemService.java index be38aec6..a69966b5 100644 --- a/server/src/main/java/actiOn/item/service/ItemService.java +++ b/server/src/main/java/actiOn/item/service/ItemService.java @@ -30,6 +30,7 @@ public Item findItem(Long itemId) { public List updateItems(List findItems, List newItems) { Store parentStore = findItems.get(0).getStore(); itemStatusChange(findItems); + List items = new ArrayList<>(); for (Item item : newItems) { Item newItem = new Item(); diff --git a/server/src/main/java/actiOn/member/controller/MemberController.java b/server/src/main/java/actiOn/member/controller/MemberController.java index 324af125..553359fa 100644 --- a/server/src/main/java/actiOn/member/controller/MemberController.java +++ b/server/src/main/java/actiOn/member/controller/MemberController.java @@ -1,5 +1,7 @@ package actiOn.member.controller; +import actiOn.Img.dto.ProfileImgDto; +import actiOn.auth.dto.LoginResponseDto; import actiOn.auth.utils.AuthUtil; import actiOn.business.dto.BusinessDto; import actiOn.business.entity.Business; @@ -41,13 +43,23 @@ public ResponseEntity signupMember(@RequestBody @Valid MemberPostDto.Signup requ return new ResponseEntity<>(HttpStatus.CREATED); } + @GetMapping("/google/login") + public ResponseEntity oauth2LoginSuccess() { + String email = AuthUtil.getCurrentMemberEmail(); + Member member = memberService.findMemberByEmail(email); + + LoginResponseDto response = memberMapper.memberGoogleLoginResponseDto(member); + return new ResponseEntity<>(response, HttpStatus.OK); + } + // ํšŒ์› ํ”„๋กœํ•„ ์‚ฌ์ง„ ๋“ฑ๋ก @PutMapping("/mypage/profile") public ResponseEntity uploadProfileImage(@RequestParam("image") MultipartFile profileImage) throws IOException { String email = AuthUtil.getCurrentMemberEmail(); - memberService.registerProfileImage(profileImage, email); + Member member = memberService.registerProfileImage(profileImage, email); - return new ResponseEntity<>(HttpStatus.OK); + ProfileImgDto response = memberMapper.profileImgResponseDto(member); + return new ResponseEntity<>(response, HttpStatus.OK); } // ํšŒ์› ํ”„๋กœํ•„ ์‚ฌ์ง„ ์‚ญ์ œ @@ -135,7 +147,7 @@ public ResponseEntity getMemberReservations() { return new ResponseEntity<>(response, HttpStatus.OK); } - // ๋งˆ์ดํŽ˜์ด์ง€ - ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ + // ๋งˆ์ดํŽ˜์ด์ง€ - ํŒŒํŠธ๋„ˆ ํŒ๋งค ์„œ๋น„์Šค ๊ด€๋ฆฌ @GetMapping("/mystores") public ResponseEntity getPartnerStores() { String email = AuthUtil.getCurrentMemberEmail(); diff --git a/server/src/main/java/actiOn/member/dto/MemberReservationResponseDto.java b/server/src/main/java/actiOn/member/dto/MemberReservationResponseDto.java index 6002c422..47832353 100644 --- a/server/src/main/java/actiOn/member/dto/MemberReservationResponseDto.java +++ b/server/src/main/java/actiOn/member/dto/MemberReservationResponseDto.java @@ -15,6 +15,7 @@ public class MemberReservationResponseDto { @Getter public static class MemberReservationDto { private Long storeId; + private Long reservationId; private String kakao; private String storeImg; private String storeName; diff --git a/server/src/main/java/actiOn/member/dto/PartnerResponseDto.java b/server/src/main/java/actiOn/member/dto/PartnerResponseDto.java index 78e548d5..999c2b12 100644 --- a/server/src/main/java/actiOn/member/dto/PartnerResponseDto.java +++ b/server/src/main/java/actiOn/member/dto/PartnerResponseDto.java @@ -10,6 +10,7 @@ @Getter @Setter @Builder +@AllArgsConstructor public class PartnerResponseDto { private List stores; diff --git a/server/src/main/java/actiOn/member/entity/Member.java b/server/src/main/java/actiOn/member/entity/Member.java index e8f7d78c..7d8b46d3 100644 --- a/server/src/main/java/actiOn/member/entity/Member.java +++ b/server/src/main/java/actiOn/member/entity/Member.java @@ -1,9 +1,9 @@ package actiOn.member.entity; -import actiOn.Img.profileImg.ProfileImg; import actiOn.auth.role.MemberRole; import actiOn.business.entity.Business; import actiOn.helper.audit.BaseEntity; +import actiOn.payment.entity.Payment; import actiOn.reservation.entity.Reservation; import actiOn.store.entity.Store; import actiOn.wish.entity.Wish; @@ -22,6 +22,8 @@ @Setter @Entity public class Member extends BaseEntity implements Principal { + private static final String DEFAULT_LINK = "default image"; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long memberId; @@ -32,14 +34,16 @@ public class Member extends BaseEntity implements Principal { @Column(nullable = false) private String password; - @Column(nullable = false) + @Column(nullable = false, unique = true) private String nickname; - @Column + @Column(unique = true) private String phoneNumber; - @OneToMany(mappedBy = "member", fetch = FetchType.EAGER, - cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.REFRESH}) + @Column(nullable = false) + private String profileImg; + + @OneToMany(mappedBy = "member", fetch = FetchType.EAGER, cascade = CascadeType.ALL) private List memberRoles = new ArrayList<>(); @OneToOne(mappedBy = "member") @@ -54,9 +58,8 @@ public class Member extends BaseEntity implements Principal { @OneToMany(mappedBy = "member") private List reservations = new ArrayList<>(); - @OneToOne(mappedBy = "member", fetch = FetchType.EAGER, - cascade = {CascadeType.REMOVE, CascadeType.PERSIST}) - private ProfileImg profileImg; + @OneToMany(mappedBy = "customer") + private List payments = new ArrayList<>(); @Override public String getName() { @@ -83,12 +86,7 @@ public String getRoleName() { } // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋งํฌ ๋ฐ˜ํ™˜ - public String getProfileImgLink() { - // ํ”„๋กœํ•„ ์‚ฌ์ง„ null์ธ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€ ๋งํฌ ๋ฆฌํ„ด - if (this.getProfileImg() == null) { - return "default image"; - } - - return this.getProfileImg().getLink(); + public String getDefaultImageLink() { + return DEFAULT_LINK; } } diff --git a/server/src/main/java/actiOn/member/mapper/MemberMapper.java b/server/src/main/java/actiOn/member/mapper/MemberMapper.java index 64ca8866..93ea4b4d 100644 --- a/server/src/main/java/actiOn/member/mapper/MemberMapper.java +++ b/server/src/main/java/actiOn/member/mapper/MemberMapper.java @@ -1,6 +1,8 @@ package actiOn.member.mapper; +import actiOn.Img.dto.ProfileImgDto; import actiOn.Img.storeImg.StoreImg; +import actiOn.auth.dto.LoginResponseDto; import actiOn.exception.BusinessLogicException; import actiOn.exception.ExceptionCode; import actiOn.member.dto.*; @@ -20,12 +22,13 @@ public interface MemberMapper { Member memberPatchDtoToMember(MemberPatchDto requestBody); + default MemberResponseDto memberToMemberResponseDto(Member member) { return MemberResponseDto.builder() .nickname(member.getNickname()) .email(member.getEmail()) .phoneNumber(member.getPhoneNumber()) - .profileImg(member.getProfileImgLink()) + .profileImg(member.getProfileImg()) .build(); } @@ -53,7 +56,7 @@ default List storesToPartnerResponseDtos(List storesToPartnerStoreRespon return partnerStoreDtos; } - PartnerStoreResponseDto.PartnerStoreDto storeToPartnerStoreResponseDto(Store store); + default PartnerStoreResponseDto.PartnerStoreDto storeToPartnerStoreResponseDto(Store store) { + List storeImgList = store.getStoreImgList(); + String storeThumbnailImgLink = findThumbnailImage(storeImgList).getLink(); + + return PartnerStoreResponseDto.PartnerStoreDto + .builder() + .storeId(store.getStoreId()) + .storeImage(storeThumbnailImgLink) + .storeName(store.getStoreName()) + .build(); + } // ์˜ˆ์•ฝ ๋‚ด์—ญ ์กฐํšŒ DTO default MemberReservationResponseDto memberToMemberReservationsDto(Member member) { @@ -121,6 +134,7 @@ default MemberReservationResponseDto.MemberReservationDto reservationToMemberRes builder.storeName(store.getStoreName()); builder.reservationDate(reservation.getReservationDate()); builder.totalPrice(reservation.getTotalPrice()); + builder.reservationId(reservation.getReservationId()); builder.itemCount(reservation.getReservationItems().size()); builder.reservationStatus(reservation.getReservationStatus().getStepDescription()); @@ -134,4 +148,21 @@ default StoreImg findThumbnailImage(List storeImgList) { .findAny() .orElseThrow(() -> new BusinessLogicException(ExceptionCode.THUMBNAIL_NOT_FOUND)); } + + // ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ์ดํ›„ response + default LoginResponseDto memberGoogleLoginResponseDto(Member member) { + return LoginResponseDto.builder() + .role(member.getRoleName()) + .nickname(member.getNickname()) + .profileImage(member.getProfileImg()) + .build(); + } + + // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ˆ˜์ • ์‹œ response + default ProfileImgDto profileImgResponseDto(Member member) { + return ProfileImgDto.builder() + .nickname(member.getNickname()) + .profileImage(member.getProfileImg()) + .build(); + } } \ No newline at end of file diff --git a/server/src/main/java/actiOn/member/service/MemberService.java b/server/src/main/java/actiOn/member/service/MemberService.java index b10ce265..b5e901f9 100644 --- a/server/src/main/java/actiOn/member/service/MemberService.java +++ b/server/src/main/java/actiOn/member/service/MemberService.java @@ -1,6 +1,5 @@ package actiOn.member.service; -import actiOn.Img.profileImg.ProfileImg; import actiOn.Img.service.ImgService; import actiOn.auth.role.MemberRole; import actiOn.auth.role.Role; @@ -32,12 +31,14 @@ public class MemberService { private final RoleService roleService; // ํšŒ์› ๋“ฑ๋ก - @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE) + @Transactional(propagation = Propagation.REQUIRED) public Member createMember(Member member) { // ์ด๋ฉ”์ผ, ๋‹‰๋„ค์ž„, ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ ์ค‘๋ณต ๊ฒ€์‚ฌ verifyExistsEmail(member.getEmail()); verifyExistsNickname(member.getNickname()); - verifyExistsPhoneNumber(member.getPhoneNumber()); + if (member.getPhoneNumber() != null) { + verifyExistsPhoneNumber(member.getPhoneNumber()); + } // Password ๋‹จ๋ฐฉํ–ฅ ์•”ํ˜ธํ™” String encryptedPW = encoder.encode(member.getPassword()); @@ -48,9 +49,9 @@ public Member createMember(Member member) { List memberRoles = addedMemberRole(member, userRole); member.setMemberRoles(memberRoles); - // ๊ธฐ๋ณธ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ €์žฅ - ProfileImg profileImg = imgService.setDefaultProfileImage(member); - member.setProfileImg(profileImg); + // ๊ธฐ๋ณธ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ๋ก + String defaultImage = member.getDefaultImageLink(); + member.setProfileImg(defaultImage); return memberRepository.save(member); } @@ -94,13 +95,24 @@ public Member registerPartnership(Business business, String email) { // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ๋ก @Transactional(propagation = Propagation.REQUIRED) - public void registerProfileImage(MultipartFile file, String email) throws IOException { + public Member registerProfileImage(MultipartFile file, String email) throws IOException { Member member = findMemberByEmail(email); // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ - ProfileImg profileImg = imgService.uploadProfileImage(file, member); + String profileImg = imgService.uploadProfileImage(file, member); member.setProfileImg(profileImg); + return memberRepository.save(member); + } + + // ๊ตฌ๊ธ€ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ๋“ฑ๋ก + @Transactional(propagation = Propagation.REQUIRED) + public void registerGoogleProfileImage(String profileImgUrl, String email) { + Member member = findMemberByEmail(email); + + // ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ + member.setProfileImg(profileImgUrl); + memberRepository.save(member); } @@ -109,12 +121,8 @@ public void registerProfileImage(MultipartFile file, String email) throws IOExce public void deleteProfileImage(String email) { Member member = findMemberByEmail(email); - // ๊ธฐ์กด ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ status DELETED๋กœ ๋ณ€๊ฒฝ - imgService.updateProfileImageStatusDeleted(member); - - // ๊ธฐ๋ณธ ํ”„๋กœํ•„๋กœ ๋ณ€๊ฒฝ - ProfileImg defaultImage = imgService.getDefaultProfileImage(member); - member.setProfileImg(defaultImage); + String defaultProfileImg = member.getDefaultImageLink(); + member.setProfileImg(defaultProfileImg); memberRepository.save(member); } @@ -171,7 +179,6 @@ private void verifyExistsNickname(String nickname) { public boolean isExistMember(String email) { Optional member = memberRepository.findByEmail(email); - return member.isPresent(); } } diff --git a/server/src/main/java/actiOn/payment/controller/PaymentController.java b/server/src/main/java/actiOn/payment/controller/PaymentController.java deleted file mode 100644 index cea5009e..00000000 --- a/server/src/main/java/actiOn/payment/controller/PaymentController.java +++ /dev/null @@ -1,4 +0,0 @@ -package actiOn.payment.controller; - -public class PaymentController { -} diff --git a/server/src/main/java/actiOn/payment/dto/PaymentCancelDto.java b/server/src/main/java/actiOn/payment/dto/PaymentCancelDto.java new file mode 100644 index 00000000..f37a136d --- /dev/null +++ b/server/src/main/java/actiOn/payment/dto/PaymentCancelDto.java @@ -0,0 +1,11 @@ +package actiOn.payment.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PaymentCancelDto { + private Long cancelAmount; + private String cancelReason = "๊ณ ๊ฐ๋ณ€์‹ฌ"; +} diff --git a/server/src/main/java/actiOn/payment/dto/PaymentConfirmDto.java b/server/src/main/java/actiOn/payment/dto/PaymentConfirmDto.java new file mode 100644 index 00000000..75b02ec8 --- /dev/null +++ b/server/src/main/java/actiOn/payment/dto/PaymentConfirmDto.java @@ -0,0 +1,12 @@ +package actiOn.payment.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PaymentConfirmDto { + private Long Amount; + private String orderId; + private String paymentKey; +} diff --git a/server/src/main/java/actiOn/payment/dto/PaymentDto.java b/server/src/main/java/actiOn/payment/dto/PaymentDto.java index 32bc380a..d4956b2e 100644 --- a/server/src/main/java/actiOn/payment/dto/PaymentDto.java +++ b/server/src/main/java/actiOn/payment/dto/PaymentDto.java @@ -1,4 +1,31 @@ package actiOn.payment.dto; +import lombok.Builder; +import lombok.Getter; +import org.hibernate.validator.constraints.Range; + +import javax.validation.constraints.NotBlank; + +@Builder +@Getter public class PaymentDto { + @NotBlank + private String paymentKey; + + @NotBlank + private String payType; + + @NotBlank + private String payMethod; + + @NotBlank + @Range(min = 0, max = 100_000_000) + private Long totalAmount; + + @NotBlank + private String orderId; + + @NotBlank + private String orderName; + } diff --git a/server/src/main/java/actiOn/payment/dto/PaymentInfoDto.java b/server/src/main/java/actiOn/payment/dto/PaymentInfoDto.java new file mode 100644 index 00000000..b1e85d98 --- /dev/null +++ b/server/src/main/java/actiOn/payment/dto/PaymentInfoDto.java @@ -0,0 +1,28 @@ +package actiOn.payment.dto; + + +import actiOn.payment.entity.Payment; +import actiOn.payment.entity.PaymentCancel; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Getter +@Setter +public class PaymentInfoDto { + private String orderId; + private String paymentKey; + private Payment.PayType type; +// private PaymentCancel cancels; + private String orderName; + private Payment.PayMethod method; + private Long totalAmount; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX") + private LocalDateTime requestedAt; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX") + private LocalDateTime approvedAt; + private Payment.Status status; + +} diff --git a/server/src/main/java/actiOn/payment/dto/PaymentResponseDto.java b/server/src/main/java/actiOn/payment/dto/PaymentResponseDto.java new file mode 100644 index 00000000..7ca89394 --- /dev/null +++ b/server/src/main/java/actiOn/payment/dto/PaymentResponseDto.java @@ -0,0 +1,28 @@ +package actiOn.payment.dto; + +import actiOn.member.entity.Member; +import actiOn.payment.entity.Payment; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Builder +public class PaymentResponseDto { + private String payType; + private Long amount; + private String orderName; + private String paymentKey; + private String orderId; + private String customerEmail; + private String customerName; +// private String successUrl; +// private String failUrl; + + private Payment.Status status; + private String failReason; +// private boolean cancelYN; + private String cancelReason; + private String createdAt; +} diff --git a/server/src/main/java/actiOn/payment/entity/Payment.java b/server/src/main/java/actiOn/payment/entity/Payment.java index f80e31a5..8a6c1201 100644 --- a/server/src/main/java/actiOn/payment/entity/Payment.java +++ b/server/src/main/java/actiOn/payment/entity/Payment.java @@ -1,4 +1,79 @@ package actiOn.payment.entity; -public class Payment { +import actiOn.helper.audit.BaseEntity; +import actiOn.member.entity.Member; +import actiOn.reservation.entity.Reservation; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@Entity +@Getter +@Setter +@NoArgsConstructor +public class Payment extends BaseEntity { + @Id + @GeneratedValue + private Long paymentId; + + @Column + private String paymentKey; + + @Column + @Enumerated(EnumType.STRING) + private PayType payType; + + @Column + @Enumerated(EnumType.STRING) + private PayMethod payMethod; + + @Column(nullable = false) + private Long totalAmount; + + @Column(nullable = false) + private String orderId; + + @Column + private String orderName; + + @Enumerated(EnumType.STRING) + @Column + private Status status = Status.READY; + + @Column + private LocalDateTime requestedAt; + + @Column + private LocalDateTime approvedAt; + + @ManyToOne + @JoinColumn(name = "MEMBER_ID") + private Member customer; + + @OneToOne(mappedBy = "payment") + private PaymentCancel cancel; + + public enum PayType { + NORMAL, + BILLING, + BRANDPAY + } + + public enum PayMethod { + ์นด๋“œ, ๊ฐ€์ƒ๊ณ„์ขŒ, ๊ฐ„ํŽธ๊ฒฐ์ œ, ๊ณ„์ขŒ์ด์ฒด + } + + public enum Status { + READY, + IN_PROGRESS, + WAITING_FOR_DEPOSIT, + DONE, + CANCELED, + PARTIAL_CANCELED, + ABORTED, + EXPIRED + } } diff --git a/server/src/main/java/actiOn/payment/entity/PaymentCancel.java b/server/src/main/java/actiOn/payment/entity/PaymentCancel.java new file mode 100644 index 00000000..cb2ab25a --- /dev/null +++ b/server/src/main/java/actiOn/payment/entity/PaymentCancel.java @@ -0,0 +1,21 @@ +package actiOn.payment.entity; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.*; + +@Entity +@Getter +@Setter +@NoArgsConstructor +public class PaymentCancel { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long cancelId; + + @OneToOne + @JoinColumn(name = "PAYMENT_ID") + private Payment payment; +} diff --git a/server/src/main/java/actiOn/payment/mapper/PaymentMapper.java b/server/src/main/java/actiOn/payment/mapper/PaymentMapper.java index fb55f888..201398ef 100644 --- a/server/src/main/java/actiOn/payment/mapper/PaymentMapper.java +++ b/server/src/main/java/actiOn/payment/mapper/PaymentMapper.java @@ -1,4 +1,37 @@ package actiOn.payment.mapper; -public class PaymentMapper { +import actiOn.exception.BusinessLogicException; +import actiOn.exception.ExceptionCode; +import actiOn.payment.dto.PaymentDto; +import actiOn.payment.dto.PaymentInfoDto; +import actiOn.payment.dto.PaymentResponseDto; +import actiOn.payment.entity.Payment; +import org.mapstruct.Mapper; +import org.springframework.stereotype.Component; + +@Mapper(componentModel = "spring") +@Component +public interface PaymentMapper { + Payment paymentDtoToPayment(PaymentDto requestBody); + + PaymentResponseDto paymentToPaymentResponseDto(Payment payment); + + default Payment paymentInfoDtoToPayment(PaymentInfoDto paymentInfoDto){ + if (paymentInfoDto==null) { + throw new BusinessLogicException(ExceptionCode.NOT_FOUND_PAYMENT); + } + Payment payment = new Payment(); + payment.setPaymentKey(paymentInfoDto.getPaymentKey()); + payment.setOrderName(paymentInfoDto.getOrderName()); + payment.setPayType(paymentInfoDto.getType()); + payment.setPayMethod(paymentInfoDto.getMethod()); + payment.setOrderId(paymentInfoDto.getOrderId()); + payment.setTotalAmount(paymentInfoDto.getTotalAmount()); + payment.setStatus(paymentInfoDto.getStatus()); + payment.setApprovedAt(paymentInfoDto.getApprovedAt()); + payment.setRequestedAt(paymentInfoDto.getRequestedAt()); + return payment; + } } + + diff --git a/server/src/main/java/actiOn/payment/repository/PaymentCancelRepository.java b/server/src/main/java/actiOn/payment/repository/PaymentCancelRepository.java new file mode 100644 index 00000000..5a68b45e --- /dev/null +++ b/server/src/main/java/actiOn/payment/repository/PaymentCancelRepository.java @@ -0,0 +1,8 @@ +package actiOn.payment.repository; + +import actiOn.payment.entity.PaymentCancel; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PaymentCancelRepository extends JpaRepository { + +} diff --git a/server/src/main/java/actiOn/payment/repository/PaymentRepository.java b/server/src/main/java/actiOn/payment/repository/PaymentRepository.java index 07c9fbb7..7d02e8f0 100644 --- a/server/src/main/java/actiOn/payment/repository/PaymentRepository.java +++ b/server/src/main/java/actiOn/payment/repository/PaymentRepository.java @@ -1,4 +1,14 @@ package actiOn.payment.repository; -public interface PaymentRepository { +import actiOn.payment.entity.Payment; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PaymentRepository extends JpaRepository { + Optional findByOrderId(String orderId); + + Optional findByPaymentKeyAndCustomer_Email(String paymentKey, String email); + + Payment findByPaymentKey(String payment); } diff --git a/server/src/main/java/actiOn/payment/service/PaymentService.java b/server/src/main/java/actiOn/payment/service/PaymentService.java index c7fa22e1..bcd57ac8 100644 --- a/server/src/main/java/actiOn/payment/service/PaymentService.java +++ b/server/src/main/java/actiOn/payment/service/PaymentService.java @@ -1,4 +1,183 @@ package actiOn.payment.service; +import actiOn.auth.utils.AuthUtil; +import actiOn.exception.BusinessLogicException; +import actiOn.exception.ExceptionCode; +import actiOn.member.entity.Member; +import actiOn.member.service.MemberService; +import actiOn.payment.dto.PaymentCancelDto; +import actiOn.payment.dto.PaymentConfirmDto; +import actiOn.payment.dto.PaymentInfoDto; +import actiOn.payment.entity.Payment; +import actiOn.payment.entity.PaymentCancel; +import actiOn.payment.repository.PaymentCancelRepository; +import actiOn.payment.repository.PaymentRepository; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Optional; + +@Service +@RequiredArgsConstructor public class PaymentService { + private final PaymentRepository paymentRepository; + private final MemberService memberService; + private final PaymentCancelRepository paymentCancelRepository; + + @Value("${payment.toss.test-client-key}") + @Getter + private String clientKey; + + @Value("${payment.toss.test-secret-key}") + @Getter + private String secretKey; + + @Value("${payment.toss.url}") + private String tossPaymentURL; + + @Transactional(isolation = Isolation.SERIALIZABLE) + public Payment requestPayment(String email, Payment payment) { + Member customer = memberService.findMemberByEmail(email); + + // ์ด ๊ฒฐ์ œ ๊ธˆ์•ก์ด 0 ์ดํ•˜์ธ ๊ฒฝ์šฐ + if (payment.getTotalAmount() <= 0) { + throw new BusinessLogicException(ExceptionCode.INVALID_PAYMENT_AMOUNT); + } + + payment.setCustomer(customer); + return paymentRepository.save(payment); + } + + @Transactional(isolation = Isolation.SERIALIZABLE) + public void handlePaymentSuccess(Payment payment, Long totalAmount, String email) { + Member customer = memberService.findMemberByEmail(email); + + verifyTotalAmount(payment, totalAmount); + + payment.setCustomer(customer); + } + + // ์กด์žฌํ•˜๋Š” ๊ฒฐ์ œ์ธ์ง€ ํ™•์ธ + public Payment findExistsPayment(String orderId) { + Optional payment = paymentRepository.findByOrderId(orderId); + + if (payment.isEmpty()) { + throw new BusinessLogicException(ExceptionCode.PAYMENT_NOT_FOUND); + } + return payment.get(); + } + + // ์ด ๊ฒฐ์ œ ๊ธˆ์•ก ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ + private void verifyTotalAmount(Payment payment, long totalAmount) { + if (payment.getTotalAmount() != totalAmount) { + throw new BusinessLogicException(ExceptionCode.PAYMENT_AMOUNT_MISMATCH); + } + } + + /** ========================================================= */ + /** + * ์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” ํ† ์ŠคํŽ˜์ด๋จผ์ธ ๋กœ ๊ฑฐ๋ž˜ ๋‚ด์—ญ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. + **/ + private String generateAuthToBase64() { + //Todo base64๋ฅผ ์ด์šฉํ•ด์„œ, secretKey๋ฅผ ์ธ์ฝ”๋”ฉ ํ•ด์•ผํ•จ + byte[] secretKeyBytes = (secretKey + ":").getBytes(StandardCharsets.UTF_8); + String encodedSecretKey = Base64.getEncoder().encodeToString(secretKeyBytes); + return encodedSecretKey; + } + + private HttpHeaders createHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", "Basic " + generateAuthToBase64()); + return headers; + } + + public PaymentInfoDto getPaymentInfoByOrderId(String orderId) { //private ์œผ๋กœ ๋ฐ”๊ฟ”์•ผ ํ•จ + try { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = createHeaders(); + HttpEntity requestEntity = new HttpEntity<>(headers); + String url = tossPaymentURL + "orders/" + orderId; + ResponseEntity responseEntity = + restTemplate.exchange(url, HttpMethod.GET, requestEntity, PaymentInfoDto.class); + PaymentInfoDto response = responseEntity.getBody(); + + if (response.getStatus().equals(Payment.Status.IN_PROGRESS)) { + response = confirmPayment(response.getOrderId(), + response.getPaymentKey(), + response.getTotalAmount()).getBody(); + } + return response; + } catch (Exception e) { + System.out.println(e.getMessage()); + throw new BusinessLogicException(ExceptionCode.NOT_FOUND_PAYMENT);// + } + } + + private ResponseEntity confirmPayment(String orderId, String paymentKey, long amount) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = createHeaders(); + PaymentConfirmDto paymentConfirmDto = new PaymentConfirmDto(); + paymentConfirmDto.setPaymentKey(paymentKey); + paymentConfirmDto.setAmount(amount); + paymentConfirmDto.setOrderId(orderId); + + HttpEntity requestEntity = new HttpEntity<>(paymentConfirmDto, headers); // ํ—ค๋”์™€ ๋ฐ”๋””๋ฅผ ํ•ฉ์ณ์„œ ๊ฐ์ฒด ์ƒ์„ฑ + String url = tossPaymentURL + "confirm"; // ์š”์ฒญ๋ณด๋‚ผ ๊ณณ + return restTemplate.postForEntity(url, requestEntity, PaymentInfoDto.class); // ์š”์ฒญ + } + +/** ========================================================= */ + /** + * ์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” ๊ฒฐ์ œ์ •๋ณด๋ฅผ ๋””๋น„์— ์ €์žฅํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ์ œ์— ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ์š”์ฒญ์ด๋”๋ผ๋„ ์ผ๋‹จ ๊ฒฐ์ œ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. + */ + public Payment saveToPaymentRepository(Payment payment) { + Member member = memberService.findMemberByEmail(AuthUtil.getCurrentMemberEmail()); + payment.setCustomer(member); + return paymentRepository.save(payment); + } + + /** ========================================================= */ + /** + * ์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” ํ™˜๋ถˆ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. + */ + public void refund(String paymentKey, Long cancelAmount) { + Payment payment = paymentRepository.findByPaymentKey(paymentKey); + if (payment == null) { + throw new BusinessLogicException(ExceptionCode.PAYMENT_NOT_FOUND); + } + + try { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = createHeaders(); + PaymentCancelDto requestData = new PaymentCancelDto(); // body ๊ฐ์ฒด ์ƒ์„ฑ + // requestData์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ์„ค์ • + requestData.setCancelAmount(cancelAmount); // body์— data set + HttpEntity requestEntity = new HttpEntity<>(requestData, headers); // ํ—ค๋”์™€ ๋ฐ”๋””๋ฅผ ํ•ฉ์ณ์„œ ๊ฐ์ฒด ์ƒ์„ฑ + String url = tossPaymentURL + paymentKey + "/cancel"; // ์š”์ฒญ๋ณด๋‚ผ ๊ณณ + restTemplate.postForEntity(url, requestEntity, PaymentInfoDto.class); // ์š”์ฒญ + refundUpdateRepository(payment); + + } catch (Exception e) { + System.out.println(e.getMessage()); + throw new BusinessLogicException(ExceptionCode.BAD_REQUEST); + } + } + + public void refundUpdateRepository(Payment payment) throws BusinessLogicException { + PaymentCancel paymentCancel = new PaymentCancel(); + paymentCancel.setPayment(payment); + paymentCancelRepository.save(paymentCancel); + payment.setCancel(paymentCancel); + payment.setStatus(Payment.Status.CANCELED); + paymentRepository.save(payment); + } } diff --git a/server/src/main/java/actiOn/redis/config/RedisConfig.java b/server/src/main/java/actiOn/redis/config/RedisConfig.java new file mode 100644 index 00000000..c8977171 --- /dev/null +++ b/server/src/main/java/actiOn/redis/config/RedisConfig.java @@ -0,0 +1,37 @@ +package actiOn.redis.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Value("${spring.redis.host}") + private String redisHost; + + @Value("${spring.redis.port}") + private int redisPort; + + @Bean + public JedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort); + return new JedisConnectionFactory(config); + } + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); + redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); + return redisTemplate; + } +} \ No newline at end of file diff --git a/server/src/main/java/actiOn/redis/service/RedisService.java b/server/src/main/java/actiOn/redis/service/RedisService.java new file mode 100644 index 00000000..3926dc5c --- /dev/null +++ b/server/src/main/java/actiOn/redis/service/RedisService.java @@ -0,0 +1,46 @@ +package actiOn.redis.service; + +import actiOn.exception.BusinessLogicException; +import actiOn.exception.ExceptionCode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.stereotype.Service; + +@Service +public class RedisService { + private final RedisTemplate redisTemplate; + + @Autowired + public RedisService(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + // JSON ์ง๋ ฌํ™” ์„ค์ • ์ถ”๊ฐ€ + redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); + redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); + } + + public void saveDataToRedis(String key, String value) { + try{ + redisTemplate.opsForValue().set(key, value); + }catch (Exception e){ + throw new BusinessLogicException(ExceptionCode.BAD_REQUEST); + } + + } + + public String getDataFromRedis(String key) { + try{ + return redisTemplate.opsForValue().get(key); + }catch (Exception e){ + return null; + } + } + + public void deleteDataFromRedis(String key) { + try { + redisTemplate.delete(key); + } catch (Exception e) { + throw new BusinessLogicException(ExceptionCode.BAD_REQUEST); + } + } +} diff --git a/server/src/main/java/actiOn/reservation/controller/ReservationController.java b/server/src/main/java/actiOn/reservation/controller/ReservationController.java index 01b786e4..1323135f 100644 --- a/server/src/main/java/actiOn/reservation/controller/ReservationController.java +++ b/server/src/main/java/actiOn/reservation/controller/ReservationController.java @@ -2,21 +2,21 @@ import actiOn.item.dto.ItemDto; import actiOn.item.service.ItemService; +import actiOn.payment.entity.Payment; import actiOn.reservation.dto.ReservationPatchDto; import actiOn.reservation.dto.ReservationPostDto; +import actiOn.reservation.dto.ReservationRedisResponseDto; import actiOn.reservation.dto.ReservationResponseDto; import actiOn.reservation.entity.Reservation; import actiOn.reservation.entity.ReservationItem; import actiOn.reservation.mapper.ReservationMapper; import actiOn.reservation.service.ReservationService; -import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import javax.validation.constraints.Positive; -import java.time.LocalDate; import java.util.List; @RestController @@ -33,15 +33,25 @@ public ReservationController(ReservationService reservationService, ReservationM this.itemService = itemService; } - //Todo RS_002 ์˜ˆ์•ฝ ๋“ฑ๋ก(์™„๋ฃŒ ์ง์ „, ํ…Œ์ŠคํŠธ ํ•„์š”) + // ์˜ˆ์•ฝ ๋“ฑ๋ก @PostMapping("/reservations/{store-id}") public ResponseEntity postReservation(@Positive @PathVariable("store-id") Long storeId, @Valid @RequestBody ReservationPostDto requestBody) { - Reservation reservation = reservationMapper.reservationPostDtoToReservation(requestBody); - List reservationItems = reservationMapper.reservationItemsDtoToReservationItem(requestBody, itemService); - reservationService.postReservation(storeId, reservation, reservationItems); - //Todo ๋‚ด์šฉ์ถ”๊ฐ€ - return new ResponseEntity<>(HttpStatus.CREATED); + String reservationKey = reservationService.redisSaveReservation(storeId, requestBody); + return new ResponseEntity<>(new ReservationRedisResponseDto(reservationKey), HttpStatus.OK); + } + + // ์˜ˆ์•ฝ ์™„๋ฃŒ ์ดํ›„ ๊ฒฐ์ œ์ •๋ณด ์ €์žฅ (๊ฒ€์ฆ) + @PostMapping("/reservation/payments") + public ResponseEntity confirmReservationAndPayment(@RequestParam("reservationKey") String reservationKey, + @RequestParam("orderId") String orderId) { + ReservationPostDto reservationPostDto = reservationService.getReservationPostDtoFromRedis(reservationKey); + Reservation reservation = reservationMapper.reservationPostDtoToReservation(reservationPostDto); + List reservationItems = reservationMapper.reservationItemsDtoToReservationItem(reservationPostDto, itemService); + + Payment payment = reservationService.createPaymentByOrderId(orderId); + reservationService.postReservation(reservationPostDto.getStoreId(), reservation, reservationItems, payment); + return new ResponseEntity(HttpStatus.CREATED); } // ์˜ˆ์•ฝ ์ˆ˜์ • @@ -53,7 +63,7 @@ public ResponseEntity patchReservation(@Positive @PathVariable("reservation-id") return new ResponseEntity<>(HttpStatus.OK); } - //Todo RS_001 ์˜ˆ์•ฝ ์ˆ˜์ • ํŽ˜์ด์ง€ ๋ Œ๋”(์™„๋ฃŒ, ํ…Œ์ŠคํŠธ ํ•„์š”) + // ์˜ˆ์•ฝ ์ˆ˜์ • ํŽ˜์ด์ง€ ๋ Œ๋” @GetMapping("/reservations/{reservation-id}") public ResponseEntity getReservations(@Positive @PathVariable("reservation-id") Long reservationId) { Reservation findReservation = reservationService.getReservations(reservationId); @@ -61,7 +71,7 @@ public ResponseEntity getReservations(@Positive @PathVariable("reservation-id") return new ResponseEntity<>(response, HttpStatus.OK); } - //Todo RS_004 ์˜ˆ์•ฝ ์ทจ์†Œ(์™„๋ฃŒ, ํ…Œ์ŠคํŠธ ํ•„์š”) + // ์˜ˆ์•ฝ ์ทจ์†Œ @DeleteMapping("/reservations/{reservation-id}") public ResponseEntity cancelReservation(@Positive @PathVariable("reservation-id") long reservationId) { reservationService.cancelReservation(reservationId); @@ -76,7 +86,7 @@ public ResponseEntity getStoreByDate(@PathVariable("store-id") @Positive long st } @PostMapping("/reservationsUsed/{reservation-id}") - public ResponseEntity doneReservation(@PathVariable("reservation-id")@Positive Long reservationId){ + public ResponseEntity doneReservation(@PathVariable("reservation-id") @Positive Long reservationId) { reservationService.changeReservationStatus(reservationId); return new ResponseEntity<>(HttpStatus.OK); } diff --git a/server/src/main/java/actiOn/reservation/dto/ReservationPostDto.java b/server/src/main/java/actiOn/reservation/dto/ReservationPostDto.java index c168b099..590367c0 100644 --- a/server/src/main/java/actiOn/reservation/dto/ReservationPostDto.java +++ b/server/src/main/java/actiOn/reservation/dto/ReservationPostDto.java @@ -3,12 +3,14 @@ import actiOn.helper.validator.NotSpace; import lombok.Builder; import lombok.Getter; +import lombok.Setter; import javax.validation.constraints.Pattern; import javax.validation.constraints.Positive; import java.util.List; @Getter +@Setter @Builder public class ReservationPostDto { @NotSpace(message = "์˜ˆ์•ฝ์ž ์„ฑํ•จ์€ ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") @@ -19,7 +21,6 @@ public class ReservationPostDto { message = "ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ๋Š” 010(ํ˜น์€ 011)๋งŒ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ•˜์ดํ”ˆ '-'์„ ํฌํ•จํ•˜์—ฌ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") private String reservationPhone; - @NotSpace private String reservationEmail; private String reservationDate; @@ -27,5 +28,7 @@ public class ReservationPostDto { @Positive private int totalPrice; + private Long storeId; + private List reservationItems; } diff --git a/server/src/main/java/actiOn/reservation/dto/ReservationRedisResponseDto.java b/server/src/main/java/actiOn/reservation/dto/ReservationRedisResponseDto.java new file mode 100644 index 00000000..5ec82ca7 --- /dev/null +++ b/server/src/main/java/actiOn/reservation/dto/ReservationRedisResponseDto.java @@ -0,0 +1,14 @@ +package actiOn.reservation.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ReservationRedisResponseDto { + private String reservationKey; + + public ReservationRedisResponseDto(String reservationKey){ + this.reservationKey = reservationKey; + } +} diff --git a/server/src/main/java/actiOn/reservation/entity/Reservation.java b/server/src/main/java/actiOn/reservation/entity/Reservation.java index e77a8e07..d9dc0903 100644 --- a/server/src/main/java/actiOn/reservation/entity/Reservation.java +++ b/server/src/main/java/actiOn/reservation/entity/Reservation.java @@ -45,14 +45,13 @@ public class Reservation extends BaseEntity { @Column private LocalDateTime deletedAt; + @Column + private String paymentKey; + + @Column(name = "STATUS") @Enumerated(EnumType.STRING) // enum ์ถ”๊ฐ€ private ReservationStatus reservationStatus = ReservationStatus.RESERVATION_REQUEST; - // payment ์•„์ง ์—†์œผ๋‹ˆ ์ผ๋‹จ ์ฃผ์„์ฒ˜๋ฆฌ - /* @OneToOne - @JoinColumn(name = "PAYMENT_ID") - private Payment payment;*/ - @ManyToOne(fetch = FetchType.LAZY) //์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‹œ์ ์— ๊ฐ€์ ธ์˜ด @JoinColumn(name = "MEMBER_ID") private Member member; @@ -82,17 +81,6 @@ public enum ReservationStatus { } } - // ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ์œ„ํ•œ ํŽธ์˜ ๋ฉ”์„œ๋“œ - public void addReservationItem(ReservationItem reservationItem) { - reservationItems.add(reservationItem); - reservationItem.setReservation(this); - } - - public void removeReservationItem(ReservationItem reservationItem) { - reservationItems.remove(reservationItem); - reservationItem.setReservation(null); - } - public Reservation(String reservationName, String reservationPhone, String reservationEmail) { this.reservationName = reservationName; this.reservationPhone = reservationPhone; diff --git a/server/src/main/java/actiOn/reservation/repository/ReservationRepository.java b/server/src/main/java/actiOn/reservation/repository/ReservationRepository.java index 33496574..da5a7319 100644 --- a/server/src/main/java/actiOn/reservation/repository/ReservationRepository.java +++ b/server/src/main/java/actiOn/reservation/repository/ReservationRepository.java @@ -6,12 +6,18 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.time.LocalDate; - import java.util.List; +import java.util.Optional; public interface ReservationRepository extends JpaRepository { List findByReservationDateAndStore(LocalDate reservationDate, Store store); +// Optional findReservationByMemberAndStore(Member member, Store store); + long countByMemberAndStore(Member member, Store store); + + long countByMemberAndStoreAndReservationStatus( + Member member, Store store, Reservation.ReservationStatus reservationStatus); + int countByStoreAndMemberAndReservationStatus(Store store, Member member, Reservation.ReservationStatus reservationStatus); } diff --git a/server/src/main/java/actiOn/reservation/service/ReservationService.java b/server/src/main/java/actiOn/reservation/service/ReservationService.java index 89b92e53..c83fc680 100644 --- a/server/src/main/java/actiOn/reservation/service/ReservationService.java +++ b/server/src/main/java/actiOn/reservation/service/ReservationService.java @@ -5,17 +5,25 @@ import actiOn.exception.ExceptionCode; import actiOn.item.dto.ItemDto; import actiOn.item.entity.Item; -import actiOn.item.service.ItemService; import actiOn.member.entity.Member; import actiOn.member.service.MemberService; +import actiOn.payment.dto.PaymentInfoDto; +import actiOn.payment.entity.Payment; +import actiOn.payment.mapper.PaymentMapper; +import actiOn.payment.service.PaymentService; +import actiOn.redis.service.RedisService; +import actiOn.reservation.dto.ReservationItemDto; +import actiOn.reservation.dto.ReservationPostDto; import actiOn.reservation.entity.Reservation; import actiOn.reservation.entity.ReservationItem; import actiOn.reservation.repository.ReservationItemRepository; import actiOn.reservation.repository.ReservationRepository; import actiOn.store.entity.Store; import actiOn.store.service.StoreService; +import com.google.gson.Gson; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -31,39 +39,106 @@ public class ReservationService { private final ReservationRepository reservationRepository; private final StoreService storeService; private final MemberService memberService; - private final ItemService itemService; private final ReservationItemRepository reservationItemRepository; + private final PaymentService paymentService; + private final RedisService redisService; + private final PaymentMapper paymentMapper; - private void validateItemId(List reservationItems, Store store) { - List items = store.getItems(); - for (ReservationItem reservationItem : reservationItems) { - if (!items.contains(reservationItem.getItem())) - throw new BusinessLogicException(ExceptionCode.REQUEST_ITEM_ID_IS_REJECTED); + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ ๋ฐ ๊ฒฐ์ œ๋ฅผ save ํ•˜๊ธฐ ์œ„ํ•œ ์˜์—ญ์ž…๋‹ˆ๋‹ค. + */ + @Transactional(propagation = Propagation.REQUIRED) + public String redisSaveReservation(Long storeId, ReservationPostDto reservationPostDto) { + validateIdentity(storeId);// ์‹ ์›๊ฒ€์ฆ + reservationPostDto.setReservationItems(filterZeroItem(reservationPostDto.getReservationItems())); + + reservationPostDto.setStoreId(storeId); + String redisKey = UUID.randomUUID().toString().replace("-", "") + + System.currentTimeMillis(); // random๋ฌธ์ž์—ด + timeStamp๋กœ ํ‚ค๊ฐ’ ์ƒ์„ฑ + Gson gson = new Gson(); + String json = gson.toJson(reservationPostDto); + redisService.saveDataToRedis(redisKey, json); //redis์— json์œผ๋กœ ์ž๋™ ํŒŒ์‹ฑ๋˜์–ด ์ €์žฅ //๋ถˆ๋Ÿฌ์˜ฌ๋•Œ๋„ ์—”ํ‹ฐํ‹ฐ๋กœ ์ž๋™ ํŒŒ์‹ฑ + return redisKey; + } + + private List filterZeroItem(List reservationItemDtos) { + List reservationItems = new ArrayList<>(); + for (ReservationItemDto reservationItemDto : reservationItemDtos) { + if (reservationItemDto.getTicketCount() == 0) continue; + reservationItems.add(reservationItemDto); } + return reservationItems; } - @Transactional(propagation = Propagation.REQUIRED) - public void postReservation(Long storeId, Reservation reservation, List reservationItems) { - //๋กœ๊ทธ์ธํ•œ ์œ ์ €์˜ ์ •๋ณด๋ฅผ reservation์— ๋‹ด๊ธฐ ๊ฒธ, ์‚ฌ์šฉ์ž ๊ฒ€์ฆ - Member member = memberService.findMemberByEmail(AuthUtil.getCurrentMemberEmail()); - reservation.setMember(member); - //์Šคํ† ์–ด ๊ฐ€์ ธ์˜ค๊ธฐ ๊ฒธ ๊ฒ€์ฆ - Store store = storeService.findStoreByStoreId(storeId); - validateItemId(reservationItems, store); - reservation.setStore(store); - //์˜ˆ์•ฝ ๋‚ ์งœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ - validateReservationDate(reservation.getReservationDate()); - validateTicketCount(store,reservation.getReservationDate(), reservationItems); - // reservationItem ์ €์žฅ - List newReservationItems = generateReservationItem(reservation, reservationItems); - reservation.setReservationItems(newReservationItems); - // ์ž…๋ ฅ๋œ ์ด ๊ธˆ์•ก๊ณผ ์ด ์˜ˆ์•ฝ ๊ฐ€๊ฒฉ์ด ๋™์ผํ•œ์ง€ ๊ฒ€์ฆ - validateTotalPrice(newReservationItems, reservation.getTotalPrice()); - //์˜ˆ์•ฝ ์ •๋ณด ์ €์žฅ - reservationRepository.save(reservation); + + private void validateIdentity(Long storeId) { + memberService.findMemberByEmail(AuthUtil.getCurrentMemberEmail()); + storeService.findStoreByStoreId(storeId); + } + + public ReservationPostDto getReservationPostDtoFromRedis(String reservationKey) { + String jsonFromRedis = redisService.getDataFromRedis(reservationKey); + Gson gson = new Gson(); + ReservationPostDto reservationPostDto = gson.fromJson(jsonFromRedis, ReservationPostDto.class); + redisService.deleteDataFromRedis(reservationKey); // ์กฐํšŒํ•˜๋ฉด ์‚ญ์ œ(1ํšŒ์šฉ) + return reservationPostDto; + } + + /** + * transaction ์ˆ˜์ค€์„ ์ตœ๊ณ ๋‹จ๊ณ„๋กœ ์„ค์ • + */ + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE) + public void postReservation(long storeId, Reservation reservationFromRedis, List reservationItems, Payment payment) { + + try { + confirmReservationWithPayment(reservationFromRedis, payment); + Reservation entity = createReservationEntity(storeId, reservationFromRedis, reservationItems); + entity.setPaymentKey(payment.getPaymentKey()); + entity.setReservationStatus(Reservation.ReservationStatus.RESERVATION_CONFIRM); + reservationRepository.save(entity); + } catch (BusinessLogicException ex) { + handleRollback(payment); + } + } + + @Transactional + public void handleRollback(Payment payment) { + paymentService.refund(payment.getPaymentKey(), payment.getTotalAmount()); + throw new BusinessLogicException(ExceptionCode.BAD_REQUEST); } + /** + * payment ์ •๋ณด์™€ ์˜ˆ์•ฝ์ •๋ณด๋ฅผ ์ด์šฉํ•ด์„œ ๊ฒ€์ฆ. ๊ฒฐ์ œ์™„๋ฃŒ์ƒํƒœ์ด์–ด์•ผ ํ•˜๊ณ , ์˜ˆ์•ฝ๊ธˆ์•ก๊ณผ ๊ฒฐ์ œ๊ธˆ์•ก์ด ๊ฐ™์•„์•ผ ํ•จ. ๋‹ค๋ฅผ ๊ฒฝ์šฐ ํ™˜๋ถˆ ์‹คํ–‰ + **/ + private void confirmReservationWithPayment(Reservation reservation, Payment payment) { + + if (!payment.getStatus().equals(Payment.Status.DONE)) + throw new BusinessLogicException(ExceptionCode.BAD_REQUEST); + else if (reservation.getTotalPrice() != payment.getTotalAmount()) { + paymentService.refund(payment.getPaymentKey(), payment.getTotalAmount()); + throw new BusinessLogicException(ExceptionCode.BAD_REQUEST); + } + } + + /** + * client ์—๊ฒŒ์„œ ๋ฐ›์€ orderId๋ฅผ ์ด์šฉํ•ด payment save + **/ + public Payment createPaymentByOrderId(String orderId) { + PaymentInfoDto paymentInfoDto = paymentService.getPaymentInfoByOrderId(orderId); + Payment payment = paymentMapper.paymentInfoDtoToPayment(paymentInfoDto); + return paymentService.saveToPaymentRepository(payment); + } + + /** ========================================================= */ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ์„ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•œ ์˜์—ญ์ž…๋‹ˆ๋‹ค. + */ @Transactional(propagation = Propagation.REQUIRED) public void updateReservation(Long reservationId, Reservation updateReservation) { + Reservation.ReservationStatus status = findReservation(reservationId).getReservationStatus(); + + if (status.equals(Reservation.ReservationStatus.RESERVATION_CANCEL) || + status.equals(Reservation.ReservationStatus.RESERVATION_USE_COMPLETED)) + throw new BusinessLogicException(ExceptionCode.REJECTED_UPDATE); //์ˆ˜์ •ํ•  ์˜ˆ์•ฝ ์ •๋ณด ์กฐํšŒ ์ฐพ๊ธฐ Reservation findReservation = findReservation(reservationId); @@ -80,7 +155,9 @@ public void updateReservation(Long reservationId, Reservation updateReservation) reservationRepository.save(findReservation); } - // ์˜ˆ์•ฝ ๊ฒ€์ฆ ๋ฐ ์กฐํšŒ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ์ด ์‹ค์ œ๋กœ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์š”์ฒญ์ž์™€ ์˜ˆ์•ฝ์ƒ์„ฑ์ž์˜ ์‹ ์›์ด ๋™์ผํ•œ์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. + **/ @Transactional(readOnly = true) public Reservation getReservations(Long reservationId) { Reservation reservation = findReservation(reservationId); @@ -88,26 +165,36 @@ public Reservation getReservations(Long reservationId) { return reservation; } - +/** ========================================================= */ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ ์ทจ์†Œ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. + **/ @Transactional(propagation = Propagation.REQUIRED) public void cancelReservation(Long reservationId) { Reservation findReservation = findReservation(reservationId); //๋กœ๊ทธ์ธํ•œ ํšŒ์› ์ •๋ณด์™€ reservation์˜ member์™€ ๋™์ผํ•œ์ง€ ๊ฒ€์ฆ verifyReservationMember(findReservation.getMember()); - //์˜ˆ์•ฝ ๋Œ€๊ธฐ -> ์˜ˆ์•ฝ ์ทจ์†Œ findReservation.setReservationStatus(Reservation.ReservationStatus.RESERVATION_CANCEL); - reservationRepository.delete(findReservation); + + //๊ฒฐ์ œ ์ทจ์†Œ + long cancelAmount = findReservation.getTotalPrice(); + paymentService.refund(findReservation.getPaymentKey(), cancelAmount); + findReservation.setReservationStatus(Reservation.ReservationStatus.RESERVATION_CANCEL); + reservationRepository.save(findReservation); //Todo ์˜ˆ์•ฝ ์ทจ์†Œ -> ํ™˜๋ถˆ } - //์˜ˆ์•ฝ ์ƒํ’ˆ ์ƒ์„ฑ ๋ฐ ์ €์žฅ ๋ฉ”์„œ๋“œ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” reservationItem ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + **/ private List generateReservationItem(Reservation reservation, List reservationItems) { List newReservationItems = new ArrayList<>(); for (ReservationItem reservationItem : reservationItems) { + if (reservationItem.getTicketCount() == 0) continue; reservationItem.setReservation(reservation); newReservationItems.add(reservationItem); } @@ -115,7 +202,10 @@ private List generateReservationItem(Reservation reservation, L return reservationItemRepository.saveAll(newReservationItems); } - private int getRemainingTicketCount(Item item, Map reservationTickets) { + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์ž”์—ฌํ‹ฐ์ผ“ ๊ณ„์‚ฐ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. + **/ + private int getRemainingTicketCount(Item item, Map reservationTickets) { int reservationTicketCount = // ์˜ˆ์•ฝ๋œ ํ‹ฐ์ผ“์ด ์—†๋‹ค๋ฉด null๋กœ ๋‚˜์˜ค๋ฏ€๋กœ, null๊ณผ int๋Š” ์—ฐ์‚ฐ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, int๋กœ ๋ณ€ํ™˜ reservationTickets.containsKey(item.getItemId()) ? reservationTickets.get(item.getItemId()) : 0; @@ -124,41 +214,53 @@ private int getRemainingTicketCount(Item item, Map reservationTick return remainingTicketCount; } + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ๊ทธ ๋‚ ์งœ์—, ๊ทธ ์Šคํ† ์–ด์˜ ์•„์ดํ…œ๋“ค ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. + **/ public List findItemsByStoreIdAndDate(long storeId, String targetDate) { - //Todo ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•˜๊ธฐ - LocalDate date; - try{ - date = LocalDate.parse(targetDate, DateTimeFormatter.BASIC_ISO_DATE); - }catch (DateTimeParseException e) { - throw new BusinessLogicException(ExceptionCode.DATE_BAD_REQUEST); - } + //Todo ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•˜๊ธฐ + LocalDate date; + try { + date = LocalDate.parse(targetDate, DateTimeFormatter.BASIC_ISO_DATE); + } catch (DateTimeParseException e) { + throw new BusinessLogicException(ExceptionCode.DATE_BAD_REQUEST); + } - List itemDtos = new ArrayList<>(); - Store findStore = storeService.findStoreByStoreId(storeId); - List findItems = findStore.getItems(); - Map reservationTickets = reservationTicketCount(findStore, date); - for (Item item : findItems) { - int remainingTicketCount = getRemainingTicketCount(item,reservationTickets); - if (remainingTicketCount < 0) remainingTicketCount = 0; - ItemDto itemDto = new ItemDto( - item.getItemId(), - item.getItemName(), - item.getTotalTicket(), - item.getPrice(), - remainingTicketCount - ); - itemDtos.add(itemDto); - } - return itemDtos; + List itemDtos = new ArrayList<>(); + Store findStore = storeService.findStoreByStoreId(storeId); + List findItems = findStore.getItems(); + Map reservationTickets = reservationTicketCount(findStore, date); + + for (Item item : findItems) { + if (item.getStatus().equals(Item.ItemStatus.DELETED)) continue; + int remainingTicketCount = getRemainingTicketCount(item, reservationTickets); + if (remainingTicketCount < 0) remainingTicketCount = 0; + ItemDto itemDto = new ItemDto( + item.getItemId(), + item.getItemName(), + item.getTotalTicket(), + item.getPrice(), + remainingTicketCount + ); + itemDtos.add(itemDto); + } + return itemDtos; } + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์„ ํƒํ•œ ๋‚ ์งœ์™€ ์Šคํ† ์–ด์— ์†ํ•ด์žˆ๋Š” ์•„์ดํ…œ๋“ค์„ ๋Œ€์ƒ์œผ๋กœ ๋ช‡ ๊ฐœ์˜ ์˜ˆ์•ฝ์ด ์ ์šฉ๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์—ญํ• ์ž…๋‹ˆ๋‹ค. remainingTicket ์„ ๊ณ„์‚ฐํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + */ public Map reservationTicketCount(Store store, LocalDate currentDate) throws BusinessLogicException { - //Todo ๋ฆฌํŽ™ํ† ๋งํ•˜๊ธฐ + //Todo ๋ฆฌํŒฉํ† ๋ง ํ•„์š” //์„ ํƒํ•œ ์—…์ฒด์™€ ๋‚ ์งœ์˜ ์˜ˆ์•ฝ๋“ค์„ ๊ฐ€์ ธ์˜ด List currentDateReservations = reservationRepository.findByReservationDateAndStore(currentDate, store); Map remainingTicketInfo = new HashMap<>(); + for (Reservation reservation : currentDateReservations) { + //์ทจ์†Œ๋œ ์˜ˆ์•ฝ์€ ์…ˆํ•˜์ง€ ์•Š๋Š”๋‹ค. + if (reservation.getReservationStatus().equals(Reservation.ReservationStatus.RESERVATION_CANCEL)) continue; + List reservationItems = reservation.getReservationItems(); for (ReservationItem reservationItem : reservationItems) { long itemId = reservationItem.getItem().getItemId(); @@ -175,7 +277,9 @@ public Map reservationTicketCount(Store store, LocalDate currentD return remainingTicketInfo; } - // ๋กœ๊ทธ์ธํ•œ ํšŒ์›๊ณผ reservation member ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ์„ ์ƒ์„ฑํ•œ ์‚ฌ๋žŒ๊ณผ, ์š”์ฒญ์ž๊ฐ€ ๋™์ผํ•œ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. + */ private Member verifyReservationMember(Member reservationMember) { String loginUserEmail = AuthUtil.getCurrentMemberEmail(); Member findMember = memberService.findMemberByEmail(loginUserEmail); @@ -187,13 +291,17 @@ private Member verifyReservationMember(Member reservationMember) { return findMember; } - //์˜ˆ์•ฝ ์ฐพ๊ธฐ + /** + * reservationId๋ฅผ ์ด์šฉํ•ด์„œ ์˜ˆ์•ฝ๋‚ด์—ญ์„ ์ฐพ์Šต๋‹ˆ๋‹ค. + */ private Reservation findReservation(Long reservationId) { return reservationRepository.findById(reservationId) .orElseThrow(() -> new BusinessLogicException(ExceptionCode.RESERVATION_NOT_FOUND)); } - // ์˜ˆ์•ฝ ๋‚ ์งœ ๊ฒ€์ฆ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ๋‚ ์งœ์˜ ๊ฒ€์ฆ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด์ œ ๋‚ ์งœ๋กœ ์˜ˆ์•ฝํ•˜๊ฒŒ ๋˜๋ฉด ๊ฒ€์ฆ์— ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. + */ private void validateReservationDate(LocalDate reservationDate) { // ์˜ค๋Š˜ ๊ธฐ์ค€ ์ด์ „ ๋‚ ์งœ๊ฐ€ ์˜ค๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ LocalDate today = LocalDate.now(); @@ -203,7 +311,10 @@ private void validateReservationDate(LocalDate reservationDate) { } } - // ์˜ˆ์•ฝ ๊ธˆ์•ก ๊ฒ€์ฆ ๋ฉ”์„œ๋“œ + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ์š”์ฒญ ์ƒํ’ˆ์˜ ์ด ๊ธˆ์•ก๊ณผ, ์‹ค์ œ ๊ฒฐ์ œ๋˜์–ด์•ผ ํ•˜๋Š” ๊ธˆ์•ก์„ ๋น„๊ตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‹ค์ œ ๊ฒฐ์ œ ๋˜์–ด์•ผ ํ•˜๋Š” ๊ธˆ์•ก์ด 100์›์ธ๋ฐ, + * 50์›์œผ๋กœ ์˜ˆ์•ฝ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋Š” ๊ฒฝ์šฐ ๊ฒ€์ฆ์— ์‹คํŒจํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + */ private void validateTotalPrice(List reservationItems, int totalPrice) { int sumTotalPrice = 0; for (ReservationItem reservationItem : reservationItems) { @@ -216,32 +327,96 @@ private void validateTotalPrice(List reservationItems, int tota } } - private void validateTicketCount(Store store,LocalDate date, List requestItems) { - //์ž”์—ฌํ‹ฐ์ผ“๊ณผ ์š”์ฒญํ‹ฐ์ผ“์„ ๊ตฌํ•ด์„œ ๋น„๊ต, ์Œ์ˆ˜๊ฐ€ ๋‚˜์˜ค๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ - // ํ˜„์žฌ ํ‹ฐ์ผ“ ์˜ˆ์•ฝ๋‚ด์—ญ ๊ฐ€์ ธ์˜ด + ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ์ž”์—ฌํ‹ฐ์ผ“ ๊ตฌํ•ด์˜ด + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝํ•˜๋ ค๋Š” ํ‹ฐ์ผ“ ์ˆ˜๋Ÿ‰์ด, ์ž”์—ฌ ํ‹ฐ์ผ“์„ ์ดˆ๊ณผํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์ฆํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + */ + private void validateTicketCount(Store store, LocalDate date, List requestItems) { Map reservationTickets = reservationTicketCount(store, date); - for (int i=0; i< store.getItems().size(); i++) { + for (int i = 0; i < store.getItems().size(); i++) { Item item = store.getItems().get(i); - int requestTicketCount = requestItems.get(i).getTicketCount(); - int remainingTicketCount = getRemainingTicketCount(item,reservationTickets); + int requestTicketCount; + try { + requestTicketCount = requestItems.get(i).getTicketCount(); + } catch (Exception e) { + requestTicketCount = 0; + } + int remainingTicketCount = getRemainingTicketCount(item, reservationTickets); if (requestTicketCount > remainingTicketCount) throw new BusinessLogicException(ExceptionCode.TICKET_QUANTITY_EXCEEDED); } } + // ํšŒ์›์ด ํ•ด๋‹น ์—…์ฒด๋ฅผ ์˜ˆ์•ฝํ•œ ๋‚ด์—ญ์ด ์žˆ๋Š”์ง€ ํ™•์ธ + public void verifyReservationByMemberAndStore(Member member, Store store) { + long reservationCount = + reservationRepository.countByMemberAndStore(member, store); + + if (reservationCount == 0) { + throw new BusinessLogicException(ExceptionCode.ONLY_RESERVED_MEMBER_REVIEW); + } + } + + // ์‚ฌ์šฉ์ž๊ฐ€ ํšŒ์›์ด ํ•ด๋‹น ์Šคํ† ์–ด๋ฅผ ์ด์šฉ์™„๋ฃŒ ํ–ˆ๋Š”์ง€ ํ™•์ธ + public void verifyReservationByReservationStatus(Member member, Store store) { + long reservation = + reservationRepository.countByMemberAndStoreAndReservationStatus( + member, store, Reservation.ReservationStatus.RESERVATION_USE_COMPLETED); + + if (reservation == 0) { + throw new BusinessLogicException(ExceptionCode.BEFORE_STORE_USE_COMPLETE); + } + } + + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•  ์ž๊ฒฉ์ด ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด, ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ์Šคํ† ์–ด์— ๋ช‡๊ฐœ์˜ ์˜ˆ์•ฝ์„ ํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + * ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜ˆ์•ฝ์„ 2๊ฐœ๋ฅผ ํ–ˆ๋‹ค๋ฉด ์‚ฌ์šฉ์ž๋Š” 2๊ฐœ์˜ ๋ฆฌ๋ทฐ๋ฅผ ๋‚จ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + */ public int countReservation(Store store, Member member) { int count = reservationRepository. - countByStoreAndMemberAndReservationStatus(store,member,Reservation.ReservationStatus.RESERVATION_USE_COMPLETED); + countByStoreAndMemberAndReservationStatus(store, + member, Reservation.ReservationStatus.RESERVATION_USE_COMPLETED); return count; } + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ ์ƒํƒœ๋ฅผ, ์‚ฌ์šฉ์™„๋ฃŒ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ์—ญํ• ๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. + */ public void changeReservationStatus(long reservationId) { Reservation findReservation = findReservation(reservationId); findReservation.setReservationStatus(Reservation.ReservationStatus.RESERVATION_USE_COMPLETED); } -} -//"RESERVATION_REQUEST" -// ); -// -//// "RESERVATION_USE_COMPLETED" \ No newline at end of file + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์•„์ดํ…œ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. + **/ + private void validateItemId(List reservationItems, Store store) { + List items = store.getItems(); + for (ReservationItem reservationItem : reservationItems) { + if (!items.contains(reservationItem.getItem())) + throw new BusinessLogicException(ExceptionCode.REQUEST_ITEM_ID_IS_REJECTED); + } + } + + /** + * ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์˜ˆ์•ฝ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด, reservation Entity๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. + */ + public Reservation createReservationEntity(Long storeId, Reservation reservation, + List reservationItems) { + //๋กœ๊ทธ์ธํ•œ ์œ ์ €์˜ ์ •๋ณด๋ฅผ reservation์— ๋‹ด๊ธฐ ๊ฒธ, ์‚ฌ์šฉ์ž ๊ฒ€์ฆ + Member member = memberService.findMemberByEmail(AuthUtil.getCurrentMemberEmail()); + reservation.setMember(member); + //์Šคํ† ์–ด ๊ฐ€์ ธ์˜ค๊ธฐ ๊ฒธ ๊ฒ€์ฆ + Store store = storeService.findStoreByStoreId(storeId); + validateItemId(reservationItems, store); + reservation.setStore(store); + //์˜ˆ์•ฝ ๋‚ ์งœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ + validateReservationDate(reservation.getReservationDate()); + validateTicketCount(store, reservation.getReservationDate(), reservationItems); + // reservationItem ์ €์žฅ + List newReservationItems = generateReservationItem(reservation, reservationItems); + reservation.setReservationItems(newReservationItems); + // ์ž…๋ ฅ๋œ ์ด ๊ธˆ์•ก๊ณผ ์ด ์˜ˆ์•ฝ ๊ฐ€๊ฒฉ์ด ๋™์ผํ•œ์ง€ ๊ฒ€์ฆ + validateTotalPrice(newReservationItems, reservation.getTotalPrice()); + return reservation; + } +} \ No newline at end of file diff --git a/server/src/main/java/actiOn/review/controller/ReviewController.java b/server/src/main/java/actiOn/review/controller/ReviewController.java index 4140160d..5d03c5d5 100644 --- a/server/src/main/java/actiOn/review/controller/ReviewController.java +++ b/server/src/main/java/actiOn/review/controller/ReviewController.java @@ -1,13 +1,13 @@ package actiOn.review.controller; -import actiOn.review.dto.ReviewDto; -import actiOn.review.dto.ReviewsResponseDto; +import actiOn.review.dto.ReviewPostDto; +import actiOn.review.dto.ReviewResponseDto; import actiOn.review.entity.Review; import actiOn.review.mapper.ReviewMapper; import actiOn.review.service.ReviewService; +import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @@ -15,29 +15,31 @@ import java.util.List; @RestController +@AllArgsConstructor +@RequestMapping public class ReviewController { - private final ReviewService reviewService; private final ReviewMapper reviewMapper; - public ReviewController(ReviewService reviewService, ReviewMapper reviewMapper) { - this.reviewService = reviewService; - this.reviewMapper = reviewMapper; - } - - //TODO RV_001 ๋ฆฌ๋ทฐ ์ž‘์„ฑ + // ๋ฆฌ๋ทฐ ์ž‘์„ฑ @PostMapping("/reviews/{store-id}") public ResponseEntity createReview(@Positive @PathVariable("store-id") Long storeId, - @Valid @RequestBody ReviewDto reviewDto){ - Review review = reviewMapper.reviewDtoToReview(reviewDto); - reviewService.createReview(storeId,review); - return new ResponseEntity(HttpStatus.CREATED); + @Valid @RequestBody ReviewPostDto requestBody) { + Review review = reviewMapper.reviewPostDtoToReview(requestBody); + + Review savedReview = reviewService.createReview(storeId, review); + reviewService.updateStoreReviewCounting(storeId, savedReview); + return new ResponseEntity<>(HttpStatus.CREATED); } - //TODO RV_001 ๋ฆฌ๋ทฐ ํŽ˜์ด์ง€ + // ๋ฆฌ๋ทฐ ํŽ˜์ด์ง€ ๋ Œ๋” @GetMapping("/reviews/{store-id}") - public ResponseEntity getAllReviews(@Positive @PathVariable("store-id") Long storeId){ - ReviewsResponseDto reviewsResponseDto = reviewService.getAllReviews(storeId); - return new ResponseEntity(reviewsResponseDto,HttpStatus.OK); + public ResponseEntity getAllReviews(@Positive @PathVariable("store-id") Long storeId) { + List reviewList = reviewService.getAllReviews(storeId); + double storeRating = reviewService.getStoreAvgRating(storeId); + + ReviewResponseDto reviewResponseDto = + reviewMapper.reviewsToReviewResponseDto(reviewList, storeRating); + return new ResponseEntity<>(reviewResponseDto, HttpStatus.OK); } } diff --git a/server/src/main/java/actiOn/review/dto/ReviewDto.java b/server/src/main/java/actiOn/review/dto/ReviewPostDto.java similarity index 53% rename from server/src/main/java/actiOn/review/dto/ReviewDto.java rename to server/src/main/java/actiOn/review/dto/ReviewPostDto.java index 0ff0876d..a1ed6d02 100644 --- a/server/src/main/java/actiOn/review/dto/ReviewDto.java +++ b/server/src/main/java/actiOn/review/dto/ReviewPostDto.java @@ -1,15 +1,16 @@ package actiOn.review.dto; +import actiOn.helper.validator.NotSpace; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import org.hibernate.validator.constraints.Range; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - @Getter -public class ReviewDto { - - @NotBlank +@Builder +@AllArgsConstructor +public class ReviewPostDto { + @NotSpace private String content; @Range(min = 0, max = 5) diff --git a/server/src/main/java/actiOn/review/dto/ReviewResponseDto.java b/server/src/main/java/actiOn/review/dto/ReviewResponseDto.java index 954d3def..cf8ce4a1 100644 --- a/server/src/main/java/actiOn/review/dto/ReviewResponseDto.java +++ b/server/src/main/java/actiOn/review/dto/ReviewResponseDto.java @@ -1,24 +1,24 @@ package actiOn.review.dto; -import actiOn.review.entity.Review; +import lombok.Builder; import lombok.Getter; import java.time.LocalDateTime; import java.util.List; @Getter +@Builder public class ReviewResponseDto { - private String profileImg; - private String nickname; - private String content; - private Integer rating; - private LocalDateTime createdAt; + private int reviewCount; + private double ratingAvg; + private List reviews; - public ReviewResponseDto(String profileImg, String nickname, String content, Integer rating, LocalDateTime createdAt) { - this.profileImg = profileImg; - this.nickname = nickname; - this.content = content; - this.rating = rating; - this.createdAt = createdAt; + @Getter + @Builder + public static class ReviewDto { + private String nickname; + private String content; + private Integer rating; + private LocalDateTime createdAt; } } diff --git a/server/src/main/java/actiOn/review/dto/ReviewsResponseDto.java b/server/src/main/java/actiOn/review/dto/ReviewsResponseDto.java deleted file mode 100644 index d4a2823b..00000000 --- a/server/src/main/java/actiOn/review/dto/ReviewsResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package actiOn.review.dto; - -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; - -@Getter @Builder -public class ReviewsResponseDto { - private int reviewCount; - private double ratingAvg; - private List reviews; -} diff --git a/server/src/main/java/actiOn/review/entity/Review.java b/server/src/main/java/actiOn/review/entity/Review.java index 2dd7f5ae..af972704 100644 --- a/server/src/main/java/actiOn/review/entity/Review.java +++ b/server/src/main/java/actiOn/review/entity/Review.java @@ -11,7 +11,8 @@ import javax.persistence.*; @NoArgsConstructor -@Getter @Setter +@Getter +@Setter @Entity public class Review extends BaseEntity { @@ -33,9 +34,4 @@ public class Review extends BaseEntity { @ManyToOne @JoinColumn(name = "STORE_ID") private Store store; - - public Review(String content, Integer rating){ - this.content = content; - this.rating = rating; - } } diff --git a/server/src/main/java/actiOn/review/mapper/ReviewMapper.java b/server/src/main/java/actiOn/review/mapper/ReviewMapper.java index 4dea8245..25de1d97 100644 --- a/server/src/main/java/actiOn/review/mapper/ReviewMapper.java +++ b/server/src/main/java/actiOn/review/mapper/ReviewMapper.java @@ -1,39 +1,43 @@ package actiOn.review.mapper; -import actiOn.review.dto.ReviewDto; +import actiOn.review.dto.ReviewPostDto; import actiOn.review.dto.ReviewResponseDto; import actiOn.review.entity.Review; +import org.mapstruct.Mapper; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; +@Mapper(componentModel = "spring") @Component -public class ReviewMapper { +public interface ReviewMapper { - public Review reviewDtoToReview(ReviewDto reviewDto){ - return new Review( - reviewDto.getContent(), - reviewDto.getRating() - ); - } + Review reviewPostDtoToReview(ReviewPostDto reviewPostDto); - public ReviewResponseDto reviewToReviewResponseDto(Review review){ - return new ReviewResponseDto( - review.getMember().getProfileImg().getLink(), - review.getMember().getNickname(), - review.getContent(), - review.getRating(), - review.getCreatedAt() - ); - } + default ReviewResponseDto reviewsToReviewResponseDto(List reviewList, double storeRating) { + List reviewDtos = new ArrayList<>(); - public List reviewsToReviewsResponseDto(List reviews){ - List reviewResponseDtoList = new ArrayList<>(reviews.size()); - for (Review review : reviews){ - reviewResponseDtoList.add(this.reviewToReviewResponseDto(review)); + for (Review review : reviewList) { + reviewDtos.add(reviewToReviewDto(review)); } - return reviewResponseDtoList; + + return ReviewResponseDto.builder() + .reviewCount(reviewList.size()) + .ratingAvg(storeRating) + .reviews(reviewDtos) + .build(); } + default ReviewResponseDto.ReviewDto reviewToReviewDto(Review review) { + ReviewResponseDto.ReviewDto.ReviewDtoBuilder builder = + ReviewResponseDto.ReviewDto.builder(); + + builder.nickname(review.getMember().getNickname()); + builder.content(review.getContent()); + builder.rating(review.getRating()); + builder.createdAt(review.getCreatedAt()); + + return builder.build(); + } } diff --git a/server/src/main/java/actiOn/review/repository/ReviewCustomRepository.java b/server/src/main/java/actiOn/review/repository/ReviewCustomRepository.java deleted file mode 100644 index a9543cb1..00000000 --- a/server/src/main/java/actiOn/review/repository/ReviewCustomRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package actiOn.review.repository; - - -import actiOn.store.entity.Store; - -public interface ReviewCustomRepository { - - Double avgStoreRating(Store store); -} diff --git a/server/src/main/java/actiOn/review/repository/ReviewRepository.java b/server/src/main/java/actiOn/review/repository/ReviewRepository.java index 5383e59b..a9b9d3a6 100644 --- a/server/src/main/java/actiOn/review/repository/ReviewRepository.java +++ b/server/src/main/java/actiOn/review/repository/ReviewRepository.java @@ -4,16 +4,12 @@ import actiOn.review.entity.Review; import actiOn.store.entity.Store; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; import java.util.List; -public interface ReviewRepository extends JpaRepository , ReviewCustomRepository{ +public interface ReviewRepository extends JpaRepository { - List findAllByStore(Store store); + List findAllByStoreOrderByCreatedAtDesc(Store store); int countByStoreAndMember(Store store, Member member); -// @Query(value = "SELECT count(r) FROM Review r WHERE r.store.storeId = ?1") -// long countByStore(Store store); - } diff --git a/server/src/main/java/actiOn/review/service/ReviewService.java b/server/src/main/java/actiOn/review/service/ReviewService.java index 7da99563..9cb60bd9 100644 --- a/server/src/main/java/actiOn/review/service/ReviewService.java +++ b/server/src/main/java/actiOn/review/service/ReviewService.java @@ -6,15 +6,11 @@ import actiOn.exception.ExceptionCode; import actiOn.member.entity.Member; import actiOn.member.service.MemberService; -import actiOn.reservation.entity.Reservation; import actiOn.reservation.service.ReservationService; -import actiOn.review.dto.ReviewResponseDto; -import actiOn.review.dto.ReviewsResponseDto; import actiOn.review.entity.Review; -import actiOn.review.mapper.ReviewMapper; import actiOn.review.repository.ReviewRepository; import actiOn.store.entity.Store; -import actiOn.store.repository.StoreRepository; +import actiOn.store.service.StoreService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,79 +21,93 @@ @Service @AllArgsConstructor public class ReviewService { - private final ReviewRepository reviewRepository; - private final StoreRepository storeRepository; - private final ReviewMapper reviewMapper; + private final StoreService storeService; private final MemberService memberService; private final ReservationService reservationService; -// public ReviewService(ReviewRepository reviewRepository, StoreRepository storeRepository, ReviewMapper reviewMapper, MemberService memberService) { -// this.reviewRepository = reviewRepository; -// this.storeRepository = storeRepository; -// this.reviewMapper = reviewMapper; -// this.memberService = memberService; -// } - + // ๋ฆฌ๋ทฐ ์ƒ์„ฑ + @Transactional public Review createReview(Long storeId, Review review) { + // store ๊ฒ€์ฆ + String email = AuthUtil.getCurrentMemberEmail(); + Member findMember = memberService.findMemberByEmail(email); + Store store = storeService.findStoreByStoreId(storeId); + + // ํšŒ์›์ด ํ•ด๋‹น ์—…์ฒด๋ฅผ ์˜ˆ์•ฝํ•œ ๋‚ด์—ญ์ด ์žˆ๋Š”์ง€ ํ™•์ธ + reservationService.verifyReservationByMemberAndStore(findMember, store); + + // ํšŒ์›์ด ํ•ด๋‹น ์—…์ฒด๋ฅผ ์ด์šฉ์™„๋ฃŒ ํ–ˆ๋Š”์ง€ ํ™•์ธ + reservationService.verifyReservationByReservationStatus(findMember, store); + + // ์ด์šฉ ์™„๋ฃŒํ•œ ์˜ˆ์•ฝ ํšŸ์ˆ˜์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฏธ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜๋ฅผ ๋น„๊ต + verifyAlreadyWroteReviews(findMember, store); + //review ๋‚ด์šฉ ์š•์„ค ๊ฒ€์ฆ - BadWordFiltering badWordFiltering = new BadWordFiltering(); - if (badWordFiltering.blankCheck(review.getContent())){ - throw new IllegalArgumentException("๋ฆฌ๋ทฐ์— ์š•์„ค์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."); - } + verifyBadWord(review); - //Todo ๋กœ๊ทธ์ธํ•œ ํšŒ์›์˜ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ - String loginUserEmail = AuthUtil.getCurrentMemberEmail(); - Member findMember = memberService.findMemberByEmail(loginUserEmail); - - //Todo ์—…์ฒด ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ - Store store = storeRepository.findById(storeId).orElseThrow( - () -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND)); - - //Todo ๋กœ๊ทธ์ธํ•œ ํšŒ์›์˜ ์ •๋ณด๊ฐ€ ํ•ด๋‹น ์—…์ฒด๋ฅผ ์˜ˆ์•ฝํ–ˆ๋Š”์ง€์˜ ์—ฌ๋ถ€ ํ™•์ธ -> ๋ฆฌํŒฉํ† ๋ง ํ•„์ˆ˜ -// List reservationList = store.getReservations(); -// boolean hasReservationEmail = reservationList.stream() -// .anyMatch(reservation -> reservation.getReservationId() == (findMember.getMemberId())); - //ํ•ด๋‹น ์˜ˆ์•ฝ์— ๋ฆฌ๋ทฐ ์ด๋ ฅ์ด ์—†์„ ๊ฒƒ + reservation์—์„œ ์Šคํ† ์–ด์™€ ๋ฉค๋ฒ„์— ํ•ด๋‹นํ•˜๋Š”๊ฒŒ ์žˆ๋Š”์ง€ ํ™•์ธ - //Todo countReservation()๋ฅผ ์ด์šฉํ•ด์„œ ์˜ˆ์•ฝ์ˆซ์ž ์กฐํšŒ // ๊ทธ๋ฆฌ๊ณ  ์กฐ๊ฑด์— ๋งž๋Š” ๋ฆฌ๋ทฐ์นด์šดํŠธ ํ•ด์„œ ์—ฌ์œ ์žˆ์œผ๋ฉด ๋ฆฌ๋ทฐ ๋‚จ๊ธฐ๊ฒŒ ํ•ด์ฃผ๊ธฐ - int reservationCount = reservationService.countReservation(store,findMember); - int nowReviewCount = reviewRepository.countByStoreAndMember(store,findMember); - if (reservationCount > nowReviewCount) { - review.setMember(findMember); - review.setStore(store); - } else { - throw new BusinessLogicException(ExceptionCode.REVIEW_CREATE_REJECTED); - } - Review saveReview = reviewRepository.save(review); + review.setMember(findMember); + review.setStore(store); + + return reviewRepository.save(review); + } + + // ์—…์ฒด์— ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ ๋“ฑ๋ก + @Transactional + public void updateStoreReviewCounting(Long storeId, Review review) { + Store store = storeService.findStoreByStoreId(storeId); - //Todo review ์ „์ฒด ํ‰์ ์˜ ํ‰๊ท  - Double avgRating = reviewRepository.avgStoreRating(store); - store.setRating(avgRating); - storeRepository.save(store); + // ํ•ด๋‹น ์—…์ฒด์˜ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ + int totalReviewCount = store.getReviewCount(); - //Todo store์— ์žˆ๋Š” review ๊ฐœ์ˆ˜ ์ถ”๊ฐ€ - storeRepository.addReviewCount(store); + // ํ•ด๋‹น ์—…์ฒด์˜ ์ด์  + double nowTotalRating = totalReviewCount * store.getRating(); - return saveReview; + // ๋”ํ•ด์ง„ ์—…์ฒด์˜ ์ด์  + double addedTotalRating = nowTotalRating + review.getRating(); + + // ์—…๋ฐ์ดํŠธ๋˜์–ด์•ผํ•˜๋Š” ์—…์ฒด์˜ ํ‰์  + double avgRating = addedTotalRating / (totalReviewCount + 1); + + // ์ „์ฒด ํ‰์ ์˜ ํ‰๊ท  ์ €์žฅ ๋ฐ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ ์ถ”๊ฐ€ + storeService.updateRatingAndReviewCount(store, avgRating); + } + + // ์—…์ฒด์˜ ๋ชจ๋“  ๋ฆฌ๋ทฐ ํƒ์ƒ‰ + public List getAllReviews(Long storeId) { + // ์—…์ฒด ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ -> ๋ฆฌํŒฉํ† ๋ง ํ•„์š” + Store store = storeService.findStoreByStoreId(storeId); + + // Store ๊ธฐ์ค€ ๋ชจ๋“  ๋ฆฌ๋ทฐ ์กฐํšŒ + List reviews = reviewRepository.findAllByStoreOrderByCreatedAtDesc(store); + + return reviews; } - public ReviewsResponseDto getAllReviews(Long storeId) { - //Todo ์—…์ฒด ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ -> ๋ฆฌํŒฉํ† ๋ง ํ•„์š” - Store store = storeRepository.findById(storeId).orElseThrow( - () -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND)); + public double getStoreAvgRating(long storeId) { + Store store = storeService.findStoreByStoreId(storeId); - //Todo Store ๊ธฐ์ค€ ๋ชจ๋“  ๋ฆฌ๋ทฐ ์กฐํšŒ - List reviews = reviewRepository.findAllByStore(store); + return store.getRating(); + } + + private void verifyBadWord(Review review) { + BadWordFiltering badWordFiltering = new BadWordFiltering(); - //Todo ์กฐํšŒํ•œ ๋ฆฌ๋ทฐ๋ฅผ ๋ฆฌ๋ทฐ DTO๋กœ ๋งคํ•‘ - List reviewResponseDtos = reviewMapper.reviewsToReviewsResponseDto(reviews); + if (badWordFiltering.blankCheck(review.getContent())) { + throw new BusinessLogicException(ExceptionCode.BAD_WORD_NOT_ALLOWED); + } + } - ReviewsResponseDto reviewsResponseDtos = ReviewsResponseDto.builder() - .reviewCount(store.getReviewCount()) - .ratingAvg(store.getRating()) - .reviews(reviewResponseDtos) - .build(); + // ์‚ฌ์šฉ์ž๊ฐ€ ์ด์šฉ์™„๋ฃŒํ•œ ์˜ˆ์•ฝ ํšŸ์ˆ˜์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฏธ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜๋ฅผ ๋น„๊ต + private void verifyAlreadyWroteReviews(Member findMember, Store store) { + // ํšŒ์›์ด ํ•ด๋‹น ์—…์ฒด์— ์˜ˆ์•ฝํ•œ ํšŸ์ˆ˜ + int reservationCount = reservationService.countReservation(store, findMember); + // ํšŒ์›์ด ํ•ด๋‹น ์—…์ฒด์— ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์˜ ๊ฐœ์ˆ˜ + int myReviewCount = reviewRepository.countByStoreAndMember(store, findMember); - return reviewsResponseDtos; + // ์ด๋ฏธ ์ž‘์„ฑํ–ˆ์œผ๋ฉด ์—๋Ÿฌ ๋˜์ง + if (reservationCount <= myReviewCount) { + throw new BusinessLogicException(ExceptionCode.ALREADY_WROTE_A_REVIEW); + } } } diff --git a/server/src/main/java/actiOn/store/controller/StoreController.java b/server/src/main/java/actiOn/store/controller/StoreController.java index 5c4d4f09..c285a16d 100644 --- a/server/src/main/java/actiOn/store/controller/StoreController.java +++ b/server/src/main/java/actiOn/store/controller/StoreController.java @@ -1,8 +1,6 @@ package actiOn.store.controller; -import actiOn.Img.service.ImgService; import actiOn.auth.utils.AuthUtil; -import actiOn.member.entity.Member; import actiOn.member.service.MemberService; import actiOn.store.dto.*; import actiOn.store.dto.mainrep.MainPageResponseDto; @@ -21,7 +19,6 @@ import javax.validation.Valid; import javax.validation.constraints.Positive; import java.io.IOException; -import java.util.ArrayList; import java.util.List; @RestController @@ -33,14 +30,12 @@ public class StoreController { private final StoreMapper storeMapper; private final StoreResponseMapper responseMapper; private final CategoryResponseMapper categoryResponseMapper; - private final ImgService imgService; - private final MemberService memberService; // ์—…์ฒด ๋“ฑ๋ก @PostMapping("/stores") // ์Šคํ† ์–ด ์ƒ์„ฑ public ResponseEntity postStore(@RequestBody @Valid StorePostDto storePostDto) { Store store = storeMapper.storePostDtoToStore(storePostDto); // dto๋ฅผ store๋กœ ๋ณ€ํ™˜ - store.setMember(memberService.findMemberByEmail(AuthUtil.getCurrentMemberEmail())); //store์— ๋งด๋ฒ„ ์ฃผ์ž… + Store savedStore = storeService.createStore(store); // ์Šคํ† ์–ด ์ƒ์„ฑ StoreIdResponseDto storeIdResponseDto = storeMapper.storeToStorePostResponseDto(savedStore); return new ResponseEntity<>(storeIdResponseDto, HttpStatus.CREATED); @@ -50,12 +45,11 @@ public ResponseEntity postStore(@RequestBody @Valid StorePostDto storePostDto) { public ResponseEntity storeImgUpload(@PathVariable("store-id") long storeId, @RequestPart(value = "images", required = false) List images, @RequestParam(value = "thumbnailImage", required = false) MultipartFile thumbnailImage) throws IOException { - storeService.validateImagePost(images,thumbnailImage); + storeService.validateImagePost(images, thumbnailImage); storeService.storeImageUpload(images, storeId, thumbnailImage); return new ResponseEntity<>(HttpStatus.CREATED); } - // ์—…์ฒด ์ˆ˜์ • @PatchMapping("/stores/{store-id}") // ์Šคํ† ์–ด ๊ธ€ ์ˆ˜์ • public ResponseEntity patchStore(@PathVariable("store-id") @Positive long storeId, @@ -65,7 +59,6 @@ public ResponseEntity patchStore(@PathVariable("store-id") @Positive long storeI StoreIdResponseDto storeIdResponseDto = storeMapper.storeToStorePostResponseDto(patchStore); return new ResponseEntity<>(storeIdResponseDto, HttpStatus.OK); - } @PatchMapping("/storeImages/{store-id}") // ์Šคํ† ์–ด ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ @@ -77,10 +70,13 @@ public ResponseEntity storeImgPatch(@PathVariable("store-id") long storeId, return new ResponseEntity<>(HttpStatus.CREATED); } - @DeleteMapping("/storeImages/{store-id}") - public void storeImagesDelete(@PathVariable("store-id") long storeId, - @RequestParam("link") String link){ - storeService.deleteStoreImgLink(link, storeId, true); + @DeleteMapping("/storeImages/{store-id}") // ์—…์ฒด ์ด๋ฏธ์ง€ ์‚ญ์ œ + public ResponseEntity storeImagesDelete(@PathVariable("store-id") long storeId, + @RequestParam("link") String link) { + + storeService.deleteStoreImgLink(link, storeId); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @GetMapping("/stores/{store-id}") // ์Šคํ† ์–ด ์ƒ์„ธํŽ˜์ด์ง€, ์ˆ˜์ •ํŽ˜์ด์ง€ ๋žœ๋”๋ง์„ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค ์‘๋‹ต @@ -91,7 +87,7 @@ public ResponseEntity getStore(@PathVariable("store-id") @Positive long storeId) return new ResponseEntity<>(storeResponseDto, HttpStatus.OK); } - // ์—…์ฒด ์‚ญ์ œ PP_003 + // ์—…์ฒด ์‚ญ์ œ @DeleteMapping("/stores/{store-id}") //์Šคํ† ์–ด ์‚ญ์ œ public ResponseEntity deleteStore(@PathVariable("store-id") @Positive Long storeId) { storeService.deleteStore(storeId); @@ -129,4 +125,23 @@ public ResponseEntity getSearchResults(@RequestParam(name = "keyword") String ke storeService.insertWishAtCategoryResponseDto(searchResultTransformDto); return new ResponseEntity<>(searchResponseDtoWithLike, HttpStatus.OK); } + + // ์ฐœ ๋“ฑ๋ก + @PostMapping("/stores/favorites/{store-id}") + public ResponseEntity registerWish(@Positive @PathVariable("store-id") Long storeId) { + String email = AuthUtil.getCurrentMemberEmail(); + + storeService.registerWish(storeId, email); + + return new ResponseEntity(HttpStatus.CREATED); + } + + // ์ฐœ ์ทจ์†Œ + @DeleteMapping("/stores/favorites/{store-id}") + public ResponseEntity cancelWish(@Positive @PathVariable("store-id") Long storeId) { + String email = AuthUtil.getCurrentMemberEmail(); + + storeService.deleteWish(storeId, email); + return new ResponseEntity(HttpStatus.CREATED); + } } diff --git a/server/src/main/java/actiOn/store/dto/CategoryResponseDto.java b/server/src/main/java/actiOn/store/dto/CategoryResponseDto.java index 9dfbabd7..353901e0 100644 --- a/server/src/main/java/actiOn/store/dto/CategoryResponseDto.java +++ b/server/src/main/java/actiOn/store/dto/CategoryResponseDto.java @@ -12,7 +12,4 @@ public class CategoryResponseDto { private List> pageInfo; private List data; - - - } diff --git a/server/src/main/java/actiOn/store/dto/CategoryStoreDto.java b/server/src/main/java/actiOn/store/dto/CategoryStoreDto.java index 26cbe735..2b1fd7b0 100644 --- a/server/src/main/java/actiOn/store/dto/CategoryStoreDto.java +++ b/server/src/main/java/actiOn/store/dto/CategoryStoreDto.java @@ -16,5 +16,4 @@ public class CategoryStoreDto { private int price; private Boolean isLike = false; private String img; - } diff --git a/server/src/main/java/actiOn/store/dto/StorePatchDto.java b/server/src/main/java/actiOn/store/dto/StorePatchDto.java index bfb17970..d4d74f5d 100644 --- a/server/src/main/java/actiOn/store/dto/StorePatchDto.java +++ b/server/src/main/java/actiOn/store/dto/StorePatchDto.java @@ -7,6 +7,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import java.util.List; @Getter @@ -33,5 +34,6 @@ public class StorePatchDto { private String category; @NotEmpty(message = "์ƒํ’ˆ๋ชฉ๋ก์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”") + @Size(min = 1, message = "์ƒํ’ˆ๋ชฉ๋ก์€ ์ตœ์†Œ 1๊ฐœ ์ด์ƒ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") private List items; } diff --git a/server/src/main/java/actiOn/store/dto/StorePostDto.java b/server/src/main/java/actiOn/store/dto/StorePostDto.java index 43264679..cac87286 100644 --- a/server/src/main/java/actiOn/store/dto/StorePostDto.java +++ b/server/src/main/java/actiOn/store/dto/StorePostDto.java @@ -7,6 +7,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import java.util.List; @Getter @@ -22,6 +23,7 @@ public class StorePostDto { private String address; @NotBlank(message = "์นด์นด์˜ค ์•„์ด๋””๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”") + @Pattern(regexp = "[a-zA-Z0-9]+", message = "์˜๋ฌธ๊ณผ ์ˆซ์ž๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.") private String kakao; @NotBlank(message = "์—ฐ๋ฝ์ฒ˜๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”") @@ -33,6 +35,7 @@ public class StorePostDto { private String category; @NotEmpty(message = "์ƒํ’ˆ๋ชฉ๋ก์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”") + @Size(min = 1, message = "์ƒํ’ˆ๋ชฉ๋ก์€ ์ตœ์†Œ 1๊ฐœ ์ด์ƒ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.") private List items; } diff --git a/server/src/main/java/actiOn/store/dto/StoreResponseDto.java b/server/src/main/java/actiOn/store/dto/StoreResponseDto.java index 7f6f76a3..aba44a23 100644 --- a/server/src/main/java/actiOn/store/dto/StoreResponseDto.java +++ b/server/src/main/java/actiOn/store/dto/StoreResponseDto.java @@ -25,12 +25,4 @@ public class StoreResponseDto { private LocalDateTime createdAt; private List items; private List storeImages; - -// public boolean getIsLike() { -// return isLike; -// } -// -// public void setIsLike(boolean isLike) { -// isLike = isLike; -// } } diff --git a/server/src/main/java/actiOn/store/entity/Store.java b/server/src/main/java/actiOn/store/entity/Store.java index 14efc3c1..54514926 100644 --- a/server/src/main/java/actiOn/store/entity/Store.java +++ b/server/src/main/java/actiOn/store/entity/Store.java @@ -9,8 +9,10 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.Where; import javax.persistence.*; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -18,6 +20,8 @@ @Getter @Setter @NoArgsConstructor +@Table(name = "STORE") +@Where(clause = "deleted_at IS NULL") public class Store extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -62,6 +66,9 @@ public class Store extends BaseEntity { @Column(nullable = false) private int lowPrice; + @Column + private LocalDateTime deletedAt; + @ManyToOne @JoinColumn(name = "MEMBER_ID") private Member member; @@ -77,4 +84,16 @@ public class Store extends BaseEntity { @OneToMany(mappedBy = "store", cascade = {CascadeType.REMOVE, CascadeType.PERSIST}) private List storeImgList = new ArrayList<>(); + + public void addLikeCount() { + this.likeCount++; + } + + public void subLikeCount() { + this.likeCount--; + } + + public void addReviewCount() { + this.reviewCount++; + } } diff --git a/server/src/main/java/actiOn/store/mapper/CategoryResponseMapper.java b/server/src/main/java/actiOn/store/mapper/CategoryResponseMapper.java index 5d8f299a..14287bc8 100644 --- a/server/src/main/java/actiOn/store/mapper/CategoryResponseMapper.java +++ b/server/src/main/java/actiOn/store/mapper/CategoryResponseMapper.java @@ -25,23 +25,20 @@ public CategoryResponseDto CategoryStoreToCategoryResponseDto(List catego CategoryStoreDto categoryStoreDto = new CategoryStoreDto(); //์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ์ด๋ฏธ์ง€ ๊ด€๋ จ - try { - String img = originStore.getStoreImgList().isEmpty() ? null : originStore.getStoreImgList().get(0).getLink(); - for (StoreImg storeImg : originStore.getStoreImgList()) { - if (storeImg.getIsThumbnail()) { - img = storeImg.getLink(); - break; - } - } - if (img == null) { - throw new IllegalArgumentException("์Šคํ† ์–ด์˜ ์ด๋ฏธ์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); + String img = originStore.getStoreImgList().isEmpty() ? null : originStore.getStoreImgList().get(0).getLink(); + + for (StoreImg storeImg : originStore.getStoreImgList()) { + if (storeImg.getIsThumbnail()) { + img = storeImg.getLink(); + break; } - categoryStoreDto.setImg(img); - } catch (IllegalArgumentException e) { } - //์œ„์—๊นŒ์ง€๊ฐ€ ์ด๋ฏธ์ง€ ๊ด€๋ จ + if (img == null) { + throw new IllegalArgumentException("์Šคํ† ์–ด์˜ ์ด๋ฏธ์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); + } + categoryStoreDto.setImg(img); categoryStoreDto.setStoreId(originStore.getStoreId()); categoryStoreDto.setCategory(originStore.getCategory()); categoryStoreDto.setTitle(originStore.getStoreName()); @@ -53,6 +50,7 @@ public CategoryResponseDto CategoryStoreToCategoryResponseDto(List catego categoryStoreDtos.add(categoryStoreDto); } + int storeCount = categoryStoreDtos.size(); Map storeCountMap = new HashMap<>(); @@ -63,6 +61,7 @@ public CategoryResponseDto CategoryStoreToCategoryResponseDto(List catego categoryResponseDto.setPageInfo(pageInfo); categoryResponseDto.setData(categoryStoreDtos); + return categoryResponseDto; } } diff --git a/server/src/main/java/actiOn/store/mapper/StoreResponseMapper.java b/server/src/main/java/actiOn/store/mapper/StoreResponseMapper.java index e241c86f..9d5955ad 100644 --- a/server/src/main/java/actiOn/store/mapper/StoreResponseMapper.java +++ b/server/src/main/java/actiOn/store/mapper/StoreResponseMapper.java @@ -26,13 +26,20 @@ public StoreResponseDto storeToStoreResponseDto(Store store) { List modifiedItems = new ArrayList<>(); LocalDate currentDate = LocalDate.now(); Map reservationTicketCountInfo = reservationService.reservationTicketCount(store, currentDate); + for (Item item : findItems) { if (item.getStatus().equals(Item.ItemStatus.DELETED)) continue; + long itemId = item.getItemId(); - int maxCount = item.getTotalTicket(); - int remainingTicketCount = maxCount; + int remainingTicketCount = item.getTotalTicket(); + if (reservationTicketCountInfo.size() != 0) { - int reservationTicketCount = reservationTicketCountInfo.get(item.getItemId()); + int reservationTicketCount; + try{ + reservationTicketCount = reservationTicketCountInfo.get(item.getItemId()); + }catch (Exception e) { + reservationTicketCount = 0; + } remainingTicketCount = remainingTicketCount - reservationTicketCount; } if (remainingTicketCount < 0) { @@ -43,8 +50,10 @@ public StoreResponseDto storeToStoreResponseDto(Store store) { ); modifiedItems.add(modifiedItem); } + List findImgs = store.getStoreImgList(); List modifiedStoreImgs = new ArrayList<>(); + for (StoreImg storeImg : findImgs) { String link = storeImg.getLink(); if (storeImg.getIsThumbnail()) { @@ -53,6 +62,7 @@ public StoreResponseDto storeToStoreResponseDto(Store store) { modifiedStoreImgs.add(link); } } + StoreResponseDto storeResponseDto = new StoreResponseDto(); storeResponseDto.setStoreName(store.getStoreName()); storeResponseDto.setCategory(store.getCategory()); @@ -65,13 +75,14 @@ public StoreResponseDto storeToStoreResponseDto(Store store) { storeResponseDto.setCreatedAt(store.getCreatedAt()); storeResponseDto.setItems(modifiedItems); storeResponseDto.setStoreImages(modifiedStoreImgs); + try { - storeResponseDto.setProfileImg(store.getMember().getProfileImg().getLink()); + storeResponseDto.setProfileImg(store.getMember().getProfileImg()); } catch (NullPointerException e) { storeResponseDto.setProfileImg(null); // null ์ž๋ฆฌ์— ๊ธฐ๋ณธ ์ด๋ฏธ์ง€ ๋„ฃ์„ ์ˆ˜ ์žˆ์Œ } + return storeResponseDto; - // } } diff --git a/server/src/main/java/actiOn/store/repository/StoreCustomRepository.java b/server/src/main/java/actiOn/store/repository/StoreCustomRepository.java deleted file mode 100644 index d0c3b8be..00000000 --- a/server/src/main/java/actiOn/store/repository/StoreCustomRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package actiOn.store.repository; - -import actiOn.store.entity.Store; - -public interface StoreCustomRepository { - - void addLikeCount(Store store); - - void subLikeCount(Store store); - - void addReviewCount(Store store); - - void setRating(Store store, double avgRating); -} diff --git a/server/src/main/java/actiOn/store/repository/StoreRepository.java b/server/src/main/java/actiOn/store/repository/StoreRepository.java index bccd11cd..3ce14033 100644 --- a/server/src/main/java/actiOn/store/repository/StoreRepository.java +++ b/server/src/main/java/actiOn/store/repository/StoreRepository.java @@ -3,15 +3,17 @@ import actiOn.store.entity.Store; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.List; -public interface StoreRepository extends JpaRepository , StoreCustomRepository{ -// List findByCategory(String category); - +@Repository +public interface StoreRepository extends JpaRepository { List findAll(Sort sort); + List findByCategory(String category, Sort sort); List findTop4ByOrderByLikeCountDesc(); - List findByStoreNameContainingOrderByRatingDesc(String keyword);// + + List findByStoreNameContainingOrderByRatingDesc(String keyword); } diff --git a/server/src/main/java/actiOn/store/service/StoreService.java b/server/src/main/java/actiOn/store/service/StoreService.java index ff4276fd..1429ac3e 100644 --- a/server/src/main/java/actiOn/store/service/StoreService.java +++ b/server/src/main/java/actiOn/store/service/StoreService.java @@ -29,6 +29,9 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -45,28 +48,54 @@ public class StoreService { private final ItemService itemService; private final ImgService imgService; - private Store shapingStore(Store store) { - GeoLocation location = kakaoMapService.addressToLocation(store.getAddress()); - store.setLatitude(Double.parseDouble(location.getLatitude())); - store.setLongitude(Double.parseDouble(location.getLongitude())); - List items = store.getItems(); - int lowPrice = 0; - for (Item item : items) { - item.setStore(store); - int itemPrice = item.getPrice(); - if (lowPrice == 0 || itemPrice < lowPrice) lowPrice = itemPrice; - } - store.setLowPrice(lowPrice); // 0์œผ๋กœ ๋‚˜์˜ค๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ํ•„์š” - return store; + // ์—…์ฒด ์ฐœ ๊ฐœ์ˆ˜ ์ถ”๊ฐ€ + @Transactional(propagation = Propagation.REQUIRED) + public Store registerWish(long storeId, String email) { + Member member = memberService.findMemberByEmail(email); + + // Store ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ + Store store = findStoreByStoreId(storeId); + + // ์ด๋ฏธ ์ข‹์•„์š” ์žˆ์œผ๋ฉด ์—๋Ÿฌ ๋ฐ˜ํ™˜ + wishService.isNotExistWish(member, store); + + // Wish ๋“ฑ๋ก + wishService.generateWish(member, store); + + // ์ฐœ ๊ฐœ์ˆ˜ ์ถ”๊ฐ€ + store.addLikeCount(); + return storeRepository.save(store); + } + + // ์—…์ฒด ์ฐœ ๊ฐœ์ˆ˜ ๋นผ๊ธฐ + @Transactional(propagation = Propagation.REQUIRED) + public Store deleteWish(long storeId, String email) { + Member member = memberService.findMemberByEmail(email); + + // Store ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ + Store store = findStoreByStoreId(storeId); + + // wish๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ ๋ฐ˜ํ™˜ + Wish wish = wishService.isExistWish(member, store); + + // wish ์‚ญ์ œ + wishService.deleteWish(wish); + + // ์ฐœ ๊ฐœ์ˆ˜ -1 + store.subLikeCount(); + return storeRepository.save(store); } + // ์—…์ฒด ๋“ฑ๋ก public Store createStore(Store store) { // store๋ฅผ ๋ฐ›์•„์„œ, ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ, ๊ทธ ์ฃผ์†Œ๋ฅผ ์นด์นด์˜ค๋กœ ๋ณด๋‚ด์„œ ์ขŒํ‘œ๋ฅผ ๋ฐ›์•„์˜ด Store shapedStore = shapingStore(store); + Member storeCreator = memberService.findMemberByEmail(AuthUtil.getCurrentMemberEmail()); shapedStore.setMember(storeCreator); return storeRepository.save(shapedStore); } + // ์—…์ฒด ์ˆ˜์ • @Transactional(propagation = Propagation.REQUIRED) public Store updateStore(Store store, long storeId) { Store findStore = findverifyIdentityStore(storeId); @@ -83,6 +112,7 @@ public Store updateStore(Store store, long storeId) { findStore.setLowPrice(lowPrice); // 0์œผ๋กœ ๋‚˜์˜ค๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ํ•„์š” findStore.setStoreName(store.getStoreName()); + findStore.setCategory(store.getCategory()); findStore.setBody(store.getBody()); findStore.setKakao(store.getKakao()); findStore.setContact(store.getContact()); @@ -90,40 +120,13 @@ public Store updateStore(Store store, long storeId) { return storeRepository.save(findStore); } - private int computeLowPrice(List items) { - int lowPrice = 0; - - for (Item item : items) { - int itemPrice = item.getPrice(); - if (lowPrice == 0 || itemPrice < lowPrice) lowPrice = itemPrice; - } - - return lowPrice; - } - - // ์œ„๋„, ๊ฒฝ๋„, ์ฃผ์†Œ ์„ค์ • - private void shapingFindStore(Store findStore, Store store) { - GeoLocation location = kakaoMapService.addressToLocation(store.getAddress()); - findStore.setAddress(store.getAddress()); - findStore.setLatitude(Double.parseDouble(location.getLatitude())); - findStore.setLongitude(Double.parseDouble(location.getLongitude())); - } - - @Transactional - public void deleteStore(Long storeId) { - Store findStore = this.findStoreByStoreId(storeId); - - //Todo member๊ฐ€ ์˜ฌ๋ฆฐ ์Šคํ† ์–ด์ธ์ง€ ํ™•์ธ ํ•„์š” - String loginUserEmail = AuthUtil.getCurrentMemberEmail(); - Member findMember = memberService.findMemberByEmail(loginUserEmail); - - if (!findStore.getMember().getMemberId().equals(findMember.getMemberId())) { - throw new IllegalArgumentException("์—…์ฒด๋ฅผ ๋“ฑ๋กํ•œ ํŒŒํŠธ๋„ˆ๋งŒ์ด ์—…์ฒด ์‚ญ์ œ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."); - } - - //Todo ์—…์ฒด๋ฅผ ์‚ญ์ œํ•  ๋•Œ ์‚ฌ์—…์ฒด ๋“ฑ๋ก๋ฒˆํ˜ธ๋ฅผ ์ฒดํฌํ•œ๋‹ค๋“ ์ง€, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ฐ›๋Š” ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๋ฉด ์–ด๋–จ๊นŒ? + // ์—…์ฒด ์‚ญ์ œ + public void deleteStore(long storeId) { + Store findStore = findverifyIdentityStore(storeId); - storeRepository.delete(findStore); + // soft delete + findStore.setDeletedAt(LocalDateTime.now()); + storeRepository.save(findStore); } public List getWishStoreIdList(Member member) { @@ -141,15 +144,6 @@ public Store findStoreByStoreId(long storeId) { .orElseThrow(() -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND)); } - private void isValidValue(String category, String sortField) { - List categoryList = Arrays.asList("all", "์Šค๋…ธํด๋ง/๋‹ค์ด๋น™", "์ˆ˜์ƒ๋ ˆ์ €", "์„œํ•‘", "์Šน๋งˆ", "ATV"); - List sortFieldList = Arrays.asList("likeCount", "rating", "lowPrice", "highPrice", "reviewCount"); - - if (!categoryList.contains(category) || !sortFieldList.contains(sortField)) { - throw new BusinessLogicException(ExceptionCode.INVALID_PARAMETER_VALUE); - } - } - public List findStoreByCategory(String category, String sortFiled) { isValidValue(category, sortFiled); Sort.Direction sortOption = Sort.Direction.DESC; @@ -160,10 +154,13 @@ public List findStoreByCategory(String category, String sortFiled) { } public List searchEnginOnStoreNameByKeyword(String keyword) { - return storeRepository.findByStoreNameContainingOrderByRatingDesc(keyword); + // ๊ฒ€์ƒ‰์–ด ๋””์ฝ”๋”ฉ + String decodedKeyword = URLDecoder.decode(keyword, StandardCharsets.UTF_8); + + return storeRepository.findByStoreNameContainingOrderByRatingDesc(decodedKeyword); } - //๋ฉ”์ธํŽ˜์ด์ง€ + // ๋ฉ”์ธํŽ˜์ด์ง€ public MainPageResponseDto getMainPage() { MainPageResponseDto mainPageResponseDto = new MainPageResponseDto(); @@ -218,7 +215,6 @@ public StoreResponseDto insertWishAtStoreResponseDto(StoreResponseDto responseDt responseDto.setIsLike(true); } return responseDto; - } public CategoryResponseDto insertWishAtCategoryResponseDto(CategoryResponseDto categoryResponseDto) { @@ -234,12 +230,20 @@ public CategoryResponseDto insertWishAtCategoryResponseDto(CategoryResponseDto c } @Transactional - public void deleteStoreImgLink(String link, long storeId, Boolean doVerify) { - findverifyIdentityStore(storeId); // TODO doVerify ์‚ญ์ œ + public void deleteStoreImgLink(String link, long storeId) { + findverifyIdentityStore(storeId); imgService.deleteStoreImage(link); } + // ํ‰๊ท  ๋ณ„์ , ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜ ์—…๋ฐ์ดํŠธ + public void updateRatingAndReviewCount(Store store, Double avgRating) { + store.setRating(avgRating); + store.addReviewCount(); + + storeRepository.save(store); + } + public Store findverifyIdentityStore(long storeId) { String memberEmail = AuthUtil.getCurrentMemberEmail(); Member member = memberService.findMemberByEmail(memberEmail); @@ -260,11 +264,17 @@ public Store findverifyIdentityStore(long storeId) { public void storeImageUpload(List images, long storeId, MultipartFile thumbnailImage) throws IOException { findverifyIdentityStore(storeId); // ๋ณธ์ธ ๊ฒ€์ฆ Store findStore = findStoreByStoreId(storeId); // ์Šคํ† ์–ด ์ฐพ๊ธฐ - if (images == null) images = new ArrayList<>(); - images.add(0, null); - if (thumbnailImage != null) images.add(0, thumbnailImage); - imgService.uploadStoreImage(images, findStore, thumbnailImage); // ์—…๋กœ๋“œ // + List newImages = new ArrayList<>(); + if (thumbnailImage != null) { + newImages.add(0, thumbnailImage); + } else { + newImages.add(0, null); + } + + newImages.addAll(images); + + imgService.uploadStoreImage(newImages, findStore, thumbnailImage); // ์—…๋กœ๋“œ // } public void validateImagePost(List images, MultipartFile thumbnailImage) { @@ -272,4 +282,47 @@ public void validateImagePost(List images, MultipartFile thumbnai if (images == null) throw new BusinessLogicException(ExceptionCode.IMAGE_LIST_IS_EMPTY); if (thumbnailImage == null) throw new BusinessLogicException(ExceptionCode.THUMBNAIL_IS_NULL); } + + // ์œ„๋„, ๊ฒฝ๋„, ์ฃผ์†Œ ์„ค์ • + private void shapingFindStore(Store findStore, Store store) { + GeoLocation location = kakaoMapService.addressToLocation(store.getAddress()); + findStore.setAddress(store.getAddress()); + findStore.setLatitude(Double.parseDouble(location.getLatitude())); + findStore.setLongitude(Double.parseDouble(location.getLongitude())); + } + + private void isValidValue(String category, String sortField) { + List categoryList = Arrays.asList("all", "์Šค๋…ธํด๋ง/๋‹ค์ด๋น™", "์ˆ˜์ƒ๋ ˆ์ €", "์„œํ•‘", "์Šน๋งˆ", "ATV"); + List sortFieldList = Arrays.asList("likeCount", "rating", "lowPrice", "highPrice", "reviewCount"); + + if (!categoryList.contains(category) || !sortFieldList.contains(sortField)) { + throw new BusinessLogicException(ExceptionCode.INVALID_PARAMETER_VALUE); + } + } + + private int computeLowPrice(List items) { + int lowPrice = 0; + + for (Item item : items) { + int itemPrice = item.getPrice(); + if (lowPrice == 0 || itemPrice < lowPrice) lowPrice = itemPrice; + } + + return lowPrice; + } + + private Store shapingStore(Store store) { + GeoLocation location = kakaoMapService.addressToLocation(store.getAddress()); + store.setLatitude(Double.parseDouble(location.getLatitude())); + store.setLongitude(Double.parseDouble(location.getLongitude())); + List items = store.getItems(); + int lowPrice = 0; + for (Item item : items) { + item.setStore(store); + int itemPrice = item.getPrice(); + if (lowPrice == 0 || itemPrice < lowPrice) lowPrice = itemPrice; + } + store.setLowPrice(lowPrice); // 0์œผ๋กœ ๋‚˜์˜ค๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ ํ•„์š” + return store; + } } \ No newline at end of file diff --git a/server/src/main/java/actiOn/wish/controller/WishController.java b/server/src/main/java/actiOn/wish/controller/WishController.java deleted file mode 100644 index 5d53f5ad..00000000 --- a/server/src/main/java/actiOn/wish/controller/WishController.java +++ /dev/null @@ -1,38 +0,0 @@ -package actiOn.wish.controller; - -import actiOn.wish.mapper.WishMapper; -import actiOn.wish.service.WishService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.constraints.Positive; - -@RestController -public class WishController { - - private final WishService wishService; - private final WishMapper wishMapper; - - public WishController(WishService wishService, WishMapper wishMapper) { - this.wishService = wishService; - this.wishMapper = wishMapper; - } - - //TODO CP_002 ์ฐœ ๋“ฑ๋ก - @PostMapping("/stores/favorites/{store-id}") - public ResponseEntity registerWish(@Positive @PathVariable("store-id") Long storeId){ - wishService.registerWish(storeId); - return new ResponseEntity(HttpStatus.CREATED); - } - - //TODO CP_002 ์ฐœ ์ทจ์†Œ - @DeleteMapping("/stores/favorites/{store-id}") - public ResponseEntity cancelWish(@Positive @PathVariable("store-id") Long storeId){ - wishService.deleteWish(storeId); - return new ResponseEntity(HttpStatus.CREATED); - } -} diff --git a/server/src/main/java/actiOn/wish/service/WishService.java b/server/src/main/java/actiOn/wish/service/WishService.java index 2a737a3c..bef8ac0f 100644 --- a/server/src/main/java/actiOn/wish/service/WishService.java +++ b/server/src/main/java/actiOn/wish/service/WishService.java @@ -1,82 +1,53 @@ package actiOn.wish.service; -import actiOn.auth.utils.AuthUtil; import actiOn.exception.BusinessLogicException; import actiOn.exception.ExceptionCode; import actiOn.member.entity.Member; -import actiOn.member.service.MemberService; import actiOn.store.entity.Store; -import actiOn.store.repository.StoreRepository; import actiOn.wish.entity.Wish; import actiOn.wish.repository.WishRepository; +import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; @Service +@AllArgsConstructor public class WishService { - private final WishRepository wishRepository; - private final StoreRepository storeRepository; - private final MemberService memberService; - public WishService(WishRepository wishRepository, StoreRepository storeRepository, MemberService memberService) { - this.wishRepository = wishRepository; - this.storeRepository = storeRepository; - this.memberService = memberService; + public List getWishListByMember(Member member) { + List wishList = wishRepository.findByMember(member); + return wishList; } - @Transactional(propagation = Propagation.REQUIRED) - public void registerWish(Long storeId){ - //Todo Login ์œ ์ € ์ฐพ๊ธฐ -> ๋ฆฌํŒฉํ† ๋ง. memberservice์—์„œ findByEmail ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ์˜ˆ์ • - String loginUserEmail = AuthUtil.getCurrentMemberEmail(); - Member findMember = memberService.findMemberByEmail(loginUserEmail); - - //Todo Store ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ - Store store = storeRepository.findById(storeId).orElseThrow( - (() -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND))); + public void isNotExistWish(Member member, Store store) { + Optional wish = wishRepository.findByMemberAndStore(member, store); - //Todo ์ด๋ฏธ ์ข‹์•„์š” ๋˜์–ด ์žˆ์œผ๋ฉด ์—๋Ÿฌ ๋ฐ˜ํ™˜ -> Frontend์—์„œ ์š”์ฒญ ๋ฉ”์„œ๋“œ ์‹ค์ˆ˜ ์žˆ์„์ˆ˜๋„ ์žˆ๊ธฐ์— ์ถ”๊ฐ€ - if (wishRepository.findByMemberAndStore(findMember,store).isPresent()){ + if (wish.isPresent()) { throw new BusinessLogicException(ExceptionCode.WISH_EXIST); } - - Wish wish = new Wish(); - wish.setMember(findMember); - wish.setStore(store); - wishRepository.save(wish); //Wish๊ฐ€ insert ๋˜๋Š” ์ˆœ๊ฐ„ store ๋ฐ์ดํ„ฐ์— s-Lock์ด ๊ฑธ๋ฆฐ๋‹ค. - - //Todo Store์— ๋Œ€ํ•œ ์ฐœ ๊ฐœ์ˆ˜ +1 ๋กœ์ง - storeRepository.addLikeCount(store); //store์—์„œ update ์ฟผ๋ฆฌ ๋ฐœ์ƒ ์‹œ Exclusive lock ๋ฐœ์ƒ } - @Transactional(propagation = Propagation.REQUIRED) - public void deleteWish(Long storeId){ - //Todo Login ์œ ์ € ์ฐพ๊ธฐ -> ๋ฆฌํŒฉํ† ๋ง. memberservice์—์„œ findByEmail ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ์˜ˆ์ • - String loginUserEmail = AuthUtil.getCurrentMemberEmail(); - Member findMember = memberService.findMemberByEmail(loginUserEmail); - - //Todo Store ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ - Store store = storeRepository.findById(storeId).orElseThrow( - (() -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND))); - - //Tdo Wish ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ - Wish wish = wishRepository.findByMemberAndStore(findMember,store) - .orElseThrow(() -> new BusinessLogicException(ExceptionCode.WISH_NOT_FOUND)); + public Wish isExistWish(Member member, Store store) { + Optional wish = wishRepository.findByMemberAndStore(member, store); - wishRepository.delete(wish); - - //Todo Store์— ๋Œ€ํ•œ ์ฐœ ๊ฐœ์ˆ˜ -1 ๋กœ์ง - storeRepository.subLikeCount(store); + if (wish.isEmpty()) { + throw new BusinessLogicException(ExceptionCode.WISH_NOT_FOUND); + } + return wish.get(); } + public Wish generateWish(Member member, Store store) { + Wish wish = new Wish(); + wish.setMember(member); + wish.setStore(store); - public List getWishListByMember(Member member) { - List wishList = wishRepository.findByMember(member); - return wishList; + return wishRepository.save(wish); //Wish๊ฐ€ insert ๋˜๋Š” ์ˆœ๊ฐ„ store ๋ฐ์ดํ„ฐ์— s-Lock์ด ๊ฑธ๋ฆฐ๋‹ค. } - + public void deleteWish(Wish wish) { + wishRepository.delete(wish); + } } diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 14f200b0..a1d0b9a9 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -1,83 +1,100 @@ spring: + redis: + host: ${REDIS_HOST} + port: 6379 + cache: + type: redis + redis: + time-to-live: 600 # ๋ฐ์ดํ„ฐ ์œ ์ง€ ์‹œ๊ฐ„(sec) + cache-null-values: true # null ์บ์‹ฑ ์—ฌ๋ถ€ h2: console: enabled: true path: /h2 settings: web-allow-others: true -# datasource: -# url: jdbc:h2:mem:test +# sql: +# init: +# data-locations: classpath*:db/h2/data.sql +# encoding: UTF-8 jpa: + database: mysql # mysql ์„ค์ • + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect hibernate: - ddl-auto: update # ์Šคํ‚ค๋งˆ ์ž๋™ ์ƒ์„ฑ // ์ˆ˜์ • - show-sql: false # SQL ์ฟผ๋ฆฌ ์ถœ๋ ฅ + ddl-auto: update + show-sql: false properties: hibernate: + connection: + characterEncoding: UTF-8 + useUniCode: true format_sql: true # SQL pretty print jdbc: time_zone: Asia/Seoul # ์„œ๋ฒ„ ์‹œ๊ฐ„ ์„œ์šธ๋กœ ๋ณ€๊ฒฝ - database: mysql - database-platform: org.hibernate.dialect.MySQL5InnoDBDialect - - # RDS mysql ์„ค์ • datasource: - driver-class-name: com.mysql.cj.jdbc.Driver -# sql: -# init: -# data-locations: classpath*:db/h2/data.sql + #url: jdbc:h2:mem:test + driver-class-name: com.mysql.cj.jdbc.Driver # RDS mysql ์„ค์ • + initialization-mode: always security: oauth2: client: registration: google: -# client-id: ${G_CLIENT_ID} -# client-secret: ${G_CLIENT_SECRET} + # ๋ฐฑ์—”๋“œ ๋„๋ฉ”์ธ + redirect-uri: http://ec2-52-78-205-102.ap-northeast-2.compute.amazonaws.com:8080/login/oauth2/code/google + client-id: ${G_CLIENT_ID} + client-secret: ${G_CLIENT_SECRET} scope: - profile - email servlet: - multipart: + multipart: # ํŒŒ์ผ ์—…๋กœ๋“œ ๊ด€๋ จ ์„ค์ • enabled: true file-size-threshold: 2KB - max-file-size: 200MB - max-request-size: 215MB + max-file-size: 100MB + max-request-size: 100MB resolve-lazily: false + logging: level: org: springframework: orm: DEBUG com: - amazonaws: + amazons: util: EC2MetadataUtils: ERROR -server: # ๋ชจ๋“  response ์— ๋Œ€ํ•ด ์ง€์ •๋œ ์ธ์ฝ”๋”ฉ ์ ์šฉ(ํ•œ๊ธ€ ๊นจ์ง ๋ฐฉ์ง€) +server: # ๋ชจ๋“  response ์— ๋Œ€ํ•ด ์ง€์ •๋œ ์ธ์ฝ”๋”ฉ ์ ์šฉ(ํ•œ๊ธ€ ๊นจ์ง ๋ฐฉ์ง€) servlet: encoding: force-response: true -jwt: # JWT ๊ด€๋ จ ์ •๋ณด - #key: ${JWT_SECRET_KEY} # ์‹œ์Šคํ…œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ ๋กœ๋“œ + +jwt: # JWT ๊ด€๋ จ ์ •๋ณด + key: ${JWT_SECRET_KEY} # ์‹œ์Šคํ…œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ ๋กœ๋“œ access-token-expiration-minutes: 100 refresh-token-expiration-minutes: 200 -#awsParameterStorePropertySource: -# enabled: true - -cloud: # ์ด๊ฑฐ ์•ˆํ•˜๋ฉด host down ์—๋Ÿฌ ๋ฐœ์ƒ +cloud: # AWS S3 ๋ฒ„ํ‚ท ์„ค์ • aws: s3: - bucket: action-project # ์ˆ˜์ • -# credentials: -# access-key: ${S3_ACCESS_KEY} -# secret-key: ${S3_SECRET_KEY} + bucket: action-project region: static: ap-northeast-2 auto: false stack: auto: false + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} -kakao: +kakao: # ์นด์นด์˜ค ์ง€๋„ ๊ด€๋ จ url: https://dapi.kakao.com/v2/local/search/address.json - #access-key: ${KAKAO_ACCESS_KEY} \ No newline at end of file + access-key: ${KAKAO_ACCESS_KEY} + +payment: # ํ† ์Šค ํŽ˜์ด๋จผ์ธ  ๊ด€๋ จ + toss: + test-client-key: ${TOSS_CLIENT_KEY} + test-secret-key: ${TOSS_SECRET_KEY} + url: "https://api.tosspayments.com/v1/payments/" \ No newline at end of file