Skip to content

Commit

Permalink
History list UI update
Browse files Browse the repository at this point in the history
  • Loading branch information
prokawsar committed Jul 27, 2024
1 parent 6fab4ea commit 0d4968a
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 117 deletions.
67 changes: 67 additions & 0 deletions src/lib/elements/HistoryRow.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script lang="ts">
import { get40Percent, type CostHistoryType } from '$lib/utils/services'
import Icon from '@iconify/svelte'
import dayjs from 'dayjs'
import { createEventDispatcher } from 'svelte'
export let cost: CostHistoryType
export let isTrash: boolean = false
const dispatch = createEventDispatcher()
let deleteConfirm = ''
</script>

<div class="flex flex-col gap-1 items-center w-full p-1 border border-dashed rounded shadow-sm">
{#if cost}
<a href="/history/{cost.id}" class="flex flex-row items-center pl-1 justify-between w-full">
<p class:hidden={!cost.name} class="truncate w-[40%]">
{cost.name}
</p>
<p class="text-gray-500 text-sm truncate">
{cost.final_price.toFixed(2)}
<span class=" text-teal-600">
({(cost.final_price + get40Percent(cost.final_price)).toFixed(2)})
</span>
</p>
<p class="w-fit text-[10px] text-gray-500 truncate">
{dayjs(cost.created_at).format('DD-MM-YYYY')}
</p>

<div class="flex flex-row items-center gap-[2px]">
<button
class:hidden={deleteConfirm == cost.id || !isTrash}
class="border border-green-300 rounded text-green-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => dispatch('restore', cost.id)}
>
<Icon icon="ic:round-settings-backup-restore" />
</button>
<button
class:hidden={deleteConfirm == cost.id}
class="border border-red-300 rounded text-red-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = cost.id || '')}
>
{#if isTrash}
<Icon icon="ic:baseline-delete-forever" />
{:else}
<Icon icon="ph:trash-light" width="16px" />
{/if}
</button>
{#if deleteConfirm == cost.id}
<button
class="border border-yellow-300 p-[3px] rounded text-yellow-600 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = '')}
>
<Icon icon="majesticons:multiply" width="16px" />
</button>
<button
class="border border-green-300 p-[3px] rounded text-green-700 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => dispatch('delete', cost.id)}
>
<Icon icon="teenyicons:tick-solid" width="15px" />
</button>
{/if}
</div>
</a>
{/if}
</div>
8 changes: 5 additions & 3 deletions src/lib/elements/Result.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<script lang="ts">
import { get40Percent } from '$lib/utils/services'
export let total: number = 0
$: _40Percent = (total * 40) / 100
$: _40Percent = get40Percent(total)
</script>

<div class="flex flex-col gap-1 w-full border shadow-md rounded py-1 px-2">
<div class="flex flex-row justify-between">
<p class="text-teal-600">Total:</p>
<p>
{total.toFixed(3)}
{total.toFixed(2)}
</p>
</div>
<div class="flex flex-row justify-between">
<p class="text-teal-600">Total with (40%):</p>
<p>
{(total + _40Percent).toFixed(3)}
{(total + _40Percent).toFixed(2)}
</p>
</div>
</div>
10 changes: 10 additions & 0 deletions src/lib/utils/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ export const calculateCost = (paper: Paper): number => {
return result * parseFloat(paper.rate)
}

// export const calculateCost = (paper: Paper): number => {
// const paperSize = parseFloat(paper.length) * parseFloat(paper.width) * parseFloat(paper.thickness)
// const result: number = parseFloat(paperSize.toFixed(2)) / PAPER_FIXED
// return result * parseFloat(parseFloat(paper.rate).toFixed(2))
// }

export const get40Percent = (cost: number) => {
return (cost * 40) / 100
}

export const addHistory = async (history: CostHistoryType) => {
const { data, error } = await supabase.from('history').insert({
name: history.name || '',
Expand Down
12 changes: 12 additions & 0 deletions src/lib/utils/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,15 @@ export const [send, receive] = crossfade({
}
}
})

export const sortedByCreatedAt = (data: any) => {
return data.sort((a: any, b: any) => {
// Convert 'created_at' strings to Date objects
let dateA = new Date(a.created_at)
let dateB = new Date(b.created_at)

if (dateA > dateB) return -1
if (dateA < dateB) return 1
return 0
})
}
5 changes: 3 additions & 2 deletions src/routes/(app)/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

<main class="h-[100svh] flex flex-col justify-between">
<Toaster
duration={2000}
richColors
toastOptions={{
class: 'py-2 mb-8'
Expand All @@ -51,7 +52,7 @@

<!-- Footer menu section -->
<div
class="max-w-6xl mx-auto w-full flex flex-row h-11 px-3 bg-slate-50 border-t border-teal-500 items-center justify-between rounded-t-lg"
class="max-w-6xl mx-auto w-full flex flex-row h-11 px-5 bg-slate-50 border-t border-teal-500 items-center justify-between rounded-t-lg"
>
<!-- <p class="text-right md:text-center text-gray-400 w-3/4">
&#x1F4BB;Developed by <a href="https://github.com/prokawsar" target="_blank">ProKawsar</a
Expand Down Expand Up @@ -81,7 +82,7 @@
{#if showSettings}
<div
transition:slide={{ axis: 'y', duration: 200 }}
class="absolute w-20 right-2 bottom-11 flex flex-col items-start divide-y divide-orange-400 gap-1 bg-slate-50 p-2 rounded"
class="absolute w-20 right-3 bottom-11 flex flex-col items-start divide-y divide-orange-400 gap-1 bg-slate-50 p-2 rounded"
>
<!-- <button on:click={() => handleLogout()}>Logout</button> -->
<button>About</button>
Expand Down
47 changes: 3 additions & 44 deletions src/routes/(app)/history/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<script lang="ts">
import { invalidateAll } from '$app/navigation'
import HistoryRow from '$lib/elements/HistoryRow.svelte'
import Loader from '$lib/elements/Loader.svelte'
import { softDeleteHistory } from '$lib/utils/services.js'
import Icon from '@iconify/svelte'
import days from 'dayjs'
import mixpanel from 'mixpanel-browser'
import { toast } from 'svelte-sonner'
export let data
let isLoading = false
let deleteConfirm = ''
mixpanel.track_pageview({
url: '/history'
Expand Down Expand Up @@ -53,48 +52,8 @@
{#if !isLoading}
{#if data.histories.length}
<div class="flex flex-col gap-2 overflow-y-auto">
{#each sortedByCreatedAt(data.histories) as { name, id, final_price, created_at }}
<div
class="flex flex-col gap-1 items-center w-full p-1 border border-dashed rounded shadow-sm"
>
<a
href="/history/{id}"
class="flex flex-row items-center pl-1 justify-between w-full"
>
<p class:hidden={!name} class="w-fit truncate">
{name}
</p>
<p class="w-fit text-sm text-gray-500 truncate">
{days(created_at).format('DD-MM-YYYY hh:mmA')}
</p>
<p class="text-gray-500 text-sm truncate">
{final_price.toFixed(2)}
</p>
<div class="flex flex-row items-center gap-[2px]">
<button
class:hidden={deleteConfirm == id}
class="border border-red-300 rounded text-red-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = id)}
>
<Icon icon="ph:trash-light" width="16px" />
</button>
{#if deleteConfirm == id}
<button
class="border border-yellow-300 p-[3px] rounded text-yellow-600 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = '')}
>
<Icon icon="majesticons:multiply" width="16px" />
</button>
<button
class="border border-green-300 p-[3px] rounded text-green-700 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => handleDelete(id)}
>
<Icon icon="teenyicons:tick-solid" width="15px" />
</button>
{/if}
</div>
</a>
</div>
{#each sortedByCreatedAt(data.histories) as cost}
<HistoryRow {cost} on:delete={(e) => handleDelete(e.detail)} />
{/each}
</div>
{:else}
Expand Down
4 changes: 2 additions & 2 deletions src/routes/(app)/history/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<title>History</title>
</svelte:head>

<section class="max-w-6xl mx-auto flex w-full max-h-[85%] flex-col gap-4 px-4 pt-5">
<section class="max-w-6xl mx-auto flex w-full max-h-[90%] flex-col gap-4 px-4 pt-5">
<h1 class="text-xl text-center">Cost Details</h1>
<div class="w-full bg-gradient-to-r from-transparent via-slate-600/10 to-transparent p-[1px]" />
{#if history}
Expand All @@ -30,7 +30,7 @@
</h1>
</div>

<div class="flex flex-col w-full justify-between gap-3 h-[75%] items-center">
<div class="flex flex-col w-full justify-between gap-3 h-[80%] items-center">
<div class="flex flex-col overflow-y-auto w-full max-w-3xl py-2">
{#if history.papers.length}
{#each history.papers as { length, width, thickness, rate, id }}
Expand Down
76 changes: 10 additions & 66 deletions src/routes/(app)/history/trash/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<script lang="ts">
import { invalidateAll } from '$app/navigation'
import HistoryRow from '$lib/elements/HistoryRow.svelte'
import Loader from '$lib/elements/Loader.svelte'
import { deleteHistory, restoreHistory } from '$lib/utils/services.js'
import Icon from '@iconify/svelte'
import days from 'dayjs'
import { sortedByCreatedAt } from '$lib/utils/tools.js'
import mixpanel from 'mixpanel-browser'
import { toast } from 'svelte-sonner'
export let data
let isLoading = false
let deleteConfirm = ''
mixpanel.track_pageview({
url: '/history/trash'
Expand All @@ -28,19 +27,7 @@
await restoreHistory(id)
await invalidateAll()
isLoading = false
toast.message('History restored successfully')
}
const sortedByCreatedAt = (data: any) => {
return data.sort((a: any, b: any) => {
// Convert 'created_at' strings to Date objects
let dateA = new Date(a.created_at)
let dateB = new Date(b.created_at)
if (dateA > dateB) return -1
if (dateA < dateB) return 1
return 0
})
toast.success('History restored successfully')
}
</script>

Expand All @@ -60,56 +47,13 @@
<div class="relative flex flex-col h-full gap-2 overflow-y-auto w-full max-w-3xl py-2 z-0">
{#if !isLoading}
{#if data.histories.length}
{#each sortedByCreatedAt(data.histories) as { name, id, final_price, created_at }}
<div
class="flex flex-col gap-1 items-center w-full p-1 border border-dashed rounded shadow-sm"
>
<a
href="/history/{id}"
class="flex flex-row items-center pl-1 justify-between w-full"
>
<p class:hidden={!name} class="w-fit truncate">
{name}
</p>
<p class="w-fit text-sm text-gray-500 truncate">
{days(created_at).format('DD-MM-YYYY hh:mmA')}
</p>
<p class="text-gray-500 text-sm truncate">
{final_price.toFixed(2)}
</p>
<div class="flex flex-row items-center gap-[2px]">
<button
class:hidden={deleteConfirm == id}
class="border border-green-300 rounded text-green-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => handleRestore(id)}
>
<Icon icon="ic:round-settings-backup-restore" />
</button>

<button
class:hidden={deleteConfirm == id}
class="border border-red-300 rounded text-red-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = id)}
>
<Icon icon="ic:baseline-delete-forever" />
</button>
{#if deleteConfirm == id}
<button
class="border border-yellow-300 p-[3px] rounded text-yellow-600 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = '')}
>
<Icon icon="majesticons:multiply" width="16px" />
</button>
<button
class="border border-green-300 p-[3px] rounded text-green-700 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => handleDelete(id)}
>
<Icon icon="teenyicons:tick-solid" width="15px" />
</button>
{/if}
</div>
</a>
</div>
{#each sortedByCreatedAt(data.histories) as cost}
<HistoryRow
isTrash
{cost}
on:restore={(e) => handleRestore(e.detail)}
on:delete={(e) => handleDelete(e.detail)}
/>
{/each}
{:else}
<p class="text-center text-gray-500">Trash is empty</p>
Expand Down

0 comments on commit 0d4968a

Please sign in to comment.