Compare commits
2 Commits
ba7082897f
...
36f352de58
| Author | SHA1 | Date | |
|---|---|---|---|
| 36f352de58 | |||
| 734dbfe24b |
51
app/api/ausgaben/autocomplete/route.ts
Normal file
51
app/api/ausgaben/autocomplete/route.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { getDbPool } from '@/lib/db';
|
||||||
|
import { RowDataPacket } from 'mysql2';
|
||||||
|
|
||||||
|
// GET /api/ausgaben/autocomplete - Fetch unique Wo and Was values for autocomplete
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const typ = searchParams.get('typ');
|
||||||
|
|
||||||
|
const pool = getDbPool();
|
||||||
|
|
||||||
|
let query = 'SELECT DISTINCT Wo, Was FROM Ausgaben';
|
||||||
|
const params: any[] = [];
|
||||||
|
|
||||||
|
if (typ !== null && typ !== undefined) {
|
||||||
|
query += ' WHERE TYP = ?';
|
||||||
|
params.push(parseInt(typ));
|
||||||
|
}
|
||||||
|
|
||||||
|
query += ' ORDER BY Wo, Was';
|
||||||
|
|
||||||
|
const [rows] = await pool.query<RowDataPacket[]>(query, params);
|
||||||
|
|
||||||
|
// Extract unique Wo and Was values
|
||||||
|
const woSet = new Set<string>();
|
||||||
|
const wasSet = new Set<string>();
|
||||||
|
|
||||||
|
rows.forEach((row) => {
|
||||||
|
if (row.Wo) woSet.add(row.Wo);
|
||||||
|
if (row.Was) wasSet.add(row.Was);
|
||||||
|
});
|
||||||
|
|
||||||
|
const wo = Array.from(woSet).sort();
|
||||||
|
const was = Array.from(wasSet).sort();
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
wo,
|
||||||
|
was,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Database error:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, error: 'Database error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,10 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
|||||||
const [year, setYear] = useState('');
|
const [year, setYear] = useState('');
|
||||||
const [isLoadingStats, setIsLoadingStats] = useState(false);
|
const [isLoadingStats, setIsLoadingStats] = useState(false);
|
||||||
|
|
||||||
|
// Autocomplete data
|
||||||
|
const [autoCompleteWo, setAutoCompleteWo] = useState<string[]>([]);
|
||||||
|
const [autoCompleteWas, setAutoCompleteWas] = useState<string[]>([]);
|
||||||
|
|
||||||
const fetchStats = useCallback(async (y: string, m: string) => {
|
const fetchStats = useCallback(async (y: string, m: string) => {
|
||||||
if (!y || !m) return;
|
if (!y || !m) return;
|
||||||
|
|
||||||
@@ -49,6 +53,19 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
|||||||
}
|
}
|
||||||
}, [typ]);
|
}, [typ]);
|
||||||
|
|
||||||
|
const fetchAutoComplete = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/ausgaben/autocomplete?typ=${typ}`);
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.success) {
|
||||||
|
setAutoCompleteWo(data.data.wo);
|
||||||
|
setAutoCompleteWas(data.data.was);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching autocomplete data:', error);
|
||||||
|
}
|
||||||
|
}, [typ]);
|
||||||
|
|
||||||
// Initialize month/year on first load
|
// Initialize month/year on first load
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@@ -65,6 +82,11 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
|||||||
}
|
}
|
||||||
}, [month, year, typ, fetchStats]);
|
}, [month, year, typ, fetchStats]);
|
||||||
|
|
||||||
|
// Fetch autocomplete data when typ changes
|
||||||
|
useEffect(() => {
|
||||||
|
fetchAutoComplete();
|
||||||
|
}, [typ, fetchAutoComplete]);
|
||||||
|
|
||||||
const handleMonthChange = (newMonth: string) => {
|
const handleMonthChange = (newMonth: string) => {
|
||||||
setMonth(newMonth);
|
setMonth(newMonth);
|
||||||
};
|
};
|
||||||
@@ -248,8 +270,14 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
|||||||
onChange={(e) => setFormData({ ...formData, Wo: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, Wo: e.target.value })}
|
||||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||||
placeholder="Geschäft/Ort"
|
placeholder="Geschäft/Ort"
|
||||||
|
list="wo-suggestions"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<datalist id="wo-suggestions">
|
||||||
|
{autoCompleteWo.map((wo, index) => (
|
||||||
|
<option key={index} value={wo} />
|
||||||
|
))}
|
||||||
|
</datalist>
|
||||||
</td>
|
</td>
|
||||||
<td className="p-2">
|
<td className="p-2">
|
||||||
<input
|
<input
|
||||||
@@ -258,8 +286,14 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
|||||||
onChange={(e) => setFormData({ ...formData, Was: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, Was: e.target.value })}
|
||||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||||
placeholder="Beschreibung"
|
placeholder="Beschreibung"
|
||||||
|
list="was-suggestions"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<datalist id="was-suggestions">
|
||||||
|
{autoCompleteWas.map((was, index) => (
|
||||||
|
<option key={index} value={was} />
|
||||||
|
))}
|
||||||
|
</datalist>
|
||||||
</td>
|
</td>
|
||||||
<td className="p-2 w-24">
|
<td className="p-2 w-24">
|
||||||
<input
|
<input
|
||||||
|
|||||||
Reference in New Issue
Block a user