diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /ping/frontend/src/routes/dashboard/transactions/+page.svelte | |
Diffstat (limited to 'ping/frontend/src/routes/dashboard/transactions/+page.svelte')
| -rw-r--r-- | ping/frontend/src/routes/dashboard/transactions/+page.svelte | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/ping/frontend/src/routes/dashboard/transactions/+page.svelte b/ping/frontend/src/routes/dashboard/transactions/+page.svelte new file mode 100644 index 0000000..86f9292 --- /dev/null +++ b/ping/frontend/src/routes/dashboard/transactions/+page.svelte @@ -0,0 +1,360 @@ +<script lang="ts"> + import TransactionModal from '$lib/components/dashboard/transactions/TransactionModal.svelte'; + import { authFetch } from '$lib/stores/auth'; + import { addToast } from '$lib/stores/toast'; + import { onMount } from 'svelte'; + + interface ITransaction { + id: string; + label: string | null; + amount: number; + currency: string; + receiverLabel: string | null; + receiverIban: string; + operationDate: Date; + eco_score: number; + creationDate: Date; + createrId: string; + } + + let searchQuery = $state(''); + let sortBy = $state('Date'); + let sortOrder = $state('Montant'); + let transactions: ITransaction[] = $state([]); + let isCreateDialogOpened = $state(false); + + let visibleTransactions = $state<ITransaction[]>([]); + + $effect(() => { + const query = searchQuery.toLowerCase(); + visibleTransactions = transactions.filter((t) => { + const matchesLabel = t.label?.toLowerCase().includes(query); + const matchesReceiver = t.receiverLabel?.toLowerCase().includes(query); + const receiverIban = t.receiverIban?.toLowerCase().includes(query); + return matchesLabel || matchesReceiver; + }); + }); + + function handleSearch() { + console.log('Searching for:', searchQuery); + } + + function applyFilters() { + console.log('Applying filters:', { sortBy, sortOrder }); + } + + function analyzeTransaction(transaction: any) { + console.log('Analyzing transaction', transaction); + } + + async function getAllTransactions(): Promise<ITransaction[]> { + const res = await authFetch('/api/transactions', { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }); + const data = await res.json(); + + if (!res.ok) { + addToast({ message: data.message, color: 'red', title: 'Erreur' }); + return []; + } + + return data.transactions as ITransaction[]; + } + + function onCreate(tr: ITransaction) { + getAllTransactions().then((transactionsData) => { + if (transactionsData) { + transactions = transactionsData; + } + }); + } + + onMount(() => { + getAllTransactions().then((transactionsData) => { + if (transactionsData) { + transactions = transactionsData; + visibleTransactions = transactionsData; + console.log(transactions); + } + }); + }); +</script> + +<section id="transactions"> + <div class="transactions-container"> + <div class="transactions-header"> + <h1>Transactions</h1> + <div class="search-bar"> + <input + type="text" + placeholder="Recherche..." + bind:value={searchQuery} + oninput={handleSearch} + /> + <button class="search-btn">🔍</button> + </div> + </div> + + <div class="filters-section"> + <div class="filters-left"> + <span class="filter-label">Trier</span> + <div class="filter-group"> + <select bind:value={sortBy} class="filter-select"> + <option value="Date">Date</option> + <option value="Amount">Montant</option> + <option value="Company">Entreprise</option> + </select> + <select bind:value={sortOrder} class="filter-select"> + <option value="Montant">Montant</option> + <option value="ASC">Croissant</option> + <option value="DESC">Décroissant</option> + </select> + </div> + </div> + <div> + <button + class="apply-btn" + onclick={() => { + isCreateDialogOpened = true; + }} + > + ➕ Créer + </button> + <button class="apply-btn" onclick={applyFilters}> 📁 Appliquer </button> + </div> + </div> + + <div class="transactions-list"> + {#each visibleTransactions as transaction} + <div class="transaction-card"> + <div class="transaction-main"> + <div class="transaction-info"> + <h3 class="transaction-type">{transaction.label}</h3> + <p class="transaction-company"> + {transaction.receiverIban} • {transaction.receiverLabel} + </p> + </div> + <div class="transaction-metrics"> + <div class="metric"> + <span class="metric-label">CO2</span> + <span class="metric-value co2">{transaction.eco_score}</span> + </div> + <div class="metric"> + <span class="metric-label">{transaction.currency}</span> + <span class="metric-value amount">{transaction.amount}</span> + </div> + </div> + <button class="analyze-btn" onclick={() => analyzeTransaction(transaction)}> + ✏️ Analyser + </button> + </div> + </div> + {/each} + </div> + </div> +</section> +<TransactionModal bind:isOpen={isCreateDialogOpened} {onCreate} /> + +<style> + #transactions { + padding: 16px; + background-color: var(--bg-secondary); + color: white; + min-height: calc(100vh - 72px); + } + + .transactions-container { + max-width: 1200px; + } + + .transactions-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + } + + h1 { + color: var(--text-lime); + font-size: 32px; + margin: 0; + font-weight: 600; + } + + .search-bar { + display: flex; + align-items: center; + background-color: var(--bg-primary); + border-radius: 8px; + padding: 4px; + gap: 8px; + } + + .search-bar input { + background: transparent; + border: none; + color: white; + padding: 12px 16px; + font-size: 14px; + outline: none; + width: 300px; + } + + .search-bar input::placeholder { + color: #888888; + } + + .search-btn { + background: transparent; + border: none; + color: #888888; + padding: 8px; + cursor: pointer; + font-size: 16px; + } + + /* Filters */ + .filters-section { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + padding: 16px; + background-color: var(--bg-primary); + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + } + + .filters-left { + display: flex; + align-items: center; + gap: 15px; + } + + .filter-label { + color: white; + font-weight: 500; + font-size: 14px; + } + + .filter-group { + display: flex; + gap: 10px; + } + + .filter-select { + background-color: var(--bg-secondary); + color: white; + border: none; + border-bottom: 2px solid var(--text-lime); + border-radius: 8px 8px 0 0; + padding: 8px 12px; + font-size: 14px; + cursor: pointer; + } + + .filter-select:focus { + outline: none; + border-bottom-color: var(--text-lime); + } + + .apply-btn { + background-color: var(--btn-primary); + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + font-weight: 600; + font-size: 14px; + transition-duration: 0.2s; + } + + .apply-btn:hover { + background-color: var(--btn-primary-hover); + transform: scale(1.025); + } + + .transactions-list { + display: flex; + flex-direction: column; + gap: 0; + } + + .transaction-card { + background-color: var(--bg-primary); + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + padding: 16px; + margin: 16px; + color: white; + width: calc(100% - 32px); + } + + .transaction-main { + display: flex; + align-items: center; + justify-content: space-between; + } + + .transaction-info h3 { + margin: 0 0 5px 0; + font-size: 18px; + font-weight: 600; + color: white; + } + + .transaction-company { + margin: 0; + font-size: 14px; + color: #888888; + } + + .transaction-metrics { + display: flex; + gap: 40px; + } + + .metric { + display: flex; + flex-direction: column; + align-items: center; + gap: 5px; + } + + .metric-label { + font-size: 12px; + color: #888888; + font-weight: 500; + } + + .metric-value { + font-size: 24px; + font-weight: bold; + } + + .metric-value.co2, + .metric-value.amount { + color: var(--text-lime); + } + + .analyze-btn { + background-color: var(--btn-primary); + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition-duration: 0.2s; + } + + .analyze-btn:hover { + background-color: var(--btn-primary-hover); + transform: scale(1.025); + } +</style> |
