LGTM
This commit is contained in:
@@ -14,22 +14,24 @@ jobs:
|
||||
- name: Verify Node.js
|
||||
run: node -v
|
||||
|
||||
- name: Install dependencies
|
||||
- name: Install electron-app dependencies
|
||||
working-directory: electron-app
|
||||
run: npm ci
|
||||
|
||||
- name: Build Windows executable
|
||||
- name: Create production .env file
|
||||
working-directory: electron-app
|
||||
env:
|
||||
WS_URL: ${{ secrets.WS_URL }}
|
||||
API_URL: ${{ secrets.API_URL }}
|
||||
RELEASE_URL: ${{ secrets.RELEASE_URL }}
|
||||
NODE_ENV: production
|
||||
run: npm run electron:build -- --win
|
||||
run: |
|
||||
echo "WS_URL=${{ secrets.WS_URL }}" > .env
|
||||
echo "API_URL=${{ secrets.API_URL }}" >> .env
|
||||
echo "NODE_ENV=production" >> .env
|
||||
|
||||
- name: Upload Windows artifact
|
||||
- name: Build Windows portable executable
|
||||
working-directory: electron-app
|
||||
run: npm run build:portable
|
||||
|
||||
- name: Upload Windows portable artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-exe
|
||||
path: electron-app/release/*.exe
|
||||
name: rmtPocketWatcher-Windows-Portable
|
||||
path: electron-app/release/rmtPocketWatcher-*.exe
|
||||
retention-days: 7
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# WebSocket connection URL
|
||||
WS_URL=ws://localhost:3000/ws
|
||||
|
||||
# API URL
|
||||
API_URL=http://localhost:3000
|
||||
|
||||
# Development mode
|
||||
NODE_ENV=development
|
||||
|
||||
209
electron-app/package-lock.json
generated
209
electron-app/package-lock.json
generated
@@ -27,6 +27,7 @@
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"rimraf": "^6.1.2",
|
||||
"typescript": "^5.3.0",
|
||||
"vite": "^5.0.0",
|
||||
"wait-on": "^7.2.0"
|
||||
@@ -1054,6 +1055,29 @@
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/brace-expansion": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
@@ -1327,6 +1351,23 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@npmcli/move-file/node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
@@ -2744,6 +2785,17 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
@@ -2788,6 +2840,58 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/rimraf/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/rimraf/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-lookup": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||
@@ -5943,6 +6047,23 @@
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp/node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp/node_modules/semver": {
|
||||
"version": "7.7.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||
@@ -6562,17 +6683,91 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz",
|
||||
"integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
"glob": "^13.0.0",
|
||||
"package-json-from-dist": "^1.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
"rimraf": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/glob": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz",
|
||||
"integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"minimatch": "^10.1.1",
|
||||
"minipass": "^7.1.2",
|
||||
"path-scurry": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/lru-cache": {
|
||||
"version": "11.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz",
|
||||
"integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/minimatch": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/path-scurry": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
|
||||
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
"build:main": "npx tsc --project tsconfig.main.json && npx tsc --project tsconfig.preload.json",
|
||||
"build:renderer": "npx vite build",
|
||||
"build": "npm run build:main && npm run build:renderer",
|
||||
"build:portable": "npm run build && npx electron-builder --win portable",
|
||||
"clean": "rimraf dist",
|
||||
"clean:dev": "npm run clean && npm run build:main && concurrently \"npm run dev\" \"wait-on http://localhost:5173 && cross-env NODE_ENV=development electron dist/main/index.js\"",
|
||||
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && cross-env NODE_ENV=development electron dist/main/index.js\"",
|
||||
"electron:build": "npm run build && electron-builder",
|
||||
"publish": "npm run build && electron-builder --publish always",
|
||||
"rebuild": "electron-rebuild",
|
||||
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -36,6 +38,7 @@
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"rimraf": "^6.1.2",
|
||||
"typescript": "^5.3.0",
|
||||
"vite": "^5.0.0",
|
||||
"wait-on": "^7.2.0"
|
||||
|
||||
@@ -33,6 +33,14 @@ export function initDatabase() {
|
||||
)
|
||||
`);
|
||||
|
||||
// Create settings table for custom AUEC amount
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
)
|
||||
`);
|
||||
|
||||
console.log('Database initialized at:', dbPath);
|
||||
}
|
||||
|
||||
@@ -80,6 +88,26 @@ export function deleteAlert(id: string): void {
|
||||
stmt.run(id);
|
||||
}
|
||||
|
||||
export function getCustomAuecAmount(): number | null {
|
||||
if (!db) throw new Error('Database not initialized');
|
||||
|
||||
const stmt = db.prepare('SELECT value FROM settings WHERE key = ?');
|
||||
const row = stmt.get('customAuecAmount') as any;
|
||||
|
||||
return row ? parseFloat(row.value) : null;
|
||||
}
|
||||
|
||||
export function setCustomAuecAmount(amount: number): void {
|
||||
if (!db) throw new Error('Database not initialized');
|
||||
|
||||
const stmt = db.prepare(`
|
||||
INSERT OR REPLACE INTO settings (key, value)
|
||||
VALUES (?, ?)
|
||||
`);
|
||||
|
||||
stmt.run('customAuecAmount', amount.toString());
|
||||
}
|
||||
|
||||
export function closeDatabase(): void {
|
||||
if (db) {
|
||||
db.close();
|
||||
|
||||
@@ -53,6 +53,8 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
|
||||
try { ipcMain.removeHandler('alerts:add'); } catch (e) { /* ignore */ }
|
||||
try { ipcMain.removeHandler('alerts:update'); } catch (e) { /* ignore */ }
|
||||
try { ipcMain.removeHandler('alerts:delete'); } catch (e) { /* ignore */ }
|
||||
try { ipcMain.removeHandler('settings:getCustomAuecAmount'); } catch (e) { /* ignore */ }
|
||||
try { ipcMain.removeHandler('settings:setCustomAuecAmount'); } catch (e) { /* ignore */ }
|
||||
|
||||
// IPC handlers for renderer requests
|
||||
ipcMain.handle('ws:connect', async () => {
|
||||
@@ -155,6 +157,26 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void {
|
||||
}
|
||||
});
|
||||
|
||||
// Custom AUEC amount handlers
|
||||
ipcMain.handle('settings:getCustomAuecAmount', async () => {
|
||||
try {
|
||||
return db.getCustomAuecAmount();
|
||||
} catch (error) {
|
||||
console.error('Failed to get custom AUEC amount:', error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:setCustomAuecAmount', async (_event, amount: number) => {
|
||||
try {
|
||||
db.setCustomAuecAmount(amount);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Failed to set custom AUEC amount:', error);
|
||||
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
|
||||
}
|
||||
});
|
||||
|
||||
// Auto-connect on startup
|
||||
wsClient.connect();
|
||||
}
|
||||
@@ -181,6 +203,8 @@ export function cleanupIpcHandlers(): void {
|
||||
ipcMain.removeHandler('alerts:add');
|
||||
ipcMain.removeHandler('alerts:update');
|
||||
ipcMain.removeHandler('alerts:delete');
|
||||
ipcMain.removeHandler('settings:getCustomAuecAmount');
|
||||
ipcMain.removeHandler('settings:setCustomAuecAmount');
|
||||
} catch (error) {
|
||||
// Handlers may not exist, ignore
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ export function App() {
|
||||
const [alertNotification, setAlertNotification] = useState<AlertNotification | null>(null);
|
||||
const alertAudioRef = useRef<HTMLAudioElement | null>(null);
|
||||
|
||||
// Custom AUEC Amount State
|
||||
const [customAuecAmount, setCustomAuecAmount] = useState<number | null>(null);
|
||||
const [customAuecInput, setCustomAuecInput] = useState('');
|
||||
|
||||
// Load alerts from database on mount
|
||||
useEffect(() => {
|
||||
const loadAlerts = async () => {
|
||||
@@ -65,6 +69,22 @@ export function App() {
|
||||
loadAlerts();
|
||||
}, []);
|
||||
|
||||
// Load custom AUEC amount from database on mount
|
||||
useEffect(() => {
|
||||
const loadCustomAmount = async () => {
|
||||
try {
|
||||
const amount = await window.electron.ipcRenderer.invoke('settings:getCustomAuecAmount');
|
||||
if (amount) {
|
||||
setCustomAuecAmount(amount);
|
||||
setCustomAuecInput(amount.toString());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load custom AUEC amount:', error);
|
||||
}
|
||||
};
|
||||
loadCustomAmount();
|
||||
}, []);
|
||||
|
||||
// Fetch initial data on mount
|
||||
useEffect(() => {
|
||||
fetchInitialData();
|
||||
@@ -374,6 +394,21 @@ export function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const saveCustomAuecAmount = async () => {
|
||||
const amount = parseFloat(customAuecInput);
|
||||
if (isNaN(amount) || amount <= 0) {
|
||||
alert('Please enter a valid AUEC amount');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await window.electron.ipcRenderer.invoke('settings:setCustomAuecAmount', amount);
|
||||
setCustomAuecAmount(amount);
|
||||
} catch (error) {
|
||||
console.error('Failed to save custom AUEC amount:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const dismissNotification = () => {
|
||||
setAlertNotification(null);
|
||||
};
|
||||
@@ -769,7 +804,41 @@ export function App() {
|
||||
|
||||
{latestPrice && (
|
||||
<div style={{ backgroundColor: '#1a1f3a', padding: '20px', borderRadius: '8px' }}>
|
||||
<h2 style={{ margin: '0 0 15px 0' }}>Current Listings ({latestPrice.allPrices.length})</h2>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '15px' }}>
|
||||
<h2 style={{ margin: 0 }}>Current Listings ({latestPrice.allPrices.length})</h2>
|
||||
<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="Enter AUEC amount"
|
||||
value={customAuecInput}
|
||||
onChange={(e) => setCustomAuecInput(e.target.value)}
|
||||
style={{
|
||||
padding: '8px 12px',
|
||||
backgroundColor: '#0a0e27',
|
||||
border: '1px solid #2a2f4a',
|
||||
borderRadius: '4px',
|
||||
color: '#fff',
|
||||
fontSize: '14px',
|
||||
width: '180px',
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
onClick={saveCustomAuecAmount}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#50e3c2',
|
||||
color: '#0a0e27',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px',
|
||||
}}
|
||||
>
|
||||
Set Amount
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{
|
||||
overflowX: 'auto',
|
||||
overflowY: 'auto',
|
||||
@@ -783,16 +852,28 @@ export function App() {
|
||||
<th style={{ textAlign: 'left', padding: '12px', color: '#888', fontWeight: 'normal' }}>Platform</th>
|
||||
<th style={{ textAlign: 'left', padding: '12px', color: '#888', fontWeight: 'normal' }}>Seller</th>
|
||||
<th style={{ textAlign: 'right', padding: '12px', color: '#888', fontWeight: 'normal' }}>Price/1M AUEC</th>
|
||||
{customAuecAmount && (
|
||||
<th style={{ textAlign: 'right', padding: '12px', color: '#888', fontWeight: 'normal' }}>
|
||||
Price for {(customAuecAmount / 1000000).toLocaleString()}M AUEC
|
||||
</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{latestPrice.allPrices.map((price) => (
|
||||
{[...latestPrice.allPrices]
|
||||
.sort((a, b) => a.pricePerMillion - b.pricePerMillion)
|
||||
.map((price) => (
|
||||
<tr key={price.id} style={{ borderBottom: '1px solid #2a2f4a' }}>
|
||||
<td style={{ padding: '12px' }}>{price.platform}</td>
|
||||
<td style={{ padding: '12px' }}>{price.sellerName}</td>
|
||||
<td style={{ textAlign: 'right', padding: '12px', color: '#50e3c2', fontWeight: 'bold' }}>
|
||||
${price.pricePerMillion.toFixed(9)}
|
||||
</td>
|
||||
{customAuecAmount && (
|
||||
<td style={{ textAlign: 'right', padding: '12px', color: '#50e3c2', fontWeight: 'bold' }}>
|
||||
${((price.pricePerMillion * customAuecAmount) / 1000000).toFixed(2)}
|
||||
</td>
|
||||
)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user