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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Link : https://app.CropWatch.io

# List of Tools & Packages Used:
- PWA Framework: Svelte, SvelteKit
- UI Components: @cropwatchdevelopment/cwui, bits-ui, @revolist/revogrid, @revolist/svelte-datagrid
- UI Components: @cropwatchdevelopment/cwui, bits-ui, @revolist/svelte-datagrid
- Styling: Tailwind CSS, @layerstack/tailwind, @tailwindcss/forms, @tailwindcss/typography
- State & IoC: @stencil/store, inversify
- Data Visualization: D3.js, ApexCharts
Expand Down
6 changes: 3 additions & 3 deletions build-info.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
=== Build Info ===
Commit : 45a5b16
Branch : master
Commit : 03cf732
Branch : pwa
Author : Kevin Cantrell
Date : 2025-07-02T14:13:08.432Z
Date : 2025-07-03T12:09:21.667Z
Builder : kevin@kevin-desktop
IP Address : 192.168.1.100
==================
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@types/event-calendar__core": "^4.4.0",
"@types/luxon": "^3.6.2",
"@types/swagger-ui": "^5.21.1",
"@vite-pwa/sveltekit": "^1.0.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^3.0.0",
Expand All @@ -65,8 +66,6 @@
"@layerstack/tailwind": "2.0.0-next.2",
"@layerstack/utils": "^1.0.0",
"@mdi/js": "^7.4.47",
"@revolist/revogrid": "^4.15.8",
"@revolist/svelte-datagrid": "^4.15.8",
"@stencil/store": "^2.1.3",
"@supabase/ssr": "^0.6.1",
"@supabase/supabase-js": "^2.49.4",
Expand All @@ -92,7 +91,9 @@
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
"@sentry/cli",
"esbuild",
"svelte-preprocess"
]
},
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
Expand Down
3,004 changes: 2,903 additions & 101 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

39 changes: 28 additions & 11 deletions src/app.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
<!doctype html>
<html lang="ja" autocapitalize="off" autocorrect="off" spellcheck="false" translate="no">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Theme is now managed by theme.svelte.ts -->
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="theme-color" content="#317EFB" />
<meta name="application-name" content="CropWatch" />
<!-- Theme is now managed by theme.svelte.ts -->
%sveltekit.head%
<style>
.titlebar-safe-area {
padding-top: env(titlebar-area-height, 0px);
}
</style>
<script>
if (navigator.windowControlsOverlay) {
console.log('Overlay supported');
}
</script>

</head>

<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>

</html>
17 changes: 16 additions & 1 deletion src/hooks.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/publi
import { createClient } from '@supabase/supabase-js';

const PUBLIC_ROUTES = [
'/offline.html',
'/auth', // All routes under /auth/
'/api/auth' // Only authentication-related API routes
'/api/auth', // Only authentication-related API routes
'/static', // All static assets
'/static/icons',
'/static/screenshots'
];

// Additional check for exact /api/ route
Expand Down Expand Up @@ -352,6 +356,17 @@ const handleSupabase: Handle = async ({ event, resolve }) => {

// Combine the handles - CORS first, then Supabase
export const handle: Handle = async ({ event, resolve }) => {
const { url } = event;
if (
url.pathname.startsWith('/sw.js') ||
url.pathname.startsWith('/workbox-') ||
url.pathname.startsWith('/manifest.webmanifest') ||
url.pathname.startsWith('/registerSW.js') ||
url.pathname.startsWith('/offline.html')
) {
return resolve(event);
}

// First apply CORS (handles preflight requests immediately)
return await handleCORS({
event,
Expand Down
33 changes: 23 additions & 10 deletions src/lib/components/UI/dashboard/DashboardCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
dark:border-gray-700 dark:bg-[#1f2532] dark:text-white dark:shadow-gray-900/20"
>
<div
class="relative min-h-[130px] bg-gray-100
text-yellow-600 dark:bg-[#2c3546] dark:text-yellow-300"
class="relative flex min-h-[60px] flex-row bg-teal-800
text-yellow-300 dark:bg-[#2c3546] dark:text-yellow-300"
>
<div class="pt-12">
<!-- Icon-only status indicator with color based on state -->
<div class="absolute top-3 left-3 flex h-10 w-10 items-center justify-center">
<!-- <div class="pt-12"> -->
<!-- Icon-only status indicator with color based on state -->
<!-- <div class="absolute top-3 left-3 flex h-10 w-10 items-center justify-center bg-white/20 rounded-full shadow-lg dark:bg-gray-800">
{#if loading}
<Icon class="text-xl text-blue-400" path={mdiClockOutline} />
{:else if allActive}
Expand All @@ -44,15 +44,28 @@
{:else}
<Icon class="text-xl text-red-500" path={mdiClose} />
{/if}
</div>
</div>
</div> -->
<!-- </div> -->

<h2
class="flex items-center justify-between px-2 py-3 text-lg font-semibold text-yellow-600 dark:text-yellow-400"
class="flex w-full flex-row justify-between px-2 pt-3 text-lg font-semibold text-yellow-600 dark:text-yellow-400"
>
<span>{location.name}</span>
<div
class="top-3 left-3 flex h-10 w-10 items-center justify-center rounded-full bg-white/20 shadow-lg dark:bg-gray-800"
>
{#if loading}
<Icon class="text-xl text-blue-400" path={mdiClockOutline} />
{:else if allActive}
<Icon class="text-xl text-green-500" path={mdiCheck} />
{:else if activeDevices.length > 0 && !allInactive}
<Icon class="rounded-lg text-xl text-orange-300" path={mdiAlert} />
{:else}
<Icon class="text-xl text-red-500" path={mdiClose} />
{/if}
</div>
<span class="ml-5 flex flex-auto">{location.name}</span>
<button
class="ml-2 inline-flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full border border-blue-200 bg-blue-50 p-0 text-blue-700 transition-colors duration-200 hover:bg-blue-100 dark:border-gray-600 dark:bg-gray-700 dark:text-blue-300 dark:hover:bg-gray-600"
class="ml-2 flex inline-flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full border border-blue-200 bg-blue-50 p-0 text-blue-700 transition-colors duration-200 hover:bg-blue-100 dark:border-gray-600 dark:bg-gray-700 dark:text-blue-300 dark:hover:bg-gray-600"
onclick={() => goto(href)}
aria-label="View details"
>
Expand Down
174 changes: 0 additions & 174 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,135 +7,6 @@
import { success, error, warning, info, neutral } from '$lib/stores/toast.svelte';
import { onMount } from 'svelte';

// Dynamic import for RevoGrid to avoid SSR issues
let RevoGrid: any = $state(null);
let ColumnRegular: any = $state(null);

let { data } = $props();

let grid_component_instance: any = $state(); // To bind the component instance if needed
const columns: any[] = $state([
{
name: '🎰 Ticker',
prop: 'symbol',
sortable: true,
pin: 'colPinStart',
cellTemplate: (h, { model, prop }) => h('strong', null, model[prop])
},
{
name: '🔠 Company Name',
prop: 'company_name',
size: 300
},
{
name: '',
prop: '📉 graph',
readonly: true,
// Custom cell render
cellTemplate(h) {
const barWidth = 5;
const barSpacing = 5;
const maxHeight = 30;
const bars = [];

// Draw 5 vertical bars with random heights
for (let i = 0; i < 5; i++) {
const barHeight = Math.random() * maxHeight;
const x = i * (barWidth + barSpacing);
const y = maxHeight - barHeight + 5;

// Create the rectangle element for the bar
const rect = h('rect', {
key: i,
x,
y,
width: barWidth,
height: barHeight,
fill: 'blue',
stroke: 'black'
});

// Append the rectangle to the group
bars.push(rect);
}
return h(
'svg',
{
width: '100%',
height: maxHeight + 10
},
h('g', {}, bars)
);
}
},
{
name: '💰 Price',
prop: 'price',
columnType: 'numeric',
sortable: true
},
{
name: '⬆️ Change',
prop: 'change',
columnType: 'numeric',
sortable: true
},
{
name: '% Change',
prop: 'percent_change'
}
]);

const source = $state([
{
symbol: 'AAPL',
company_name: 'Apple Inc.',
price: 150.25,
change: 1.5,
percent_change: '1.01%'
},
{
symbol: 'MSFT',
company_name: 'Microsoft Corp.',
price: 280.75,
change: -0.5,
percent_change: '-0.18%'
},
{
symbol: 'GOOGL',
company_name: 'Alphabet Inc.',
price: 2700.5,
change: 10.2,
percent_change: '0.38%'
}
]);

onMount(() => {
// Dynamically import RevoGrid only on the client side
if (browser) {
import('@revolist/svelte-datagrid').then((module) => {
RevoGrid = module.RevoGrid;
ColumnRegular = module.ColumnRegular;
});
}

const interval = setInterval(() => {
source.forEach((item) => {
item.price = parseFloat((Math.random() * 3000).toFixed(2));
item.change = parseFloat((Math.random() * 20 - 10).toFixed(2)); // Random change between -10 and 10
const priceForCalc = item.price === 0 ? 1 : item.price; // Avoid division by zero
item.percent_change = `${((item.change / priceForCalc) * 100).toFixed(2)}%`;
});
// With Svelte 5 runes, direct modification of $state array items should be reactive.
// If the grid doesn't update, uncommenting the next line might be necessary if RevoGrid needs an explicit push.
// source = [...source];
}, 2000); // Update every 2 seconds

return () => {
clearInterval(interval); // Clear interval on component destroy
};
});

// Define the AlertPoint type locally to match the one in NumberLine.svelte
type AlertPoint = {
id: number;
Expand Down Expand Up @@ -309,29 +180,6 @@ success('Custom message', {
</div>
</div>

<div class="bg-foreground-light dark:bg-foreground-dark p-4 dark:text-white">
{#if browser && RevoGrid}
<RevoGrid
bind:this={grid_component_instance}
{columns}
{source}
filter={true}
canFocus={true}
sorters={true}
columnTypes={{
numeric: {
name: 'Numeric',
autoSize: true,
// Numeric columns will have this default sorting
sortable: true
}
}}
/>
{:else}
<p>Loading data grid...</p>
{/if}
</div>

<section>
<Vpd
lineData={[
Expand All @@ -349,26 +197,4 @@ success('Custom message', {
font-size: 0.9rem;
line-height: 1.5;
}

/* RevoGrid dark/light mode styles */
:global(.dark) .bg-foreground-light.dark\:bg-foreground-dark :global(revogr-data) {
--rgb-text: 255, 255, 255; /* White text for dark mode */
--color-text: rgb(var(--rgb-text));
}

:global(:not(.dark)) .bg-foreground-light.dark\:bg-foreground-dark :global(revogr-data) {
--rgb-text: 0, 0, 0; /* Black text for light mode */
--color-text: rgb(var(--rgb-text));
}

/* Optional: Ensure header text has good contrast in both modes */
:global(.dark) .bg-foreground-light.dark\:bg-foreground-dark :global(revogr-header) {
--rgb-header-text: 255, 255, 255;
--header-text-color: rgb(var(--rgb-header-text));
}

:global(:not(.dark)) .bg-foreground-light.dark\:bg-foreground-dark :global(revogr-header) {
--rgb-header-text: 0, 0, 0;
--header-text-color: rgb(var(--rgb-header-text));
}
</style>
1 change: 1 addition & 0 deletions src/routes/auth/login/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
id="email"
bind:value={email}
required
autocomplete="email"
placeholder="✉️ {$_('Enter your email')}"
disabled={loading}
class="text-text-light dark:text-text-dark focus:ring-primary w-full rounded-md border border-gray-300
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Loading