authentication fix

This commit is contained in:
2026-01-31 11:32:31 -06:00
parent 1d10863887
commit 9ca490075b
8 changed files with 77 additions and 54 deletions
+22
View File
@@ -1,3 +1,25 @@
# 🚀 TasGrid Server Management
This project uses **PM2** (via Bun) to stay online 24/7. The app runs on port `4000` and is managed by the scripts in `package.json`.
## 🛠 Quick Commands
| Action | Command | Description |
| :--- | :--- | :--- |
| **Check Status** | `bun status` | See if the site is online/how much memory it's using. |
| **Update Site** | `bun deploy` | Pulls latest code, builds, and restarts the server. |
| **Stop Server** | `bun stop` | Shuts down the site (use for maintenance). |
| **View Logs** | `bun logs` | See real-time errors or console output (Ctrl+C to exit). |
## 🔄 Deployment Workflow
To push new changes live, simply run:
```bash
bun deploy
## Usage
```bash
+8 -2
View File
@@ -4,9 +4,15 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0 --port 4000",
"dev": "vite --host 0.0.0.0 --port 4001",
"build": "tsc -b && vite build",
"preview": "vite preview"
"serve": "vite preview --host 0.0.0.0 --port 4000",
"---PM2 COMMANDS---": "------------------",
"status": "bun $(command -v pm2) status",
"logs": "bun $(command -v pm2) logs tasgrid",
"stop": "bun $(command -v pm2) stop tasgrid",
"start-prod": "bun $(command -v pm2) start \"bun run serve\" --name \"tasgrid\"",
"deploy": "git pull && bun run build && bun $(command -v pm2) restart tasgrid"
},
"dependencies": {
"@kobalte/core": "^0.13.11",
-27
View File
@@ -1,27 +0,0 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.solid:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}
+6
View File
@@ -34,7 +34,10 @@ export const AuthCallback = (props: { onSuccess: () => void }) => {
<form onSubmit={handleLogin} class="space-y-4">
<div class="space-y-2">
<input
id="email"
name="email"
type="email"
autocomplete="email"
placeholder="Email"
value={email()}
onInput={(e) => setEmail(e.currentTarget.value)}
@@ -44,7 +47,10 @@ export const AuthCallback = (props: { onSuccess: () => void }) => {
</div>
<div class="space-y-2">
<input
id="password"
name="password"
type="password"
autocomplete="current-password"
placeholder="Password"
value={password()}
onInput={(e) => setPassword(e.currentTarget.value)}
+4 -2
View File
@@ -61,10 +61,12 @@ export const Layout: Component<LayoutProps> = (props) => {
</div>
)}
<main class="flex-1 overflow-auto p-4 md:p-8 pt-4 pb-20 md:pb-8 scroll-smooth relative z-0">
{/* Main Content Area */}
<main class="flex-1 overflow-y-auto overflow-x-hidden p-4 sm:p-6 lg:p-8 pb-32 sm:pb-6">
<div class="max-w-5xl mx-auto w-full">
{props.children}
</div>
</main>
{/* Mobile Bottom Nav */}
<BottomNav currentView={props.currentView} setView={props.setView} />
</div>
+2
View File
@@ -154,6 +154,8 @@ export const QuickEntry: Component = () => {
<Search class="text-muted-foreground mr-3" size={20} />
<TextField class="flex-1">
<TextFieldInput
id="quick-entry-input"
name="task-title"
ref={inputRef}
value={input()}
onInput={(e) => setInput(e.currentTarget.value)}
+4
View File
@@ -78,6 +78,8 @@ export const TaskDetail: Component<TaskDetailProps> = (props) => {
{/* Header Area */}
<div class="px-6 pt-6 pb-2 shrink-0">
<textarea
id="task-detail-title"
name="task-title"
value={title()}
onInput={(e) => {
updateTitle(e.currentTarget.value);
@@ -160,6 +162,8 @@ export const TaskDetail: Component<TaskDetailProps> = (props) => {
<div class="flex items-center gap-1 text-muted-foreground group relative shrink-0 min-w-0 flex-1 sm:flex-initial">
<Calendar size={14} class="group-hover:text-primary transition-colors shrink-0" />
<input
id="task-detail-date"
name="due-date"
type="datetime-local"
value={dateString()}
onInput={onDateInputChange}
+26 -18
View File
@@ -3,7 +3,10 @@ import { createSignal, createEffect, createRoot } from "solid-js";
import { pb, TASGRID_COLLECTION } from "@/lib/pocketbase";
import { toast } from "solid-sonner";
const STORAGE_KEY = "tasgrid_data_v1";
const getStorageKey = () => {
const userId = pb.authStore.model?.id;
return userId ? `tasgrid_data_${userId}` : null;
};
export const [now, setNow] = createSignal(Date.now());
export const [activeTaskId, setActiveTaskId] = createSignal<string | null>(null);
@@ -30,30 +33,21 @@ interface TaskStore {
prefId?: string; // ID of the user_preferences record
}
// Synchronous hydration from localStorage for "instant" first paint
const getInitialState = (): TaskStore => {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
try {
return JSON.parse(saved);
} catch (e) {
console.error("Failed to parse cached data", e);
}
}
return {
// Initial empty state
export const [store, setStore] = createStore<TaskStore>({
tasks: [],
pWeight: 1.0,
uWeight: 1.0,
matrixScaleDays: 30,
};
};
export const [store, setStore] = createStore<TaskStore>(getInitialState());
});
// Auto-persist changes to localStorage (wrapped in root to avoid console warning)
createRoot(() => {
createEffect(() => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(store));
const key = getStorageKey();
if (key) {
localStorage.setItem(key, JSON.stringify(store));
}
});
});
@@ -100,6 +94,19 @@ let heartbeatInterval: number | undefined;
export const initStore = async () => {
if (!pb.authStore.isValid) return;
// 0. Synchronous hydration from localStorage for "instant" first paint
const key = getStorageKey();
if (key) {
const saved = localStorage.getItem(key);
if (saved) {
try {
setStore(JSON.parse(saved));
} catch (e) {
console.error("Failed to parse cached data", e);
}
}
}
// Heartbeat - Ensure only one interval is running
if (heartbeatInterval) clearInterval(heartbeatInterval);
heartbeatInterval = setInterval(() => setNow(Date.now()), 60000);
@@ -127,8 +134,9 @@ export const initStore = async () => {
console.warn("Failed to load preferences from user profile:", prefErr);
}
// 2. Fetch Tasks
// 2. Fetch Tasks - Explicitly filtered by user and sorted
const records = await pb.collection(TASGRID_COLLECTION).getFullList({
filter: `user = "${pb.authStore.model?.id}"`,
sort: '-created',
});