moved website content to root

This commit is contained in:
2026-01-11 15:53:42 -07:00
parent 23f527b769
commit 4e10921fd8
40 changed files with 92 additions and 5 deletions
@@ -0,0 +1,126 @@
{{/* TODO: make the save button disabled based on an api call */}}
{{/* .Identity.Account.AccountID, .Accounts */}}
{{- $dot := or .dot . -}}
{{- $acctID := $dot.Identity.Account.AccountID }}
{{- $orderIndex := or $dot.OrderIndex (parseInt $dot.PathParams.orderIndex) -}}
{{- $entry := $dot.Accounts.GetSyncGroupListingDraft $acctID $orderIndex }}
{{- $selectedShopPlatform := $entry.Platform }}
{{- $selectedShopID := $entry.ShopID }}
{{- $selectedListingID := $entry.ListingID }}
<tr _="
init
set @data-filled-out to false
def setFilledOut(val)
set @data-filled-out to val
send rowUpdated() to closest <tbody/>
end
on setListing(listing)
call setFilledOut(true)
on resetListing
call setFilledOut(false)
"
>
<td>
{{- $shops := $dot.Accounts.GetShops $acctID -}}
<select
class="min-w-fit cursor-pointer"
hx-put="/accounts/{{$acctID}}/inventory/sync-groups/draft/listings/{{$orderIndex}}/shop"
hx-vals='js:{
platform: event.target.value.replace(/-[^ ]*/, ""),
"shop-id": event.target.value.replace(/[^ ]*-/, "")
}'
hx-target="closest tr"
hx-swap="outerHTML"
_="
on change
send resetListing() to closest <tr/>
"
>
<option disabled {{- if not $selectedShopID }}selected{{- end }}>- Shops -</option>
{{- range $shop := $shops }}
{{- $isSelectedShop := and
(eq $selectedShopPlatform $shop.Platform)
(eq $selectedShopID $shop.ShopID)
}}
<option
value="{{$shop.Platform}}-{{$shop.ShopID}}"
{{- if $isSelectedShop }}selected{{- end }}
>
{{ $shop.Name }} - {{$shop.Platform}} - {{$shop.ShopID}}
</option>
{{- end }}
</select>
</td>
<td>
{{- $selectedListing := "" }}
{{- if $selectedShopID }}
{{- $listings := $dot.Accounts.GetListingsForShop $acctID $selectedShopPlatform $selectedShopID }}
{{- if $listings }}
<select
class="min-w-fit cursor-pointer"
hx-put="/accounts/{{$acctID}}/inventory/sync-groups/draft/listings/{{$orderIndex}}/listing"
hx-vals='js:{
"listing-id": event.target.value,
}'
hx-target="closest tr"
hx-swap="outerHTML"
_="
on input
set dataset to (my selectedOptions)[0].dataset
send setListing(listing: dataset) to the closest <tr/>
"
>
<option disabled {{if not $selectedListingID}}selected{{end}}>- Listings -</option>
{{- range $i, $listing := $listings }}
{{- if eq $selectedListingID $listing.ListingID }}
{{ $selectedListing = $listing }}
{{- end }}
<option
value="{{$listing.ListingID}}"
{{if eq $selectedListingID $listing.ListingID}}selected{{end}}
data-name="{{ $listing.Name }}"
data-sku="{{ $listing.SKU }}"
data-description="{{ $listing.Description }}"
data-count="{{ $listing.Count }}"
>
{{ $listing.Name }}
</option>
{{- end }}
</select>
{{- else }}
no listings found
{{- end }}
{{- else }}
-
{{- end }}
</td>
<td data-id="sku">
{{if $selectedListing}}{{$selectedListing.SKU}}{{else}}-{{end}}
</td>
<td data-id="description">
{{if $selectedListing}}{{$selectedListing.Description}}{{else}}-{{end}}
</td>
<td data-id="remove">
{{ componentBody "button-dev"
"HXDelete" (printf "/accounts/%d/inventory/sync-groups/draft/listings/%d" $acctID $orderIndex)
"HXTarget" "closest tr"
"HXSwap" "outerHTML"
"Text" "Remove"
}}
</td>
</tr>
@@ -0,0 +1,88 @@
{{- $dot := or .dot . }}
{{- .Auth.ByMatchingAccountID 2 }}
{{- $acctID := 0 }}
{{- if $dot.Identity }}
{{- $acctID = $dot.Identity.Account.AccountID }}
{{- else if .PathParams }}
{{- $acctID = $dot.PathParams.acctID | parseInt64 }}
{{- else }}
{{- $acctID = $dot.AccountID }}
{{- end }}
{{- $stores := $dot.Accounts.GetShops $acctID -}}
<table id="inventory-table-2" class="max-w-full overflow-x-auto">
<thead>
<tr>
<th>
Shop
</th>
<th>
Listing
</th>
<th>
SKU
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</thead>
<tbody
_="
init
set element allRowsFilledOut to false
set element numRows to 0
def checkIfAllRowsAreFilledOut()
set rows to my children
set element allRowsFilledOut to true
set element numRows to rows.length
for row in rows
set filledOut to row.dataset.filledOut is 'true'
if not filledOut then
set element allRowsFilledOut to false
break
end
end
end
on rowUpdated
checkIfAllRowsAreFilledOut()
send setDisabled(disabled: not allRowsFilledOut or numRows < 2) to #create-sync-group-button
"
>
{{- $listings := $dot.Accounts.GetSyncGroupListingDrafts $acctID }}
{{- range $i, $listing := $listings }}
{{- componentBody "accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}"
"dot" ($dot | addPathParam "orderIndex" $i)
}}
{{- end }}
</tbody>
<tfoot>
<tr>
<th>
Shop
</th>
<th>
Listing
</th>
<th>
SKU
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</tfoot>
</table>
@@ -0,0 +1,46 @@
{{- $dot := or .dot . }}
{{- $dot.Auth.ByMatchingAccountID 2 }}
{{- $acctID := $dot.Identity.Account.AccountID }}
{{- $stores := $dot.Accounts.GetShops $acctID -}}
<table id="inventory-table" class="max-w-full overflow-x-scroll">
<thead>
<tr>
{{- range $store := $stores }}
<th class="text-nowrap">
{{ $store.Platform }}: {{ $store.Name }}
</th>
<th class="text-nowrap">
Count
</th>
{{- end }}
<th>
</th>
</tr>
</thead>
<tbody>
{{- componentBody "accounts/{acctID}/inventory/sync-table/new-row" "dot" $dot }}
</tbody>
<tfoot>
<tr>
{{- range $store := $stores }}
<th class="text-nowrap">
{{ $store.Platform }}: {{ $store.Name }}
</th>
<th class="text-nowrap">
Count
</th>
{{- end }}
<th>
</th>
</tr>
</tfoot>
</table>
@@ -0,0 +1,55 @@
{{/* TODO: delete when done with the newer draft */}}
{{- $dot := or .dot .}}
{{- $dot.Auth.ByMatchingAccountID 2 }}
{{- $acctID := $dot.Identity.Account.AccountID }}
{{- $shops := $dot.Accounts.GetShops $acctID -}}
<tr>
{{- range $shop := $shops }}
<td>
<select
class="min-w-fit cursor-pointer"
_="
on change
set dataset to the dataset of the first of my selectedOptions
set listingShowcase to the <#listing-showcase/>
if <#listing-showcase/> then
send displayListing(
id: dataset.id,
name: dataset.name,
description: dataset.description,
count: dataset.count
) to listingShowcase
end
set the innerHTML of the next <td/> to the dataset.count
"
>
<option disabled selected>- Listings -</option>
{{/*- $listings := $dot.Accounts.GetListingsForShop $acctID $shop.ShopID }}
{{- range $listing := $listings }}
<option
value="{{$listing.ListingID}}"
data-id="{{$listing.ListingID}}"
data-name="{{$listing.Name}}"
data-description="{{$listing.Description}}"
data-count="{{$listing.Count}}"
>
{{ $listing.Name }}
</option>
{{- end */}}
</select>
</td>
<td>
</td>
{{- end }}
<td>
<button class="cursor-pointer underline w-full">
Save
</button>
</td>
</tr>
@@ -0,0 +1,40 @@
<table class="max-w-full"
id="listing-showcase"
_="
on displayListing(id, name, description, count)
set innerHTML of <#listing-showcase-id/> to id
set innerHTML of <#listing-showcase-name/> to name
set innerHTML of <#listing-showcase-description/> to description
set innerHTML of <#listing-showcase-count/> to count
"
>
<thead>
<th>
ID
</th>
<th>
Name
</th>
<th>
Description
</th>
<th>
Count
</th>
</thead>
<tbody>
<th id="listing-showcase-id">
-
</th>
<th id="listing-showcase-name">
-
</th>
<th id="listing-showcase-description">
-
</th>
<th id="listing-showcase-count">
-
</th>
</tbody>
</table>
@@ -0,0 +1,45 @@
{{/* .HXGet | .HXPost | .HXDelete, .HXTarget, .HXSwap, .HXVals, ._, .Text, .ID, .Class, .Disabled */}}
<button
class="
border-thin
bg-card
rounded-sm
p-[0.5em]
font-semibold
cursor-pointer
hover:underline
hover:bg-accent
disabled:bg-accent-secondary
disabled:cursor-not-allowed
disabled:no-underline
{{.Class}}
"
{{- if .ID }}
id="{{.ID}}"
{{- end }}
{{- if .HXGet }}
hx-get="{{.HXGet}}"
{{- else if .HXPost }}
hx-post="{{.HXPost}}"
{{- else if .HXDelete }}
hx-delete="{{.HXDelete}}"
{{- end }}
{{- if .HXTarget }}
hx-target="{{.HXTarget}}"
{{- end }}
{{- if .HXSwap }}
hx-swap="{{.HXSwap}}"
{{- end }}
{{- if .HXVals }}
hx-vals="{{.HXVals}}"
{{- end }}
{{- if .Disabled}}
disabled
{{- end}}
{{- if ._ }}
_="{{ ._ }}"
{{- end }}
>
{{.Text}}
</button>
@@ -0,0 +1,70 @@
{{/* TODO: delete, once not needed */}}
{{/* "dot" . */}}
<nav
style="
margin: 0;
padding: 1em;
background-color: #bdf;
font-size: 1.25em;
display: flex;
flex-direction: column;
align-items: center;
"
>
<ul>
<li>
<a href="/">
Home
</a>
</li>
{{/* */}}
{{- $userID := .dot.Identity.User.UserID }}
{{- $acct := .dot.Identity.Account }}
{{- $acctID := 0 }}
{{- if $acct }}
{{- $acctID = $acct.AccountID }}
{{- end }}
{{- if not $userID }}
<li>
<a href="/login">
Log In / Sign Up
</a>
</li>
{{- else if $acctID }}
<li>
<a href="/accounts/{{$acctID}}">
Account
</a>
</li>
<li>
<a href="/accounts/{{$acctID}}/reports">
Reports
</a>
</li>
<li>
<a href="/accounts/{{$acctID}}/inventory">
Inventory
</a>
</li>
<li>
<a href="/logout">
Log Out
</a>
</li>
{{- end }}
</ul>
</nav>
+91
View File
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html class="min-h-full flex flex-col items-stretch">
<head>
<title>
{{ block "title" . }} Inventory++ {{ end }}
</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="stylesheet" href="/styles/index.css">
<script src="/scripts/htmx.min.js.gz"></script>
<script src="/scripts/_hyperscript.min.js.gz"></script>
<script src="https://unpkg.com/htmx-ext-path-params@2.0.0/path-params.js"></script>
{{/* This is where the page_head template will be inserted into the page */}}
{{- block "head" . }}{{ end }}
</head>
<body class="basis-full grow bg-background flex flex-col items-stretch" hx-ext="path-params">
<header>
<nav class="flex flex-col items-center text-xl overflow-x-scroll overflow-y-hidden ">
{{- $path := or .Request.URL.Path "/" }}
<ul class="flex text-nowrap overflow-x-scroll overflow-y-hidden">
<li class="pt-[1em] pb-[1em]">
<a href="/" class="p-[1em] font-bold {{ if eq $path "/" }}selected{{ end }}">
Home
</a>
</li>
{{/* */}}
{{- $userID := .Identity.User.UserID }}
{{- $acct := .Identity.Account }}
{{- $acctID := 0 }}
{{- if $acct }}
{{- $acctID = $acct.AccountID }}
{{- end }}
{{- if not $userID }}
<li class="pt-[1em] pb-[1em]">
<a href="/login" class="p-[1em] font-bold {{ if eq $path "/login" }}selected{{ end }}">
Log In / Sign Up
</a>
</li>
{{- else if $acctID }}
<li class="pt-[1em] pb-[1em]">
<a href="/accounts/{{$acctID}}" class="p-[1em] font-bold {{ if eq $path (printf "/accounts/%d" $acctID) }}selected{{ end }}">
Account
</a>
</li>
<li class="pt-[1em] pb-[1em]">
<a href="/accounts/{{$acctID}}/inventory" class="p-[1em] font-bold {{ if eq $path (printf "/accounts/%d/inventory" $acctID) }}selected{{ end }}">
Inventory
</a>
</li>
<li class="pt-[1em] pb-[1em]">
<a href="/accounts/{{$acctID}}/reports" class="p-[1em] font-bold {{ if eq $path (printf "/accounts/%d/reports" $acctID) }}selected{{ end }}">
Reports
</a>
</li>
<li class="pt-[1em] pb-[1em]">
<a href="/logout" class="p-[1em] font-bold">
Log Out
</a>
</li>
{{- end }}
</ul>
</nav>
</header>
<main class="basis-full grow p-[1em] max-w-full">
{{/* This is where the page_body template will be inserted into the page */}}
{{- block "body" . }}{{ end }}
</main>
<footer class="flex flex-col items-center">
<address class="flex items-center">
<a href="mailto:contact-us@inventory-plus-plus.com" class="p-[1em] font-bold">Contact Us</a>
<a href="mailto:support@inventory-plus-plus.com" class="p-[1em] font-bold">Support</a>
</address>
</footer>
</body>
</html>
@@ -0,0 +1,14 @@
{{- define "title" }} Inventory++ Create an Account {{ end }}
{{/* TODO: will need to verify the email address */}}
<section style="margin-top: 2em;">
<form method="post" action="/accounts">
<label>
Email:
<input type="email" required name="email" />
</label>
<input type="submit" value="Create Account" />
</form>
</section>
@@ -0,0 +1,20 @@
{{- .Auth.ByMatchingAccountID 2 }}
{{- define "title" }} Inventory++ Account {{ end }}
{{- $acctID := .Identity.Account }}
<h1>Account: {{ $acctID.Email }}</h1>
{{- $etsyUser := .Etsy.GetUserPointerByAccountID $acctID.AccountID }}
{{- if $etsyUser }}
<h3>Etsy User: {{ $etsyUser.UserID }}; Shop ID: {{ $etsyUser.ShopID }}</h3>
{{- else }}
<h3>
{{/* TODO: create this link dynamically, not EVERYTIME THE PAGE IS LOADED */}}
<a href="{{ printf "/webhooks/etsy/%d/new-account-link" $acctID.AccountID }}">
Link Your Etsy Store!
</a>
</h3>
{{- end }}
<h2><a href="/accounts/{{$acctID.AccountID}}/reports">View Reports</a></h2>
@@ -0,0 +1,74 @@
{{- .Auth.ByMatchingAccountID 2 }}
{{- $acctID := .Identity.Account.AccountID }}
{{- $stores := .Accounts.GetShops $acctID -}}
{{- define "title" }} Inventory++ {{ end }}
<h1 class="text-center mb-[0.5em]">Inventory</h1>
<h2 class="text-center mb-[0.5em]">Synced Listings</h2>
<section class="w-full flex flex-col items-center">
<h3>
Create a Sync Group
</h3>
<h4>
(Draft 2)
</h4>
{{ componentBody "accounts/{acctID}/inventory/sync-table-v2" "dot" . }}
<div>
{{ componentBody "button-dev"
"HXPost" (printf "/accounts/%d/inventory/sync-groups/draft/listings" $acctID)
"HXTarget" "previous table > tbody"
"HXSwap" "beforeend"
"Class" "mt-[1em] mb-[1em]"
"Text" "Add Listing"
"_" `
on click
send rowUpdated to the first <tbody/> in #inventory-table-2
`
}}
{{/* TODO: enable the button when all listings are filled and there are at least two listings */}}
{{/* TODO: save the listings as a sync group on click */}}
{{ componentBody "button-dev"
"ID" "create-sync-group-button"
"HXPost" (printf "/accounts/%d/sync-groups" $acctID)
"Class" "mt-[1em] mb-[1em]"
"Text" "Save Sync Group"
"Disabled" true
"_" `
on setDisabled(disabled)
if disabled then
add @disabled to me
else
remove @disabled from me
end
`
}}
</div>
</section>
<section class="w-full flex flex-col items-center">
<h3>
Draft 1
</h3>
{{ componentBody "accounts/{acctID}/inventory/sync-table" "dot" . }}
</section>
<section class="flex justify-center mt-[1em]">
{{ componentBody "accounts/{acctID}/inventory/sync-table/showcase-table" "dot" . }}
</section>
<section class="w-full flex justify-center mt-[1em]">
{{ componentBody "button-dev"
"HXGet" (printf "/accounts/%d/inventory/sync-table/new-row" $acctID)
"HXTarget" "#inventory-table > tbody"
"HXSwap" "beforeend"
"Class" "mt-[1em] mb-[1em]"
"Text" "Add Row"
}}
</section>
@@ -0,0 +1,91 @@
{{- .Auth.ByMatchingAccountID 2 }}
{{- define "title" }} Inventory++ Reports {{ end }}
{{ $storeID := .Request.URL.Query.Get "store-id" }}
<h1>Reports</h1>
<main>
<select
_='
on change
make a URL from window.location.href called currentURL
set currentQuery to searchParams of currentURL
set storeID to event.target.value
js(currentQuery, storeID) currentQuery.set("store-id", storeID) end
set search of currentURL to currentQuery.toString()
set window.location to currentURL
'
>
{{ if not $storeID }}
<option selected disabled>
choose a store
</option>
{{ end }}
<option {{ if eq $storeID "test-store-1" }}selected{{ end }} >
test-store-1
</option>
<option {{ if eq $storeID "test-store-2" }}selected{{ end }} >
test-store-2
</option>
<option {{ if eq $storeID "test-store-3" }}selected{{ end }} >
test-store-3
</option>
</select>
{{- if $storeID }}
<section
style="
display: grid;
grid-template-columns: auto auto auto 1fr;
column-gap: 1em;
row-gap: 0.5em;
margin: 1em 0;
"
>
<div style="border-bottom: solid black 1px;">
Date
</div>
<div style="border-bottom: solid black 1px;">
Time
</div>
<div style="border-bottom: solid black 1px;">
ID
</div>
<div style="border-bottom: solid black 1px;">
Payload
</div>
{{ $events := .RawEvents.LoadEventsForStore "etsy" $storeID }}
{{ range $e := $events }}
<div>
{{ printf "%d/%02d/%02d" $e.EventTimestamp.Year $e.EventTimestamp.Month $e.EventTimestamp.Day }}
</div>
<div>
{{ $suffix := "am" }}
{{ $ts := $e.EventTimestamp }}
{{- $hr := $ts.Hour }}
{{- if eq $hr 0 }}
{{- $hr = 12 }}
{{- else if eq $hr 12 }}
{{- $suffix = "pm" }}
{{- else if gt $hr 12 }}
{{- $hr = subInt $hr 12 }}
{{- $suffix = "pm" }}
{{- end }}
{{- $hrColorHex := multInt $hr 10 | subInt (subInt 256 128) | printf "%02x" }}
{{- $minColorHex := multInt $ts.Minute 2 | subInt (subInt 256 128) | printf "%02x" }}
{{- $secColorHex := multInt $ts.Second 2 | subInt (subInt 256 128) | printf "%02x" }}
<span style="color: #{{ $hrColorHex }}{{ $hrColorHex }}{{ $hrColorHex }};">{{ printf "%02d" $hr }}</span>:<span style="color: #{{ $minColorHex }}{{ $minColorHex }}{{ $minColorHex }};">{{ printf "%02d" $ts.Minute }}</span>:<span style="color: #{{ $secColorHex }}{{ $secColorHex }}{{ $secColorHex }};">{{ printf "%02d" $ts.Second }}</span>{{ printf " %s" $suffix }}
</div>
<div>
{{ $e.EventID }}
</div>
<div>
{{ prettyPrintJSON $e.Payload }}
</div>
{{ end }}
</section>
{{- end }}
</main>
+11
View File
@@ -0,0 +1,11 @@
{{- define "title" }} Inventory++ Invalid Link {{ end }}
<section>
Invalid Link: {{ .Request.URL.Path }}
</section>
<section>
<a href="/">Return Home</a>
</section>
+27
View File
@@ -0,0 +1,27 @@
<section class="flex justify-center max-w-full mt-[3em] mb-[3em]">
<h1 class="bg-card max-w-full p-[2em] border-[1px] border-sidebar-border rounded-lg text-nowrap">
Inventory++
</h1>
</section>
{{- if and .Identity.User.UserID (not .Identity.Account) }}
{{/* TODO: make account creation automatic as part of the user creation process */}}
<h2><a href="/account-creation">New Account</a></h2>
{{- end }}
<section class="flex flex-col items-center max-w-full mt-[1em] mb-[1em] gap-y-[2em]">
<p class="text-lg text-center max-w-[50%]">
Synchronize inventory automatically!
</p>
<div class="border-button border-sidebar-border bg-card text-lg text-center max-w-[50%]">
<a href="/login" class="block p-[1em] font-bold">
Create an Account
</a>
</div>
<p class="text-lg text-center max-w-[50%]">
...and start syncing your shops today!
</p>
</section>
+11
View File
@@ -0,0 +1,11 @@
{{/* TODO: delete this page, when certain it's not wanted anymore */}}
<h1>Log In</h1>
<form action="login" method="post">
<label>
Email:
<input type="text" required name="email" />
</label>
<input type="submit" value="login" />
</form>
+11
View File
@@ -0,0 +1,11 @@
{{- define "title" }} Inventory++ Page Not Found {{ end }}
<section>
Page Not Found: {{ .Request.URL.Path }}
</section>
<section>
<a href="/">Return Home</a>
</section>
+11
View File
@@ -0,0 +1,11 @@
{{/* TODO: not used - read for deletion */}}
<h1>Sign Up</h1>
<form action="accounts" method="post">
<label>
Email:
<input type="text" required name="email" />
</label>
<input type="submit" value="Submit" />
</form>