stemedb/applications/aphoria-dashboard/src/components/ui/date-picker.tsx
jml cce54358d2 feat(aphoria): add git commit tracking + comprehensive documentation
**Git Commit Tracking**
- Automatically capture git commit hash when claims/observations are ingested
- Store in assertion metadata for temporal context and audit trails
- Graceful degradation in non-git environments
- Solves double-commit problem by capturing hash at ingestion time

**Implementation**
- walker/git.rs: get_current_commit_hash() utility function
- bridge.rs: Accept optional git_commit parameter in all conversion functions
- episteme/local: Store project_root, capture git hash during ingestion
- 5 new tests for git hash tracking + metadata validation
- All 1162 aphoria tests passing

**Documentation Overhaul**
- README: Added Observations vs Claims distinction, git tracking, dashboard
- CLI Reference: New sections for git integration and ignore/exclusion system
- Comprehensive ignore documentation: .aphoriaignore, inline comments, 4 methods
- Enhanced verification engine docs with matching capabilities
- DOCUMENTATION_UPDATES.md: Complete audit summary

**Dashboard Separation**
- Moved Aphoria-specific UI from stemedb-dashboard to aphoria-dashboard
- Clean separation of concerns: StemeDB for core, Aphoria for security
- Added dashboard documentation and setup guides

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 18:36:46 +00:00

89 lines
2.5 KiB
TypeScript

"use client";
import { forwardRef } from "react";
import { cn } from "@/lib/utils";
interface DatePickerProps {
value?: Date;
onChange: (date: Date | undefined) => void;
placeholder?: string;
disabled?: boolean;
className?: string;
max?: Date;
min?: Date;
}
export const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(
(
{
value,
onChange,
placeholder = "Select date...",
disabled = false,
className,
max,
min,
},
ref
) => {
// Convert Date to YYYY-MM-DD string for input value
const formatForInput = (date: Date | undefined): string => {
if (!date) return "";
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const val = e.target.value;
if (!val) {
onChange(undefined);
return;
}
// Parse YYYY-MM-DD to Date
const [year, month, day] = val.split("-").map(Number);
const date = new Date(year, month - 1, day);
onChange(date);
};
const handleClear = () => {
onChange(undefined);
};
return (
<div className={cn("relative flex items-center gap-2", className)}>
<input
ref={ref}
type="date"
value={formatForInput(value)}
onChange={handleChange}
disabled={disabled}
max={max ? formatForInput(max) : undefined}
min={min ? formatForInput(min) : undefined}
placeholder={placeholder}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-xs transition-colors",
"file:border-0 file:bg-transparent file:text-sm file:font-medium",
"placeholder:text-muted-foreground",
"focus-visible:outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"disabled:cursor-not-allowed disabled:opacity-50"
)}
/>
{value && !disabled && (
<button
type="button"
onClick={handleClear}
className="absolute right-2 text-muted-foreground hover:text-foreground text-xs"
aria-label="Clear date"
>
Clear
</button>
)}
</div>
);
}
);
DatePicker.displayName = "DatePicker";