remove freight-web from main
This commit is contained in:
2
packages/freight-web/.gitignore
vendored
2
packages/freight-web/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
*.env
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
build/
|
|
||||||
coverage/
|
|
||||||
*.min.js
|
|
||||||
*.min.css
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"useTabs": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"printWidth": 100,
|
|
||||||
"tabWidth": 4,
|
|
||||||
"plugins": ["@ripple-ts/prettier-plugin"]
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
# Ripple Basic Template
|
|
||||||
|
|
||||||
A minimal Ripple application template with TypeScript and Vite.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
1. Install dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install # or pnpm or yarn
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Start the development server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Build for production:
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Code Formatting
|
|
||||||
|
|
||||||
This template includes Prettier with the Ripple plugin for consistent code formatting.
|
|
||||||
|
|
||||||
### Available Commands
|
|
||||||
|
|
||||||
- `npm run format` - Format all files
|
|
||||||
- `npm run format:check` - Check if files are formatted correctly
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
Prettier is configured in `.prettierrc` with the following settings:
|
|
||||||
|
|
||||||
- Uses tabs for indentation
|
|
||||||
- Single quotes for strings
|
|
||||||
- 100 character line width
|
|
||||||
- Includes the `@ripple-ts/prettier-plugin` for `.ripple` file formatting
|
|
||||||
|
|
||||||
### VS Code Integration
|
|
||||||
|
|
||||||
For the best development experience, install the [Prettier VS Code extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) and the [Ripple VS Code extension](https://marketplace.visualstudio.com/items?itemName=ripple-ts.vscode-plugin).
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
- [Ripple Documentation](https://github.com/Ripple-TS/ripple)
|
|
||||||
- [Vite Documentation](https://vitejs.dev/)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import ripple from '@ripple-ts/eslint-plugin';
|
|
||||||
|
|
||||||
export default [...ripple.configs.recommended];
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
|
|
||||||
<link
|
|
||||||
href="https://cdn.jsdelivr.net/npm/beercss@3.12.13/dist/cdn/beer.min.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="module"
|
|
||||||
src="https://cdn.jsdelivr.net/npm/beercss@3.12.13/dist/cdn/beer.min.js"
|
|
||||||
></script>
|
|
||||||
<!-- <script
|
|
||||||
type="module"
|
|
||||||
src="https://cdn.jsdelivr.net/npm/material-dynamic-colors@1.1.2/dist/cdn/material-dynamic-colors.min.js"
|
|
||||||
></script> -->
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/css"
|
|
||||||
href="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.1/src/regular/style.css"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
type="text/css"
|
|
||||||
href="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.1/src/fill/style.css"
|
|
||||||
/>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/src/assets/global.css" />
|
|
||||||
<title>Ripple App</title>
|
|
||||||
</head>
|
|
||||||
<body id="root">
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<script src="/src/index.ts" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "freight-web",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A Ripple application created with create-ripple",
|
|
||||||
"type": "module",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "vite",
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"lint": "eslint .",
|
|
||||||
"serve": "vite preview",
|
|
||||||
"format": "prettier --write .",
|
|
||||||
"format:check": "prettier --check ."
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint": "^9.0.0",
|
|
||||||
"@ripple-ts/eslint-plugin": "latest",
|
|
||||||
"prettier": "^3.6.2",
|
|
||||||
"@ripple-ts/prettier-plugin": "latest",
|
|
||||||
"typescript": "^5.9.2",
|
|
||||||
"vite": "^7.1.4",
|
|
||||||
"@ripple-ts/vite-plugin": "latest",
|
|
||||||
"@ripple-ts/typescript-plugin": "latest"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"lucide-ripple": "^0.0.6",
|
|
||||||
"ripple": "latest",
|
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
|
||||||
"@star-kitten/eve": "workspace:^0.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { track } from 'ripple';
|
|
||||||
import { Quoute } from './components/calculator/Quoute.ripple';
|
|
||||||
import { Header } from './components/Header.ripple';
|
|
||||||
import { Footer } from './components/Footer.ripple';
|
|
||||||
|
|
||||||
export component App() {
|
|
||||||
<Header />
|
|
||||||
<main class="responsive">
|
|
||||||
<div class="grid">
|
|
||||||
<div class="s8">
|
|
||||||
<Quoute />
|
|
||||||
</div>
|
|
||||||
<div class="s4">
|
|
||||||
<article class="border medium no-padding center-align middle-align">
|
|
||||||
<div class="padding">
|
|
||||||
<h5>{'Placeholder Contract Info'}</h5>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<Footer />
|
|
||||||
|
|
||||||
<style>
|
|
||||||
main.responsive {
|
|
||||||
max-inline-size: min(150vw, 100rem);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,39 +0,0 @@
|
|||||||
:root,
|
|
||||||
body.dark {
|
|
||||||
--primary: #78dc77;
|
|
||||||
--on-primary: #00390a;
|
|
||||||
--primary-container: #005313;
|
|
||||||
--on-primary-container: #94f990;
|
|
||||||
--secondary: #baccb3;
|
|
||||||
--on-secondary: #253423;
|
|
||||||
--secondary-container: #3b4b38;
|
|
||||||
--on-secondary-container: #d5e8cf;
|
|
||||||
--tertiary: #a0cfd4;
|
|
||||||
--on-tertiary: #00363b;
|
|
||||||
--tertiary-container: #1f4d52;
|
|
||||||
--on-tertiary-container: #bcebf0;
|
|
||||||
--error: #ffb4ab;
|
|
||||||
--on-error: #690005;
|
|
||||||
--error-container: #93000a;
|
|
||||||
--on-error-container: #ffb4ab;
|
|
||||||
--background: #1a1c19;
|
|
||||||
--on-background: #e2e3dd;
|
|
||||||
--surface: #121411;
|
|
||||||
--on-surface: #e2e3dd;
|
|
||||||
--surface-variant: #424940;
|
|
||||||
--on-surface-variant: #c2c9bd;
|
|
||||||
--outline: #8c9388;
|
|
||||||
--outline-variant: #424940;
|
|
||||||
--shadow: #000000;
|
|
||||||
--scrim: #000000;
|
|
||||||
--inverse-surface: #e2e3dd;
|
|
||||||
--inverse-on-surface: #2f312d;
|
|
||||||
--inverse-primary: #006e1c;
|
|
||||||
--surface-dim: #121411;
|
|
||||||
--surface-bright: #383a36;
|
|
||||||
--surface-container-lowest: #0c0f0c;
|
|
||||||
--surface-container-low: #1a1c19;
|
|
||||||
--surface-container: #1e201d;
|
|
||||||
--surface-container-high: #282b27;
|
|
||||||
--surface-container-highest: #333531;
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
@@ -1,5 +0,0 @@
|
|||||||
export component Footer() {
|
|
||||||
<footer>
|
|
||||||
<p>{'© 2025 Asgard Logistics'}</p>
|
|
||||||
</footer>
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
export component Header() {
|
|
||||||
<header class="secondary-container">
|
|
||||||
<nav>
|
|
||||||
<button class="circle transparent">
|
|
||||||
<i>{'rocket_launch'}</i>
|
|
||||||
</button>
|
|
||||||
<h3 class="max left-align">{'Asgard Logistics'}</h3>
|
|
||||||
<a href="#" class="active">{'Freight Calculator'}</a>
|
|
||||||
<a href="#">{'View Rates'}</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
import { track, effect } from 'ripple';
|
|
||||||
import { Icon } from '../core/Icon.ripple';
|
|
||||||
import { RouteSelect } from './RouteSelect.ripple';
|
|
||||||
import { formatNumber } from '../../lib/utils';
|
|
||||||
import { fetchRoutes, type Route } from '../../lib/route';
|
|
||||||
import { RouteDetails } from './RouteDetals.ripple';
|
|
||||||
import { janice } from '@star-kitten/eve/third-party';
|
|
||||||
|
|
||||||
export component Quoute() {
|
|
||||||
const routes = #[] as TrackedArray<Route>;
|
|
||||||
let rush = track(false);
|
|
||||||
let cargo = track('');
|
|
||||||
|
|
||||||
effect(async () => {
|
|
||||||
const fetchedRoutes = await fetchRoutes();
|
|
||||||
routes.push(...fetchedRoutes);
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectedRouteId = track(-1);
|
|
||||||
const selectedRoute = track(() => {
|
|
||||||
return routes.find((r) => r.id === @selectedRouteId);
|
|
||||||
});
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<header>
|
|
||||||
<h4>
|
|
||||||
<i>{'calculate'}</i>
|
|
||||||
{' Freight Calculator'}
|
|
||||||
</h4>
|
|
||||||
</header>
|
|
||||||
<section>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'1. Select a route'}</legend>
|
|
||||||
<RouteSelect {@routes} onChange={(id) => (@selectedRouteId = id)} />
|
|
||||||
if (@selectedRoute) {
|
|
||||||
<RouteDetails route={@selectedRoute} />
|
|
||||||
}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'2. Add cargo'}</legend>
|
|
||||||
<div class="field border label textarea extra">
|
|
||||||
<textarea onChange={(e) => (@cargo = (e.target as HTMLTextArea).value)} />
|
|
||||||
<label>
|
|
||||||
{`Paste your cargo here... (one item per line, e.g. Tritanium 10000)`}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'3. Apply adjustments (optional)'}</legend>
|
|
||||||
<div class="field middle-align">
|
|
||||||
<nav>
|
|
||||||
<div class="max">
|
|
||||||
<h6>{'Add Rush Shipping'}</h6>
|
|
||||||
<span class="helper">
|
|
||||||
{'Guaranteed delivery within 24 hours or the entire contract is free!'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<label class="switch">
|
|
||||||
<input type="checkbox" onChange={(e) => (@rush = !@rush)} />
|
|
||||||
<span />
|
|
||||||
</label>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field suffix">
|
|
||||||
<input type="number" min="1" placeholder="Additional Volume (m³)" />
|
|
||||||
<Icon name="cube" />
|
|
||||||
<span class="helper">
|
|
||||||
{'In addition to the calculated volume from your cargo.'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="field suffix">
|
|
||||||
<input type="number" min="0" placeholder="Additional Collateral (ISK)" />
|
|
||||||
<i>{'currency_exchange'}</i>
|
|
||||||
<span class="helper">
|
|
||||||
{'In addition to the calculated value of your cargo.'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<nav>
|
|
||||||
<button class="circle small">
|
|
||||||
<i>{'done'}</i>
|
|
||||||
</button>
|
|
||||||
<div>{'Select a route'}</div>
|
|
||||||
<hr class="max" />
|
|
||||||
<button class="circle small">{'2'}</button>
|
|
||||||
<div>{'Add cargo'}</div>
|
|
||||||
<hr class="max" />
|
|
||||||
<button class="circle small" disabled>{'3'}</button>
|
|
||||||
<div>{'Apply adjustments'}</div>
|
|
||||||
<hr class="max" />
|
|
||||||
<button class="circle small" disabled>{'4'}</button>
|
|
||||||
<div>{'Calculate'}</div>
|
|
||||||
</nav>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
// Calculate quote logic goes here
|
|
||||||
<button
|
|
||||||
class="responsive large-elevate extra"
|
|
||||||
onClick={async () => {
|
|
||||||
console.log('Calculating quote...');
|
|
||||||
console.log('Selected Route ID:', @selectedRouteId);
|
|
||||||
console.log('Rush Shipping:', @rush);
|
|
||||||
console.log('Cargo:', @cargo);
|
|
||||||
const appraisal = await janice.appraiseItems(
|
|
||||||
@cargo,
|
|
||||||
2,
|
|
||||||
'DUyi5Q3Dod48IoswUBkEfNRs8Qf3cwNN',
|
|
||||||
);
|
|
||||||
console.log('Appraised Cargo:', appraisal);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{'Calculate Quote'}
|
|
||||||
</button>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
pre {
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import type { Route } from '../../lib/route';
|
|
||||||
import { formatNumber } from '../../lib/utils';
|
|
||||||
|
|
||||||
export component RouteDetails({ route }: { route: Route }) {
|
|
||||||
<div class="s12">
|
|
||||||
<fieldset>
|
|
||||||
<legend>
|
|
||||||
{'Route Details'}
|
|
||||||
</legend>
|
|
||||||
<div class="grid">
|
|
||||||
<div class="s4">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'Max Volume'}</legend>
|
|
||||||
<h6>{formatNumber(route.max_volume)}</h6>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<div class="s4">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'Min Volume'}</legend>
|
|
||||||
<h6>{formatNumber(route.min_volume || 0)}</h6>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<div class="s4">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'Restrictions'}</legend>
|
|
||||||
{'No Assembled Ships or Containers'}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<div class="s6">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'Base Price'}</legend>
|
|
||||||
<h6>{(route.isk_m3 ? formatNumber(route.isk_m3 || 0) + ' ISK/m³ + ' : route.isk_flatrate + ' ISK flatrate + ') + formatNumber(route.collat_pct) + '% of total collateral'}</h6>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<div class="s6">
|
|
||||||
<fieldset>
|
|
||||||
<legend>
|
|
||||||
{'Rush Fee '}
|
|
||||||
<i>{'warning'}</i>
|
|
||||||
<div class="tooltip top">{'Guaranteed delivery in 24 hours or your money back'}</div>
|
|
||||||
</legend>
|
|
||||||
<h6>{'+' + (route.rush_pct ? formatNumber(route.rush_pct) + '%' : route.rush_fee + ' ISK')}</h6>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import { track, type TrackedArray } from 'ripple';
|
|
||||||
import { Selector } from './Selector.ripple';
|
|
||||||
import type { Route } from '../../lib/route';
|
|
||||||
import { formatNumber } from '../../lib/utils';
|
|
||||||
|
|
||||||
export interface RouteSelectProps {
|
|
||||||
routes: TrackedArray<Route>;
|
|
||||||
onChange?: (id: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export component RouteSelect({ routes, onChange }: RouteSelectProps) {
|
|
||||||
let typeTab = track('JF');
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<nav class="tabbed small">
|
|
||||||
<a class={'JF' === @typeTab ? 'active' : ''} onClick={() => {
|
|
||||||
@typeTab = 'JF';
|
|
||||||
onChange?.('');
|
|
||||||
}}>
|
|
||||||
<i>{'rocket'}</i>
|
|
||||||
<span>{'Jump Freighter'}</span>
|
|
||||||
</a>
|
|
||||||
<a class={'DST' === @typeTab ? 'active' : ''} onClick={() => {
|
|
||||||
@typeTab = 'DST';
|
|
||||||
onChange?.('');
|
|
||||||
}}>
|
|
||||||
<i>{'pallet'}</i>
|
|
||||||
<span>{'Deep Space Transport'}</span>
|
|
||||||
</a>
|
|
||||||
<a class={'BR' === @typeTab ? 'active' : ''} onClick={() => {
|
|
||||||
@typeTab = 'BR';
|
|
||||||
onChange?.('');
|
|
||||||
}}>
|
|
||||||
<i>{'visibility_off'}</i>
|
|
||||||
<span>{'Blockade Runner'}</span>
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
<div class={'page padding' + ('JF' === @typeTab ? ' active' : '')}>
|
|
||||||
<Selector
|
|
||||||
routes={@routes.filter((r) => r.route_type === 'JF')}
|
|
||||||
onChange={(routeId: string) => {
|
|
||||||
onChange?.(routeId);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class={'page padding' + ('DST' === @typeTab ? ' active' : '')}>
|
|
||||||
<Selector
|
|
||||||
routes={@routes.filter((r) => r.route_type === 'DST')}
|
|
||||||
onChange={(routeId: string) => {
|
|
||||||
onChange?.(routeId);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class={'page padding' + ('BR' === @typeTab ? ' active' : '')}>
|
|
||||||
<Selector
|
|
||||||
routes={@routes.filter((r) => r.route_type === 'BR')}
|
|
||||||
onChange={(routeId: string) => {
|
|
||||||
onChange?.(routeId);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
import { track, type TrackedArray } from 'ripple';
|
|
||||||
import type { Route } from '../../lib/route';
|
|
||||||
import { formatNumber } from '../../lib/utils';
|
|
||||||
|
|
||||||
export interface OriginDestProps {
|
|
||||||
routes: TrackedArray<Route>;
|
|
||||||
onChange?: (routeId: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export component Selector({ routes, onChange }: OriginDestProps) {
|
|
||||||
const selectedRoute = track<Route>(undefined);
|
|
||||||
let origin = track('');
|
|
||||||
|
|
||||||
const origins = track(() => {
|
|
||||||
const uniqueOrigins = new Set<string>();
|
|
||||||
for (const route of routes) {
|
|
||||||
uniqueOrigins.add(route.origin);
|
|
||||||
}
|
|
||||||
return Array.from(uniqueOrigins);
|
|
||||||
});
|
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<div class="s6">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'Origin'}</legend>
|
|
||||||
<div class="field suffix border">
|
|
||||||
<select
|
|
||||||
onChange={(e) => {
|
|
||||||
@origin = (e.target as HTMLSelectElement).value;
|
|
||||||
@selectedRoute = undefined;
|
|
||||||
onChange?.('');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<option value="">{'Select origin'}</option>
|
|
||||||
for (const text of @origins) {
|
|
||||||
<option value={text}>{text}</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
<i>{'arrow_drop_down'}</i>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<div class="s6">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{'Destination'}</legend>
|
|
||||||
<div class="field suffix border">
|
|
||||||
<select
|
|
||||||
onChange={(e) => {
|
|
||||||
const id = (e.target as HTMLSelectElement).value;
|
|
||||||
@selectedRoute = @routes.find((r: Route) => r.id === id);
|
|
||||||
onChange?.(id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<option value="">{'Select a route'}</option>
|
|
||||||
for (const route of @routes) {
|
|
||||||
const rt = route as Route;
|
|
||||||
if (rt.origin === @origin) {
|
|
||||||
<option value={rt.id}>{rt.destination}</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
<i>{'arrow_drop_down'}</i>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.field {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
export interface IconProps {
|
|
||||||
name: string;
|
|
||||||
style?: Record<string, string | number>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export component Icon({ name, style }: IconProps) {
|
|
||||||
<i class={`ph ph-${name}`} {style} />
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { mount } from 'ripple';
|
|
||||||
// @ts-expect-error: known issue, we're working on it
|
|
||||||
import { App } from './App.ripple';
|
|
||||||
|
|
||||||
mount(App, {
|
|
||||||
target: document.getElementById('root'),
|
|
||||||
});
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
export interface Route {
|
|
||||||
id: string;
|
|
||||||
route_type: 'JF' | 'DST' | 'BR';
|
|
||||||
origin: string;
|
|
||||||
origin_type: string;
|
|
||||||
destination: string;
|
|
||||||
detination_type: string;
|
|
||||||
max_volume: number;
|
|
||||||
max_collat: string;
|
|
||||||
collat_pct: number;
|
|
||||||
isk_m3?: number;
|
|
||||||
isk_flatrate?: string;
|
|
||||||
min_volume?: number;
|
|
||||||
rush_pct?: number;
|
|
||||||
rush_fee?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchRoutes(): Promise<Route[]> {
|
|
||||||
const response = await fetch(
|
|
||||||
'https://docs.google.com/spreadsheets/d/e/2PACX-1vSuUV7yKNkgSFFLz2LSUqD4WRQ71usoRuYUMKL00HsJHz52VfgFAIkE8w2DG59V93kCkEKFlqFux-OI/pub?gid=0&single=true&output=csv'
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Failed to fetch routes: ${response.status} ${response.statusText}`);
|
|
||||||
}
|
|
||||||
const text = await response.text();
|
|
||||||
const lines = text.trim().split('\n');
|
|
||||||
const routes: Route[] = [];
|
|
||||||
const headers = lines[0].split(',').map((h) => h.trim());
|
|
||||||
for (let i = 1; i < lines.length; i++) {
|
|
||||||
const values = lines[i].split(',').map((v) => v.trim());
|
|
||||||
const row: any = {};
|
|
||||||
for (let j = 0; j < headers.length; j++) {
|
|
||||||
row[headers[j]] = values[j];
|
|
||||||
}
|
|
||||||
routes.push(row);
|
|
||||||
}
|
|
||||||
return routes;
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export function formatNumber(num: number): string {
|
|
||||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ESNext",
|
|
||||||
"module": "ESNext",
|
|
||||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"jsx": "preserve",
|
|
||||||
"jsxImportSource": "ripple",
|
|
||||||
"noEmit": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"plugins": [{ "name": "@ripple-ts/typescript-plugin" }],
|
|
||||||
"paths": {
|
|
||||||
"@*": ["./src/*"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import { defineConfig } from 'vite';
|
|
||||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
||||||
import { ripple } from '@ripple-ts/vite-plugin';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [tsconfigPaths(), ripple()],
|
|
||||||
server: {
|
|
||||||
port: 3000,
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
target: 'esnext',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user