Compare commits
	
		
			2 Commits
		
	
	
		
			579cbd1bc9
			...
			d5ed0fce58
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						d5ed0fce58
	
				 | 
					
					
						|||
| 
						
						
							
						
						766a384df8
	
				 | 
					
					
						
@@ -214,15 +214,6 @@
 | 
			
		||||
          {/if}
 | 
			
		||||
 | 
			
		||||
          <div class="panel-actions">
 | 
			
		||||
            {#if payment && payment.createdBy === session?.user?.nickname}
 | 
			
		||||
              <button 
 | 
			
		||||
                class="btn-danger" 
 | 
			
		||||
                on:click={deletePayment}
 | 
			
		||||
                disabled={deleting}
 | 
			
		||||
              >
 | 
			
		||||
                {deleting ? 'Deleting...' : 'Delete Payment'}
 | 
			
		||||
              </button>
 | 
			
		||||
            {/if}
 | 
			
		||||
            <button class="btn-secondary" on:click={closeModal}>Close</button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -230,7 +221,7 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{#if payment && payment.createdBy === session?.user?.nickname}
 | 
			
		||||
{#if payment}
 | 
			
		||||
  <EditButton href="/cospend/payments/edit/{paymentId}" />
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
@@ -480,6 +471,9 @@
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    transition: all 0.2s;
 | 
			
		||||
    border: none;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .btn-primary {
 | 
			
		||||
@@ -616,11 +610,50 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 768px) {
 | 
			
		||||
    .panel-content {
 | 
			
		||||
      height: 100vh;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .panel-header {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
      position: sticky;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      z-index: 10;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .panel-header h2 {
 | 
			
		||||
      font-size: 1.2rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .close-button {
 | 
			
		||||
      padding: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 600px) {
 | 
			
		||||
    .panel-header h2 {
 | 
			
		||||
      font-size: 1.1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-header {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      gap: 1rem;
 | 
			
		||||
      text-align: center;
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-info {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .splits-section {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .panel-actions {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .receipt-image {
 | 
			
		||||
@@ -629,16 +662,55 @@
 | 
			
		||||
 | 
			
		||||
    .info-grid {
 | 
			
		||||
      grid-template-columns: 1fr;
 | 
			
		||||
      gap: 0.75rem;
 | 
			
		||||
      margin-bottom: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .panel-actions {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
    .info-item {
 | 
			
		||||
      gap: 0.125rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .label {
 | 
			
		||||
      font-size: 0.8rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .value {
 | 
			
		||||
      font-size: 0.9rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .description {
 | 
			
		||||
      padding-top: 1rem;
 | 
			
		||||
      margin-bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .description h3 {
 | 
			
		||||
      font-size: 0.95rem;
 | 
			
		||||
      margin-bottom: 0.5rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .description p {
 | 
			
		||||
      font-size: 0.9rem;
 | 
			
		||||
      line-height: 1.4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .splits-section h3 {
 | 
			
		||||
      font-size: 0.95rem;
 | 
			
		||||
      margin-bottom: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .splits-list {
 | 
			
		||||
      gap: 0.5rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .split-item {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      align-items: flex-start;
 | 
			
		||||
      gap: 0.5rem;
 | 
			
		||||
      padding: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .split-amount {
 | 
			
		||||
      font-size: 0.9rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -89,10 +89,13 @@ export const GET: RequestHandler = async ({ locals }) => {
 | 
			
		||||
    // Separate into who owes you vs who you owe
 | 
			
		||||
    const whoOwesMe = debtSummaries.filter(debt => debt.netAmount < 0).map(debt => ({
 | 
			
		||||
      ...debt,
 | 
			
		||||
      netAmount: Math.abs(debt.netAmount) // Make positive for display
 | 
			
		||||
      netAmount: Math.round(Math.abs(debt.netAmount) * 100) / 100 // Round to 2 decimal places and make positive for display
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    const whoIOwe = debtSummaries.filter(debt => debt.netAmount > 0);
 | 
			
		||||
    const whoIOwe = debtSummaries.filter(debt => debt.netAmount > 0).map(debt => ({
 | 
			
		||||
      ...debt,
 | 
			
		||||
      netAmount: Math.round(debt.netAmount * 100) / 100 // Round to 2 decimal places
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    return json({
 | 
			
		||||
      whoOwesMe,
 | 
			
		||||
 
 | 
			
		||||
@@ -129,26 +129,53 @@
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 768px) {
 | 
			
		||||
    .layout-container.has-modal .main-content {
 | 
			
		||||
      margin-right: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .side-panel {
 | 
			
		||||
      position: fixed;
 | 
			
		||||
      top: 4rem;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      right: 0;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      height: calc(100vh - 4rem);
 | 
			
		||||
      transform: translateY(100%);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .layout-container.has-modal .side-panel {
 | 
			
		||||
      transform: translateY(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 480px) {
 | 
			
		||||
    .layout-container.has-modal {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .layout-container.has-modal .main-content {
 | 
			
		||||
      flex: none;
 | 
			
		||||
      height: 50vh;
 | 
			
		||||
      height: 40vh;
 | 
			
		||||
      overflow-y: auto;
 | 
			
		||||
      margin-right: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .side-panel {
 | 
			
		||||
      flex: none;
 | 
			
		||||
      height: 50vh;
 | 
			
		||||
      height: 60vh;
 | 
			
		||||
      min-width: unset;
 | 
			
		||||
      max-width: unset;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      border-left: none;
 | 
			
		||||
      border-top: 1px solid #dee2e6;
 | 
			
		||||
      box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
 | 
			
		||||
      top: auto;
 | 
			
		||||
      bottom: 0;
 | 
			
		||||
      transform: translateY(100%);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .layout-container.has-modal .side-panel {
 | 
			
		||||
      transform: translateY(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -674,12 +674,18 @@
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 600px) {
 | 
			
		||||
    .cospend-main {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
      padding: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .dashboard-layout {
 | 
			
		||||
      gap: 0.75rem;
 | 
			
		||||
      margin-bottom: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .actions {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      margin-bottom: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .btn {
 | 
			
		||||
@@ -688,52 +694,87 @@
 | 
			
		||||
      text-align: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Mobile Settlement Flow */
 | 
			
		||||
    /* Mobile Settlement Flow - Keep Horizontal */
 | 
			
		||||
    .settlement-flow-activity {
 | 
			
		||||
      padding: 0.75rem;
 | 
			
		||||
      margin: 0 auto 0.75rem auto;
 | 
			
		||||
      max-width: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-user-flow {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      gap: 1rem;
 | 
			
		||||
      gap: 0.75rem;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-payer, .settlement-receiver {
 | 
			
		||||
      order: 1;
 | 
			
		||||
      gap: 0.5rem;
 | 
			
		||||
      flex: 0 0 auto;
 | 
			
		||||
      min-width: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-payer :global(.profile-picture),
 | 
			
		||||
    .settlement-receiver :global(.profile-picture) {
 | 
			
		||||
      width: 40px !important;
 | 
			
		||||
      height: 40px !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-username {
 | 
			
		||||
      font-size: 0.8rem;
 | 
			
		||||
      line-height: 1.1;
 | 
			
		||||
      max-width: 60px;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-arrow-section {
 | 
			
		||||
      order: 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-flow-arrow {
 | 
			
		||||
      transform: rotate(90deg);
 | 
			
		||||
      font-size: 1.5rem;
 | 
			
		||||
      gap: 0.25rem;
 | 
			
		||||
      flex: 1;
 | 
			
		||||
      min-width: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-amount-large {
 | 
			
		||||
      font-size: 1.3rem;
 | 
			
		||||
      font-size: 1.1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-flow-arrow {
 | 
			
		||||
      font-size: 1.2rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-date {
 | 
			
		||||
      font-size: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .dashboard-layout {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    gap: 2rem;
 | 
			
		||||
    margin-bottom: 2rem;
 | 
			
		||||
    max-width: 1400px;
 | 
			
		||||
    gap: 1rem;
 | 
			
		||||
    margin-bottom: 1.5rem;
 | 
			
		||||
    margin-left: auto;
 | 
			
		||||
    margin-right: auto;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (min-width: 768px) {
 | 
			
		||||
    .dashboard-layout {
 | 
			
		||||
      gap: 1.5rem;
 | 
			
		||||
      margin-bottom: 2rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (min-width: 1200px) {
 | 
			
		||||
    .dashboard-layout {
 | 
			
		||||
      display: grid;
 | 
			
		||||
      grid-template-columns: 1fr 1fr;
 | 
			
		||||
      gap: 3rem;
 | 
			
		||||
      gap: 2rem;
 | 
			
		||||
      align-items: start;
 | 
			
		||||
      max-width: 1200px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .balance-section {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      gap: 2rem;
 | 
			
		||||
      gap: 1.5rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -264,12 +264,12 @@
 | 
			
		||||
  .payments-list {
 | 
			
		||||
    max-width: 1200px;
 | 
			
		||||
    margin: 0 auto;
 | 
			
		||||
    padding: 2rem;
 | 
			
		||||
    padding: 1rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   h1 {
 | 
			
		||||
    margin-block: 0 2rem;
 | 
			
		||||
    margin-block: 0 1rem;
 | 
			
		||||
    margin-inline: auto;
 | 
			
		||||
    color: var(--nord0);
 | 
			
		||||
    text-align: center;
 | 
			
		||||
@@ -380,9 +380,9 @@
 | 
			
		||||
 | 
			
		||||
  .payments-grid {
 | 
			
		||||
    display: grid;
 | 
			
		||||
    grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
 | 
			
		||||
    gap: 1.5rem;
 | 
			
		||||
    margin-bottom: 2rem;
 | 
			
		||||
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
 | 
			
		||||
    gap: 1rem;
 | 
			
		||||
    margin-bottom: 1.5rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .payment-card {
 | 
			
		||||
@@ -684,24 +684,70 @@
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 600px) {
 | 
			
		||||
  @media (max-width: 768px) {
 | 
			
		||||
    .payments-list {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .header {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      gap: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .header-actions {
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      padding: 0.75rem;
 | 
			
		||||
      max-width: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payments-grid {
 | 
			
		||||
      grid-template-columns: 1fr;
 | 
			
		||||
      gap: 0.75rem;
 | 
			
		||||
      margin-bottom: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-card {
 | 
			
		||||
      padding: 1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-header {
 | 
			
		||||
      margin-bottom: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-meta {
 | 
			
		||||
      gap: 0.5rem;
 | 
			
		||||
      font-size: 0.85rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .title-with-category .category-emoji {
 | 
			
		||||
      font-size: 1.1rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-title h3 {
 | 
			
		||||
      font-size: 1.1rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 480px) {
 | 
			
		||||
    .payments-list {
 | 
			
		||||
      padding: 0.5rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payments-grid {
 | 
			
		||||
      gap: 0.5rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .payment-card {
 | 
			
		||||
      padding: 0.75rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Make settlement flow more compact on very small screens */
 | 
			
		||||
    .settlement-flow {
 | 
			
		||||
      gap: 0.5rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-user-from, .settlement-user-to {
 | 
			
		||||
      gap: 0.25rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-user-from .username,
 | 
			
		||||
    .settlement-user-to .username {
 | 
			
		||||
      font-size: 0.8rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .settlement-badge-small {
 | 
			
		||||
      font-size: 0.55rem;
 | 
			
		||||
      padding: 0.1rem 0.25rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -72,32 +72,6 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let deleting = false;
 | 
			
		||||
 | 
			
		||||
  async function deletePayment() {
 | 
			
		||||
    if (!confirm('Are you sure you want to delete this payment? This action cannot be undone.')) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      deleting = true;
 | 
			
		||||
      const response = await fetch(`/api/cospend/payments/${data.paymentId}`, {
 | 
			
		||||
        method: 'DELETE'
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (!response.ok) {
 | 
			
		||||
        throw new Error('Failed to delete payment');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Redirect to dashboard after successful deletion
 | 
			
		||||
      goto('/cospend');
 | 
			
		||||
      
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      error = err.message;
 | 
			
		||||
    } finally {
 | 
			
		||||
      deleting = false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<svelte:head>
 | 
			
		||||
@@ -199,7 +173,7 @@
 | 
			
		||||
  {/if}
 | 
			
		||||
</main>
 | 
			
		||||
 | 
			
		||||
{#if payment && payment.createdBy === data.session.user.nickname}
 | 
			
		||||
{#if payment}
 | 
			
		||||
  <EditButton href="/cospend/payments/edit/{data.paymentId}" />
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user