Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
rleed committed Sep 26, 2023
2 parents d9c4753 + b7eb83b commit 0ec4135
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 14 deletions.
8 changes: 5 additions & 3 deletions api/resolvers/growth.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export function interval (when) {
case 'year':
return '1 year'
case 'forever':
case 'custom':
return null
default:
return '1 day'
Expand All @@ -19,6 +20,7 @@ export function timeUnit (when) {
switch (when) {
case 'week':
case 'month':
case 'custom':
return 'day'
case 'year':
case 'forever':
Expand Down Expand Up @@ -46,15 +48,15 @@ export function withClause (when) {
// HACKY AF this is a performance enhancement that allows us to use the created_at indices on tables
export function intervalClause (when, table, and) {
const unit = timeUnit(when)
if (when === 'forever') {
if (when === 'forever' || when === 'custom') {
return and ? '' : 'TRUE'
}

return `"${table}".created_at >= date_trunc('${unit}', now_utc() - interval '${interval(when)}') ${and ? 'AND' : ''} `
return `"${table}".created_at >= date_trunc('${unit}', now_utc() - interval '${(when)}') ${and ? 'AND' : ''} `
}

export function viewIntervalClause (when, view, and) {
if (when === 'forever') {
if (when === 'forever' || when === 'custom') {
return and ? '' : 'TRUE'
}

Expand Down
1 change: 1 addition & 0 deletions api/resolvers/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ function whenClause (when, type) {
let interval = ` AND "${type === 'bookmarks' ? 'Bookmark' : 'Item'}".created_at >= $1 - INTERVAL `
switch (when) {
case 'forever':
case 'custom':
interval = ''
break
case 'week':
Expand Down
2 changes: 2 additions & 0 deletions components/charts.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const dateFormatter = when => {
switch (when) {
case 'week':
case 'month':
case 'custom':
return `${('0' + (date.getUTCMonth() % 12 + 1)).slice(-2)}/${date.getUTCDate()}`
case 'year':
case 'forever':
Expand All @@ -35,6 +36,7 @@ function xAxisName (when) {
switch (when) {
case 'week':
case 'month':
case 'custom':
return 'days'
case 'year':
case 'forever':
Expand Down
29 changes: 29 additions & 0 deletions components/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import TextareaAutosize from 'react-textarea-autosize'
import { useToast } from './toast'
import { useInvoiceable } from './invoice'
import { numWithUnits } from '../lib/format'
import ReactDatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
import { dayMonthYear } from '../lib/time'

export function SubmitButton ({
children, variant, value, onClick, disabled, cost, ...props
Expand Down Expand Up @@ -582,3 +585,29 @@ export function Select ({ label, items, groupClassName, onChange, noForm, overri
</FormGroup>
)
}

export function DatePicker ({ fromName, toName, noForm, onMount, ...props }) {
const formik = noForm ? null : useFormikContext()
const onChangeSupplied = props.onChange
const [,, fromHelpers] = noForm ? [{}, {}, {}] : useField({ ...props, name: fromName })
const [,, toHelpers] = noForm ? [{}, {}, {}] : useField({ ...props, name: toName })

useEffect(() => {
if (onMount) {
const [from, to] = onMount()
fromHelpers.setValue(from)
toHelpers.setValue(to)
}
}, [])

return (
<ReactDatePicker
{...props}
onChange={([from, to], e) => {
fromHelpers.setValue(dayMonthYear(from))
toHelpers.setValue(dayMonthYear(to))
onChangeSupplied(formik, [from, to], e)
}}
/>
)
}
40 changes: 35 additions & 5 deletions components/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import Container from 'react-bootstrap/Container'
import styles from './search.module.css'
import SearchIcon from '../svgs/search-line.svg'
import { useEffect, useRef, useState } from 'react'
import { Form, Input, Select, SubmitButton } from './form'
import { Form, Input, Select, DatePicker, SubmitButton } from './form'
import { useRouter } from 'next/router'
import { dayMonthYear } from '../lib/time'

export default function Search ({ sub }) {
const router = useRouter()
Expand Down Expand Up @@ -35,6 +36,7 @@ export default function Search ({ sub }) {
if (values.what === '' || values.what === 'all') delete values.what
if (values.sort === '' || values.sort === 'zaprank') delete values.sort
if (values.when === '' || values.when === 'forever') delete values.when
if (values.when !== 'custom') { delete values.from; delete values.to }
await router.push({
pathname: prefix + '/search',
query: values
Expand All @@ -46,13 +48,21 @@ export default function Search ({ sub }) {
const what = router.pathname.startsWith('/stackers') ? 'stackers' : router.query.what || 'all'
const sort = router.query.sort || 'zaprank'
const when = router.query.when || 'forever'
const from = router.query.from || dayMonthYear(new Date())
const to = router.query.to || dayMonthYear(new Date())

const [datePicker, setDatePicker] = useState(when === 'custom')
// The following state is needed for the date picker (and driven by the date picker).
// Substituting router.query or formik values would cause network lag and/or timezone issues.
const timepart = 'T' + new Date().toISOString().split('T')[1]
const [range, setRange] = useState({ start: new Date(from + timepart), end: new Date(to + timepart) })

return (
<>
<div className={styles.searchSection}>
<Container className={`px-md-0 ${styles.searchContainer} ${filter ? styles.leaveRoom : ''}`}>
<Form
initial={{ q, what, sort, when }}
initial={{ q, what, sort, when, from, to }}
onSubmit={search}
>
<div className={`${styles.active} my-3`}>
Expand Down Expand Up @@ -97,13 +107,33 @@ export default function Search ({ sub }) {
for
<Select
groupClassName='mb-0 ms-2'
onChange={(formik, e) => search({ ...formik?.values, when: e.target.value })}
onChange={(formik, e) => {
search({ ...formik?.values, when: e.target.value, from: from || dayMonthYear(new Date()), to: to || dayMonthYear(new Date()) })
setDatePicker(e.target.value === 'custom')
if (e.target.value === 'custom') setRange({ start: new Date(), end: new Date() })
}}
name='when'
size='sm'
overrideValue={when}
items={['forever', 'day', 'week', 'month', 'year']}
items={['custom', 'forever', 'day', 'week', 'month', 'year']}
/>

{datePicker &&
<DatePicker
fromName='from' toName='to'
className='form-control ms-2 p-0 px-2'
onMount={() => {
setRange({ start: new Date(from + timepart), end: new Date(to + timepart) })
return [from, to]
}}
onChange={(formik, [start, end], e) => {
setRange({ start, end })
search({ ...formik?.values, from: start && dayMonthYear(start), to: end && dayMonthYear(end) })
}}
selected={range.start}
startDate={range.start} endDate={range.end}
selectsRange
maxDate={new Date()}
/>}
</>}
</div>}
</Form>
Expand Down
102 changes: 96 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"react-avatar-editor": "^13.0.0",
"react-bootstrap": "^2.8.0",
"react-countdown": "^2.3.5",
"react-datepicker": "^4.17.0",
"react-dom": "^18.2.0",
"react-longpressable": "^1.1.1",
"react-markdown": "^8.0.7",
Expand Down

0 comments on commit 0ec4135

Please sign in to comment.