summaryrefslogtreecommitdiff
path: root/ping/frontend/src/routes/dashboard/transactions
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
commit967be9e750221ab2ab783f95df79bb26d290a45e (patch)
tree6802900a5e975f9f68b169f0f503f040056d6952 /ping/frontend/src/routes/dashboard/transactions
add: added projectsHEADmain
Diffstat (limited to 'ping/frontend/src/routes/dashboard/transactions')
-rw-r--r--ping/frontend/src/routes/dashboard/transactions/+page.svelte360
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>