mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 10:29:35 +01:00
feat(scanner): Mobile Scanner App mit echten Produktionsaufträgen
Scanner-App Tauri v2 Android App mit Login, Barcode-Scanner, Consume/Move/Book-Flows und Aufgabenliste. TasksPage lädt echte RELEASED/IN_PROGRESS Produktionsaufträge via API, Consume-Flow nutzt den konkreten Auftrag für korrekte Rezept-Skalierung statt blind den ersten IN_PROGRESS-Auftrag zu nehmen. Backend: FindStockByBatchId Use Case + REST-Endpoint für Stock-Lookup per Chargennummer.
This commit is contained in:
parent
72979c9537
commit
bf09e3b747
93 changed files with 8977 additions and 60 deletions
|
|
@ -2,7 +2,7 @@
|
|||
* Base axios client for the Effigenix API
|
||||
*/
|
||||
|
||||
import axios, { type AxiosInstance } from 'axios';
|
||||
import axios, { type AxiosAdapter, type AxiosInstance } from 'axios';
|
||||
import { type ApiConfig, DEFAULT_API_CONFIG } from '@effigenix/config';
|
||||
import { setupAuthInterceptor } from './interceptors/auth-interceptor.js';
|
||||
import { setupRefreshInterceptor } from './interceptors/refresh-interceptor.js';
|
||||
|
|
@ -30,6 +30,7 @@ export function createApiClient(
|
|||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
...(resolvedConfig.adapter ? { adapter: resolvedConfig.adapter as AxiosAdapter } : {}),
|
||||
});
|
||||
|
||||
setupAuthInterceptor(client, tokenProvider);
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ export function createStocksResource(client: AxiosInstance) {
|
|||
return res.data;
|
||||
},
|
||||
|
||||
async findByBatchId(batchId: string): Promise<StockDTO[]> {
|
||||
const res = await client.get<StockDTO[]>(`${BASE}/by-batch/${encodeURIComponent(batchId)}`);
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async create(request: CreateStockRequest): Promise<CreateStockResponse> {
|
||||
const res = await client.post<CreateStockResponse>(BASE, request);
|
||||
return res.data;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ export interface ApiConfig {
|
|||
baseUrl: string;
|
||||
timeoutMs: number;
|
||||
retries: number;
|
||||
/** Custom axios adapter (e.g. Tauri HTTP plugin fetch). */
|
||||
adapter?: unknown;
|
||||
}
|
||||
|
||||
export const DEFAULT_API_CONFIG: ApiConfig = {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"source": "./src/index.ts",
|
||||
"import": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { forwardRef, type ButtonHTMLAttributes } from 'react';
|
||||
import { cn } from '../lib/cn';
|
||||
|
||||
type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';
|
||||
type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'success';
|
||||
type ButtonSize = 'sm' | 'md' | 'lg';
|
||||
|
||||
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
|
|
@ -13,16 +13,18 @@ const variantStyles: Record<ButtonVariant, string> = {
|
|||
primary:
|
||||
'bg-brand-600 text-white hover:bg-brand-700 active:bg-brand-800 focus-visible:ring-brand-500',
|
||||
secondary:
|
||||
'bg-warm-100 text-warm-800 hover:bg-warm-200 active:bg-warm-300 focus-visible:ring-warm-400 border border-warm-300',
|
||||
'bg-white text-warm-800 hover:bg-warm-50 active:bg-warm-100 focus-visible:ring-warm-400 border border-warm-300',
|
||||
ghost: 'text-warm-700 hover:bg-warm-100 active:bg-warm-200 focus-visible:ring-warm-400',
|
||||
danger:
|
||||
'bg-danger-600 text-white hover:bg-danger-700 active:bg-danger-800 focus-visible:ring-danger-500',
|
||||
success:
|
||||
'bg-success-600 text-white hover:bg-success-700 active:bg-success-800 focus-visible:ring-success-500',
|
||||
};
|
||||
|
||||
const sizeStyles: Record<ButtonSize, string> = {
|
||||
sm: 'px-3 py-1.5 text-sm',
|
||||
md: 'px-4 py-2 text-sm',
|
||||
lg: 'px-5 py-2.5 text-base',
|
||||
sm: 'px-4 py-2 text-sm',
|
||||
md: 'px-6 py-3 text-sm',
|
||||
lg: 'px-8 py-4 text-base',
|
||||
};
|
||||
|
||||
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
|
|
@ -31,9 +33,10 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
<button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center font-medium rounded-md transition-colors',
|
||||
'inline-flex items-center justify-center gap-2 font-semibold rounded-xl transition-colors',
|
||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
|
||||
'disabled:opacity-50 disabled:pointer-events-none',
|
||||
'active:scale-[0.97]',
|
||||
variantStyles[variant],
|
||||
sizeStyles[size],
|
||||
className
|
||||
|
|
|
|||
|
|
@ -79,10 +79,16 @@
|
|||
|
||||
/* Font */
|
||||
--font-sans: 'Poppins', ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
|
||||
|
||||
/* Radius */
|
||||
--radius-sm: 0.375rem;
|
||||
--radius-md: 0.5rem;
|
||||
--radius-lg: 0.75rem;
|
||||
--radius-xl: 1rem;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-xs: 0 1px 3px oklch(0 0 0 / 0.04);
|
||||
--shadow-brand: 0 2px 8px oklch(0.65 0.19 55 / 0.3);
|
||||
--shadow-brand-lg: 0 4px 16px oklch(0.65 0.19 55 / 0.4);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue