| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- import { View, Text, Image } from "@tarojs/components";
- import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
- import { getLatestJournal, records } from "@/services/health";
- import './History.scss'
- import Calendar from "./calendar";
- import { useDispatch, useSelector } from "react-redux";
- import HistoryItem from "./HistoryItem";
- import { rpxToPx } from "@/utils/tools";
- import { jumpPage } from "../trackTimeDuration/hooks/Common";
- import Taro, { useReady } from "@tarojs/taro";
- import { getScenario, getThemeColor } from "./hooks/health_hooks";
- import { TimeFormatter } from "@/utils/time_format";
- import dayjs from "dayjs";
- import { MainColorType } from "@/context/themes/color";
- import { IconArrow, IconCellArrow, IconClose } from "@/components/basic/Icons";
- import NoRecord from "@/_health/components/no_record";
- import ListFooter from "@/_health/components/list_footer";
- import { useTranslation } from "react-i18next";
- import { setActiveTip, setEatTip, setFirstActiveId, setFirstEatId } from "@/store/health";
- import RightArrowRow from "@/_health/components/right_arrow_row";
- import NewButton, { NewButtonType } from "@/_health/base/new_button";
- import TimelineDate from "@/_health/components/timeline_date";
- let lastMode = ''
- let myScrollTop = 0
- export default forwardRef((props: { type?: string, fast_type?: string, updateDate?: any, refreshSuccess?: any }, ref) => {
- const [itemLayouts, setItemLayouts] = useState<any>([])
- const [itemHeights, setItemHeights] = useState<any>([])
- const [list, setList] = useState<any>([])
- const [page, setPage] = useState(1)
- const [total, setTotal] = useState(0)
- const [loaded, setLoaded] = useState(false)
- const health = useSelector((state: any) => state.health);
- const user = useSelector((state: any) => state.user);
- const [loading, setLoading] = useState(false)
- const [showEatArchive, setShowEatArchive] = useState(true)
- const [showActiveArchive, setShowActiveArchive] = useState(true)
- const [fastList, setFastList] = useState<any>([])
- const [eatList, setEatList] = useState<any>([])
- const [activeList, setActiveList] = useState<any>([])
- const [sleepList, setSleepList] = useState<any>([])
- const [fastTotal, setFastTotal] = useState(-1)
- const [eatTotal, setEatTotal] = useState(-1)
- const [activeTotal, setActiveTotal] = useState(-1)
- const [sleepTotal, setSleepTotal] = useState(-1)
- const [hideEatArchiveTip, setHideEatArchiveTip] = useState(false)
- const [hideActiveArchiveTip, setHideActiveArchiveTip] = useState(false)
- const [hideFastTip, setHideFastTip] = useState(false)
- const [hideSleepTip, setHideSleepTip] = useState(false)
- const [pageTop, setPageTop] = useState(0)
- const query = Taro.createSelectorQuery()
- const dispatch = useDispatch()
- const { t } = useTranslation()
- useImperativeHandle(ref, () => ({
- onScroll: onScroll,
- refresh: refresh,
- more: more
- }))
- useEffect(() => {
- if (list.length > 0) {
- setTimeout(() => {
- measureItemLayouts()
- }, 300)
- }
- }, [list])
- useEffect(() => {
- if (!user.isLogin) {
- setList([])
- }
- }, [user.isLogin])
- useEffect(()=>{
- return ()=>{
- myScrollTop = 0
- }
- },[])
- global.refreshHistory = () => {
- refresh()
- refreshItem('FAST')
- refreshItem('SLEEP')
- refreshItem('EAT')
- refreshItem('ACTIVE')
- }
- useEffect(() => {
- if (props.type) {
- loadData(1)
- }
- }, [props.type])
- useEffect(() => {
- if (lastMode != health.mode) {
- lastMode = health.mode
- // loadData(1)
- setPage(1)
- switch (health.mode) {
- case 'DAY':
- case 'NIGHT':
- setList([])
- return
- case 'FAST':
- if (fastList.length > 0) {
- setList(fastList)
- setTotal(fastTotal)
- return;
- }
- break
- case 'EAT':
- if (eatList.length > 0) {
- setList(eatList)
- setTotal(eatTotal)
- return;
- }
- break
- case 'SLEEP':
- if (sleepList.length > 0) {
- setList(sleepList)
- setTotal(sleepTotal)
- return;
- }
- break
- case 'ACTIVE':
- if (activeList.length > 0) {
- setList(activeList)
- setTotal(activeTotal)
- return;
- }
- break
- }
- loadData(1)
- }
- }, [health.mode])
- function measureItemLayouts() {
-
- list.forEach((item, index) => {
- query.select(`#history-${index}`).boundingClientRect()
- });
- query.exec((res) => {
- var layouts: any = []
- var heights: any = []
- res.forEach((rect, index) => {
- if (rect) {
- layouts[index] = rect.top + myScrollTop
- heights[index] = rect.height
- }
- });
- setItemLayouts(layouts)
- setItemHeights(heights)
- })
- }
- function onScroll(e) {
- // var top = e.detail.scrollTop
- // myScrollTop = top
- var top = e.detail.scrollTop - e.detail.deltaY
- myScrollTop = e.detail.scrollTop
- setPageTop(top)
- if (itemLayouts.length > 0) {
- var i = -1
- var date = ''
- list.forEach((item, index) => {
- if (top >= itemLayouts[index] - 50) {
- i = index
- if (TimeFormatter.isTimestampInThisWeek(item.window_range.start_timestamp)) {
- date = t('health.this_week')
- }
- else if (dayjs(item.window_range.start_timestamp).format('YYYY') == dayjs().format('YYYY')) {
- date = global.language == 'en' ? dayjs(item.window_range.start_timestamp).format('MMMM') : dayjs(item.window_range.start_timestamp).format('MMMM')
- }
- else {
- date = global.language == 'en' ? dayjs(item.window_range.start_timestamp).format('YYYY') : dayjs(item.window_range.start_timestamp).format('YYYY年')
- }
- }
- })
- if (props.updateDate) {
- props.updateDate({
- show: i != -1,
- date: date
- })
- }
- }
- else {
- if (props.updateDate) {
- props.updateDate({
- show: false,
- date: ''
- })
- }
- }
- }
- function refresh() {
- loadData(1)
- setPage(1)
- }
- function more() {
- if (loading) return;
- if (total == list.length) return;
- var index = page;
- index++;
- setPage(index)
- loadData(index)
- }
- function refreshItem(type) {
- setPage(1)
- var params: any = {
- window: type,
- limit: 10,
- page: 1
- }
- records(params).then(res => {
- var array = (res as any).data
- array.map(item => {
- var temps: any = []
- var lastType = ''
- var lastTextArray: any = []
- var lastImageArray: any = []
- item.events.map(event => {
- event.moments && event.moments.map(moment => {
- switch (moment.type) {
- case 'TEXT':
- {
- lastTextArray.push({
- title: moment.title,
- description: moment.description,
- event_id: event.id
- })
- if (lastType == 'PIC') {
- temps.push({
- type: 'PIC',
- data: JSON.parse(JSON.stringify(lastImageArray))
- })
- lastImageArray = []
- }
- lastType = 'TEXT'
- }
- break;
- case 'PIC':
- {
- lastImageArray.push(moment.media[0].url)
- if (lastType == 'TEXT') {
- temps.push({
- type: 'TEXT',
- data: JSON.parse(JSON.stringify(lastTextArray))
- })
- lastTextArray = []
- }
- lastType = 'PIC'
- }
- break;
- case 'PIC_TEXT':
- if (lastType == 'PIC') {
- temps.push({
- type: 'PIC',
- data: JSON.parse(JSON.stringify(lastImageArray))
- })
- lastImageArray = []
- }
- if (lastType == 'TEXT') {
- temps.push({
- type: 'TEXT',
- data: JSON.parse(JSON.stringify(lastTextArray))
- })
- lastTextArray = []
- }
- temps.push({
- type: 'PIC_TEXT',
- data: [
- {
- title: moment.title,
- description: moment.description,
- url: moment.media[0].url,
- urls:moment.media,
- event_id: event.id
- }
- ]
- })
- lastType = 'PIC_TEXT'
- break;
- }
- })
- })
- if (lastType == 'PIC') {
- temps.push({
- type: 'PIC',
- data: JSON.parse(JSON.stringify(lastImageArray))
- })
- lastImageArray = []
- }
- if (lastType == 'TEXT') {
- temps.push({
- type: 'TEXT',
- data: JSON.parse(JSON.stringify(lastTextArray))
- })
- lastTextArray = []
- }
- item.dataArray = temps;
- })
- switch (type) {
- case 'FAST':
- setFastList(array)
- setFastTotal((res as any).total)
- break
- case 'SLEEP':
- setSleepList(array)
- setSleepTotal((res as any).total)
- break
- case 'EAT':
- setEatList(array)
- setEatTotal((res as any).total)
- break
- case 'ACTIVE':
- setActiveList(array)
- setActiveTotal((res as any).total)
- break
- }
- })
- }
- function loadData(index: number) {
- // console.log('load data, page',index)
- if (index == 1) {
- Taro.setStorage({
- key: 'lastRefresh',
- data: new Date().getTime() + ''
- })
- }
- var params: any = {
- window: props.type ? props.type : health.mode,
- limit: 10,
- page: index
- }
- if (props.fast_type) {
- params.fast_type = props.fast_type
- }
- setPage(index)
- setLoading(true)
- records(params).then(res => {
- var array = (res as any).data
-
- array.map(item => {
- var temps: any = []
- var lastType = ''
- var lastTextArray: any = []
- var lastImageArray: any = []
- item.events.map(event => {
- event.moments && event.moments.map(moment => {
- switch (moment.type) {
- case 'TEXT':
- {
- lastTextArray.push({
- title: moment.title,
- description: moment.description,
- event_id: event.id
- })
- if (lastType == 'PIC') {
- temps.push({
- type: 'PIC',
- data: JSON.parse(JSON.stringify(lastImageArray))
- })
- lastImageArray = []
- }
- lastType = 'TEXT'
- }
- break;
- case 'PIC':
- {
- lastImageArray.push(moment.media[0].url)
- if (lastType == 'TEXT') {
- temps.push({
- type: 'TEXT',
- data: JSON.parse(JSON.stringify(lastTextArray))
- })
- lastTextArray = []
- }
- lastType = 'PIC'
- }
- break;
- case 'PIC_TEXT':
- if (lastType == 'PIC') {
- temps.push({
- type: 'PIC',
- data: JSON.parse(JSON.stringify(lastImageArray))
- })
- lastImageArray = []
- }
- if (lastType == 'TEXT') {
- temps.push({
- type: 'TEXT',
- data: JSON.parse(JSON.stringify(lastTextArray))
- })
- lastTextArray = []
- }
- temps.push({
- type: 'PIC_TEXT',
- data: [
- {
- title: moment.title,
- description: moment.description,
- url: moment.media[0].url,
- urls:moment.media,
- event_id: event.id
- }
- ]
- })
- lastType = 'PIC_TEXT'
- break;
- }
- })
- })
- if (lastType == 'PIC') {
- temps.push({
- type: 'PIC',
- data: JSON.parse(JSON.stringify(lastImageArray))
- })
- lastImageArray = []
- }
- if (lastType == 'TEXT') {
- temps.push({
- type: 'TEXT',
- data: JSON.parse(JSON.stringify(lastTextArray))
- })
- lastTextArray = []
- }
- item.dataArray = temps;
- })
- setLoading(false)
- setLoaded(true)
- if (index == 1) {
- // console.log(props.type,health.mode)
- if (!props.type && array.length >= 0) {
- if (health.mode == 'EAT') {
- setEatList(array)
- setList(array)
- setEatTotal((res as any).total)
- }
- else if (health.mode == 'ACTIVE') {
- setActiveList(array)
- setList(array)
- setActiveTotal((res as any).total)
- }
- else if (health.mode == 'FAST') {
- setFastList(array)
- setList(array)
- setFastTotal((res as any).total)
- }
- else if (health.mode == 'SLEEP') {
- setSleepList(array)
- setList(array)
- setSleepTotal((res as any).total)
- }
- }
- setTotal((res as any).total)
- if (props.refreshSuccess) {
- props.refreshSuccess()
- }
- }
- else {
- setList([...list, ...array])
- }
- }).catch(e => {
- setLoading(false)
- })
- }
- function historyMonth(index) {
- var showDate = false;
- var dateStr = ''
- if (index == 0) {
- var currentDate = global.language == 'en' ? dayjs(list[index].window_range.start_timestamp).format('YYYY') : dayjs(list[index].window_range.start_timestamp).format('YYYY年')
- var now = global.language == 'en' ? dayjs().format('YYYY') : dayjs().format('YYYY年')
- if (currentDate != now) {
- showDate = true
- dateStr = currentDate
- }
- }
- else {
- var currentDate = global.language == 'en' ? dayjs(list[index].window_range.start_timestamp).format('YYYY') : dayjs(list[index].window_range.start_timestamp).format('YYYY年')
- var now = global.language == 'en' ? dayjs(list[index - 1].window_range.start_timestamp).format('YYYY') : dayjs(list[index - 1].window_range.start_timestamp).format('YYYY年')
- if (currentDate != now) {
- showDate = true
- dateStr = currentDate
- }
- }
- if (showDate) {
- return <View className="history_year_month h42 bold" style={{ marginBottom: rpxToPx(60) }}>{dateStr}</View>
- }
- return <View />
- }
- function hideLine(index) {
- var currentDate = dayjs(list[index].window_range.start_timestamp).format('YYYY年M月D日')
- if (list.length > index + 1) {
- var nextDate = dayjs(list[index + 1].window_range.start_timestamp).format('YYYY年M月D日')
- if (currentDate == nextDate) return true
- }
- return false
- }
- if (!loaded || health.mode == 'DAY' || health.mode == 'NIGHT')
- return <View />
- if (!user.isLogin) return <View />
- function showTipF() {
- var showTip = false
- if (getScenario(health.windows, health.mode).status == 'OG') {
- if (health.mode == 'EAT') {
- showTip = !global.hideEatArchiveTip
- }
- else if (health.mode == 'ACTIVE') {
- showTip = !global.hideActiveArchiveTip
- }
- }
- return showTip
- }
- function newJournalTip() {
- if (!props.type) {
- var show = false
- if (health.mode == 'EAT' && health.eat_journal_tip) {
- show = true
- }
- else if (health.mode == 'ACTIVE' && health.active_journal_tip) {
- show = true
- }
- if (show) {
- return <View style={{
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- paddingTop: rpxToPx(82),
- paddingBottom: rpxToPx(82),
- backgroundColor: '#fff',
- position: 'relative'
- }}>
- <View className="archived_bg" onClick={() => {
- // jumpPage('/_health/pages/archive')
- var data = list[0]
- jumpPage(`/_health/pages/timeline_detail?window_id=${data.window_id}&type=recent&isfastsleep=0×tamp=${data.publish.timestamp}`)
- // getLatestJournal(false, {
- // id: health.mode == 'EAT' ? global.eatTipId : global.activeTipId,
- // user_confirmed: true
- // }).then(res => {
- // })
- setTimeout(() => {
- if (health.mode == 'EAT') {
- dispatch(setEatTip(false))
- }
- else {
- dispatch(setActiveTip(false))
- }
- }, 1000)
- }}>
- <Text className="archived_text bold" style={{ color: getThemeColor(health.mode) }}>{t('health.new_journal_created')}</Text>
- {/* {
- health.eatArchived.images.map((item, index) => {
- return <Image src={item} key={index} className="archived_img" mode="aspectFill" />
- })
- } */}
- <IconArrow color={MainColorType.g02} width={rpxToPx(34)} />
- </View>
- <View className="border_footer_line" />
- </View>
- // return <View className="h28 bold"
- // onClick={()=>{
- // if (health.mode == 'EAT'){
- // dispatch(setEatTip(false))
- // }
- // else {
- // dispatch(setActiveTip(false))
- // }
- // }}
- // style={{
- // width:rpxToPx(750),
- // height:rpxToPx(156),
- // display:'flex',
- // alignItems:'center',
- // justifyContent:'center',
- // backgroundColor:'#fff',
- // color:getThemeColor(health.mode),
- // }}>
- // New Journal Created {'>'}
- // </View>
- }
- }
- return <View />
- }
- function markDoneTip() {
- if (health.mode == 'DAY' && health.mode != 'NIGHT') return
- var scenario = getScenario(health.windows, health.mode)
- if (scenario.status != 'OG') return
- if (health.mode == 'EAT' && hideEatArchiveTip) return
- if (health.mode == 'ACTIVE' && hideActiveArchiveTip) return
- if (health.mode == 'FAST' && hideFastTip) return
- if (health.mode == 'SLEEP' && hideSleepTip) return
- function tipContent() {
- var strTime = ''
- var today = new Date().getDate()
- var date = new Date(scenario.archive_timestamp).getDate()
- var time = dayjs(scenario.archive_timestamp).format('HH:mm')
- if (today == date) {
- strTime = t('health.today_at', { time: time })
- if (global.language == 'en') {
- if (time == '23:59') {
- strTime = 'at midnight'
- }
- else {
- strTime = `today at ${time}`
- }
- }
- }
- else {
- strTime = t('health.tomorrow_at', { time: time })
- if (global.language == 'en') {
- strTime = `tomorrow at ${time}`
- }
- }
- switch (health.mode) {
- case 'FAST':
- if (global.language == 'en') {
- return <Text className="h26 g01"><Text className="bold">Today's Moments</Text> will appear in Recents when you <Text className="italic">log end fast</Text>.</Text>
- }
- return <Text className="h26 g01"><Text className="bold">今天的时刻</Text> 将在您 <Text className="italic">记录结束断食</Text> 之际,出现在最近记录中。</Text>
- case 'SLEEP':
- if (global.language == 'en') {
- return <Text className="h26 g01"><Text className="bold">Today's Moments</Text> will appear in Recents when you <Text className="italic">log wake up</Text>.</Text>
- }
- return <Text className="h26 g01"><Text className="bold">今天的时刻</Text> 将在您 <Text className="italic">记录起床</Text> 之际,出现在最近记录中。</Text>
- case 'EAT':
- case 'ACTIVE':
- if (global.language == 'en') {
- return <Text className="h26 g01"><Text className="bold">Today's Moments</Text> will appear in Recents {strTime} or when you <Text className="italic">mark done</Text>.</Text>
- }
- return <Text className="h26 g01"><Text className="bold">今天的时刻</Text> 将在今夜或在您 <Text className="italic">标记完成</Text> 之际,出现在最近记录中。</Text>
- }
- return <Text className="h26">1</Text>
- }
- return <View className="mark_done_tip" style={{
- backgroundColor: '#fff'//getThemeColor(health.mode) + '1A'
- }}>
- <View style={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
- {
- tipContent()
- }
- </View>
- <NewButton type={NewButtonType.img} btnStyle={{
- paddingLeft: 20,
- height: rpxToPx(32),
- width: rpxToPx(32)
- }} onClick={() => {
- switch (health.mode) {
- case 'FAST':
- setHideFastTip(true)
- break;
- case 'EAT':
- setHideEatArchiveTip(true)
- break;
- case 'SLEEP':
- setHideSleepTip(true)
- break
- case 'ACTIVE':
- setHideActiveArchiveTip(true)
- break
- }
- }}>
- <IconClose color={MainColorType.g03} width={rpxToPx(32)} height={rpxToPx(32)} />
- </NewButton>
- <View className="border_footer_line" />
- </View>
- }
- return <View style={{ width: rpxToPx(750) }}>
- {
- (list.length >= 0 || health.mode == 'EAT' || health.mode == 'ACTIVE') && <View className="new_header_bg2">
- <Text className="h50 bold">{t('health.recents')}</Text>
- {
- (health.mode == 'EAT' || health.mode == 'ACTIVE') && <View style={{ marginTop: rpxToPx(0) }}><RightArrowRow
- height={rpxToPx(50)}
- title={t('health.my_journal')}
- bgColor="transparent"
- onClick={() => {
- var showBadge = (health.mode == 'EAT' && health.eat_journal_tip) ||
- (health.mode == 'ACTIVE' && health.active_journal_tip)
- jumpPage('/pages/account/Journal?type=' + health.mode + `&show_tip=${showTipF() && false ? '1' : '0'}&show_badge=${showBadge ? 1 : 0}`)
- }} />
- </View>
- }
- </View>
- }
- {
- markDoneTip()
- }
- {
- list.length == 0 && <NoRecord />
- }
- {
- list.length > 0 && <View style={{ minHeight: rpxToPx(464), backgroundColor: '#fff', paddingTop: rpxToPx(60) }}>
- {
- list.map((item, index) => {
- if (itemLayouts.length >= index + 1 && pageTop > 0) {
- if (Math.abs(itemLayouts[index] - pageTop) > 3000) {
- return <View style={{ height: itemHeights[index] }} id={`history-${index}`}>
- {/* {index} */}
- </View>
- }
- if (Math.abs(itemLayouts[index] - pageTop) > 1500) {
- return <View style={{
- height: itemHeights[index], display: 'flex',
- paddingLeft: rpxToPx(40),
- paddingRight: rpxToPx(40),
- boxSizing: 'border-box',
- flexDirection: 'row'
- }} id={`history-${index}`}>
- <TimelineDate timestamp={item.window_range.start_timestamp}
- pre_timestamp={index > 0 ? list[index - 1].window_range.start_timestamp : null}
- />
- <View style={{
- display: 'flex', flexDirection: 'column', flex: 1,
- width: rpxToPx(552), height: itemHeights[index] - rpxToPx(60), backgroundColor: '#fafafa'
- }}>
- </View>
- </View>
- }
- }
- return <View id={`history-${index}`} key={index}>
- {
- historyMonth(index)
- }
- <HistoryItem
- data={item}
- preData={index > 0 ? list[index - 1] : null}
- index={index}
- mode={props.type ?? health.mode}
- fast_type={props.fast_type}
- type={props.type}
- hideLine={hideLine(index)}
- onClick={() => {
- }} />
- </View>
- })
- }
- </View>
- }
- {/* <View style={{ height: rpxToPx(40), flexShrink: 0, backgroundColor: '#fff' }} /> */}
- <ListFooter noMore={(list.length > 0) && (total == list.length)} loading={loading} />
- </View>
- })
|