diff --git a/.cursor/debug.log b/.cursor/debug.log deleted file mode 100644 index be9f56d..0000000 --- a/.cursor/debug.log +++ /dev/null @@ -1,278 +0,0 @@ -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032347685,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032347686,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:165","message":"parseViaExtension: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","hasChrome":true,"hasRuntime":true},"timestamp":1769032347686,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:175","message":"parseViaExtension: got extension ID","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032347694,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:178","message":"parseViaExtension: sending message","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032347694,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032347696,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118967,"url":""},"timestamp":1769032347707,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348580,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348582,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348621,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348967,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348970,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348974,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348975,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348978,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348979,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348980,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032348980,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118967,"status":"complete","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032349179,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118967,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032349180,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118967,"attempt":0},"timestamp":1769032351183,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118967,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032351184,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118967},"timestamp":1769032351183,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118967},"timestamp":1769032351184,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118967,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032351184,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118967},"timestamp":1769032351185,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118967,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032351186,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118967,"frameId":0},"timestamp":1769032351187,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118967},"timestamp":1769032351188,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118967,"pingAttempt":0},"timestamp":1769032351494,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118967,"pingAttempt":0},"timestamp":1769032351495,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118967,"injected":true},"timestamp":1769032351495,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118967,"attempt":0},"timestamp":1769032351496,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118967,"hasResponse":true,"ok":true},"timestamp":1769032351497,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:196","message":"parseViaExtension: response success","data":{"hasStats":true,"itemsSold":348728,"stats":{"itemsSold":348728}},"timestamp":1769032351513,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"AccountsPage.jsx:93","message":"handleRefreshAccount: update payload","data":{"payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728}},"timestamp":1769032351513,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728},"payloadKeys":["account_platform_market","account_platform_account_id","account_shop_name","account_sells"]},"timestamp":1769032351513,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032351603,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032358262,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032358264,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:165","message":"parseViaExtension: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","hasChrome":true,"hasRuntime":true},"timestamp":1769032358263,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:175","message":"parseViaExtension: got extension ID","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032358275,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:178","message":"parseViaExtension: sending message","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032358276,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032358277,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118969,"url":""},"timestamp":1769032358289,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118969,"status":"loading","url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=a41c5b80-ed2d-4186-a1f1-e146e4aee0f1&iim=aMTQ1LjR&iia=HOIyNC43wL&iiz=YnjMy4yMjU*Doi"},"timestamp":1769032358785,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118969,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=a41c5b80-ed2d-4186-a1f1-e146e4aee0f1&iim=aMTQ1LjR&iia=HOIyNC43wL&iiz=YnjMy4yMjU*Doi"},"timestamp":1769032358836,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118969,"status":"complete","url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=a41c5b80-ed2d-4186-a1f1-e146e4aee0f1&iim=aMTQ1LjR&iia=HOIyNC43wL&iiz=YnjMy4yMjU*Doi"},"timestamp":1769032358892,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118969,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=a41c5b80-ed2d-4186-a1f1-e146e4aee0f1&iim=aMTQ1LjR&iia=HOIyNC43wL&iiz=YnjMy4yMjU*Doi","isEbayUrl":true},"timestamp":1769032358892,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118969,"attempt":0},"timestamp":1769032360901,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118969},"timestamp":1769032360901,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118969,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=a41c5b80-ed2d-4186-a1f1-e146e4aee0f1&iim=aMTQ1LjR&iia=HOIyNC43wL&iiz=YnjMy4yMjU*Doi","isEbayUrl":true},"timestamp":1769032360902,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118969},"timestamp":1769032360902,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118969,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032361126,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118969},"timestamp":1769032361127,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118969,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=a41c5b80-ed2d-4186-a1f1-e146e4aee0f1&iim=aMTQ1LjR&iia=HOIyNC43wL&iiz=YnjMy4yMjU*Doi"},"timestamp":1769032361128,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118969,"frameId":0},"timestamp":1769032361130,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118969},"timestamp":1769032361132,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118969,"pingAttempt":0},"timestamp":1769032361443,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118969,"pingAttempt":0},"timestamp":1769032361444,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118969,"injected":true},"timestamp":1769032361444,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118969,"attempt":0},"timestamp":1769032361445,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118969,"hasResponse":true,"ok":true},"timestamp":1769032361446,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:196","message":"parseViaExtension: response success","data":{"hasStats":true,"itemsSold":null,"stats":{"itemsSold":null}},"timestamp":1769032361460,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"AccountsPage.jsx:93","message":"handleRefreshAccount: update payload","data":{"payload":{"account_platform_market":"DE","account_shop_name":"Bitte bestätigen Sie zum Fortfahren Ihre Identität","account_sells":null}},"timestamp":1769032361460,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_shop_name":"Bitte bestätigen Sie zum Fortfahren Ihre Identität"},"payloadKeys":["account_platform_market","account_shop_name"]},"timestamp":1769032361460,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032361564,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032441216,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032441217,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:165","message":"parseViaExtension: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","hasChrome":true,"hasRuntime":true},"timestamp":1769032441216,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:175","message":"parseViaExtension: got extension ID","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032441224,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:178","message":"parseViaExtension: sending message","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032441225,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032441226,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118971,"url":""},"timestamp":1769032441238,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118971,"status":"loading","url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=1bd50360-556b-409a-951f-01bca5aaf679&iim=GMTQ1Ljm&iia=hsIyNC43kV&iiz=zlQMy4yMjU*eRR"},"timestamp":1769032441726,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118971,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=1bd50360-556b-409a-951f-01bca5aaf679&iim=GMTQ1Ljm&iia=hsIyNC43kV&iiz=zlQMy4yMjU*eRR"},"timestamp":1769032441732,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118971,"status":"complete","url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=1bd50360-556b-409a-951f-01bca5aaf679&iim=GMTQ1Ljm&iia=hsIyNC43kV&iiz=zlQMy4yMjU*eRR"},"timestamp":1769032441786,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118971,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=1bd50360-556b-409a-951f-01bca5aaf679&iim=GMTQ1Ljm&iia=hsIyNC43kV&iiz=zlQMy4yMjU*eRR","isEbayUrl":true},"timestamp":1769032441786,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118971,"attempt":0},"timestamp":1769032443790,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118971},"timestamp":1769032443791,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118971,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=1bd50360-556b-409a-951f-01bca5aaf679&iim=GMTQ1Ljm&iia=hsIyNC43kV&iiz=zlQMy4yMjU*eRR","isEbayUrl":true},"timestamp":1769032443792,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118971},"timestamp":1769032443792,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118971,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032443793,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118971},"timestamp":1769032443793,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118971,"url":"https://www.ebay.de/splashui/captcha?ap=1&appName=orch&ru=https%3A%2F%2Fwww.ebay.de%2Fstr%2Fsbdirect24%3F_trksid%3Dp4429486.m3561.l161211&iid=1bd50360-556b-409a-951f-01bca5aaf679&iim=GMTQ1Ljm&iia=hsIyNC43kV&iiz=zlQMy4yMjU*eRR"},"timestamp":1769032443794,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118971,"frameId":0},"timestamp":1769032443795,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118971},"timestamp":1769032443797,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118971,"pingAttempt":0},"timestamp":1769032444100,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118971,"pingAttempt":0},"timestamp":1769032444101,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118971,"injected":true},"timestamp":1769032444102,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118971,"attempt":0},"timestamp":1769032444102,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118971,"hasResponse":true,"ok":true},"timestamp":1769032444103,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:196","message":"parseViaExtension: response success","data":{"hasStats":true,"itemsSold":null,"stats":{"itemsSold":null}},"timestamp":1769032444116,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"AccountsPage.jsx:93","message":"handleRefreshAccount: update payload","data":{"payload":{"account_platform_market":"DE","account_shop_name":"Bitte bestätigen Sie zum Fortfahren Ihre Identität","account_sells":null}},"timestamp":1769032444116,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_shop_name":"Bitte bestätigen Sie zum Fortfahren Ihre Identität"},"payloadKeys":["account_platform_market","account_shop_name"]},"timestamp":1769032444117,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032444203,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032465359,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032465359,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:165","message":"parseViaExtension: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","hasChrome":true,"hasRuntime":true},"timestamp":1769032465359,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:175","message":"parseViaExtension: got extension ID","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032465366,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:178","message":"parseViaExtension: sending message","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032465366,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032465367,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118975,"url":""},"timestamp":1769032465376,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466284,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466287,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466315,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466656,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466659,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466663,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466663,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466664,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466665,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466667,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466667,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118975,"status":"complete","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032466804,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118975,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032466804,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118975,"attempt":0},"timestamp":1769032468807,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118975},"timestamp":1769032468808,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118975,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032468808,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118975},"timestamp":1769032468808,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118975,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032468809,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118975},"timestamp":1769032468809,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118975,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032468809,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118975,"frameId":0},"timestamp":1769032468811,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118975},"timestamp":1769032468812,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118975,"pingAttempt":0},"timestamp":1769032469121,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118975,"pingAttempt":0},"timestamp":1769032469122,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118975,"injected":true},"timestamp":1769032469123,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118975,"attempt":0},"timestamp":1769032469123,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118975,"hasResponse":true,"ok":true},"timestamp":1769032469124,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:196","message":"parseViaExtension: response success","data":{"hasStats":true,"itemsSold":348728,"stats":{"itemsSold":348728}},"timestamp":1769032469138,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"AccountsPage.jsx:93","message":"handleRefreshAccount: update payload","data":{"payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728}},"timestamp":1769032469138,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728},"payloadKeys":["account_platform_market","account_platform_account_id","account_shop_name","account_sells"]},"timestamp":1769032469139,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032469243,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032683600,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032683601,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:165","message":"parseViaExtension: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","hasChrome":true,"hasRuntime":true},"timestamp":1769032683601,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:175","message":"parseViaExtension: got extension ID","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032683609,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:178","message":"parseViaExtension: sending message","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032683609,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032683610,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118977,"url":""},"timestamp":1769032683621,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032684632,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032684634,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032684639,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685105,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685108,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685112,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685113,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685114,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685115,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685116,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685117,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118977,"status":"complete","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032685262,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118977,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032685263,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118977,"attempt":0},"timestamp":1769032687278,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118977},"timestamp":1769032687278,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118977,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032687279,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118977},"timestamp":1769032687279,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118977,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032687280,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118977},"timestamp":1769032687281,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118977,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032687281,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118977,"frameId":0},"timestamp":1769032687283,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118977},"timestamp":1769032687284,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118977,"pingAttempt":0},"timestamp":1769032687590,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118977,"pingAttempt":0},"timestamp":1769032687591,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118977,"injected":true},"timestamp":1769032687591,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118977,"attempt":0},"timestamp":1769032687591,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118977,"hasResponse":true,"ok":true},"timestamp":1769032687593,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:196","message":"parseViaExtension: response success","data":{"hasStats":true,"itemsSold":348728,"stats":{"itemsSold":348728}},"timestamp":1769032687608,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728},"payloadKeys":["account_platform_market","account_platform_account_id","account_shop_name","account_sells"]},"timestamp":1769032687608,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032687693,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032795025,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032795025,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032795080,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118979,"url":""},"timestamp":1769032795089,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796012,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796014,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796026,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796358,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796361,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796365,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796365,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796366,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796367,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796368,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796368,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118979,"status":"complete","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032796823,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118979,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032796823,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118979,"attempt":0},"timestamp":1769032798837,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118979},"timestamp":1769032798837,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118979,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032798838,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118979},"timestamp":1769032798838,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118979,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032798839,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118979},"timestamp":1769032798839,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118979,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032798840,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118979,"frameId":0},"timestamp":1769032798841,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118979},"timestamp":1769032798842,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118979,"pingAttempt":0},"timestamp":1769032799147,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118979,"pingAttempt":0},"timestamp":1769032799149,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118979,"injected":true},"timestamp":1769032799149,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118979,"attempt":0},"timestamp":1769032799149,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118979,"hasResponse":true,"ok":true},"timestamp":1769032799151,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:160","message":"parseViaExtension: response data from extension","data":{"hasStats":true,"itemsSold":348728,"stats":{"itemsSold":348728}},"timestamp":1769032799167,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728},"payloadKeys":["account_platform_market","account_platform_account_id","account_shop_name","account_sells"]},"timestamp":1769032799168,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"AccountsPage.jsx:93","message":"handleRefreshAccount: update payload","data":{"payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728}},"timestamp":1769032799167,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032799416,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032812193,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032812190,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032812190,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118983,"url":""},"timestamp":1769032812203,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813057,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813059,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813069,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813381,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813384,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813387,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813388,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813389,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813390,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813391,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813392,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118983,"status":"complete","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032813527,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118983,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032813527,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118983,"attempt":0},"timestamp":1769032815528,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118983},"timestamp":1769032815529,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118983,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032815529,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118983},"timestamp":1769032815529,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118983,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032815530,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118983},"timestamp":1769032815531,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118983,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032815531,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118983,"frameId":0},"timestamp":1769032815533,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118983},"timestamp":1769032815535,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118983,"pingAttempt":0},"timestamp":1769032815838,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118983,"pingAttempt":0},"timestamp":1769032815839,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118983,"injected":true},"timestamp":1769032815839,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118983,"attempt":0},"timestamp":1769032815839,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118983,"hasResponse":true,"ok":true},"timestamp":1769032815841,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:160","message":"parseViaExtension: response data from extension","data":{"hasStats":true,"itemsSold":348728,"stats":{"itemsSold":348728}},"timestamp":1769032815854,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728},"payloadKeys":["account_platform_market","account_platform_account_id","account_shop_name","account_sells"]},"timestamp":1769032815855,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"AccountsPage.jsx:93","message":"handleRefreshAccount: update payload","data":{"payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728}},"timestamp":1769032815854,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032815938,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"ebayParserService.js:292","message":"parseEbayAccount: route decision","data":{"extAvailable":true,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032819428,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:135","message":"getExtensionId: found via cache","data":{"cachedExtensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc"},"timestamp":1769032819429,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:165","message":"parseViaExtension: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","hasChrome":true,"hasRuntime":true},"timestamp":1769032819429,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:175","message":"parseViaExtension: got extension ID","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032819437,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"ebayParserService.js:178","message":"parseViaExtension: sending message","data":{"extensionId":"ikldokdleojiinjklkhkkhfhpfafeaoc","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032819437,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:73","message":"handleParseRequest: entry","data":{"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032819438,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:89","message":"handleParseRequest: tab created","data":{"tabId":1015118985,"url":""},"timestamp":1769032819449,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820280,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820282,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820287,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820626,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820629,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820633,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820634,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820635,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820636,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820637,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"loading","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820638,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:104","message":"checkTabLoaded: tab update","data":{"tabId":1015118985,"status":"complete","url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032820785,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:108","message":"checkTabLoaded: tab complete","data":{"tabId":1015118985,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032820786,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:187","message":"sendParseMessageWithRetry: entry","data":{"tabId":1015118985,"attempt":0},"timestamp":1769032822797,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"background.js:143","message":"ensureContentScriptInjected: entry","data":{"tabId":1015118985},"timestamp":1769032822798,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:147","message":"ensureContentScriptInjected: tab info","data":{"tabId":1015118985,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211","isEbayUrl":true},"timestamp":1769032822798,"sessionId":"debug-session","runId":"run1","hypothesisId":"C"} -{"location":"background.js:153","message":"ensureContentScriptInjected: sending PING","data":{"tabId":1015118985},"timestamp":1769032822798,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:158","message":"ensureContentScriptInjected: PING failed","data":{"tabId":1015118985,"error":"Could not establish connection. Receiving end does not exist."},"timestamp":1769032822799,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:162","message":"ensureContentScriptInjected: attempting injection","data":{"tabId":1015118985},"timestamp":1769032822799,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} -{"location":"background.js:165","message":"ensureContentScriptInjected: tab info before injection","data":{"tabId":1015118985,"url":"https://www.ebay.de/str/sbdirect24?_trksid=p4429486.m3561.l161211"},"timestamp":1769032822800,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} -{"location":"background.js:172","message":"ensureContentScriptInjected: listener injection success","data":{"tabId":1015118985,"frameId":0},"timestamp":1769032822801,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} -{"location":"background.js:207","message":"ensureContentScriptInjected: test injection success","data":{"tabId":1015118985},"timestamp":1769032822802,"sessionId":"debug-session","runId":"run1","hypothesisId":"G"} -{"location":"background.js:169","message":"ensureContentScriptInjected: ping after injection","data":{"tabId":1015118985,"pingAttempt":0},"timestamp":1769032823107,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:176","message":"ensureContentScriptInjected: ping success after injection","data":{"tabId":1015118985,"pingAttempt":0},"timestamp":1769032823108,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:195","message":"sendParseMessageWithRetry: injection result","data":{"tabId":1015118985,"injected":true},"timestamp":1769032823109,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"background.js:204","message":"sendParseMessageWithRetry: sending PARSE_EBAY","data":{"tabId":1015118985,"attempt":0},"timestamp":1769032823109,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"background.js:206","message":"sendParseMessageWithRetry: response received","data":{"tabId":1015118985,"hasResponse":true,"ok":true},"timestamp":1769032823111,"sessionId":"debug-session","runId":"run1","hypothesisId":"B"} -{"location":"ebayParserService.js:196","message":"parseViaExtension: response success","data":{"hasStats":true,"itemsSold":348728,"stats":{"itemsSold":348728}},"timestamp":1769032823124,"sessionId":"debug-session","runId":"run1","hypothesisId":"D"} -{"location":"accountsService.js:133","message":"updateManagedAccount: before updateDocument","data":{"accountId":"69714472002ab5f0dd0e","payload":{"account_platform_market":"DE","account_platform_account_id":"sbdirect24","account_shop_name":"sbdirect24","account_sells":348728,"account_updated_at":"2026-01-21T22:00:23.125Z"},"payloadKeys":["account_platform_market","account_platform_account_id","account_shop_name","account_sells","account_updated_at"]},"timestamp":1769032823125,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} -{"location":"accountsService.js:147","message":"updateManagedAccount: success","data":{"accountId":"69714472002ab5f0dd0e"},"timestamp":1769032823218,"sessionId":"debug-session","runId":"run1","hypothesisId":"A"} diff --git a/Extension/background.js b/Extension/background.js index b194cfe..9038d0b 100644 --- a/Extension/background.js +++ b/Extension/background.js @@ -2,9 +2,12 @@ const STORAGE_KEY = "auth_jwt"; const BACKEND_URL = "http://localhost:5173"; // TODO: Backend URL konfigurieren const PARSE_TIMEOUT_MS = 15000; // 15 seconds -const SCAN_TIMEOUT_MS = 20000; // 20 seconds (seller listing pages can be slower) +const SCAN_TIMEOUT_MS = 45000; // 45 seconds (listing with _ipg=240 can be slow) const activeParseRequests = new Map(); // Map -const activeScanRequests = new Map(); // Map +const activeScanRequests = new Map(); // Map; + +/** Aktueller Scan-Fortschritt für GET_SCAN_PROGRESS (Polling durch Web-App) */ +let currentScanProgress = null; // Messages from content script (der von der Web-App kommt) chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { @@ -64,6 +67,11 @@ chrome.runtime.onMessageExternal.addListener((msg, sender, sendResponse) => { handleScanProductsRequest(msg.url, msg.accountId, sendResponse); return true; // async } + + if (msg?.action === "GET_SCAN_PROGRESS") { + sendResponse(currentScanProgress ?? { percent: 0, phase: "idle", total: 0, current: 0, complete: false }); + return false; + } }); /** @@ -72,10 +80,6 @@ chrome.runtime.onMessageExternal.addListener((msg, sender, sendResponse) => { */ async function handleParseRequest(url, sendResponse) { try { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:73',message:'handleParseRequest: entry',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - // Validate URL if (!url || typeof url !== 'string' || !url.toLowerCase().includes('ebay.')) { sendResponse({ ok: false, error: "Invalid eBay URL" }); @@ -92,10 +96,6 @@ async function handleParseRequest(url, sendResponse) { const tabId = tab.id; console.log("[BACKGROUND] Tab created:", tabId); - - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:89',message:'handleParseRequest: tab created',data:{tabId,url:tab.url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion // Set up timeout const timeoutId = setTimeout(() => { @@ -112,19 +112,11 @@ async function handleParseRequest(url, sendResponse) { const checkTabLoaded = (updatedTabId, changeInfo, updatedTab) => { if (updatedTabId !== tabId) return; - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:104',message:'checkTabLoaded: tab update',data:{tabId:updatedTabId,status:changeInfo.status,url:updatedTab.url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); - // #endregion - // Tab is fully loaded if (changeInfo.status === 'complete' && updatedTab.url) { chrome.tabs.onUpdated.removeListener(checkTabLoaded); console.log("[BACKGROUND] Tab loaded, sending parse message:", updatedTab.url); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:108',message:'checkTabLoaded: tab complete',data:{tabId,url:updatedTab.url,isEbayUrl:isEbayUrl(updatedTab.url)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); - // #endregion - // Wait longer for content script to auto-load (if it does) // Content scripts from manifest.json might need more time in hidden tabs setTimeout(() => { @@ -159,17 +151,9 @@ function isEbayUrl(url) { */ async function ensureContentScriptInjected(tabId) { try { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:143',message:'ensureContentScriptInjected: entry',data:{tabId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - // First, check if tab URL is an eBay URL const tab = await chrome.tabs.get(tabId); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:147',message:'ensureContentScriptInjected: tab info',data:{tabId,url:tab.url,isEbayUrl:isEbayUrl(tab.url)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); - // #endregion - if (!isEbayUrl(tab.url)) { console.log("[BACKGROUND] Tab is not an eBay URL:", tab.url); return false; @@ -177,157 +161,27 @@ async function ensureContentScriptInjected(tabId) { // Check if content script is already loaded by sending a ping try { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:153',message:'ensureContentScriptInjected: sending PING',data:{tabId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - await chrome.tabs.sendMessage(tabId, { action: "PING" }); console.log("[BACKGROUND] Content script already loaded"); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:156',message:'ensureContentScriptInjected: PING success',data:{tabId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - return true; } catch (pingError) { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:158',message:'ensureContentScriptInjected: PING failed',data:{tabId,error:pingError.message,runtimeError:chrome.runtime.lastError?.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - // Content script not loaded, try to inject it manually console.log("[BACKGROUND] Content script not found, injecting manually..."); try { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:162',message:'ensureContentScriptInjected: attempting injection',data:{tabId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'E'})}).catch(()=>{}); - // #endregion - // Get tab info to check frames const tabInfo = await chrome.tabs.get(tabId); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:165',message:'ensureContentScriptInjected: tab info before injection',data:{tabId,url:tabInfo.url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{}); - // #endregion - - // Inject the message listener directly as a function (not as a file) - // This ensures it runs in the correct context with access to chrome.runtime + // Inject full ebay-content-script.js so PING, PARSE_EBAY and PARSE_PRODUCT_LIST are all handled. + // The previous inline injection only handled PING+PARSE_EBAY; SCAN sends PARSE_PRODUCT_LIST. try { await chrome.scripting.executeScript({ target: { tabId: tabId, frameIds: [0] }, - func: () => { - // Register message listener directly - if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.onMessage) { - chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - if (message.action === "PING") { - sendResponse({ ok: true, ready: true }); - return true; - } - - if (message.action === "PARSE_EBAY") { - // Simple parsing - extract from URL and DOM - try { - const url = window.location.href; - const hostname = window.location.hostname.toLowerCase(); - - // Extract market - let market = "US"; - if (hostname.includes('.de')) market = 'DE'; - else if (hostname.includes('.uk')) market = 'UK'; - else if (hostname.includes('.fr')) market = 'FR'; - else if (hostname.includes('.it')) market = 'IT'; - else if (hostname.includes('.es')) market = 'ES'; - - // Extract seller ID from URL - let sellerId = ""; - const usrMatch = url.match(/\/usr\/([^\/\?]+)/i); - if (usrMatch && usrMatch[1]) { - sellerId = usrMatch[1].trim(); - } else { - const strMatch = url.match(/\/str\/([^\/\?]+)/i); - if (strMatch && strMatch[1]) { - sellerId = strMatch[1].trim(); - } - } - - // Extract shop name - let shopName = ""; - try { - const h1 = document.querySelector('h1'); - if (h1) { - shopName = h1.textContent?.trim() || ""; - } - } catch (e) {} - - // Extract items sold - let itemsSold = null; - try { - const container = document.querySelector(".str-seller-card__store-stats-content"); - if (container) { - const divs = container.querySelectorAll("div"); - for (const div of divs) { - const divText = div.textContent || ""; - if (divText.includes("Artikel verkauft")) { - const span = div.querySelector('span[class*="BOLD"]') || div.querySelector("span.BOLD"); - if (span) { - let valueText = span.textContent?.trim() || ""; - valueText = valueText.replace(/\s/g, "").replace(/[.,]/g, "").replace(/\D/g, ""); - if (valueText.length > 0) { - const parsedValue = parseInt(valueText, 10); - if (!isNaN(parsedValue) && parsedValue >= 0) { - itemsSold = parsedValue; - } - } - } - } - } - } - } catch (e) {} - - sendResponse({ - ok: true, - data: { - sellerId: sellerId || "", - shopName: shopName || "", - market: market, - status: (sellerId || shopName) ? "active" : "unknown", - stats: { - itemsSold: itemsSold - } - } - }); - } catch (error) { - sendResponse({ - ok: true, - data: { - sellerId: "", - shopName: "", - market: "US", - status: "unknown", - stats: {} - } - }); - } - return true; - } - - return false; - }); - - console.log("[EBAY-CONTENT] Message listener registered"); - } - } + files: ["ebay-content-script.js"] }); - console.log("[BACKGROUND] Content script message listener injected successfully"); - - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:172',message:'ensureContentScriptInjected: listener injection success',data:{tabId,frameId:0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H'})}).catch(()=>{}); - // #endregion + console.log("[BACKGROUND] ebay-content-script.js injected successfully"); } catch (injectError) { - console.error("[BACKGROUND] Failed to inject message listener:", injectError); - - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:178',message:'ensureContentScriptInjected: listener injection failed',data:{tabId,error:injectError.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H'})}).catch(()=>{}); - // #endregion - + console.error("[BACKGROUND] Failed to inject ebay-content-script:", injectError); throw injectError; } @@ -337,31 +191,11 @@ async function ensureContentScriptInjected(tabId) { target: { tabId: tabId, frameIds: [0] }, func: () => { console.log("[TEST-INJECTION] Test script executed in main frame"); - // Try to send a log via fetch - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{ - method:'POST', - headers:{'Content-Type':'application/json'}, - body:JSON.stringify({ - location:'background.js:test-injection', - message:'test injection: script executed', - data:{url:window.location.href,hasChrome:typeof chrome!=='undefined',hasRuntime:typeof chrome!=='undefined'&&!!chrome.runtime}, - timestamp:Date.now(), - sessionId:'debug-session', - runId:'run1', - hypothesisId:'G' - }) - }).catch(()=>{}); } }); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:207',message:'ensureContentScriptInjected: test injection success',data:{tabId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{}); - // #endregion - } catch (testError) { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:210',message:'ensureContentScriptInjected: test injection failed',data:{tabId,error:testError.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{}); - // #endregion - } + } catch (testError) { + } // Wait longer for the script to fully initialize and register message listeners // Retry PING to verify the script is ready @@ -370,10 +204,6 @@ async function ensureContentScriptInjected(tabId) { await new Promise(resolve => setTimeout(resolve, 300)); // 300ms between pings try { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:169',message:'ensureContentScriptInjected: ping after injection',data:{tabId,pingAttempt},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - // Try sending to main frame explicitly try { await chrome.tabs.sendMessage(tabId, { action: "PING" }, { frameId: 0 }); @@ -382,44 +212,25 @@ async function ensureContentScriptInjected(tabId) { await chrome.tabs.sendMessage(tabId, { action: "PING" }); } - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:176',message:'ensureContentScriptInjected: ping success after injection',data:{tabId,pingAttempt},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - console.log("[BACKGROUND] Content script ready after injection"); return true; } catch (pingErr) { // Continue to next attempt - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:182',message:'ensureContentScriptInjected: ping failed after injection',data:{tabId,pingAttempt,error:pingErr.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - } + } } - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:189',message:'ensureContentScriptInjected: ping timeout after injection',data:{tabId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - // Even if PING failed, return true - the script might still work console.warn("[BACKGROUND] Content script injected but PING not responding"); return true; } catch (injectError) { console.error("[BACKGROUND] Failed to inject content script:", injectError); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:172',message:'ensureContentScriptInjected: injection failed',data:{tabId,error:injectError.message,runtimeError:chrome.runtime.lastError?.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'E'})}).catch(()=>{}); - // #endregion - return false; } } } catch (error) { console.error("[BACKGROUND] Error checking/injecting content script:", error); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:177',message:'ensureContentScriptInjected: error',data:{tabId,error:error.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - return false; } } @@ -436,18 +247,10 @@ async function sendParseMessageWithRetry(tabId, attempt) { try { console.log(`[BACKGROUND] Sending parse message (attempt ${attempt + 1}/${maxAttempts}) to tab:`, tabId); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:187',message:'sendParseMessageWithRetry: entry',data:{tabId,attempt},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'D'})}).catch(()=>{}); - // #endregion - // On first attempt, ensure content script is injected if (attempt === 0) { const injected = await ensureContentScriptInjected(tabId); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:195',message:'sendParseMessageWithRetry: injection result',data:{tabId,injected},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - if (!injected) { throw new Error("Could not inject content script"); } @@ -455,10 +258,6 @@ async function sendParseMessageWithRetry(tabId, attempt) { // Check if content script is injected by trying to send a ping // If this fails, the content script might not be loaded yet - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:204',message:'sendParseMessageWithRetry: sending PARSE_EBAY',data:{tabId,attempt},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - // Try sending to main frame explicitly first let response; try { @@ -470,10 +269,6 @@ async function sendParseMessageWithRetry(tabId, attempt) { console.log("[BACKGROUND] Parse response received:", response); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:206',message:'sendParseMessageWithRetry: response received',data:{tabId,hasResponse:!!response,ok:response?.ok},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - if (response && response.ok && response.data) { handleParseComplete(tabId, response.data); } else { @@ -498,10 +293,6 @@ async function sendParseMessageWithRetry(tabId, attempt) { isContentScriptError: isContentScriptError }); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'background.js:217',message:'sendParseMessageWithRetry: error',data:{tabId,attempt,error:err.message,runtimeError,isContentScriptError},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - if (isContentScriptError && attempt < maxAttempts) { // Content script not ready yet, retry after delay console.log(`[BACKGROUND] Content script not ready, retrying in ${retryDelay}ms...`); @@ -563,9 +354,32 @@ async function cleanupParseRequest(tabId, data, error) { } } +/** + * Transform account URL (e.g. /str/topmons) to listing URL with 240 items per page. + * Example: https://www.ebay.de/str/topmons?... → https://www.ebay.de/sch/i.html?_ssn=topmons&store_name=topmons&_ipg=240 + */ +function transformAccountUrlTo240ItemsUrl(accountUrl) { + try { + const url = new URL(accountUrl); + const pathname = url.pathname; + + const strMatch = pathname.match(/\/str\/([^\/\?]+)/); + if (!strMatch || !strMatch[1]) { + throw new Error("Could not extract account name from URL (expected /str/{name})"); + } + + const accountName = strMatch[1]; + const baseUrl = `${url.protocol}//${url.hostname}`; + const listingUrl = `${baseUrl}/sch/i.html?_ssn=${encodeURIComponent(accountName)}&store_name=${encodeURIComponent(accountName)}&_ipg=240`; + return listingUrl; + } catch (e) { + throw new Error(`Failed to transform account URL: ${e.message}`); + } +} + /** * Handles eBay product scan request - * Creates a hidden tab, waits for load, sends parse message to content script + * Transforms account URL to listing URL with _ipg=240, creates hidden tab, parses, then loads each item in separate tab. */ async function handleScanProductsRequest(url, accountId, sendResponse) { try { @@ -575,9 +389,18 @@ async function handleScanProductsRequest(url, accountId, sendResponse) { return; } + let targetUrl = url; + try { + targetUrl = transformAccountUrlTo240ItemsUrl(url); + console.log("[BACKGROUND] Scan using listing URL (240 items):", targetUrl); + } catch (transformErr) { + console.warn("[BACKGROUND] URL transform failed, using original URL:", transformErr.message); + // Fallback: use original URL (e.g. already /sch/ or non-/str/) + } + // Create hidden tab const tab = await chrome.tabs.create({ - url: url, + url: targetUrl, active: false }); @@ -594,14 +417,14 @@ async function handleScanProductsRequest(url, accountId, sendResponse) { sendResponse: sendResponse }); + currentScanProgress = { percent: 0, phase: "listing", total: 0, current: 0, complete: false }; + // Wait for tab to load, then send parse message const checkTabLoaded = (updatedTabId, changeInfo, updatedTab) => { if (updatedTabId !== tabId) return; - // Tab is fully loaded if (changeInfo.status === 'complete' && updatedTab.url) { chrome.tabs.onUpdated.removeListener(checkTabLoaded); - // Small delay to ensure DOM is ready setTimeout(() => { sendScanMessageWithRetry(tabId, 0); @@ -655,8 +478,12 @@ async function sendScanMessageWithRetry(tabId, attempt) { meta: meta }); } else { - // Erfolg: sende items + meta - handleScanComplete(tabId, { items, meta }); + if (currentScanProgress) { + currentScanProgress.phase = "details"; + currentScanProgress.total = items.length; + currentScanProgress.percent = 10; + } + await handleScanComplete(tabId, { items, meta }); } } else { // Fehler: sende error + meta @@ -709,11 +536,104 @@ async function sendScanMessageWithRetry(tabId, attempt) { } } +const ITEM_TAB_LOAD_TIMEOUT_MS = 3000; + +/** + * Opens each item URL in a separate background tab, waits for load, parses detail page + * (title, price, currency, category, condition), merges into item, then closes tab. + */ +async function loadAndParseEachItemTab(items) { + if (!Array.isArray(items) || items.length === 0) return; + + const total = items.length; + for (let i = 0; i < total; i++) { + const item = items[i]; + if (!item || !item.url) continue; + + try { + const tab = await chrome.tabs.create({ + url: item.url, + active: false + }); + + await new Promise((resolve) => { + const listener = (tabId, changeInfo) => { + if (tabId === tab.id && changeInfo.status === "complete") { + chrome.tabs.onUpdated.removeListener(listener); + resolve(); + } + }; + chrome.tabs.onUpdated.addListener(listener); + + setTimeout(() => { + chrome.tabs.onUpdated.removeListener(listener); + resolve(); + }, ITEM_TAB_LOAD_TIMEOUT_MS); + }); + + const injected = await ensureContentScriptInjected(tab.id); + if (!injected) { + console.warn(`[BACKGROUND] Content script not ready in item tab ${i + 1}, skipping detail parse`); + } + + try { + const response = injected + ? await chrome.tabs.sendMessage(tab.id, { action: "PARSE_ITEM_DETAIL" }) + : null; + if (response?.ok && response?.data) { + const d = response.data; + if (d.title != null && d.title !== "") item.title = d.title; + if (d.price != null) item.price = d.price; + if (d.currency != null && d.currency !== "") item.currency = d.currency; + if (d.category != null && d.category !== "") item.category = d.category; + if (d.condition != null && d.condition !== "") item.condition = d.condition; + if (d.quantityAvailable != null) item.quantityAvailable = d.quantityAvailable; + if (d.quantitySold != null) item.quantitySold = d.quantitySold; + if (d.watchCount != null) item.watchCount = d.watchCount; + if (d.inCartsCount != null) item.inCartsCount = d.inCartsCount; + } + } catch (parseErr) { + console.warn(`[BACKGROUND] PARSE_ITEM_DETAIL failed for ${item.url}:`, parseErr); + } + + if (currentScanProgress && total > 0) { + currentScanProgress.current = i + 1; + currentScanProgress.percent = Math.min(99, 10 + Math.round((90 * (i + 1)) / total)); + } + + try { + await chrome.tabs.remove(tab.id); + } catch (removeErr) { + console.warn(`[BACKGROUND] Could not close item tab:`, removeErr); + } + } catch (e) { + console.warn(`[BACKGROUND] Failed to load/parse item tab ${i + 1}/${total}:`, item.url, e); + } + } +} + /** * Handles scan complete response from content script */ -function handleScanComplete(tabId, data) { - cleanupScanRequest(tabId, data, null); +async function handleScanComplete(tabId, data) { + const request = activeScanRequests.get(tabId); + if (request && request.timeout) { + clearTimeout(request.timeout); + request.timeout = null; + } + + const items = data?.items || []; + if (items.length > 0) { + await loadAndParseEachItemTab(items); + } + + if (currentScanProgress) { + currentScanProgress.percent = 100; + currentScanProgress.complete = true; + currentScanProgress.current = items.length; + } + + await cleanupScanRequest(tabId, data, null); } /** @@ -731,6 +651,8 @@ async function cleanupScanRequest(tabId, data, error) { // Remove from active requests activeScanRequests.delete(tabId); + currentScanProgress = null; + // Close tab (always, even on error) try { await chrome.tabs.remove(tabId); diff --git a/Extension/content-script.js b/Extension/content-script.js index 43113c0..64aa3a3 100644 --- a/Extension/content-script.js +++ b/Extension/content-script.js @@ -10,6 +10,10 @@ function setExtensionFlag() { const hasRuntime = hasChrome && chrome.runtime; const runtimeId = hasRuntime ? chrome.runtime.id : null; if (typeof window !== 'undefined' && hasChrome && hasRuntime && runtimeId) { + // WICHTIG: Content Scripts haben einen isolierten Context + // window.__EBAY_EXTENSION__ wird im Content Script Context gesetzt, + // aber die Web-App läuft im Page Context - diese sind getrennt! + // Daher verlassen wir uns hauptsächlich auf postMessage window.__EBAY_EXTENSION__ = true; window.__EBAY_EXTENSION_ID__ = runtimeId; // Extension-ID für chrome.runtime.sendMessage console.log('[ESHIP-CONTENT] window.__EBAY_EXTENSION__ set to true, ID:', runtimeId); @@ -23,6 +27,8 @@ function setExtensionFlag() { // Versuche Flag sofort zu setzen console.log('[ESHIP-CONTENT] Content script loaded'); +console.log('[ESHIP-CONTENT] URL:', window.location.href); +console.log('[ESHIP-CONTENT] ReadyState:', document.readyState); if (!setExtensionFlag()) { // Wenn window nicht verfügbar, warte auf DOMContentLoaded oder document.readyState if (document.readyState === 'loading') { @@ -35,34 +41,113 @@ if (!setExtensionFlag()) { setExtensionFlag(); }, 0); } -} +} else { + } // Sende Extension-ID an Web-App via postMessage (da Content Script Isolation verhindert, dass window-Properties geteilt werden) // Die Web-App kann dann die Extension-ID in ihrem eigenen Context speichern function sendExtensionIdToWebApp() { try { const runtimeId = chrome.runtime?.id; + const hasRuntime = !!chrome.runtime; + const hasId = !!runtimeId; + const currentUrl = window.location.href; + if (runtimeId) { - // Sende Extension-ID an Web-App - window.postMessage({ + const message = { source: "eship-extension", type: "EXTENSION_ID", extensionId: runtimeId - }, "*"); - } + }; + + // Sende Extension-ID an Web-App + window.postMessage(message, "*"); + + } else { + } } catch (e) { console.error('[ESHIP-CONTENT] Error sending extension ID:', e); } } -// Sende Extension-ID beim Laden +// Sende Extension-ID sofort beim Laden (wichtig für Seiten-Reload) sendExtensionIdToWebApp(); -// Auch nach kurzer Verzögerung nochmal (falls Web-App noch nicht bereit ist) + +// Sende auch nach kurzen Verzögerungen (falls Web-App noch nicht bereit ist) +setTimeout(sendExtensionIdToWebApp, 100); setTimeout(sendExtensionIdToWebApp, 500); +setTimeout(sendExtensionIdToWebApp, 1000); +setTimeout(sendExtensionIdToWebApp, 2000); + +// Kontinuierlich postMessage senden, damit die Web-App die Extension erkennen kann +// (auch wenn der User die Extension NACH dem Laden der Seite installiert) +let extensionAnnounceInterval = setInterval(() => { + sendExtensionIdToWebApp(); +}, 2000); // Alle 2 Sekunden senden + +// Stoppe das Intervall nach 5 Minuten (um Ressourcen zu sparen, aber lange genug für Onboarding) +setTimeout(() => { + if (extensionAnnounceInterval) { + clearInterval(extensionAnnounceInterval); + extensionAnnounceInterval = null; + } +}, 300000); // 5 Minuten window.addEventListener("message", (event) => { + // PING_EXTENSION Handler: Web-App fragt aktiv nach Extension + // Akzeptiere sowohl "eship-webapp" als auch "eship-webapp-page-context" + if ((event.data?.source === MESSAGE_SOURCE || event.data?.source === "eship-webapp-page-context") && event.data?.type === "PING_EXTENSION") { + // Verwende console.log als Fallback, da fetch möglicherweise fehlschlägt + console.log('[ESHIP-CONTENT] Received PING_EXTENSION, responding...', event.data); + + // Antworte sofort mit Extension-ID + const runtimeId = chrome.runtime?.id; + console.log('[ESHIP-CONTENT] Runtime ID:', runtimeId); + + if (runtimeId) { + const response = { + source: "eship-extension", + type: "EXTENSION_ID", + extensionId: runtimeId, + requestId: event.data?.requestId + }; + + console.log('[ESHIP-CONTENT] Sending response:', response); + window.postMessage(response, "*"); + + // Setze user_extension_load auf true im Backend + // Hole JWT aus Storage und sende an Backend + chrome.storage.local.get("auth_jwt").then((data) => { + const jwt = data.auth_jwt; + if (jwt) { + // Backend-Endpoint aufrufen + fetch("http://localhost:3000/api/user/set-extension-loaded", { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${jwt}` + } + }) + .then(res => res.json()) + .then(result => { + console.log('[ESHIP-CONTENT] user_extension_load set to true:', result); + }) + .catch(err => { + console.error('[ESHIP-CONTENT] Failed to set user_extension_load:', err); + }); + } else { + console.warn('[ESHIP-CONTENT] No JWT found, cannot set user_extension_load'); + } + }); + + } else { + console.error('[ESHIP-CONTENT] No runtime ID available!'); + } + return; + } + // Sicherheitscheck: Nur Nachrichten von derselben Origin akzeptieren - if (event.data?.source !== MESSAGE_SOURCE) return; + if (event.data?.source !== MESSAGE_SOURCE && event.data?.source !== "eship-webapp-page-context") return; // Auth Messages (JWT) if (event.data.type === "AUTH_JWT" || event.data.type === "AUTH_CLEARED") { diff --git a/Extension/ebay-content-script.js b/Extension/ebay-content-script.js index 0e41832..141b39f 100644 --- a/Extension/ebay-content-script.js +++ b/Extension/ebay-content-script.js @@ -6,29 +6,15 @@ // Log dass Content Script geladen wurde console.log("[EBAY-CONTENT] Content script loaded on:", window.location.href); -// #region agent log -fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'ebay-content-script.js:7',message:'ebay-content-script: loaded',data:{url:window.location.href,readyState:document.readyState},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); -// #endregion - // Message Listener für Parsing-Anfragen chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'ebay-content-script.js:10',message:'ebay-content-script: message received',data:{action:message.action},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion - // Ping-Handler für Content Script Verfügbarkeitsprüfung if (message.action === "PING") { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'ebay-content-script.js:13',message:'ebay-content-script: PING handler',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion sendResponse({ ok: true, ready: true }); return true; } if (message.action === "PARSE_EBAY") { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'ebay-content-script.js:17',message:'ebay-content-script: PARSE_EBAY handler',data:{readyState:document.readyState},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion // Wrapper um sicherzustellen, dass immer eine Antwort gesendet wird try { // Prüfe ob DOM bereit ist @@ -75,6 +61,17 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { return true; // async response } + if (message.action === "PARSE_ITEM_DETAIL") { + try { + const detail = parseItemDetailPage(); + sendResponse({ ok: true, data: detail }); + } catch (e) { + console.warn("[EBAY-CONTENT] PARSE_ITEM_DETAIL error:", e); + sendResponse({ ok: true, data: {} }); + } + return true; + } + if (message.action === "PARSE_PRODUCT_LIST") { // async function, need to return promise parseProductList() @@ -183,6 +180,12 @@ function extractSellerId() { return strMatch[1].trim(); } + // Pattern: _ssn=username (Seller Name Parameter in Suchergebnis-URLs) + const ssnMatch = url.match(/[?&]_ssn=([^&]+)/i); + if (ssnMatch && ssnMatch[1]) { + return decodeURIComponent(ssnMatch[1]).trim(); + } + // Methode 2: DOM-Elemente suchen // Suche nach verschiedenen Selektoren, die Seller-ID enthalten könnten const possibleSelectors = [ @@ -683,7 +686,6 @@ async function parseProductList() { let pageType = detectPageType(); let finalUrl = window.location.href; let reason = null; - try { // Schritt 1: Warte auf Item-Links (Polling) let links = await waitForItemLinks(4000, 250, 5); @@ -768,17 +770,14 @@ async function parseProductList() { } } - // Return max 60 items (first page) - const result = parsedItems.slice(0, 60); - return { ok: true, - items: result, + items: parsedItems, meta: { pageType, finalUrl, attempts, - reason: reason || (result.length > 0 ? "items_found" : "parsed_zero_items") + reason: reason || (parsedItems.length > 0 ? "items_found" : "parsed_zero_items") } }; @@ -796,66 +795,103 @@ async function parseProductList() { }; } } + +/** + * Parst Produktdetail-Seite (/itm/...) für title, price, currency, category, condition, + * quantityAvailable, quantitySold, watchCount, inCartsCount. + */ +function parseItemDetailPage() { + const out = { + title: "", + price: null, + currency: null, + category: null, + condition: null, + quantityAvailable: null, + quantitySold: null, + watchCount: null, + inCartsCount: null + }; try { - const url = window.location.href; - const urlLower = url.toLowerCase(); - - // Determine page type - const isStorePage = urlLower.includes('/str/') || urlLower.includes('/store/'); - const isSellerPage = urlLower.includes('/usr/'); - - // Check if seller profile without items (try to find link to listings) - if (isSellerPage && !isStorePage) { - const itemsLink = document.querySelector('a[href*="/usr/"][href*="?items="]') || - document.querySelector('a[href*="schid=mksr"]') || - Array.from(document.querySelectorAll('a')).find(a => { - const text = (a.textContent || '').toLowerCase(); - return text.includes('artikel') || text.includes('angebote') || - text.includes('items for sale') || text.includes('see all items'); - }); - - if (!itemsLink) { - // Try to find item cards directly - const hasItems = findItemLinks().length > 0; - if (!hasItems) { - throw new Error("no_items_page"); + const titleEl = document.querySelector("[data-testid=\"x-item-title\"] h1 .ux-textspans") || + document.querySelector("h1.x-item-title__mainTitle .ux-textspans"); + if (titleEl) { + out.title = (titleEl.textContent || "").trim().replace(/\s+/g, " "); + } + + const priceEl = document.querySelector("[data-testid=\"x-price-primary\"] .ux-textspans"); + if (priceEl) { + const priceText = (priceEl.textContent || "").trim(); + const parsed = parsePrice(priceText); + out.price = parsed.price; + out.currency = parsed.currency; + } + + const breadcrumbs = document.querySelectorAll("a.seo-breadcrumb-text span"); + if (breadcrumbs.length > 0) { + const parts = []; + breadcrumbs.forEach((span) => { + const t = (span.textContent || "").trim(); + if (t) parts.push(t); + }); + out.category = parts.join(" > "); + } + + const condEl = document.querySelector("dd.ux-labels-values__values .ux-textspans"); + if (condEl) { + const raw = (condEl.textContent || "").trim(); + const colonIdx = raw.indexOf(":"); + out.condition = colonIdx >= 0 ? raw.slice(0, colonIdx).trim() : raw.slice(0, 80); + } + + // x-quantity__availability: "9 verfügbar", "8 verkauft" + const availEl = document.querySelector(".x-quantity__availability"); + if (availEl) { + const text = (availEl.textContent || "").trim(); + const verfMatch = text.match(/(\d+)\s*verfügbar/i); + if (verfMatch && verfMatch[1]) { + const n = parseInt(verfMatch[1], 10); + if (!isNaN(n) && n >= 0) out.quantityAvailable = n; + } + const verkMatch = text.match(/(\d+)\s*verkauft/i); + if (verkMatch && verkMatch[1]) { + const n = parseInt(verkMatch[1], 10); + if (!isNaN(n) && n >= 0) out.quantitySold = n; + } + } + + // x-watch-heart-btn: .x-watch-heart-btn-text "14" oder aria-label "14 Beobachter" + const watchBtn = document.querySelector("button.x-watch-heart-btn"); + if (watchBtn) { + const textEl = watchBtn.querySelector(".x-watch-heart-btn-text"); + if (textEl) { + const n = parseInt((textEl.textContent || "").trim().replace(/\D/g, ""), 10); + if (!isNaN(n) && n >= 0) out.watchCount = n; + } + if (out.watchCount == null) { + const label = (watchBtn.getAttribute("aria-label") || "").trim(); + const m = label.match(/(\d+)\s*Beobachter/i); + if (m && m[1]) { + const n = parseInt(m[1], 10); + if (!isNaN(n) && n >= 0) out.watchCount = n; } } } - - // Extract items - const items = findItemLinks(); - - if (items.length === 0) { - throw new Error("no_items_found"); - } - - // Parse each item - const parsedItems = []; - const seenIds = new Set(); - - for (const itemLink of items) { - try { - const item = parseItemFromLink(itemLink); - - // Deduplicate by platformProductId - if (item.platformProductId && !seenIds.has(item.platformProductId)) { - seenIds.add(item.platformProductId); - parsedItems.push(item); - } - } catch (e) { - // Continue with next item if one fails - console.warn("Failed to parse item:", e); + + // [data-testid="x-ebay-signal"]: "In 8 Warenkörben" + const signalEl = document.querySelector("[data-testid=\"x-ebay-signal\"]"); + if (signalEl) { + const text = (signalEl.textContent || "").trim(); + const m = text.match(/in\s*(\d+)\s*warenkörben/i); + if (m && m[1]) { + const n = parseInt(m[1], 10); + if (!isNaN(n) && n >= 0) out.inCartsCount = n; } } - - // Return max 60 items (first page) - return parsedItems.slice(0, 60); - - } catch (error) { - // Re-throw to be caught by message handler - throw error; + } catch (e) { + console.warn("[EBAY-CONTENT] parseItemDetailPage error:", e); } + return out; } /** diff --git a/Server/backend/server.js b/Server/backend/server.js index ac12809..717366d 100644 --- a/Server/backend/server.js +++ b/Server/backend/server.js @@ -49,6 +49,41 @@ app.post("/api/action", async (req, res) => { } }); +// Endpoint: Setze user_extension_load auf true +app.post("/api/user/set-extension-loaded", async (req, res) => { + try { + const auth = req.headers.authorization || ""; + const jwt = auth.startsWith("Bearer ") ? auth.slice(7) : ""; + if (!jwt) return res.status(401).json({ ok: false, error: "missing token" }); + + // 1) User token validieren + const userClient = makeUserClient(jwt); + const account = new Account(userClient); + const user = await account.get(); + + // 2) User-Dokument mit Admin Key aktualisieren + const adminClient = makeAdminClient(); + const db = new Databases(adminClient); + const databaseId = process.env.APPWRITE_DATABASE_ID || "eship-db"; + const usersCollectionId = process.env.APPWRITE_USERS_COLLECTION_ID || "users"; + + // Update user document: setze user_extension_load auf true + await db.updateDocument( + databaseId, + usersCollectionId, + user.$id, + { + user_extension_load: true + } + ); + + return res.json({ ok: true, userId: user.$id }); + } catch (e) { + console.error("Error in /api/user/set-extension-loaded:", e); + return res.status(401).json({ ok: false, error: "unauthorized" }); + } +}); + app.listen(PORT, () => { console.log(`Backend server running on port ${PORT}`); }); diff --git a/Server/package-lock.json b/Server/package-lock.json index 45a4a69..6a1665f 100644 --- a/Server/package-lock.json +++ b/Server/package-lock.json @@ -74,7 +74,6 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -331,7 +330,6 @@ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", "license": "MIT", - "peer": true, "dependencies": { "@emotion/memoize": "^0.9.0" } @@ -1707,7 +1705,6 @@ "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1755,7 +1752,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2031,7 +2027,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2656,7 +2651,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3191,8 +3185,7 @@ "version": "3.14.2", "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.14.2.tgz", "integrity": "sha512-P8/mMxVLU7o4+55+1TCnQrPmgjPKnwkzkXOK1asnR9Jg2lna4tEY5qBJjMmAaOBDDZWtlRjBXjLa0w53G/uBLA==", - "license": "Standard 'no charge' license: https://gsap.com/standard-license.", - "peer": true + "license": "Standard 'no charge' license: https://gsap.com/standard-license." }, "node_modules/has-bigints": { "version": "1.1.0", @@ -4510,7 +4503,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -4615,7 +4607,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4625,7 +4616,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -5425,7 +5415,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", diff --git a/Server/public/extension.zip b/Server/public/extension.zip new file mode 100644 index 0000000..51dfd0c Binary files /dev/null and b/Server/public/extension.zip differ diff --git a/Server/src/App.jsx b/Server/src/App.jsx index dda16f8..141aa85 100644 --- a/Server/src/App.jsx +++ b/Server/src/App.jsx @@ -18,9 +18,13 @@ import { OnboardingGate } from "./components/onboarding/OnboardingGate"; import { SidebarHeader } from "./components/sidebar/SidebarHeader"; import { useHashRoute } from "./lib/routing"; import { account, databases, databaseId, usersCollectionId } from "./lib/appwrite"; +import { fetchManagedAccounts } from "./services/accountsService"; +import { useScan } from "./context/ScanContext"; +import ScanningLoader from "./components/ui/ScanningLoader"; export default function App() { const { route, navigate } = useHashRoute(); + const { scanning, scanProgress } = useScan(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [status, setStatus] = useState({ loading: true, authed: false, error: "" }); @@ -32,8 +36,15 @@ export default function App() { const [checkingUserDoc, setCheckingUserDoc] = useState(false); const [onboardingLoading, setOnboardingLoading] = useState(false); const [onboardingError, setOnboardingError] = useState(""); + const [userExtensionLoad, setUserExtensionLoad] = useState(null); // null = nicht geprüft, true/false = geprüft + const [hasAccounts, setHasAccounts] = useState(false); // true wenn User Accounts hat - const showGate = !hasUserDoc && !checkingUserDoc && authUser !== null; + // Gate soll angezeigt werden, wenn: + // 1. User-Dokument nicht existiert ODER + // 2. User-Dokument existiert, aber user_extension_load = false UND keine Accounts vorhanden + // Gate wird versteckt, wenn: + // - User-Dokument existiert UND (user_extension_load = true ODER Accounts vorhanden) + const showGate = (!hasUserDoc || (hasUserDoc && userExtensionLoad === false && !hasAccounts)) && !checkingUserDoc && authUser !== null; async function checkUserDocument(userId) { if (!databases || !databaseId || !usersCollectionId) { @@ -66,13 +77,53 @@ export default function App() { // Prüfe, ob User-Dokument existiert const userDocExists = await checkUserDocument(user.$id); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:68',message:'refreshAuth: userDocExists check',data:{userId:user.$id,userDocExists},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); + // #endregion setHasUserDoc(userDocExists); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:71',message:'refreshAuth: hasUserDoc set',data:{hasUserDoc:userDocExists,showGateWillBe:!userDocExists && !checkingUserDoc && user !== null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); + // #endregion + + // Prüfe user_extension_load und Accounts, wenn User-Dokument existiert + if (userDocExists && databases && databaseId && usersCollectionId) { + try { + const userDoc = await databases.getDocument(databaseId, usersCollectionId, user.$id); + const extensionLoad = userDoc?.user_extension_load === true; + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:78',message:'refreshAuth: userDoc retrieved for extension check',data:{userExtensionLoad:userDoc?.user_extension_load,userExtensionLoadType:typeof userDoc?.user_extension_load,userExtensionLoadStrictFalse:userDoc?.user_extension_load === false,extensionLoad},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); + // #endregion + setUserExtensionLoad(extensionLoad); + + // Prüfe auch Accounts + try { + const existingAccounts = await fetchManagedAccounts(user.$id); + const hasAccountsValue = Array.isArray(existingAccounts) && existingAccounts.length > 0; + setHasAccounts(hasAccountsValue); + } catch (accountsErr) { + setHasAccounts(false); + } + } catch (docErr) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:82',message:'refreshAuth: error getting userDoc for extension check',data:{error:docErr.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); + // #endregion + // Bei Fehler: Setze auf null (nicht geprüft) + setUserExtensionLoad(null); + setHasAccounts(false); + } + } else { + // Kein User-Dokument → user_extension_load ist nicht relevant + setUserExtensionLoad(null); + setHasAccounts(false); + } await handoffJwtToExtension(); } catch (e) { setStatus({ loading: false, authed: false, error: "" }); setAuthUser(null); setHasUserDoc(false); + setUserExtensionLoad(null); + setHasAccounts(false); } finally { setCheckingUserDoc(false); } @@ -94,18 +145,50 @@ export default function App() { const userDocExists = await checkUserDocument(user.$id); setHasUserDoc(userDocExists); + // Prüfe user_extension_load und Accounts, wenn User-Dokument existiert + if (userDocExists && databases && databaseId && usersCollectionId) { + try { + const userDoc = await databases.getDocument(databaseId, usersCollectionId, user.$id); + const extensionLoad = userDoc?.user_extension_load === true; + setUserExtensionLoad(extensionLoad); + + // Prüfe auch Accounts + try { + const existingAccounts = await fetchManagedAccounts(user.$id); + const hasAccountsValue = Array.isArray(existingAccounts) && existingAccounts.length > 0; + setHasAccounts(hasAccountsValue); + } catch (accountsErr) { + setHasAccounts(false); + } + } catch (docErr) { + setUserExtensionLoad(null); + setHasAccounts(false); + } + } else { + setUserExtensionLoad(null); + setHasAccounts(false); + } + await handoffJwtToExtension(); } catch (e) { setStatus({ loading: false, authed: false, error: "Login fehlgeschlagen" }); setAuthUser(null); setHasUserDoc(false); + setUserExtensionLoad(null); + setHasAccounts(false); } finally { setCheckingUserDoc(false); } } async function handleOnboardingStart() { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:162',message:'handleOnboardingStart: entry',data:{hasAuthUser:!!authUser,hasDatabases:!!databases,hasDatabaseId:!!databaseId,hasUsersCollectionId:!!usersCollectionId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion if (!authUser || !databases || !databaseId || !usersCollectionId) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:165',message:'handleOnboardingStart: configuration incomplete',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion setOnboardingError("Fehler: Konfiguration unvollständig"); return; } @@ -114,38 +197,147 @@ export default function App() { setOnboardingError(""); try { - await databases.createDocument( - databaseId, - usersCollectionId, - authUser.$id, // Document-ID = Auth-User-ID - { - user_name: authUser.name || "User" - } - ); - - // Erfolg: User-Dokument erstellt - setHasUserDoc(true); - setOnboardingError(""); - } catch (e) { - // 409 Conflict bedeutet, dass das Dokument bereits existiert - // Das ist ok, da wir idempotent sein wollen - if (e.code === 409 || e.type === 'document_already_exists') { - setHasUserDoc(true); - setOnboardingError(""); - } else if (e.code === 401 || e.type === 'general_unauthorized_scope') { - // 401 Unauthorized: Permissions nicht richtig gesetzt - setOnboardingError( - "Berechtigung verweigert. Bitte prüfe in Appwrite, ob die users Collection die richtigen Permissions hat. " + - "Siehe setup/USERS_COLLECTION_SETUP.md für Details." - ); - } else { - // Andere Fehler anzeigen - setOnboardingError(e.message || "Fehler beim Erstellen des Profils. Bitte versuche es erneut."); + // Prüfe zuerst, ob User-Dokument bereits existiert + let userDocExists = false; + try { + await databases.getDocument(databaseId, usersCollectionId, authUser.$id); + userDocExists = true; + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:178',message:'handleOnboardingStart: userDoc exists',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + } catch (e) { + // Dokument existiert nicht - wird erstellt + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:182',message:'handleOnboardingStart: userDoc does not exist, will create',data:{error:e.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + } + + if (!userDocExists) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:187',message:'handleOnboardingStart: creating userDoc',data:{userId:authUser.$id},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + await databases.createDocument( + databaseId, + usersCollectionId, + authUser.$id, // Document-ID = Auth-User-ID + { + user_name: authUser.name || "User", + user_extension_load: false + } + ); + // Erfolg: User-Dokument erstellt + setHasUserDoc(true); + // user_extension_load ist false beim Erstellen (siehe payload) + setUserExtensionLoad(false); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:202',message:'handleOnboardingStart: userDoc created, setting hasUserDoc=true',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + + // Prüfe, ob User bereits Accounts hat (nach dem Erstellen des User-Dokuments) + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:207',message:'handleOnboardingStart: checking for accounts after userDoc creation',data:{userId:authUser.$id},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + try { + const existingAccounts = await fetchManagedAccounts(authUser.$id); + const hasAccountsValue = Array.isArray(existingAccounts) && existingAccounts.length > 0; + setHasAccounts(hasAccountsValue); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:212',message:'handleOnboardingStart: accounts check result after creation',data:{hasAccounts:hasAccountsValue,accountsCount:existingAccounts?.length || 0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + } catch (accountsErr) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:216',message:'handleOnboardingStart: error checking accounts after creation',data:{error:accountsErr.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + setHasAccounts(false); + } + } else { + // Dokument existiert bereits - prüfe user_extension_load + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:206',message:'handleOnboardingStart: userDoc exists, checking extension load',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + const userDoc = await databases.getDocument(databaseId, usersCollectionId, authUser.$id); + const extensionLoad = userDoc?.user_extension_load === true; + setHasUserDoc(true); + setUserExtensionLoad(extensionLoad); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:212',message:'handleOnboardingStart: userDoc retrieved, setting hasUserDoc=true',data:{extensionLoad},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + } + + // Prüfe, ob User Accounts hat (nach dem Erstellen/Prüfen des User-Dokuments) + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:217',message:'handleOnboardingStart: checking for accounts',data:{userId:authUser.$id},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + try { + const existingAccounts = await fetchManagedAccounts(authUser.$id); + const hasAccountsValue = Array.isArray(existingAccounts) && existingAccounts.length > 0; + setHasAccounts(hasAccountsValue); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:222',message:'handleOnboardingStart: accounts check result',data:{hasAccounts:hasAccountsValue,accountsCount:existingAccounts?.length || 0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + } catch (accountsErr) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:226',message:'handleOnboardingStart: error checking accounts',data:{error:accountsErr.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + setHasAccounts(false); + } + + setOnboardingError(""); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:232',message:'handleOnboardingStart: success, showGate will be',data:{hasUserDoc:true,userExtensionLoad,hasAccounts,showGateWillBe:(hasUserDoc && userExtensionLoad === false && !hasAccounts)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + } catch (e) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:220',message:'handleOnboardingStart: error caught',data:{errorCode:e.code,errorType:e.type,errorMessage:e.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + // 409 Conflict bedeutet, dass das Dokument bereits existiert + // Das ist ok, da wir idempotent sein wollen + if (e.code === 409 || e.type === 'document_already_exists') { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:225',message:'handleOnboardingStart: document already exists (409)',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + setHasUserDoc(true); + // Prüfe user_extension_load für existierendes Dokument + if (authUser && databases && databaseId && usersCollectionId) { + try { + const userDoc = await databases.getDocument(databaseId, usersCollectionId, authUser.$id); + const extensionLoad = userDoc?.user_extension_load === true; + setUserExtensionLoad(extensionLoad); + + // Prüfe auch Accounts + try { + const existingAccounts = await fetchManagedAccounts(authUser.$id); + const hasAccountsValue = Array.isArray(existingAccounts) && existingAccounts.length > 0; + setHasAccounts(hasAccountsValue); + } catch (accountsErr) { + setHasAccounts(false); + } + } catch (docErr) { + setUserExtensionLoad(null); + setHasAccounts(false); + } + } else { + setUserExtensionLoad(null); + setHasAccounts(false); + } + setOnboardingError(""); + } else if (e.code === 401 || e.type === 'general_unauthorized_scope') { + // 401 Unauthorized: Permissions nicht richtig gesetzt + setOnboardingError( + "Berechtigung verweigert. Bitte prüfe in Appwrite, ob die users Collection die richtigen Permissions hat. " + + "Siehe setup/USERS_COLLECTION_SETUP.md für Details." + ); + } else { + // Andere Fehler anzeigen + setOnboardingError(e.message || "Fehler beim Erstellen des Profils. Bitte versuche es erneut."); + } + } finally { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'App.jsx:245',message:'handleOnboardingStart: finally, setting loading=false',data:{hasUserDoc,userExtensionLoad,showGateWillBe:(!hasUserDoc || (hasUserDoc && userExtensionLoad === false)) && !checkingUserDoc && authUser !== null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + setOnboardingLoading(false); } - } finally { - setOnboardingLoading(false); } - } async function logout() { setStatus((s) => ({ ...s, loading: true, error: "" })); @@ -153,9 +345,11 @@ export default function App() { await account.deleteSession("current"); } catch {} setStatus({ loading: false, authed: false, error: "" }); - setAuthUser(null); - setHasUserDoc(false); - setOnboardingError(""); + setAuthUser(null); + setHasUserDoc(false); + setUserExtensionLoad(null); + setHasAccounts(false); + setOnboardingError(""); // Extension informieren: Token weg sendToExtension({ type: "AUTH_CLEARED" }); @@ -202,6 +396,7 @@ export default function App() { icon: ( ), + disabled: scanning, onClick: (e) => { e.preventDefault(); navigate("/accounts"); @@ -288,6 +483,7 @@ export default function App() { onStart={handleOnboardingStart} loading={onboardingLoading} error={onboardingError} + initialPhase={userExtensionLoad === false ? "extension" : "welcome"} /> )}
@@ -297,26 +493,31 @@ export default function App() { "flex w-full flex-1 flex-col overflow-hidden rounded-md border border-neutral-200 bg-gray-100 md:flex-row dark:border-neutral-700 dark:bg-neutral-800", "h-screen relative z-10" )}> - - -
- -
- {links.map((link, idx) => ( - - ))} + {!scanning && ( + + +
+ +
+ {links.map((link, idx) => ( + + ))} +
-
-
- { - e.preventDefault(); - logout(); - }} /> -
- - +
+ { + e.preventDefault(); + logout(); + }} /> +
+ + + )} {renderContent()}
+ {scanning && ( + + )}
)} diff --git a/Server/src/components/dashboard/sections/ProductsSection.jsx b/Server/src/components/dashboard/sections/ProductsSection.jsx index e2ee43b..36cf0b7 100644 --- a/Server/src/components/dashboard/sections/ProductsSection.jsx +++ b/Server/src/components/dashboard/sections/ProductsSection.jsx @@ -1,12 +1,16 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { DataTable } from "../ui/DataTable"; import { Pagination } from "../ui/Pagination"; import { Filters } from "../ui/Filters"; import { cn } from "../../../lib/utils"; import { getProductsPage, getProductPreview } from "../../../services/dashboardService"; import { scanProductsForAccount } from "../../../services/productsService"; +import { getScanProgress } from "../../../services/ebayParserService"; +import { useScan } from "../../../context/ScanContext"; import { AnimatePresence, motion } from "motion/react"; +const SCAN_POLL_MS = 300; + export const ProductsSection = ({ onJumpToSection, activeAccountId }) => { const [statusFilter, setStatusFilter] = useState("all"); const [searchQuery, setSearchQuery] = useState(""); @@ -18,8 +22,9 @@ export const ProductsSection = ({ onJumpToSection, activeAccountId }) => { const [total, setTotal] = useState(0); const [selectedProduct, setSelectedProduct] = useState(null); const [previewLoading, setPreviewLoading] = useState(false); - const [scanning, setScanning] = useState(false); const [scanToast, setScanToast] = useState({ show: false, message: "", type: "success" }); + const pollRef = useRef(null); + const { scanning, startScan, endScan, updateProgress } = useScan(); // Lade Products wenn activeAccountId oder Filter sich ändern useEffect(() => { @@ -121,17 +126,39 @@ export const ProductsSection = ({ onJumpToSection, activeAccountId }) => { return; } - setScanning(true); setError(null); + startScan(); + + const stopPolling = () => { + if (pollRef.current) { + clearInterval(pollRef.current); + pollRef.current = null; + } + }; + + pollRef.current = setInterval(async () => { + try { + const p = await getScanProgress(); + if (p && (p.percent != null || p.phase || p.complete)) { + updateProgress({ + percent: p.percent ?? 0, + phase: p.phase ?? "idle", + total: p.total ?? 0, + current: p.current ?? 0, + complete: !!p.complete, + }); + } + } catch { + // ignore + } + }, SCAN_POLL_MS); try { - // Führe Scan aus const result = await scanProductsForAccount(activeAccountId); + stopPolling(); - // Refresh Products-Liste await loadProducts(); - // Zeige Erfolgs-Toast const updated = result.updated ?? 0; setScanToast({ show: true, @@ -142,23 +169,45 @@ export const ProductsSection = ({ onJumpToSection, activeAccountId }) => { setScanToast({ show: false, message: "", type: "success" }); }, 3000); } catch (e) { + stopPolling(); console.error("Fehler beim Scannen der Produkte:", e); - - // Logge meta für Dev-Debugging + const meta = e.meta || {}; if (Object.keys(meta).length > 0) { console.log("[scan meta]", meta); } - - // Prüfe auf no_items_found oder empty_items + const errorMsg = e.message || "Fehler beim Scannen der Produkte"; const isNoItems = errorMsg.includes("no_items_found") || errorMsg.includes("empty_items"); - - // Zeige Toast mit spezifischer Meldung für 0 Items - const toastMessage = isNoItems - ? "0 Produkte gefunden. Bitte pruefe, ob die URL auf den Shop/Artikel-Bereich des Sellers zeigt." - : errorMsg; - + const isParsingFailed = errorMsg.includes("Parsing failed"); + + let toastMessage = errorMsg; + if (isNoItems) { + toastMessage = "0 Produkte gefunden. Bitte prüfe, ob die URL auf den Shop/Artikel-Bereich des Sellers zeigt."; + } else if (isParsingFailed) { + toastMessage = "Extension konnte keine Produkte finden. "; + if (meta.pageType && meta.pageType !== "unknown") { + toastMessage += `Seitentyp: ${meta.pageType}. `; + } + if (meta.reason) { + toastMessage += `Grund: ${meta.reason}. `; + } + if (meta.finalUrl) { + toastMessage += `URL: ${meta.finalUrl}`; + } + if (!meta.pageType && !meta.reason && !meta.finalUrl) { + toastMessage += "Bitte stelle sicher, dass die Account-URL auf eine Seite mit Produkt-Listings zeigt (z.B. Storefront oder Seller-Listings)."; + } + } else if (e.meta) { + const m = e.meta; + if (m.pageType && m.pageType !== "unknown") { + toastMessage += ` (Seitentyp: ${m.pageType})`; + } + if (m.reason) { + toastMessage += ` (${m.reason})`; + } + } + setScanToast({ show: true, message: toastMessage, @@ -166,9 +215,13 @@ export const ProductsSection = ({ onJumpToSection, activeAccountId }) => { }); setTimeout(() => { setScanToast({ show: false, message: "", type: "success" }); - }, 3000); + }, 5000); } finally { - setScanning(false); + if (pollRef.current) { + clearInterval(pollRef.current); + pollRef.current = null; + } + endScan(); } }; diff --git a/Server/src/components/onboarding/OnboardingGate.jsx b/Server/src/components/onboarding/OnboardingGate.jsx index c311c75..f2f923e 100644 --- a/Server/src/components/onboarding/OnboardingGate.jsx +++ b/Server/src/components/onboarding/OnboardingGate.jsx @@ -1,6 +1,7 @@ "use client"; -import React, { useState } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { motion, AnimatePresence } from "motion/react"; +import styled from "styled-components"; import { BackgroundRippleEffect } from "@/components/layout/BackgroundRippleEffect"; import Shuffle from "@/components/ui/Shuffle"; import ColourfulText from "@/components/ui/colourful-text"; @@ -10,14 +11,178 @@ import { IPhoneNotification } from "@/components/ui/iphone-notification"; import { parseEbayAccount } from "@/services/ebayParserService"; import { createManagedAccount, fetchManagedAccounts } from "@/services/accountsService"; import { account, databases, databaseId, usersCollectionId } from "@/lib/appwrite"; +import { DottedGlowBackground } from "@/components/ui/dotted-glow-background"; -export const OnboardingGate = ({ userName, onStart, loading, error }) => { - const [phase, setPhase] = useState("shuffle"); +const StyledDownloadButton = styled.div` + .button { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 5.3em; + height: 5.3em; + border: none; + cursor: pointer; + border-radius: 0.4em; + background: rgba(66, 67, 67, 0.6); + text-decoration: none; + } + + .container { + position: relative; + width: 3.5em; + height: 3.1em; + background: none; + overflow: hidden; + } + + .folder { + content: ""; + position: absolute; + } + + .folder_one { + bottom: 0; + width: 100%; + height: 88%; + border-radius: 3px; + border-top: 2px solid rgb(206, 167, 39); + background: linear-gradient(-35deg, rgb(238, 194, 47) 5%, rgb(255, 223, 118)); + } + + .folder_two { + top: 5%; + width: 38%; + height: 19%; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + background-color: rgb(206, 167, 39); + box-shadow: 0 1px 5px -2px rgba(0, 0, 0, 0.5); + } + + .folder_two::before { + content: ""; + position: absolute; + display: inline; + left: 88%; + width: 0; + height: 0; + border-left: 7px solid rgb(206, 167, 39); + border-top: 0.3em solid transparent; + border-bottom: 0.3em solid transparent; + } + + .folder_three { + display: flex; + align-items: center; + justify-content: center; + left: 0.5em; + bottom: 0; + width: 2.5em; + height: 0.9em; + border-radius: 4px 4px 0 0; + background: linear-gradient(-35deg, rgb(25, 102, 218), rgb(109, 165, 249)); + box-shadow: 0 0 5px rgba(0, 0, 0, 0.4); + } + + .folder_four { + left: 1em; + bottom: 0.3em; + width: 1.5em; + height: 0.18em; + border-radius: 1em; + background-color: rgb(20, 77, 163); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + } + + .active_line { + content: ""; + position: absolute; + bottom: 0; + width: 0.9em; + height: 0.4em; + background-color: #999; + border: none; + border-radius: 1em; + transition: all 0.15s linear; + } + + .button:active .active_line, + .button:focus .active_line { + width: 2.3em; + background-color: rgb(41, 126, 255); + } + + .button:focus .container { + animation: wow 1s forwards; + } + + @keyframes wow { + 20% { + scale: 0.8; + } + + 30% { + scale: 1; + transform: translateY(0); + } + + 50% { + transform: translateY(-6px); + } + + 65% { + transform: translateY(4px); + } + + 80% { + transform: translateY(0); + } + + 100% { + scale: 1; + } + } + + .text { + content: ""; + position: absolute; + top: -4.5em; + width: 7.7em; + height: 2.6em; + background-color: #666; + color: #fff; + display: flex; + justify-content: center; + align-items: center; + border: none; + border-radius: 5px; + text-shadow: 0 0 10px rgb(0, 0, 0); + opacity: 0; + transition: all 0.25s linear; + font-size: 0.7em; + white-space: nowrap; + padding: 0 0.5em; + } + + .button:hover .text { + opacity: 1; + } +`; + +export const OnboardingGate = ({ userName, onStart, loading, error, initialPhase = "welcome" }) => { + const [phase, setPhase] = useState(initialPhase); const [submitting, setSubmitting] = useState(false); const [submitError, setSubmitError] = useState(""); const [showNotification, setShowNotification] = useState(false); const [notificationMessage, setNotificationMessage] = useState("bitte eine gueltige url verwenden!"); const [skipHovered, setSkipHovered] = useState(false); + const [extensionDetected, setExtensionDetected] = useState(false); + const extensionCheckIntervalRef = useRef(null); + const [showManualContinue, setShowManualContinue] = useState(false); + const [extensionDownloaded, setExtensionDownloaded] = useState(false); + const [userExtensionLoaded, setUserExtensionLoaded] = useState(false); const loadingStates = [ { text: "URL wird verarbeitet..." }, @@ -32,9 +197,320 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { "Paste deine eBay Shop-URL hier...", ]; + // PostMessage Listener - MUSS IMMER aktiv sein (nicht nur in extension Phase) + // damit wir auch Nachrichten empfangen, wenn Extension nach dem Laden installiert wird + useEffect(() => { + const handleMessage = (event) => { + if (event.data?.source === "eship-extension" && event.data?.type === "EXTENSION_ID") { + setExtensionDetected(true); + return true; + } + return false; + }; + + // Registriere Listener IMMER (nicht nur in extension Phase) + window.addEventListener("message", handleMessage); + + // Sende sofort mehrere Anfragen beim Mount (falls Extension bereits geladen ist) + // Wichtig: Mehrfach senden, da Timing variieren kann + const sendPing = () => { + window.postMessage({ + source: "eship-webapp", + type: "PING_EXTENSION", + requestId: Date.now() + }, "*"); + }; + + // Sofort, dann nach kurzen Verzögerungen (für verschiedene Timing-Szenarien) + sendPing(); + setTimeout(sendPing, 100); + setTimeout(sendPing, 500); + setTimeout(sendPing, 1000); + setTimeout(sendPing, 2000); + + return () => { + window.removeEventListener("message", handleMessage); + }; + }, []); // Nur einmal beim Mount - Listener bleibt für die gesamte Lebensdauer aktiv + + // Extension-Erkennung: Prüfe window.__EBAY_EXTENSION__ und postMessage + useEffect(() => { + if (phase !== "extension") return; + + // Prüfe sofort, ob Extension bereits verfügbar ist + const checkExtension = () => { + const hasWindow = typeof window !== 'undefined'; + const ebayExtension = hasWindow ? window.__EBAY_EXTENSION__ : undefined; + const isDetected = hasWindow && ebayExtension === true; + + if (isDetected) { + setExtensionDetected(true); + return true; + } + return false; + }; + + // Zusätzlicher Listener nur für die extension Phase (für zusätzliche PING-Anfragen) + // Der globale Listener oben ist bereits aktiv, aber hier senden wir aktive Anfragen + + // Aktive Suche: Sende postMessage an Extension und bitte um Antwort + const requestExtensionId = () => { + // Sende eine Nachricht, die der Content Script erkennen sollte + // Der Content Script sollte darauf antworten + window.postMessage({ + source: "eship-webapp", + type: "PING_EXTENSION", + requestId: Date.now() + }, "*"); + + // Zusätzlich: Injiziere ein Script in den Page Context, das nach der Extension sucht + // Dies funktioniert nur, wenn wir Zugriff auf chrome.runtime haben (was wir nicht haben) + // Stattdessen: Prüfe, ob ein Script-Tag mit Extension-Marker existiert + try { + // Erstelle ein temporäres Script-Element, das postMessage sendet + const script = document.createElement('script'); + script.textContent = ` + (function() { + // Prüfe, ob chrome.runtime verfügbar ist (nur im Content Script Context) + // Da wir im Page Context sind, können wir das nicht direkt prüfen + // Aber wir können postMessage senden und hoffen, dass der Content Script antwortet + window.postMessage({ + source: "eship-webapp-page-context", + type: "PING_EXTENSION", + requestId: ${Date.now()} + }, "*"); + })(); + `; + document.documentElement.appendChild(script); + document.documentElement.removeChild(script); + } catch (e) { + // Script injection failed - ignore + } + }; + + // Prüfe sofort + const immediateCheck = checkExtension(); + + if (immediateCheck) { + return; + } + + // Der globale Listener ist bereits aktiv (siehe useEffect oben) + // Hier starten wir nur das aktive Polling für die extension Phase + + // Aktive Suche: Sende sofort eine Anfrage + requestExtensionId(); + + // Polling-Mechanismus: Prüfe alle 500ms UND sende alle 2 Sekunden eine Anfrage + extensionCheckIntervalRef.current = setInterval(() => { + if (checkExtension()) { + if (extensionCheckIntervalRef.current) { + clearInterval(extensionCheckIntervalRef.current); + extensionCheckIntervalRef.current = null; + } + } + }, 500); + + // Aktive Suche: Sende alle 2 Sekunden eine Anfrage an die Extension + const requestInterval = setInterval(() => { + if (!extensionDetected) { + requestExtensionId(); + } else { + clearInterval(requestInterval); + } + }, 2000); + + // Cleanup für requestInterval + const cleanupRequestInterval = () => { + clearInterval(requestInterval); + }; + + // Cleanup + return () => { + // NICHT window.removeEventListener hier - der globale Listener muss aktiv bleiben! + if (extensionCheckIntervalRef.current) { + clearInterval(extensionCheckIntervalRef.current); + extensionCheckIntervalRef.current = null; + } + cleanupRequestInterval(); + }; + }, [phase]); + + // Prüfe beim Mount, ob user_extension_load bereits true ist (nach Reload) + useEffect(() => { + const checkUserExtensionLoaded = async () => { + try { + const authUser = await account.get(); + if (authUser && databases && databaseId && usersCollectionId) { + try { + const userDoc = await databases.getDocument(databaseId, usersCollectionId, authUser.$id); + if (userDoc.user_extension_load === true) { + setUserExtensionLoaded(true); + + // Prüfe, ob User bereits Accounts hat + try { + const existingAccounts = await fetchManagedAccounts(authUser.$id); + + // Debug: Log in Browser-Konsole + console.log("[OnboardingGate] checkUserExtensionLoaded: Accounts-Prüfung", { + userId: authUser.$id, + accountsArray: existingAccounts, + accountsCount: Array.isArray(existingAccounts) ? existingAccounts.length : 0, + hasAccounts: Array.isArray(existingAccounts) && existingAccounts.length > 0 + }); + + // Prüfe explizit: Ist es ein Array und hat es Einträge? + const hasAccounts = Array.isArray(existingAccounts) && existingAccounts.length > 0; + + if (hasAccounts) { + // User hat bereits Accounts → direkt zum Dashboard + console.log("[OnboardingGate] checkUserExtensionLoaded: Accounts gefunden, rufe onStart() auf", { + accountsCount: existingAccounts.length + }); + if (onStart) { + onStart(); + } + } else { + // User hat keine Accounts → zur Input-Phase + console.log("[OnboardingGate] checkUserExtensionLoaded: KEINE Accounts gefunden, wechsle zur Input-Phase", { + accountsCount: Array.isArray(existingAccounts) ? existingAccounts.length : 0, + currentPhase: phase + }); + // Wechsle zur Input-Phase, unabhängig von der aktuellen Phase + setTimeout(() => { + setPhase("input"); + }, 1000); + } + } catch (accountsErr) { + // Fehler beim Laden der Accounts → zur Input-Phase + console.warn("Fehler beim Laden der Accounts:", accountsErr); + setTimeout(() => { + setPhase("input"); + }, 1000); + } + } else if (userDoc.user_extension_load === false) { + // User hat Extension noch nicht geladen → zur Extension-Phase (sofort, ohne Delay) + console.log("[OnboardingGate] checkUserExtensionLoaded: user_extension_load ist false, wechsle zur Extension-Phase", { + currentPhase: phase + }); + if (phase !== "extension") { + // Setze Phase sofort, ohne Delay + setPhase("extension"); + } + } + } catch (e) { + // Dokument existiert nicht oder Fehler - ignorieren + } + } + } catch (err) { + // User nicht eingeloggt oder Fehler - ignorieren + } + }; + + checkUserExtensionLoaded(); + }, []); // Nur einmal beim Mount + + // Prüfe kontinuierlich, ob user_extension_load true wurde (während extension Phase) + useEffect(() => { + if (phase !== "extension" || userExtensionLoaded) return; + + const checkInterval = setInterval(async () => { + try { + const authUser = await account.get(); + if (authUser && databases && databaseId && usersCollectionId) { + try { + const userDoc = await databases.getDocument(databaseId, usersCollectionId, authUser.$id); + if (userDoc.user_extension_load === true) { + setUserExtensionLoaded(true); + + // Prüfe, ob User bereits Accounts hat + try { + const existingAccounts = await fetchManagedAccounts(authUser.$id); + + // Debug: Log in Browser-Konsole + console.log("[OnboardingGate] checkInterval: Accounts-Prüfung", { + userId: authUser.$id, + accountsArray: existingAccounts, + accountsCount: Array.isArray(existingAccounts) ? existingAccounts.length : 0, + hasAccounts: Array.isArray(existingAccounts) && existingAccounts.length > 0 + }); + + // Prüfe explizit: Ist es ein Array und hat es Einträge? + const hasAccounts = Array.isArray(existingAccounts) && existingAccounts.length > 0; + + if (hasAccounts) { + // User hat bereits Accounts → direkt zum Dashboard + console.log("[OnboardingGate] checkInterval: Accounts gefunden, rufe onStart() auf", { + accountsCount: existingAccounts.length + }); + // Interval stoppen, bevor onStart() aufgerufen wird + clearInterval(checkInterval); + if (onStart) { + onStart(); + } + } else { + // User hat keine Accounts → zur Input-Phase + console.log("[OnboardingGate] checkInterval: KEINE Accounts gefunden, wechsle zur Input-Phase", { + accountsCount: Array.isArray(existingAccounts) ? existingAccounts.length : 0 + }); + // Interval stoppen, bevor zur Input-Phase gewechselt wird + clearInterval(checkInterval); + setTimeout(() => { + setPhase("input"); + }, 1000); + } + } catch (accountsErr) { + // Fehler beim Laden der Accounts → zur Input-Phase + console.warn("Fehler beim Laden der Accounts:", accountsErr); + // Interval stoppen bei Fehler + clearInterval(checkInterval); + setTimeout(() => { + setPhase("input"); + }, 1000); + } + } + } catch (e) { + // Dokument existiert nicht oder Fehler - ignorieren + } + } + } catch (err) { + // User nicht eingeloggt oder Fehler - ignorieren + } + }, 2000); // Alle 2 Sekunden prüfen + + return () => clearInterval(checkInterval); + }, [phase, userExtensionLoaded, onStart]); + + // Zeige manuellen "Weiter"-Button nach 10 Sekunden, wenn Extension nicht erkannt wurde + useEffect(() => { + if (phase === "extension" && !extensionDetected && !userExtensionLoaded) { + const timer = setTimeout(() => { + setShowManualContinue(true); + }, 10000); // 10 Sekunden + return () => clearTimeout(timer); + } else { + setShowManualContinue(false); + } + }, [phase, extensionDetected, userExtensionLoaded]); + + // Automatischer Übergang zu "input" Phase, wenn Extension erkannt wurde + useEffect(() => { + if (phase === "extension" && extensionDetected) { + // Warte 1-2 Sekunden, dann wechsle zur input Phase + const timer = setTimeout(() => { + setPhase("input"); + }, 1500); + return () => clearTimeout(timer); + } + }, [phase, extensionDetected]); + + const handleManualContinue = () => { + setPhase("input"); + }; + const handleOverlayClick = async (e) => { - // Only handle clicks on the overlay itself or when in shuffle phase - if (phase === "shuffle") { + // Only handle clicks on the overlay itself or when in welcome phase + if (phase === "welcome") { // Create user document first (but don't call onStart, as that would hide the gate) // We need to create it directly to ensure it exists for account creation later try { @@ -46,7 +522,8 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { usersCollectionId, authUser.$id, { - user_name: authUser.name || "User" + user_name: authUser.name || "User", + user_extension_load: false } ); } catch (docErr) { @@ -64,7 +541,7 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { // Add small delay to let the shuffle exit animation complete // Exit animation is 0.5s, so we wait a bit longer to see it fully setTimeout(() => { - setPhase("input"); + setPhase("extension"); }, 600); // 600ms delay - slightly longer than exit animation (500ms) } }; @@ -79,14 +556,7 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { // Validate eBay URL const isValidEbayUrl = (url) => { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:45',message:'isValidEbayUrl: entry',data:{url,hasUrl:!!url,trimmedUrl:url?.trim()},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - if (!url || !url.trim()) { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:48',message:'isValidEbayUrl: empty url',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion return false; } @@ -98,16 +568,9 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { const hostname = urlObj.hostname; const patternMatches = ebayHostnamePattern.test(hostname); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:62',message:'isValidEbayUrl: validation result',data:{url,hostname,patternMatches,pattern:ebayHostnamePattern.toString()},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion - return patternMatches; } catch (e) { // Invalid URL format - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:62',message:'isValidEbayUrl: URL parse error',data:{url,error:e.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); - // #endregion return false; } }; @@ -116,12 +579,12 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { e.preventDefault(); // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:59',message:'handleAccountSubmit: entry',data:{url,hasUrl:!!url,phase},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:418',message:'handleAccountSubmit: entry',data:{url,hasUrl:!!url,phase},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion if (!url || !url.trim()) { // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:64',message:'handleAccountSubmit: empty url, showing notification',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:422',message:'handleAccountSubmit: empty url',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion setNotificationMessage("bitte eine gueltige url verwenden!"); setShowNotification(true); @@ -131,12 +594,12 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { // Validate eBay URL const isValid = isValidEbayUrl(url); // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:71',message:'handleAccountSubmit: validation result',data:{url,isValid},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:430',message:'handleAccountSubmit: validation result',data:{url,isValid},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion if (!isValid) { // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:76',message:'handleAccountSubmit: invalid url, showing notification',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:434',message:'handleAccountSubmit: invalid url',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion setNotificationMessage("bitte eine gueltige url verwenden!"); setShowNotification(true); @@ -149,30 +612,46 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { // Wait 2 seconds for vanish animation, then switch to loading phase setTimeout(async () => { // Switch to loading phase first + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:444',message:'handleAccountSubmit: switching to loading phase',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H4'})}).catch(()=>{}); + // #endregion setPhase("loading"); try { - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:88',message:'handleAccountSubmit: before parseEbayAccount',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); - // #endregion - // Parse eBay account - const accountData = await parseEbayAccount(url); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:93',message:'handleAccountSubmit: parseEbayAccount success',data:{url,hasAccountData:!!accountData,market:accountData?.market,sellerId:accountData?.sellerId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:449',message:'handleAccountSubmit: before parseEbayAccount',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); + // #endregion + const accountData = await parseEbayAccount(url); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:452',message:'handleAccountSubmit: parseEbayAccount success',data:{url,hasAccountData:!!accountData,market:accountData?.market,sellerId:accountData?.sellerId},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion // Validate that sellerId was extracted successfully if (!accountData.sellerId || accountData.sellerId.trim() === "") { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:456',message:'handleAccountSubmit: sellerId validation failed',data:{accountData},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); + // #endregion throw new Error("Die eBay-URL konnte nicht verarbeitet werden. Bitte stelle sicher, dass es eine gültige eBay-Shop-URL ist."); } // Get current user + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:462',message:'handleAccountSubmit: before account.get',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion const authUser = await account.get(); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:465',message:'handleAccountSubmit: account.get success',data:{hasAuthUser:!!authUser,userId:authUser?.$id},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion // Check for duplicate account before creating + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:469',message:'handleAccountSubmit: before fetchManagedAccounts',data:{userId:authUser.$id},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion const existingAccounts = await fetchManagedAccounts(authUser.$id); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:472',message:'handleAccountSubmit: fetchManagedAccounts success',data:{accountsCount:existingAccounts?.length || 0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion const duplicateAccount = existingAccounts.find( (acc) => acc.account_platform_account_id === accountData.sellerId && @@ -180,31 +659,52 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { ); if (duplicateAccount) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:480',message:'handleAccountSubmit: duplicate account found',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion throw new Error("Dieser Account ist bereits verbunden."); } // Create account in database + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:485',message:'handleAccountSubmit: before createManagedAccount',data:{userId:authUser.$id,accountData,itemsSold:accountData.stats?.itemsSold},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion await createManagedAccount(authUser.$id, { account_platform_market: accountData.market, account_platform_account_id: accountData.sellerId, account_shop_name: accountData.shopName || null, account_url: url, account_status: accountData.status || "active", + account_sells: accountData.stats?.itemsSold ?? null, // Setze account_sells wenn verfügbar }); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:494',message:'handleAccountSubmit: createManagedAccount success',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H3'})}).catch(()=>{}); + // #endregion // Account erstellt erfolgreich, rufe onStart auf - onStart && onStart(); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:498',message:'handleAccountSubmit: before onStart',data:{hasOnStart:!!onStart},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + if (onStart) { + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:501',message:'handleAccountSubmit: calling onStart',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + await onStart(); + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:504',message:'handleAccountSubmit: onStart completed, resetting phase',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H1'})}).catch(()=>{}); + // #endregion + // Phase zurücksetzen, damit der Loading-Screen verschwindet + // (onStart versteckt das Gate, aber die Phase bleibt auf "loading") + setPhase("input"); + setSubmitting(false); + } // Trigger event to reload Dashboard accounts - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:142',message:'handleAccountSubmit: account created, triggering reload event',data:{url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{}); - // #endregion window.dispatchEvent(new CustomEvent('accountsUpdated')); } catch (err) { console.error("Fehler beim Erstellen des Accounts:", err); - // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:106',message:'handleAccountSubmit: error caught',data:{url,errorMessage:err.message,errorCode:err.code,errorType:err.type,errorStack:err.stack?.substring(0,200)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:512',message:'handleAccountSubmit: error caught',data:{url,errorMessage:err.message,errorCode:err.code,errorType:err.type,errorStack:err.stack?.substring(0,200)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion // Show notification for URL validation, duplicate, or parsing errors @@ -216,17 +716,20 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { err.message?.includes("already") ) { // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:205',message:'handleAccountSubmit: URL/duplicate error, showing notification',data:{errorMessage:err.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:523',message:'handleAccountSubmit: URL/duplicate error, showing notification',data:{errorMessage:err.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion // Use the actual error message or default message setNotificationMessage(err.message || "bitte eine gueltige url verwenden!"); setShowNotification(true); } else { // #region agent log - fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:175',message:'handleAccountSubmit: non-URL error, setting submitError',data:{errorMessage:err.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{}); + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:530',message:'handleAccountSubmit: non-URL error, setting submitError',data:{errorMessage:err.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H2'})}).catch(()=>{}); // #endregion setSubmitError(err.message || "Fehler beim Erstellen des Accounts. Bitte versuche es erneut."); } + // #region agent log + fetch('http://127.0.0.1:7242/ingest/246fe132-ecc5-435f-bd9c-fe5e8e26089d',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'OnboardingGate.jsx:534',message:'handleAccountSubmit: error handler - switching back to input phase',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H4'})}).catch(()=>{}); + // #endregion setPhase("input"); setSubmitting(false); } @@ -235,7 +738,7 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { return (
@@ -277,11 +780,11 @@ export const OnboardingGate = ({ userName, onStart, loading, error }) => { duration={4000} /> - {/* Shuffle and Input Phases - Combined AnimatePresence for smooth transition */} + {/* Welcome, Extension and Input Phases - Combined AnimatePresence for smooth transition */} - {phase === "shuffle" && ( + {phase === "welcome" && ( {
)} + + {phase === "extension" && ( + +
+
+ Lade die + C + h + r + o + m + e + + E + x + t + e + n + s + i + o + n + herunter und aktiviere sie +
+ + {!extensionDownloaded ? ( +
+ + + { + setExtensionDownloaded(true); + }} + > +
+
+
+
+
+
+
+ ) : ( + + )} + + {userExtensionLoaded ? ( +
+ + + + Extension aktiviert! Weiterleitung... +
+ ) : extensionDetected ? ( +
+ + + + Extension erkannt! Weiterleitung... +
+ ) : ( + <> +
+
+ Warte auf Extension... +
+ + )} +
+ + )} {phase === "input" && ( { const { open, animate } = useSidebar(); + const disabled = !!link.disabled; + const handleClick = (e) => { + if (disabled) { + e.preventDefault(); + return; + } + link.onClick?.(e); + }; return ( {link.icon} +
+ {LETTERS.map((char, i) => ( + + {char} + + ))} + {Math.round(percent)}% +
+
+ + ); +} diff --git a/Server/src/components/ui/colourful-text.jsx b/Server/src/components/ui/colourful-text.jsx index 16b0d88..0095e06 100644 --- a/Server/src/components/ui/colourful-text.jsx +++ b/Server/src/components/ui/colourful-text.jsx @@ -2,8 +2,8 @@ import React from "react"; import { motion } from "motion/react"; -export default function ColourfulText({ text }) { - const colors = [ +export default function ColourfulText({ text, usePurpleTheme = false }) { + const defaultColors = [ "rgb(131, 179, 32)", "rgb(47, 195, 106)", "rgb(42, 169, 210)", @@ -15,6 +15,21 @@ export default function ColourfulText({ text }) { "rgb(232, 98, 63)", "rgb(249, 129, 47)", ]; + + const purpleColors = [ + "rgb(174, 182, 192)", + "rgb(217, 141, 233)", + "rgb(212, 170, 235)", + "rgb(230, 170, 239)", + "rgb(231, 170, 240)", + "rgb(231, 170, 240)", + "rgb(231, 170, 240)", + "rgb(231, 170, 240)", + "rgb(231, 170, 240)", + "rgb(231, 170, 240)", + ]; + + const colors = usePurpleTheme ? purpleColors : defaultColors; const [currentColors, setCurrentColors] = React.useState(colors); const [count, setCount] = React.useState(0); diff --git a/Server/src/components/ui/dotted-glow-background.jsx b/Server/src/components/ui/dotted-glow-background.jsx new file mode 100644 index 0000000..2abf634 --- /dev/null +++ b/Server/src/components/ui/dotted-glow-background.jsx @@ -0,0 +1,260 @@ +"use client"; +import React, { useEffect, useRef, useState } from "react"; + +/** + * Canvas-based dotted background that randomly glows and dims. + * - Uses a stable grid of dots. + * - Each dot gets its own phase + speed producing organic shimmering. + * - Handles high-DPI and resizes via ResizeObserver. + */ +export const DottedGlowBackground = ({ + className, + gap = 12, + radius = 2, + color = "rgba(0,0,0,0.7)", + darkColor, + glowColor = "rgba(0, 170, 255, 0.85)", + darkGlowColor, + colorLightVar, + colorDarkVar, + glowColorLightVar, + glowColorDarkVar, + opacity = 0.6, + backgroundOpacity = 0, + speedMin = 0.4, + speedMax = 1.3, + speedScale = 1 +}) => { + const canvasRef = useRef(null); + const containerRef = useRef(null); + const [resolvedColor, setResolvedColor] = useState(color); + const [resolvedGlowColor, setResolvedGlowColor] = useState(glowColor); + + // Resolve CSS variable value from the container or root + const resolveCssVariable = (el, variableName) => { + if (!variableName) return null; + const normalized = variableName.startsWith("--") + ? variableName + : `--${variableName}`; + const fromEl = getComputedStyle(el) + .getPropertyValue(normalized) + .trim(); + if (fromEl) return fromEl; + const root = document.documentElement; + const fromRoot = getComputedStyle(root).getPropertyValue(normalized).trim(); + return fromRoot || null; + }; + + const detectDarkMode = () => { + const root = document.documentElement; + if (root.classList.contains("dark")) return true; + if (root.classList.contains("light")) return false; + return (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches); + }; + + // Keep resolved colors in sync with theme changes and prop updates + useEffect(() => { + const container = containerRef.current ?? document.documentElement; + + const compute = () => { + const isDark = detectDarkMode(); + + let nextColor = color; + let nextGlow = glowColor; + + if (isDark) { + const varDot = resolveCssVariable(container, colorDarkVar); + const varGlow = resolveCssVariable(container, glowColorDarkVar); + nextColor = varDot || darkColor || nextColor; + nextGlow = varGlow || darkGlowColor || nextGlow; + } else { + const varDot = resolveCssVariable(container, colorLightVar); + const varGlow = resolveCssVariable(container, glowColorLightVar); + nextColor = varDot || nextColor; + nextGlow = varGlow || nextGlow; + } + + setResolvedColor(nextColor); + setResolvedGlowColor(nextGlow); + }; + + compute(); + + const mql = window.matchMedia + ? window.matchMedia("(prefers-color-scheme: dark)") + : null; + const handleMql = () => compute(); + mql?.addEventListener?.("change", handleMql); + + const mo = new MutationObserver(() => compute()); + mo.observe(document.documentElement, { + attributes: true, + attributeFilter: ["class", "style"], + }); + + return () => { + mql?.removeEventListener?.("change", handleMql); + mo.disconnect(); + }; + }, [ + color, + darkColor, + glowColor, + darkGlowColor, + colorLightVar, + colorDarkVar, + glowColorLightVar, + glowColorDarkVar, + ]); + + useEffect(() => { + const el = canvasRef.current; + const container = containerRef.current; + if (!el || !container) return; + + const ctx = el.getContext("2d"); + if (!ctx) return; + + let raf = 0; + let stopped = false; + + const dpr = Math.max(1, window.devicePixelRatio || 1); + + const resize = () => { + const { width, height } = container.getBoundingClientRect(); + el.width = Math.max(1, Math.floor(width * dpr)); + el.height = Math.max(1, Math.floor(height * dpr)); + el.style.width = `${Math.floor(width)}px`; + el.style.height = `${Math.floor(height)}px`; + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + }; + + const ro = new ResizeObserver(resize); + ro.observe(container); + resize(); + + // Precompute dot metadata for a medium-sized grid and regenerate on resize + let dots = []; + + const regenDots = () => { + dots = []; + const { width, height } = container.getBoundingClientRect(); + const cols = Math.ceil(width / gap) + 2; + const rows = Math.ceil(height / gap) + 2; + const min = Math.min(speedMin, speedMax); + const max = Math.max(speedMin, speedMax); + for (let i = -1; i < cols; i++) { + for (let j = -1; j < rows; j++) { + const x = i * gap + (j % 2 === 0 ? 0 : gap * 0.5); // offset every other row + const y = j * gap; + // Randomize phase and speed slightly per dot + const phase = Math.random() * Math.PI * 2; + const span = Math.max(max - min, 0); + const speed = min + Math.random() * span; // configurable rad/s + dots.push({ x, y, phase, speed }); + } + } + }; + + const regenThrottled = () => { + regenDots(); + }; + + regenDots(); + + let last = performance.now(); + + const draw = (now) => { + if (stopped) return; + const dt = (now - last) / 1000; // seconds + last = now; + const { width, height } = container.getBoundingClientRect(); + + ctx.clearRect(0, 0, el.width, el.height); + ctx.globalAlpha = opacity; + + // optional subtle background fade for depth (defaults to 0 = transparent) + if (backgroundOpacity > 0) { + const grad = ctx.createRadialGradient( + width * 0.5, + height * 0.4, + Math.min(width, height) * 0.1, + width * 0.5, + height * 0.5, + Math.max(width, height) * 0.7 + ); + grad.addColorStop(0, "rgba(0,0,0,0)"); + grad.addColorStop(1, `rgba(0,0,0,${Math.min(Math.max(backgroundOpacity, 0), 1)})`); + ctx.fillStyle = grad; + ctx.fillRect(0, 0, width, height); + } + + // animate dots + ctx.save(); + ctx.fillStyle = resolvedColor; + + const time = (now / 1000) * Math.max(speedScale, 0); + for (let i = 0; i < dots.length; i++) { + const d = dots[i]; + // Linear triangle wave 0..1..0 for linear glow/dim + const mod = (time * d.speed + d.phase) % 2; + const lin = mod < 1 ? mod : 2 - mod; // 0..1..0 + const a = 0.25 + 0.55 * lin; // 0.25..0.8 linearly + + // draw glow when bright + if (a > 0.6) { + const glow = (a - 0.6) / 0.4; // 0..1 + ctx.shadowColor = resolvedGlowColor; + ctx.shadowBlur = 6 * glow; + } else { + ctx.shadowColor = "transparent"; + ctx.shadowBlur = 0; + } + + ctx.globalAlpha = a * opacity; + ctx.beginPath(); + ctx.arc(d.x, d.y, radius, 0, Math.PI * 2); + ctx.fill(); + } + ctx.restore(); + + raf = requestAnimationFrame(draw); + }; + + const handleResize = () => { + resize(); + regenThrottled(); + }; + + window.addEventListener("resize", handleResize); + raf = requestAnimationFrame(draw); + + return () => { + stopped = true; + cancelAnimationFrame(raf); + window.removeEventListener("resize", handleResize); + ro.disconnect(); + }; + }, [ + gap, + radius, + resolvedColor, + resolvedGlowColor, + opacity, + backgroundOpacity, + speedMin, + speedMax, + speedScale, + ]); + + return ( +
+ +
+ ); +}; diff --git a/Server/src/context/ScanContext.jsx b/Server/src/context/ScanContext.jsx new file mode 100644 index 0000000..59ea152 --- /dev/null +++ b/Server/src/context/ScanContext.jsx @@ -0,0 +1,51 @@ +import React, { createContext, useContext, useState, useCallback } from "react"; + +const ScanContext = createContext(null); + +export function useScan() { + const ctx = useContext(ScanContext); + if (!ctx) { + throw new Error("useScan must be used within ScanProvider"); + } + return ctx; +} + +/** + * ScanProvider – hält scanning + scanProgress für Scan-UI (Loader, Dashboard ausblenden, etc.) + */ +export function ScanProvider({ children }) { + const [scanning, setScanning] = useState(false); + const [scanProgress, setScanProgress] = useState({ + percent: 0, + phase: "idle", + total: 0, + current: 0, + complete: false, + }); + + const startScan = useCallback(() => { + setScanning(true); + setScanProgress({ percent: 0, phase: "listing", total: 0, current: 0, complete: false }); + }, []); + + const updateProgress = useCallback((data) => { + setScanProgress((prev) => ({ ...prev, ...data })); + }, []); + + const endScan = useCallback(() => { + setScanning(false); + setScanProgress({ percent: 0, phase: "idle", total: 0, current: 0, complete: false }); + }, []); + + const value = { + scanning, + setScanning, + scanProgress, + setScanProgress, + startScan, + updateProgress, + endScan, + }; + + return {children}; +} diff --git a/Server/src/index.css b/Server/src/index.css index 2d493a1..97a6703 100644 --- a/Server/src/index.css +++ b/Server/src/index.css @@ -41,3 +41,9 @@ } } } + +@keyframes spin { + to { + transform: rotate(360deg); + } +} diff --git a/Server/src/main.jsx b/Server/src/main.jsx index 89f91e5..0b61d8c 100644 --- a/Server/src/main.jsx +++ b/Server/src/main.jsx @@ -1,10 +1,13 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import App from './App.jsx' +import { ScanProvider } from './context/ScanContext' import './index.css' createRoot(document.getElementById('root')).render( - + + + , ) diff --git a/Server/src/pages/AccountsPage.jsx b/Server/src/pages/AccountsPage.jsx index 6845a9c..6ac08d1 100644 --- a/Server/src/pages/AccountsPage.jsx +++ b/Server/src/pages/AccountsPage.jsx @@ -99,7 +99,7 @@ export const AccountsPage = () => { updatePayload.account_platform_account_id = parsedData.sellerId; } - // Shop-Name und account_sells können auch leer sein (optional) + // Shop-Name kann auch leer sein (optional) updatePayload.account_shop_name = parsedData.shopName || null; updatePayload.account_sells = parsedData.stats?.itemsSold ?? null; @@ -584,21 +584,6 @@ export const AccountsPage = () => {

-
- - -

- Automatisch aus dem eBay-Profil gelesen. -

-
-