- Added package.json with dependencies for Next.js, React, and Tailwind CSS. - Created postcss.config.js for Tailwind CSS and autoprefixer integration. - Added SVG icon for the application in public/icons/icon.svg. - Created manifest.json for PWA support with app details and icon. - Configured Tailwind CSS in tailwind.config.js with custom colors and animations. - Set up TypeScript configuration in tsconfig.json for strict type checking and module resolution.
149 lines
4.1 KiB
TypeScript
149 lines
4.1 KiB
TypeScript
import PocketBase from 'pocketbase';
|
|
import { AppSettings, DEFAULT_SETTINGS, Collection, DriverLocation } from './types';
|
|
|
|
const POCKETBASE_URL = process.env.NEXT_PUBLIC_POCKETBASE_URL || 'https://pocketbase-gnqc88suy8fqk6wyryjjdpvl.169.239.180.130.sslip.io';
|
|
|
|
export const pb = new PocketBase(POCKETBASE_URL);
|
|
|
|
// Auth helpers
|
|
export const isAuthenticated = () => pb.authStore.isValid;
|
|
|
|
export const getCurrentUser = () => pb.authStore.model;
|
|
|
|
export const logout = () => {
|
|
pb.authStore.clear();
|
|
if (typeof window !== 'undefined') {
|
|
window.location.href = '/login/';
|
|
}
|
|
};
|
|
|
|
export const login = async (email: string, password: string) => {
|
|
return await pb.collection('users').authWithPassword(email, password);
|
|
};
|
|
|
|
// Collection data helpers
|
|
export const getAssignedCollections = async () => {
|
|
const user = getCurrentUser();
|
|
if (!user) return [];
|
|
|
|
const today = new Date();
|
|
today.setHours(0, 0, 0, 0);
|
|
const tomorrow = new Date(today);
|
|
tomorrow.setDate(tomorrow.getDate() + 2);
|
|
|
|
const records = await pb.collection('collections').getFullList({
|
|
filter: `status = "assigned" && driver = "${user.id}" && planned_date <= "${tomorrow.toISOString()}"`,
|
|
expand: 'order_item,supplier',
|
|
sort: 'supplier.suppliername',
|
|
});
|
|
|
|
return records as unknown as Collection[];
|
|
};
|
|
|
|
export const getPendingCollections = async () => {
|
|
const records = await pb.collection('collections').getFullList({
|
|
filter: 'status = "pending" || status = "problem"',
|
|
expand: 'order_item,supplier',
|
|
sort: 'supplier.suppliername',
|
|
});
|
|
|
|
return records as unknown as Collection[];
|
|
};
|
|
|
|
export const updateCollectionStatus = async (
|
|
id: string,
|
|
status: string,
|
|
data: Partial<Collection>
|
|
) => {
|
|
return await pb.collection('collections').update(id, {
|
|
status,
|
|
...data,
|
|
});
|
|
};
|
|
|
|
export const reportProblem = async (
|
|
collectionId: string,
|
|
problemType: string,
|
|
description: string
|
|
) => {
|
|
// Update collection status
|
|
await pb.collection('collections').update(collectionId, {
|
|
status: 'problem',
|
|
notes: description,
|
|
});
|
|
|
|
// Create problem record
|
|
return await pb.collection('collection_problems').create({
|
|
collection: collectionId,
|
|
problem_type: problemType,
|
|
description,
|
|
});
|
|
};
|
|
|
|
// Location tracking
|
|
export const saveDriverLocation = async (location: Omit<DriverLocation, 'id'>) => {
|
|
return await pb.collection('driver_locations').create(location);
|
|
};
|
|
|
|
// Settings helpers
|
|
const SETTINGS_KEY = '1driver_settings';
|
|
|
|
export const getSettings = (): AppSettings => {
|
|
if (typeof window === 'undefined') return DEFAULT_SETTINGS;
|
|
const saved = localStorage.getItem(SETTINGS_KEY);
|
|
if (saved) {
|
|
try {
|
|
return { ...DEFAULT_SETTINGS, ...JSON.parse(saved) };
|
|
} catch {
|
|
return DEFAULT_SETTINGS;
|
|
}
|
|
}
|
|
return DEFAULT_SETTINGS;
|
|
};
|
|
|
|
export const saveSettings = (settings: Partial<AppSettings>) => {
|
|
if (typeof window === 'undefined') return;
|
|
const current = getSettings();
|
|
const updated = { ...current, ...settings };
|
|
localStorage.setItem(SETTINGS_KEY, JSON.stringify(updated));
|
|
return updated;
|
|
};
|
|
|
|
// Offline queue helpers
|
|
const QUEUE_KEY = '1driver_offline_queue';
|
|
|
|
export interface QueueItem {
|
|
id: string;
|
|
type: 'status_update' | 'problem_report';
|
|
data: Record<string, unknown>;
|
|
timestamp: string;
|
|
}
|
|
|
|
export const addToQueue = (item: Omit<QueueItem, 'id' | 'timestamp'>) => {
|
|
if (typeof window === 'undefined') return;
|
|
const queue = getQueue();
|
|
const newItem: QueueItem = {
|
|
...item,
|
|
id: crypto.randomUUID(),
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
queue.push(newItem);
|
|
localStorage.setItem(QUEUE_KEY, JSON.stringify(queue));
|
|
};
|
|
|
|
export const getQueue = (): QueueItem[] => {
|
|
if (typeof window === 'undefined') return [];
|
|
const saved = localStorage.getItem(QUEUE_KEY);
|
|
return saved ? JSON.parse(saved) : [];
|
|
};
|
|
|
|
export const removeFromQueue = (id: string) => {
|
|
if (typeof window === 'undefined') return;
|
|
const queue = getQueue().filter((item) => item.id !== id);
|
|
localStorage.setItem(QUEUE_KEY, JSON.stringify(queue));
|
|
};
|
|
|
|
export const clearQueue = () => {
|
|
if (typeof window === 'undefined') return;
|
|
localStorage.removeItem(QUEUE_KEY);
|
|
};
|