|
|
|
@ -6,6 +6,19 @@
|
|
|
|
import { zod } from 'sveltekit-superforms/adapters'
|
|
|
|
import { zod } from 'sveltekit-superforms/adapters'
|
|
|
|
import { formSchema, intervals } from './schema'
|
|
|
|
import { formSchema, intervals } from './schema'
|
|
|
|
import { categories } from './schema'
|
|
|
|
import { categories } from './schema'
|
|
|
|
|
|
|
|
import { CalendarIcon } from 'lucide-svelte'
|
|
|
|
|
|
|
|
import { Calendar } from '$lib/components/ui/calendar/index.js'
|
|
|
|
|
|
|
|
import * as Popover from '$lib/components/ui/popover/index.js'
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
|
|
|
CalendarDate,
|
|
|
|
|
|
|
|
DateFormatter,
|
|
|
|
|
|
|
|
type DateValue,
|
|
|
|
|
|
|
|
getLocalTimeZone,
|
|
|
|
|
|
|
|
parseDate,
|
|
|
|
|
|
|
|
today,
|
|
|
|
|
|
|
|
} from '@internationalized/date'
|
|
|
|
|
|
|
|
import { cn } from '$lib/utils.js'
|
|
|
|
|
|
|
|
import { buttonVariants } from '$lib/components/ui/button'
|
|
|
|
|
|
|
|
|
|
|
|
let { data } = $props()
|
|
|
|
let { data } = $props()
|
|
|
|
|
|
|
|
|
|
|
|
@ -14,16 +27,25 @@
|
|
|
|
resetForm: false,
|
|
|
|
resetForm: false,
|
|
|
|
SPA: true,
|
|
|
|
SPA: true,
|
|
|
|
validators: zod(formSchema),
|
|
|
|
validators: zod(formSchema),
|
|
|
|
onUpdate: async ({ form }) => {
|
|
|
|
onUpdated: async ({ form }) => {
|
|
|
|
|
|
|
|
if (!form.valid) return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log(form.data)
|
|
|
|
// Form validation
|
|
|
|
// Form validation
|
|
|
|
const url = new URL(apiEndpoint)
|
|
|
|
const url = new URL(apiEndpoint)
|
|
|
|
url.searchParams.set('symbol', form.data.symbol)
|
|
|
|
url.searchParams.set('symbol', form.data.symbol)
|
|
|
|
url.searchParams.set('interval', form.data.interval)
|
|
|
|
url.searchParams.set('interval', form.data.interval)
|
|
|
|
if (form.data.start)
|
|
|
|
|
|
|
|
url.searchParams.set('start', form.data.start.toString())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (form.data.end)
|
|
|
|
const start = new Date(
|
|
|
|
url.searchParams.set('end', form.data.end.toString())
|
|
|
|
form.data.start + ' ' + form.data.startTime + ':00',
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
url.searchParams.set('start', start.getTime().toString())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const end = new Date(
|
|
|
|
|
|
|
|
form.data.end + ' ' + form.data.endTime + ':00',
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
url.searchParams.set('end', end.getTime().toString())
|
|
|
|
|
|
|
|
|
|
|
|
if (form.data.limit)
|
|
|
|
if (form.data.limit)
|
|
|
|
url.searchParams.set('limit', form.data.limit.toString())
|
|
|
|
url.searchParams.set('limit', form.data.limit.toString())
|
|
|
|
@ -36,10 +58,20 @@
|
|
|
|
const data = await response.json()
|
|
|
|
const data = await response.json()
|
|
|
|
|
|
|
|
|
|
|
|
console.log(data.result.list)
|
|
|
|
console.log(data.result.list)
|
|
|
|
|
|
|
|
|
|
|
|
let csvContent =
|
|
|
|
let csvContent =
|
|
|
|
'data:text/csv;charset=utf-8,' +
|
|
|
|
'data:text/csv;charset=utf-8,' +
|
|
|
|
'startTime,openPrice,highPrice,lowPrice,closePrice,volume,turnover\n' +
|
|
|
|
'startTime,openPrice,highPrice,lowPrice,closePrice,volume,turnover\n' +
|
|
|
|
data.result.list.map((e: any) => e.join(',')).join('\n')
|
|
|
|
data.result.list
|
|
|
|
|
|
|
|
.map((data: string[]) => {
|
|
|
|
|
|
|
|
let newData = data
|
|
|
|
|
|
|
|
newData[0] = new Date(parseInt(newData[0]))
|
|
|
|
|
|
|
|
.toLocaleString()
|
|
|
|
|
|
|
|
.replace(',', ' |')
|
|
|
|
|
|
|
|
return newData
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.map((e: any) => e.join(','))
|
|
|
|
|
|
|
|
.join('\n')
|
|
|
|
|
|
|
|
|
|
|
|
var encodedUri = encodeURI(csvContent)
|
|
|
|
var encodedUri = encodeURI(csvContent)
|
|
|
|
var link = document.createElement('a')
|
|
|
|
var link = document.createElement('a')
|
|
|
|
@ -52,6 +84,20 @@
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const { form: formData, enhance } = form
|
|
|
|
const { form: formData, enhance } = form
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const df = new DateFormatter('en-US', {
|
|
|
|
|
|
|
|
dateStyle: 'long',
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let start = $state<DateValue | undefined>()
|
|
|
|
|
|
|
|
let end = $state<DateValue | undefined>()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$effect(() => {
|
|
|
|
|
|
|
|
start = $formData.start ? parseDate($formData.start) : undefined
|
|
|
|
|
|
|
|
end = $formData.end ? parseDate($formData.end) : undefined
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let placeholder = $state<DateValue>(today(getLocalTimeZone()))
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<form method="POST" use:enhance>
|
|
|
|
<form method="POST" use:enhance>
|
|
|
|
@ -122,27 +168,114 @@
|
|
|
|
<Form.Description>Category</Form.Description>
|
|
|
|
<Form.Description>Category</Form.Description>
|
|
|
|
<Form.FieldErrors />
|
|
|
|
<Form.FieldErrors />
|
|
|
|
</Form.Field>
|
|
|
|
</Form.Field>
|
|
|
|
<Form.Field {form} name="start">
|
|
|
|
<Form.Field {form} name="start" class="flex flex-col">
|
|
|
|
<Form.Control>
|
|
|
|
<Form.Control>
|
|
|
|
{#snippet children({ props })}
|
|
|
|
{#snippet children({ props })}
|
|
|
|
<Form.Label>Start</Form.Label>
|
|
|
|
<Form.Label>Start Date</Form.Label>
|
|
|
|
|
|
|
|
<Popover.Root>
|
|
|
|
|
|
|
|
<Popover.Trigger
|
|
|
|
|
|
|
|
{...props}
|
|
|
|
|
|
|
|
class={cn(
|
|
|
|
|
|
|
|
buttonVariants({ variant: 'outline' }),
|
|
|
|
|
|
|
|
'w-[280px] justify-start pl-4 text-left font-normal',
|
|
|
|
|
|
|
|
!start && 'text-muted-foreground',
|
|
|
|
|
|
|
|
)}>
|
|
|
|
|
|
|
|
{start
|
|
|
|
|
|
|
|
? df.format(start.toDate(getLocalTimeZone()))
|
|
|
|
|
|
|
|
: 'Pick a date'}
|
|
|
|
|
|
|
|
<CalendarIcon class="ml-auto size-4 opacity-50" />
|
|
|
|
|
|
|
|
</Popover.Trigger>
|
|
|
|
|
|
|
|
<Popover.Content class="w-auto p-0" side="top">
|
|
|
|
|
|
|
|
<Calendar
|
|
|
|
|
|
|
|
type="single"
|
|
|
|
|
|
|
|
value={start as DateValue}
|
|
|
|
|
|
|
|
bind:placeholder
|
|
|
|
|
|
|
|
minValue={new CalendarDate(1900, 1, 1)}
|
|
|
|
|
|
|
|
maxValue={today(getLocalTimeZone())}
|
|
|
|
|
|
|
|
calendarLabel="Date of birth"
|
|
|
|
|
|
|
|
onValueChange={(v) => {
|
|
|
|
|
|
|
|
if (v) {
|
|
|
|
|
|
|
|
$formData.start = v.toString()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
$formData.start = ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}} />
|
|
|
|
|
|
|
|
</Popover.Content>
|
|
|
|
|
|
|
|
</Popover.Root>
|
|
|
|
|
|
|
|
<Form.Description>
|
|
|
|
|
|
|
|
Your date of birth is used to calculator your age
|
|
|
|
|
|
|
|
</Form.Description>
|
|
|
|
|
|
|
|
<Form.FieldErrors />
|
|
|
|
|
|
|
|
<input hidden value={$formData.start} name={props.name} />
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
</Form.Control>
|
|
|
|
|
|
|
|
</Form.Field>
|
|
|
|
|
|
|
|
<Form.Field {form} name="startTime">
|
|
|
|
|
|
|
|
<Form.Control>
|
|
|
|
|
|
|
|
{#snippet children({ props })}
|
|
|
|
|
|
|
|
<Form.Label>Start Time</Form.Label>
|
|
|
|
<Input
|
|
|
|
<Input
|
|
|
|
{...props}
|
|
|
|
{...props}
|
|
|
|
bind:value={$formData.start}
|
|
|
|
bind:value={$formData.startTime}
|
|
|
|
type="number" />
|
|
|
|
type="time" />
|
|
|
|
{/snippet}
|
|
|
|
{/snippet}
|
|
|
|
</Form.Control>
|
|
|
|
</Form.Control>
|
|
|
|
<Form.Description>Start</Form.Description>
|
|
|
|
<Form.Description>Limit</Form.Description>
|
|
|
|
<Form.FieldErrors />
|
|
|
|
<Form.FieldErrors />
|
|
|
|
</Form.Field>
|
|
|
|
</Form.Field>
|
|
|
|
<Form.Field {form} name="end">
|
|
|
|
<Form.Field {form} name="end" class="flex flex-col">
|
|
|
|
|
|
|
|
<Form.Control>
|
|
|
|
|
|
|
|
{#snippet children({ props })}
|
|
|
|
|
|
|
|
<Form.Label>End Date</Form.Label>
|
|
|
|
|
|
|
|
<Popover.Root>
|
|
|
|
|
|
|
|
<Popover.Trigger
|
|
|
|
|
|
|
|
{...props}
|
|
|
|
|
|
|
|
class={cn(
|
|
|
|
|
|
|
|
buttonVariants({ variant: 'outline' }),
|
|
|
|
|
|
|
|
'w-[280px] justify-start pl-4 text-left font-normal',
|
|
|
|
|
|
|
|
!end && 'text-muted-foreground',
|
|
|
|
|
|
|
|
)}>
|
|
|
|
|
|
|
|
{end
|
|
|
|
|
|
|
|
? df.format(end.toDate(getLocalTimeZone()))
|
|
|
|
|
|
|
|
: 'Pick a date'}
|
|
|
|
|
|
|
|
<CalendarIcon class="ml-auto size-4 opacity-50" />
|
|
|
|
|
|
|
|
</Popover.Trigger>
|
|
|
|
|
|
|
|
<Popover.Content class="w-auto p-0" side="top">
|
|
|
|
|
|
|
|
<Calendar
|
|
|
|
|
|
|
|
type="single"
|
|
|
|
|
|
|
|
value={end as DateValue}
|
|
|
|
|
|
|
|
bind:placeholder
|
|
|
|
|
|
|
|
minValue={new CalendarDate(1900, 1, 1)}
|
|
|
|
|
|
|
|
maxValue={today(getLocalTimeZone())}
|
|
|
|
|
|
|
|
calendarLabel="Date of birth"
|
|
|
|
|
|
|
|
onValueChange={(v) => {
|
|
|
|
|
|
|
|
if (v) {
|
|
|
|
|
|
|
|
$formData.end = v.toString()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
$formData.end = ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}} />
|
|
|
|
|
|
|
|
</Popover.Content>
|
|
|
|
|
|
|
|
</Popover.Root>
|
|
|
|
|
|
|
|
<Form.Description>
|
|
|
|
|
|
|
|
Your date of birth is used to calculator your age
|
|
|
|
|
|
|
|
</Form.Description>
|
|
|
|
|
|
|
|
<Form.FieldErrors />
|
|
|
|
|
|
|
|
<input hidden value={$formData.end} name={props.name} />
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
</Form.Control>
|
|
|
|
|
|
|
|
</Form.Field>
|
|
|
|
|
|
|
|
<Form.Field {form} name="endTime">
|
|
|
|
<Form.Control>
|
|
|
|
<Form.Control>
|
|
|
|
{#snippet children({ props })}
|
|
|
|
{#snippet children({ props })}
|
|
|
|
<Form.Label>End</Form.Label>
|
|
|
|
<Form.Label>End Time</Form.Label>
|
|
|
|
<Input {...props} bind:value={$formData.end} type="number" />
|
|
|
|
<Input
|
|
|
|
|
|
|
|
{...props}
|
|
|
|
|
|
|
|
bind:value={$formData.endTime}
|
|
|
|
|
|
|
|
type="time" />
|
|
|
|
{/snippet}
|
|
|
|
{/snippet}
|
|
|
|
</Form.Control>
|
|
|
|
</Form.Control>
|
|
|
|
<Form.Description>End</Form.Description>
|
|
|
|
<Form.Description>Limit</Form.Description>
|
|
|
|
<Form.FieldErrors />
|
|
|
|
<Form.FieldErrors />
|
|
|
|
</Form.Field>
|
|
|
|
</Form.Field>
|
|
|
|
<Form.Button>Submit</Form.Button>
|
|
|
|
<Form.Button>Submit</Form.Button>
|
|
|
|
|