Compare commits
2 Commits
39c730c676
...
805a6361d7
| Author | SHA1 | Date |
|---|---|---|
|
|
805a6361d7 | |
|
|
0165e1ef87 |
|
|
@ -1 +0,0 @@
|
|||
import{R as c,j as s,Q as u,q as l,P as d}from"./popup-D--aKLqS.js";import"./base64-BbJB1hmJ.js";import"./product-api.service-DR0CE0o9.js";import"./app-C7VSS-q9.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&i(o)}).observe(document,{childList:!0,subtree:!0});function n(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?r.credentials="include":e.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(e){if(e.ep)return;e.ep=!0;const r=n(e);fetch(e.href,r)}})();c.createRoot(document.getElementById("root")).render(s.jsx(u,{client:l,children:s.jsx(d,{})}));
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,18 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<script type="module" crossorigin src="/assets/popup.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/base64-BbJB1hmJ.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/product-api.service-DR0CE0o9.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/app-C7VSS-q9.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/popup-D--aKLqS.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Auto post facebook extensions",
|
||||
"version": "1.0",
|
||||
"action": {
|
||||
"default_popup": "index.html",
|
||||
"default_icon": {
|
||||
"16": "icons/16.png",
|
||||
"32": "icons/32.png",
|
||||
"128": "icons/128.png"
|
||||
}
|
||||
},
|
||||
"background": {
|
||||
"service_worker": "background/background.js",
|
||||
"type": "module"
|
||||
},
|
||||
"host_permissions": ["https://www.facebook.com/*"],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://www.facebook.com/*"],
|
||||
"js": ["content/content.js"],
|
||||
"type": "module"
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": ["content/inject-ui.js", "assets/*"],
|
||||
"matches": ["https://www.facebook.com/*"]
|
||||
}
|
||||
],
|
||||
"permissions": ["storage", "tabs", "activeTab", "scripting"],
|
||||
"icons": {
|
||||
"16": "icons/16.png",
|
||||
"32": "icons/32.png",
|
||||
"128": "icons/128.png"
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
class s{static ID_EXTENSION="ex-root"}export{s as C};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{R as c,j as s,Q as u,q as l,P as d}from"./popup-7ET7snnx.js";import"./_commonjsHelpers-CqkleIqs.js";import"./contants-D9-9W2RY.js";import"./app-C7VSS-q9.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&i(o)}).observe(document,{childList:!0,subtree:!0});function n(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?r.credentials="include":e.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(e){if(e.ep)return;e.ep=!0;const r=n(e);fetch(e.href,r)}})();c.createRoot(document.getElementById("root")).render(s.jsx(u,{client:l,children:s.jsx(d,{})}));
|
||||
import{R as c,j as s,Q as u,q as l,P as d}from"./popup-D7Kw3eOc.js";import"./_commonjsHelpers-CqkleIqs.js";import"./app-BbB6QE4i.js";import"./contants-Ds_B-epI.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&i(o)}).observe(document,{childList:!0,subtree:!0});function n(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?r.credentials="include":e.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(e){if(e.ep)return;e.ep=!0;const r=n(e);fetch(e.href,r)}})();c.createRoot(document.getElementById("root")).render(s.jsx(u,{client:l,children:s.jsx(d,{})}));
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{r as m,j as o,T as b,R as j,Q as E,q as T,P as C}from"../assets/popup-7ET7snnx.js";import{C as w}from"../assets/contants-D9-9W2RY.js";import"../assets/_commonjsHelpers-CqkleIqs.js";import"../assets/app-C7VSS-q9.js";var I=(t,n,d,a,i,r,u,p)=>{let s=document.documentElement,h=["light","dark"];function c(e){(Array.isArray(t)?t:[t]).forEach(l=>{let g=l==="class",S=g&&r?i.map(y=>r[y]||y):i;g?(s.classList.remove(...S),s.classList.add(r&&r[e]?r[e]:e)):s.setAttribute(l,e)}),x(e)}function x(e){p&&h.includes(e)&&(s.style.colorScheme=e)}function v(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}if(a)c(a);else try{let e=localStorage.getItem(n)||d,l=u&&e==="system"?v():e;c(l)}catch{}},N=m.createContext(void 0),R={setTheme:t=>{},themes:[]},k=()=>{var t;return(t=m.useContext(N))!=null?t:R};m.memo(({forcedTheme:t,storageKey:n,attribute:d,enableSystem:a,enableColorScheme:i,defaultTheme:r,value:u,themes:p,nonce:s,scriptProps:h})=>{let c=JSON.stringify([d,n,r,t,p,u,a,i]).slice(1,-1);return m.createElement("script",{...h,suppressHydrationWarning:!0,nonce:typeof window>"u"?s:"",dangerouslySetInnerHTML:{__html:`(${I.toString()})(${c})`}})});const M=({...t})=>{const{theme:n="system"}=k();return o.jsx(b,{theme:n,className:"toaster group",style:{"--normal-bg":"var(--popover)","--normal-text":"var(--popover-foreground)","--normal-border":"var(--border)"},...t})},f=document.getElementById(w.ID_EXTENSION);f&&j.createRoot(f).render(o.jsx(o.Fragment,{children:o.jsxs(E,{client:T,children:[o.jsx("div",{className:"fixed bottom-20 right-6 ex-root",children:o.jsx(C,{})}),o.jsx(M,{position:"top-right"})]})}));
|
||||
import{r as m,j as o,T as b,R as j,Q as E,q as T,P as C}from"../assets/popup-D7Kw3eOc.js";import{C as w}from"../assets/contants-Ds_B-epI.js";import"../assets/_commonjsHelpers-CqkleIqs.js";import"../assets/app-BbB6QE4i.js";var I=(t,n,d,a,i,r,u,p)=>{let s=document.documentElement,h=["light","dark"];function c(e){(Array.isArray(t)?t:[t]).forEach(l=>{let g=l==="class",S=g&&r?i.map(y=>r[y]||y):i;g?(s.classList.remove(...S),s.classList.add(r&&r[e]?r[e]:e)):s.setAttribute(l,e)}),x(e)}function x(e){p&&h.includes(e)&&(s.style.colorScheme=e)}function v(){return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}if(a)c(a);else try{let e=localStorage.getItem(n)||d,l=u&&e==="system"?v():e;c(l)}catch{}},N=m.createContext(void 0),R={setTheme:t=>{},themes:[]},k=()=>{var t;return(t=m.useContext(N))!=null?t:R};m.memo(({forcedTheme:t,storageKey:n,attribute:d,enableSystem:a,enableColorScheme:i,defaultTheme:r,value:u,themes:p,nonce:s,scriptProps:h})=>{let c=JSON.stringify([d,n,r,t,p,u,a,i]).slice(1,-1);return m.createElement("script",{...h,suppressHydrationWarning:!0,nonce:typeof window>"u"?s:"",dangerouslySetInnerHTML:{__html:`(${I.toString()})(${c})`}})});const M=({...t})=>{const{theme:n="system"}=k();return o.jsx(b,{theme:n,className:"toaster group",style:{"--normal-bg":"var(--popover)","--normal-text":"var(--popover-foreground)","--normal-border":"var(--border)"},...t})},f=document.getElementById(w.ID_EXTENSION);f&&j.createRoot(f).render(o.jsx(o.Fragment,{children:o.jsxs(E,{client:T,children:[o.jsx("div",{className:"fixed bottom-20 right-6 ex-root",children:o.jsx(C,{})}),o.jsx(M,{position:"top-right"})]})}));
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
<title>Vite + React + TS</title>
|
||||
<script type="module" crossorigin src="/assets/popup.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/_commonjsHelpers-CqkleIqs.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/contants-D9-9W2RY.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/app-C7VSS-q9.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/popup-7ET7snnx.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/app-BbB6QE4i.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/contants-Ds_B-epI.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/popup-D7Kw3eOc.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit e7fd818c75881047115599e0227d093b4a460f4e
|
||||
|
|
@ -4,52 +4,53 @@ import type { IPost, ISyncItem } from "@/lib/utils";
|
|||
class ProductApiService {
|
||||
item_per_page = 10;
|
||||
|
||||
async index(filter?: {
|
||||
skip?: number;
|
||||
limit?: number;
|
||||
order?: string;
|
||||
where?: Record<string, any>;
|
||||
info?: any;
|
||||
}) {
|
||||
const defaultFilter = {
|
||||
skip: 0,
|
||||
limit: 10,
|
||||
order: "updatedAt desc",
|
||||
where: {
|
||||
account: "prology_net",
|
||||
status: "Updated",
|
||||
},
|
||||
};
|
||||
|
||||
async index(params?: Record<string, any>) {
|
||||
return axios({
|
||||
method: "POST",
|
||||
data: {
|
||||
urlAPI: "/api/ebay-listing/listing-get-list",
|
||||
filter: {
|
||||
...defaultFilter,
|
||||
...filter, // merge filter vào defaultFilter
|
||||
where: {
|
||||
...defaultFilter.where,
|
||||
...filter?.where, // merge where riêng để không mất account/status mặc định
|
||||
},
|
||||
},
|
||||
},
|
||||
method: "GET",
|
||||
url: "products",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
async get(data: IPost) {
|
||||
// return axios({
|
||||
// method: "POST",
|
||||
// data: {
|
||||
// filter: {
|
||||
// where: {
|
||||
// account: "prology_net",
|
||||
// condition: data.raw_condition,
|
||||
// productModelCode: data.sku,
|
||||
// },
|
||||
// },
|
||||
// pageCurrent: "/ebaytools/listing-ebay",
|
||||
// urlAPI: "/api/ebay-listing/get-image-listing",
|
||||
// },
|
||||
// });
|
||||
return axios({
|
||||
method: "GET",
|
||||
url: "products/" + data.ebayListingId,
|
||||
});
|
||||
}
|
||||
|
||||
async publish(data: IPost) {
|
||||
return axios({
|
||||
method: "POST",
|
||||
url: "products/publish/" + data.ebayListingId,
|
||||
data: {
|
||||
filter: {
|
||||
where: {
|
||||
account: "prology_net",
|
||||
condition: data.raw_condition,
|
||||
productModelCode: data.sku,
|
||||
info: (data as any).info || {},
|
||||
hash_info: (data as any).hash_info,
|
||||
},
|
||||
},
|
||||
pageCurrent: "/ebaytools/listing-ebay",
|
||||
urlAPI: "/api/ebay-listing/get-image-listing",
|
||||
});
|
||||
}
|
||||
|
||||
async unlist(data: IPost) {
|
||||
return axios({
|
||||
method: "POST",
|
||||
url: "products/unlist/" + data.ebayListingId,
|
||||
data: {
|
||||
info: (data as any).info || {},
|
||||
hash_info: (data as any).hash_info,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -77,9 +78,10 @@ class ProductApiService {
|
|||
});
|
||||
}
|
||||
|
||||
async getPublistedProducts() {
|
||||
async getPublistedProducts(info: string) {
|
||||
return axios({
|
||||
url: "data",
|
||||
params: { info },
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function ImprovedToggleFilter({
|
|||
|
||||
<ToggleGroupItem
|
||||
size={"sm"}
|
||||
value="unlisted"
|
||||
value="unlist"
|
||||
aria-label="Ẩn khỏi danh sách"
|
||||
className="flex items-center gap-2 px-3 py-2 rounded-md data-[state=on]:bg-orange-100 data-[state=on]:text-orange-700 data-[state=on]:border-orange-200 hover:bg-orange-50 transition-colors"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -37,12 +37,10 @@ import {
|
|||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { delay } from "@/features/app";
|
||||
import useActionPostMutation from "@/hooks/use-action-post-mutation";
|
||||
import usePost from "@/hooks/use-post-hook";
|
||||
import { mapToIPost, type IPost } from "@/lib/utils";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import z from "zod/v3";
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
|
|
@ -178,25 +176,25 @@ export default function ProductModal({
|
|||
})();
|
||||
}, [query.data, data]);
|
||||
|
||||
const saveMutation = useMutation({
|
||||
mutationKey: ["save_product"],
|
||||
mutationFn: async (values: any) => {
|
||||
await delay(300);
|
||||
return productApi.apiRequest("saveProductLocalServer", {
|
||||
id: data?.id,
|
||||
mapped: true,
|
||||
...values,
|
||||
});
|
||||
},
|
||||
onSuccess() {
|
||||
toast.success("Saved", {
|
||||
description: (
|
||||
<span className="!text-black font-medium">{"Product was saved"}</span>
|
||||
),
|
||||
});
|
||||
refetch();
|
||||
},
|
||||
});
|
||||
// const saveMutation = useMutation({
|
||||
// mutationKey: ["save_product"],
|
||||
// mutationFn: async (values: any) => {
|
||||
// await delay(300);
|
||||
// return productApi.apiRequest("saveProductLocalServer", {
|
||||
// id: data?.id,
|
||||
// mapped: true,
|
||||
// ...values,
|
||||
// });
|
||||
// },
|
||||
// onSuccess() {
|
||||
// toast.success("Saved", {
|
||||
// description: (
|
||||
// <span className="!text-black font-medium">{"Product was saved"}</span>
|
||||
// ),
|
||||
// });
|
||||
// refetch();
|
||||
// },
|
||||
// });
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ function DropdownMenuContent({
|
|||
container,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content> & {
|
||||
container: Element;
|
||||
container?: Element;
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Portal container={container}>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { productApi } from "@/api/product-api.service";
|
|||
import { delayRD } from "@/features/app";
|
||||
import { Contants } from "@/lib/contants";
|
||||
import { Queue } from "@/lib/queue";
|
||||
import type { IPost } from "@/lib/utils";
|
||||
import { hashInfo, type IPost } from "@/lib/utils";
|
||||
import { facebookService } from "@/services/facebook.service";
|
||||
import MessageService from "@/services/message.service";
|
||||
import { thiefService } from "@/services/thief.service";
|
||||
|
|
@ -160,12 +160,19 @@ window.addEventListener("message", async (event) => {
|
|||
case "index": {
|
||||
const info = await facebookService.getInfo();
|
||||
|
||||
const response = await productApi.index({ info, ...body });
|
||||
const hash = await hashInfo(info);
|
||||
|
||||
const response = await productApi.index({
|
||||
"filter.info": hash,
|
||||
...body,
|
||||
});
|
||||
data = response.data;
|
||||
break;
|
||||
}
|
||||
case "getPublistedProducts": {
|
||||
const response = await productApi.getPublistedProducts();
|
||||
const info = await facebookService.getInfo();
|
||||
|
||||
const response = await productApi.getPublistedProducts(info);
|
||||
data = response.data;
|
||||
break;
|
||||
}
|
||||
|
|
@ -173,8 +180,6 @@ window.addEventListener("message", async (event) => {
|
|||
const response = await productApi.get(body);
|
||||
data = response.data;
|
||||
|
||||
console.log({ data, body });
|
||||
|
||||
break;
|
||||
}
|
||||
case "createBlobUrl": {
|
||||
|
|
@ -188,12 +193,18 @@ window.addEventListener("message", async (event) => {
|
|||
"background-to-content-create-blod-urls"
|
||||
);
|
||||
|
||||
console.log({ data });
|
||||
|
||||
break;
|
||||
}
|
||||
case "publist": {
|
||||
const info = await facebookService.getInfo();
|
||||
|
||||
const hash = await hashInfo(info);
|
||||
|
||||
msgService.send("background", "content-to-background-actions", {
|
||||
type: "publist",
|
||||
data: body,
|
||||
data: { ...body, info, hash_info: hash },
|
||||
});
|
||||
|
||||
data = await msgService.waitForMessage(
|
||||
|
|
@ -204,9 +215,13 @@ window.addEventListener("message", async (event) => {
|
|||
}
|
||||
|
||||
case "unlist": {
|
||||
const info = await facebookService.getInfo();
|
||||
|
||||
const hash = await hashInfo(info);
|
||||
|
||||
msgService.send("background", "content-to-background-actions", {
|
||||
type: "unlist",
|
||||
data: body,
|
||||
data: { ...body, info, hash_info: hash },
|
||||
});
|
||||
|
||||
data = await msgService.waitForMessage(
|
||||
|
|
@ -216,10 +231,9 @@ window.addEventListener("message", async (event) => {
|
|||
break;
|
||||
}
|
||||
case "sync": {
|
||||
const el = await thiefService.waitForElement(
|
||||
await thiefService.waitForElement(
|
||||
facebookService.selectors.collection_marketplace
|
||||
);
|
||||
console.log("Element đã xuất hiện:", el);
|
||||
|
||||
await facebookService.waitForPageReady(
|
||||
facebookService.sellingPath,
|
||||
|
|
@ -244,8 +258,6 @@ window.addEventListener("message", async (event) => {
|
|||
const response = await productApi.getProductOnLocalServer(body);
|
||||
data = response.data;
|
||||
|
||||
console.log({ data, body });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +265,6 @@ window.addEventListener("message", async (event) => {
|
|||
const response = await productApi.saveProductOnLocalServer(body);
|
||||
data = response.data;
|
||||
|
||||
console.log({ data, body });
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -268,6 +278,8 @@ window.addEventListener("message", async (event) => {
|
|||
"*"
|
||||
);
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
|
||||
window.postMessage(
|
||||
{
|
||||
type: "API_RESPONSE",
|
||||
|
|
@ -320,24 +332,24 @@ const runSync = () => {
|
|||
|
||||
// tiện ích khởi chạy sync + app
|
||||
const startApp = () => {
|
||||
runSync();
|
||||
// runSync();
|
||||
injectApp();
|
||||
};
|
||||
|
||||
if (window.location.href.includes(facebookService.sellingPath)) {
|
||||
try {
|
||||
await delayRD(800, 1000);
|
||||
// if (window.location.href.includes(facebookService.sellingPath)) {
|
||||
// try {
|
||||
// await delayRD(800, 1000);
|
||||
|
||||
const el = await thiefService.waitForElement(
|
||||
facebookService.selectors.collection_marketplace
|
||||
);
|
||||
console.log("Element đã xuất hiện:", el);
|
||||
// const el = await thiefService.waitForElement(
|
||||
// facebookService.selectors.collection_marketplace
|
||||
// );
|
||||
// console.log("Element đã xuất hiện:", el);
|
||||
|
||||
await delayRD(800, 1000);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
// await delayRD(800, 1000);
|
||||
// } catch (err) {
|
||||
// console.error(err);
|
||||
// }
|
||||
// }
|
||||
|
||||
startApp();
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import { productApi } from "@/api/product-api.service";
|
|||
import { mapToIPost, type IPost } from "@/lib/utils";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
|
||||
const useActionPostMutation = () => {
|
||||
const useActionPostMutation = (options?: { onSetted: () => void }) => {
|
||||
return useMutation({
|
||||
mutationKey: ["action-mutaions"],
|
||||
mutationFn: async (data: IPost) => {
|
||||
if (data.status) {
|
||||
if (data.listedProducts?.length) {
|
||||
return productApi.apiRequest("unlist", data);
|
||||
}
|
||||
|
||||
|
|
@ -28,6 +28,9 @@ const useActionPostMutation = () => {
|
|||
images: mapToIPost({ ...(res as any)?.data }).images,
|
||||
});
|
||||
},
|
||||
onSettled() {
|
||||
options?.onSetted?.();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ export interface IPost {
|
|||
raw_condition?: string;
|
||||
base64Images?: string[];
|
||||
mapped?: boolean;
|
||||
listedProducts?: { id: string }[] | null;
|
||||
ebayListingId: string;
|
||||
}
|
||||
|
||||
export interface ISyncItem {
|
||||
|
|
@ -90,5 +92,15 @@ export function mapToIPost(raw: any): IPost {
|
|||
publist_id: raw?.listingId,
|
||||
raw_condition: raw?.condition,
|
||||
mapped: true,
|
||||
listedProducts: raw?.listedProducts || null,
|
||||
ebayListingId: raw?.ebayListingId,
|
||||
};
|
||||
}
|
||||
|
||||
export async function hashInfo(info: any) {
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(JSON.stringify(info));
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ import {
|
|||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import type { Noti } from "@/content/content";
|
||||
import { removeFalsyValues } from "@/features/app";
|
||||
import { delay, removeFalsyValues } from "@/features/app";
|
||||
import useActionPostMutation from "@/hooks/use-action-post-mutation";
|
||||
import { useShadowPortal } from "@/hooks/use-shadow-portal";
|
||||
import { mapToIPost, type IPost } from "@/lib/utils";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
|
|
@ -35,6 +35,7 @@ import {
|
|||
Eye,
|
||||
EyeOff,
|
||||
MoreHorizontal,
|
||||
RefreshCcw,
|
||||
Search,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
|
|
@ -58,35 +59,38 @@ export default function Popup() {
|
|||
);
|
||||
|
||||
// --- React Query fetch ---
|
||||
const { data: rawProducts, isFetching } = useQuery({
|
||||
const {
|
||||
data: rawProducts,
|
||||
isFetching,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey,
|
||||
queryFn: async () => {
|
||||
await delay(300);
|
||||
|
||||
const data = await productApi.apiRequest(
|
||||
"index",
|
||||
removeFalsyValues({
|
||||
skip: (currentPage - 1) * productApi.item_per_page,
|
||||
where: {
|
||||
productModelCode: searchTerm,
|
||||
status_listing:
|
||||
filter?.statusFilter === "all" ? undefined : filter.statusFilter,
|
||||
},
|
||||
page: currentPage,
|
||||
search: searchTerm,
|
||||
["filter.status"]: filter.statusFilter || undefined,
|
||||
})
|
||||
);
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
const { data: publistedProducts } = useQuery({
|
||||
queryKey: ["publised-products"],
|
||||
queryFn: async () => {
|
||||
const data = await productApi.apiRequest("getPublistedProducts", {});
|
||||
return data ?? [];
|
||||
},
|
||||
staleTime: 0, // luôn coi là stale -> gọi lại API mỗi lần mount
|
||||
refetchOnMount: "always",
|
||||
});
|
||||
// const { data: publistedProducts } = useQuery({
|
||||
// queryKey: ["publised-products"],
|
||||
// queryFn: async () => {
|
||||
// const data = await productApi.apiRequest("getPublistedProducts", {});
|
||||
// return data ?? [];
|
||||
// },
|
||||
// staleTime: 0, // luôn coi là stale -> gọi lại API mỗi lần mount
|
||||
// refetchOnMount: "always",
|
||||
// });
|
||||
|
||||
const actionMutation = useActionPostMutation();
|
||||
const actionMutation = useActionPostMutation({ onSetted: refetch });
|
||||
|
||||
const data: IPost[] = useMemo(() => {
|
||||
if (!rawProducts || !(rawProducts as any)?.data) return [];
|
||||
|
|
@ -119,17 +123,6 @@ export default function Popup() {
|
|||
// --- reset page when filter changes ---
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
const from = useMemo(() => {
|
||||
return (currentPage - 1) * productApi.item_per_page + 1;
|
||||
}, [currentPage]);
|
||||
|
||||
const to = useMemo(() => {
|
||||
return Math.min(
|
||||
currentPage * productApi.item_per_page,
|
||||
(rawProducts as any)?.total ?? 0
|
||||
);
|
||||
}, [currentPage, rawProducts]);
|
||||
|
||||
const handleActionListing = async (data: IPost) => {
|
||||
actionMutation.mutate(data);
|
||||
};
|
||||
|
|
@ -179,6 +172,7 @@ export default function Popup() {
|
|||
}
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<TrigerOpenModal />
|
||||
|
|
@ -201,17 +195,48 @@ export default function Popup() {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<ImprovedToggleFilter
|
||||
filter={filter as any}
|
||||
setFilter={setFilter}
|
||||
activeFiltersCount={activeFiltersCount}
|
||||
clearFilters={clearFilters}
|
||||
/>
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<div className="w-full flex items-center justify-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 w-8 p-0 mx-auto"
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
container={portalContainer as Element}
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuItem
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onClick={() => refetch()}
|
||||
>
|
||||
<RefreshCcw className="h-4 w-4 mr-2" /> Refresh
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between w-full gap-8">
|
||||
<span>
|
||||
Showing {from}-{to} of {(rawProducts as any)?.total ?? 0} products
|
||||
Showing {(rawProducts as any)?.from}-{(rawProducts as any)?.to} of{" "}
|
||||
{(rawProducts as any)?.total ?? 0} products
|
||||
</span>
|
||||
{totalPages > 1 && (
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
|
|
@ -320,7 +345,12 @@ export default function Popup() {
|
|||
</div>
|
||||
|
||||
<div className="rounded-md border overflow-x-auto relative">
|
||||
<ScrollArea className="h-[66vh] w-full">
|
||||
<ScrollArea className="h-[66vh] w-full relative">
|
||||
{isFetching && (
|
||||
<div className="h-full flex items-center justify-center w-full absolute inset-0 bg-[rgba(0,0,0,.1)] z-20 ">
|
||||
<Loader size="size-6" />
|
||||
</div>
|
||||
)}
|
||||
<Table className="h-fit">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
|
@ -334,19 +364,6 @@ export default function Popup() {
|
|||
</TableHeader>
|
||||
|
||||
<TableBody className="relative">
|
||||
{isFetching && (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={10}
|
||||
className="text-center py-8 text-muted-foreground "
|
||||
>
|
||||
<div className="h-full flex items-center justify-center w-full">
|
||||
<Loader />
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
||||
{data.length === 0 && !isFetching ? (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
|
|
@ -360,12 +377,6 @@ export default function Popup() {
|
|||
</TableRow>
|
||||
) : (
|
||||
data.map((post) => {
|
||||
const status = (publistedProducts as any)?.some(
|
||||
(item: any) => item.title.includes(post.sku)
|
||||
);
|
||||
|
||||
post.status = status;
|
||||
|
||||
return (
|
||||
<TableRow key={post.id}>
|
||||
<TableCell className="font-medium">
|
||||
|
|
@ -387,7 +398,9 @@ export default function Popup() {
|
|||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="secondary">
|
||||
{post?.status ? "Listed" : "Unlisted"}
|
||||
{post?.listedProducts?.length
|
||||
? "Listed"
|
||||
: "Unlisted"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
|
||||
|
|
@ -421,12 +434,14 @@ export default function Popup() {
|
|||
<DropdownMenuItem
|
||||
onClick={() => handleActionListing(post)}
|
||||
>
|
||||
{post.status ? (
|
||||
{post.listedProducts?.length ? (
|
||||
<EyeOff className="h-4 w-4 mr-2" />
|
||||
) : (
|
||||
<Eye className="h-4 w-4 mr-2" />
|
||||
)}
|
||||
{post.status ? "Unlist" : "List"}
|
||||
{post.listedProducts?.length
|
||||
? "Unlist"
|
||||
: "List"}
|
||||
|
||||
{/* {actionMutation.isPending && <Loader />} */}
|
||||
</DropdownMenuItem>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { delay, delayRD } from "@/features/app";
|
||||
import type { IPost, ISyncItem } from "@/lib/utils";
|
||||
import { thiefService } from "./thief.service";
|
||||
import { productApi } from "@/api/product-api.service";
|
||||
|
||||
class FacebookService {
|
||||
sellingPath = "https://www.facebook.com/marketplace/you/selling";
|
||||
|
|
@ -266,10 +267,18 @@ class FacebookService {
|
|||
|
||||
await this.clickNext();
|
||||
|
||||
// await delayRD(300, 500);
|
||||
await delayRD(300, 500);
|
||||
|
||||
// await this.clickPublist();
|
||||
|
||||
console.log({ abc: document?.querySelector('[aria-label="Publish"]') });
|
||||
|
||||
document
|
||||
?.querySelector('[aria-label="Publish"]')
|
||||
?.addEventListener("click", async () => {
|
||||
await productApi.publish(item);
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -541,7 +550,7 @@ class FacebookService {
|
|||
closeBtnModalFeedback?.click();
|
||||
|
||||
// Gọi API backend để đánh dấu sản phẩm đã xóa (published = false)
|
||||
// await productApi.finistDelete(payload, { published: false });
|
||||
await productApi.unlist(payload);
|
||||
|
||||
// Gửi message đến background/content script thông báo là delete đã xong
|
||||
chrome.runtime.sendMessage({ type: "delete-done" });
|
||||
|
|
|
|||
Loading…
Reference in New Issue