Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@
<div class="brand-title">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
<span>Mothotsi Quotation</span>
<span class="badge">KV: weel</span>
<span class="badge">KV: work</span>
</div>

<div class="nav-actions">
Expand All @@ -702,7 +702,7 @@
Saved Quotes (<span id="saved-count">0</span>)
</button>

<button type="button" class="btn btn-success" id="btn-save-quote" title="Save this quotation to Cloudflare KV (weel)">
<button type="button" class="btn btn-success" id="btn-save-quote" title="Save this quotation to Cloudflare KV (work)">
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
Save to KV
</button>
Expand All @@ -726,7 +726,7 @@
</a>
</div>
<div>
<span class="badge-kv">KV Namespace: weel</span>
<span class="badge-kv">KV Namespace: work</span>
</div>
</div>

Expand Down Expand Up @@ -885,7 +885,7 @@ <h1 class="company-name">MOTHOTSI</h1>
<div class="modal-overlay" id="saved-modal">
<div class="modal-content">
<div class="modal-header">
<h3>Saved Quotations (Cloudflare KV: weel)</h3>
<h3>Saved Quotations (Cloudflare KV: work)</h3>
<button type="button" class="btn-close-modal" id="btn-close-modal">&times;</button>
</div>
<div class="modal-body">
Expand Down Expand Up @@ -913,7 +913,7 @@ <h3>Saved Quotations (Cloudflare KV: weel)</h3>
<div id="toast-container"></div>

<script>
// Configuration: Cloudflare Worker backend URL communicating with KV 'weel'
// Configuration: Cloudflare Worker backend URL communicating with KV 'work'
const BACKEND_WORKER_URL = "https://spring-glade-780c.michealtshiamo1.workers.dev";

// Application State
Expand Down Expand Up @@ -1108,7 +1108,7 @@ <h3>Saved Quotations (Cloudflare KV: weel)</h3>

const data = await response.json();
currentQuoteId = payload.id;
showToast("Quotation saved successfully to Cloudflare KV ('weel')!", "success");
showToast("Quotation saved successfully to Cloudflare KV ('work')!", "success");
// Also keep local fallback
saveToLocalFallback(payload);
fetchSavedQuotesCount();
Expand Down
29 changes: 16 additions & 13 deletions worker.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Cloudflare Worker for Quotation Web App
* Uses Cloudflare KV namespace 'work' (bound as env.weel)
* Uses Cloudflare KV namespace 'work' (supporting env.work or env.weel binding)
*/

export default {
Expand Down Expand Up @@ -35,12 +35,15 @@ export default {
};

try {
// Resolve KV namespace safely regardless of whether bound as 'work' or 'weel'
const kv = env && (env.work || env.weel);

// Health check or root endpoint
if (pathname === "/" || pathname === "/api" || pathname === "/api/health") {
return jsonResponse({
success: true,
service: "Quotation API",
namespace: "weel",
namespace: "work",
endpoints: [
{ method: "GET", path: "/api/quotes", description: "List all quotations" },
{ method: "GET", path: "/api/quotes/:id", description: "Get quotation by ID" },
Expand All @@ -51,9 +54,9 @@ export default {
});
}

// Ensure KV namespace 'weel' is bound
if (!env.weel) {
return errorResponse("Cloudflare KV namespace 'work' is not bound. Please bind 'weel' in wrangler.toml or Worker settings.", 500);
// Ensure KV namespace is bound
if (!kv) {
return errorResponse("Cloudflare KV namespace 'work' is not bound. Please bind 'work' in wrangler.toml or Worker settings.", 500);
}

// Router for /api/quotes
Expand All @@ -64,7 +67,7 @@ export default {
// GET /api/quotes or GET /api/quotes/:id
if (request.method === "GET") {
if (id) {
const rawData = await env.work.get(`quote:${id}`);
const rawData = await kv.get(`quote:${id}`);
if (!rawData) {
return errorResponse(`Quotation with id '${id}' not found`, 404);
}
Expand All @@ -73,11 +76,11 @@ export default {
} else {
// List all quotations
// KV list returns keys with prefix 'quote:'
const listResult = await env.work.list({ prefix: "quote:" });
const listResult = await kv.list({ prefix: "quote:" });
const quotes = [];
for (const key of listResult.keys) {
// Read summary metadata or full data
const rawData = await env.work.get(key.name);
const rawData = await kv.get(key.name);
if (rawData) {
try {
const parsed = JSON.parse(rawData);
Expand Down Expand Up @@ -120,7 +123,7 @@ export default {
};

const keyName = `quote:${quoteId}`;
await env.weel.put(keyName, JSON.stringify(quoteData), {
await kv.put(keyName, JSON.stringify(quoteData), {
metadata: {
id: quoteId,
clientName: quoteData.clientName || "",
Expand Down Expand Up @@ -149,7 +152,7 @@ export default {
return errorResponse("Invalid JSON payload", 400);
}

const existingRaw = await env.work.get(`quote:${id}`);
const existingRaw = await kv.get(`quote:${id}`);
let existingData = {};
if (existingRaw) {
try {
Expand All @@ -166,7 +169,7 @@ export default {
};

const keyName = `quote:${id}`;
await env.weel.put(keyName, JSON.stringify(updatedQuote), {
await kv.put(keyName, JSON.stringify(updatedQuote), {
metadata: {
id: id,
clientName: updatedQuote.clientName || "",
Expand All @@ -189,12 +192,12 @@ export default {
}

const keyName = `quote:${id}`;
const existing = await env.work.get(keyName);
const existing = await kv.get(keyName);
if (!existing) {
return errorResponse(`Quotation with id '${id}' not found`, 404);
}

await env.weel.delete(keyName);
await kv.delete(keyName);

return jsonResponse({
success: true,
Expand Down