import React from 'react'
import * as types from 'notion-types'
import formatNumber from 'format-number'
import { format } from 'date-fns'
import { cs } from '../utils'
import { Checkbox } from './checkbox'
import { useNotionContext } from '../context'
import { Text } from './text'
import { evalFormula } from '../eval-formula'
import { PageTitle } from './page-title'
import { GracefulImage } from './graceful-image'
/**
* Renders a single value of structured Notion data according to its schema.
*
* This corresponds to rendering the content of a single cell in a table.
* Property rendering is re-used across all the different types of collection views.
*/
export const Property: React.FC<{
schema?: types.CollectionPropertySchema
data?: types.Decoration[]
block?: types.Block
collection?: types.Collection
inline?: boolean
}> = ({ schema, data, block, collection, inline = false }) => {
const { components, mapImageUrl, mapPageUrl } = useNotionContext()
if (schema) {
let content = null
if (
data ||
schema.type === 'checkbox' ||
schema.type === 'title' ||
schema.type === 'formula' ||
schema.type === 'created_by' ||
schema.type === 'last_edited_by' ||
schema.type === 'created_time' ||
schema.type === 'last_edited_time'
) {
switch (schema.type) {
case 'relation':
// console.log('relation', schema, data)
content =
break
case 'formula':
// TODO
// console.log('formula', schema.formula, {
// schema: collection?.schema,
// properties: block?.properties
// })
try {
content = evalFormula(schema.formula, {
schema: collection?.schema,
properties: block?.properties
})
if (isNaN(content)) {
console.log('NaN', schema.formula)
}
if (content instanceof Date) {
content = format(content, 'MMM d, YYY hh:mm aa')
}
} catch (err) {
// console.log('error evaluating formula', schema.formula, err)
content = null
}
break
case 'title':
if (block) {
content = (
)
} else {
content =
}
break
case 'select':
// intentional fallthrough
case 'multi_select':
const values = (data[0][0] || '').split(',')
content = values.map((value, index) => {
const option = schema.options?.find(
(option) => value === option.value
)
const color = option?.color
return (
{value}
)
})
break
case 'person':
// console.log('person', schema, data)
content =
break
case 'file':
// TODO: assets should be previewable via image-zoom
const files = data
.filter((v) => v.length === 2)
.map((f) => f.flat().flat())
content = files.map((file, i) => (
))
break
case 'checkbox':
const isChecked = data && data[0][0] === 'Yes'
return
case 'url':
// TODO: refactor to less hackyh solution
const d = JSON.parse(JSON.stringify(data))
if (inline) {
try {
const url = new URL(d[0][0])
d[0][0] = url.hostname.replace(/^www\./, '')
} catch (err) {
// ignore invalid urls
}
}
content = (
)
break
case 'email':
content =
break
case 'phone_number':
content =
break
case 'number':
const value = parseFloat(data[0][0] || '0')
let breakEarly = false
let output = ''
if (isNaN(value)) {
content =
} else {
switch (schema.number_format) {
case 'number_with_commas':
output = formatNumber()(value)
break
case 'percent':
output = formatNumber({ suffix: '%' })(value * 100)
break
case 'dollar':
output = formatNumber({ prefix: '$', round: 2, padRight: 2 })(
value
)
break
case 'euro':
output = formatNumber({ prefix: '€', round: 2, padRight: 2 })(
value
)
break
case 'pound':
output = formatNumber({ prefix: '£', round: 2, padRight: 2 })(
value
)
break
case 'yen':
output = formatNumber({ prefix: '¥', round: 0 })(value)
break
case 'rupee':
output = formatNumber({ prefix: '₹', round: 2, padRight: 2 })(
value
)
break
case 'won':
output = formatNumber({ prefix: '₩', round: 0 })(value)
break
case 'yuan':
output = formatNumber({ prefix: 'CN¥', round: 2, padRight: 2 })(
value
)
break
default:
content =
breakEarly = true
break
}
if (!breakEarly) {
content =
}
}
break
case 'created_time':
content = format(new Date(block.created_time), 'MMM d, YYY hh:mm aa')
break
case 'last_edited_time':
content = format(
new Date(block.last_edited_time),
'MMM d, YYY hh:mm aa'
)
break
case 'created_by':
console.log('created_by', schema, data)
break
case 'last_edited_by':
console.log('last_edited_by', schema, data)
break
default:
content =
break
}
}
return (
{content}
)
}
return null
}