-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
if ur reading this please save me from kyle
- Loading branch information
1 parent
4454c72
commit 8099623
Showing
6 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { UUID } from 'crypto'; | ||
Check failure on line 1 in api/supabase/queries/dashboard.ts
|
||
import { PlantTip } from '@/types/schema'; | ||
import supabase from '../createClient'; | ||
|
||
//quick lil documentation drop: | ||
// Retrieve all tips from the database. Let’s say there are N tips. | ||
// Determine the cycle number using cycleNumber = floor(today’s timestamp / (N * 86400000)). | ||
// This ensures that after N days, a new cycle begins, and the order reshuffles. | ||
// Shuffle tips using a deterministic seed (based on cycleNumber). | ||
// This creates a unique but repeatable order for each cycle. | ||
// Fisher-Yates shuffle ensures every tip appears exactly once before repeating. | ||
// Select today's tip based on day position in the cycle. | ||
// dayInCycle = (today’s date % N), ensuring each tip is picked once per cycle. | ||
|
||
// Function to create a seeded shuffle (Fisher-Yates with a consistent seed) | ||
const seededShuffle = (array: PlantTip[], seed: number): PlantTip[] => { | ||
let shuffled = [...array]; | ||
Check failure on line 17 in api/supabase/queries/dashboard.ts
|
||
for (let i = shuffled.length - 1; i > 0; i--) { | ||
const j = (seed * (i + 1)) % shuffled.length; // Deterministic shuffle | ||
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; | ||
} | ||
return shuffled; | ||
}; | ||
|
||
// Function to get a randomized but cycle-complete daily plant tip | ||
export const getDailyPlantTip = async (): Promise<PlantTip | null> => { | ||
const { data, error } = await supabase.from('gardening_tips').select('*'); | ||
|
||
if (error) { | ||
throw new Error(`Error getting plant tip: ${error.message}`); | ||
} | ||
|
||
// Determine the cycle number (each cycle displays all tips once) | ||
const cycleLength = data.length; | ||
const cycleNumber = Math.floor( | ||
new Date().getTime() / (cycleLength * 86400000), | ||
); // New cycle every 'cycleLength' days | ||
|
||
// Shuffle deterministically based on the cycle number | ||
const shuffledTips = seededShuffle(data, cycleNumber); | ||
|
||
// Select today's tip | ||
const dayInCycle = new Date().getDate() % cycleLength; | ||
return shuffledTips[dayInCycle]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
'use client'; | ||
|
||
import { useEffect, useState } from 'react'; | ||
import { getDailyPlantTip } from '@/api/supabase/queries/dashboard'; | ||
import SingleTip from '@/components/SingleTip'; | ||
import { PlantTip } from '@/types/schema'; | ||
import { useAuth } from '@/utils/AuthProvider'; | ||
import { | ||
ArrowIcon, | ||
CalendarContainer, | ||
Circle, | ||
Container, | ||
DashboardTitle, | ||
Greeting, | ||
Header, | ||
InfoContainer, | ||
InfoHead, | ||
PlaceholderText, | ||
ReminderContainer, | ||
SeeAllLink, | ||
TaskContainer, | ||
Title, | ||
WeatherContainer, | ||
WeatherReminderWrapper, | ||
} from './styles'; | ||
|
||
export default function Page() { | ||
const [plantTip, setPlantTip] = useState<PlantTip | null>(null); | ||
const { userId, loading: authLoading } = useAuth(); | ||
|
||
useEffect(() => { | ||
if (!authLoading && userId) { | ||
const fetchTip = async () => { | ||
const tip = await getDailyPlantTip(); | ||
|
||
setPlantTip(tip); | ||
}; | ||
fetchTip(); | ||
} | ||
}, [authLoading, userId]); | ||
|
||
return ( | ||
<div> | ||
{authLoading || !userId ? ( | ||
<p>Log in please!</p> | ||
) : ( | ||
<Container> | ||
<Greeting>Hi, [Name]!</Greeting> | ||
<DashboardTitle>My Dashboard</DashboardTitle> | ||
<TaskContainer> | ||
<PlaceholderText>Task Placeholder</PlaceholderText> | ||
</TaskContainer> | ||
<CalendarContainer> | ||
<PlaceholderText>Calendar Placeholder</PlaceholderText> | ||
</CalendarContainer> | ||
<WeatherReminderWrapper> | ||
<WeatherContainer> | ||
<PlaceholderText>Weather Placeholder</PlaceholderText> | ||
</WeatherContainer> | ||
<ReminderContainer> | ||
<PlaceholderText>Reminder Placeholder</PlaceholderText> | ||
</ReminderContainer> | ||
</WeatherReminderWrapper> | ||
<Header> | ||
<Title>Resources</Title> | ||
<SeeAllLink href="/resources"> | ||
See All <ArrowIcon>→</ArrowIcon> | ||
</SeeAllLink> | ||
</Header> | ||
|
||
<InfoContainer> | ||
<Circle /> | ||
<InfoHead>Tips are refreshed daily!</InfoHead> | ||
</InfoContainer> | ||
|
||
{plantTip == null ? ( | ||
<p>Loading...</p> | ||
) : ( | ||
<SingleTip | ||
category={plantTip.category} | ||
body_text={plantTip.body_text} | ||
/> | ||
)} | ||
</Container> | ||
)} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import styled from 'styled-components'; | ||
import COLORS from '@/styles/colors'; | ||
|
||
export const Container = styled.div` | ||
padding: 2rem; | ||
max-width: 1000px; | ||
margin: 0 auto; | ||
`; | ||
|
||
export const Header = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
margin-bottom: 4px; | ||
`; | ||
|
||
export const Title = styled.h1` | ||
color: ${COLORS.shrub}; | ||
font-family: Lexend; | ||
font-size: 16px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
margin: 0; | ||
`; | ||
|
||
export const SeeAllLink = styled.a` | ||
display: flex; | ||
align-items: center; | ||
color: ${COLORS.midgray}; | ||
font-family: Lexend; | ||
font-size: 10px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
text-decoration: none; | ||
`; | ||
|
||
export const ArrowIcon = styled.span` | ||
margin-left: 5px; | ||
`; | ||
|
||
export const InfoContainer = styled.div` | ||
display: flex; | ||
align-items: center; | ||
margin-bottom: 12px; | ||
`; | ||
|
||
export const InfoHead = styled.p` | ||
color: ${COLORS.midgray}; | ||
font-family: Lexend; | ||
font-size: 10px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
`; | ||
|
||
export const Circle = styled.div` | ||
color: ${COLORS.midgray}; | ||
width: 10px; | ||
height: 10px; | ||
border: 1px solid #666; | ||
border-radius: 50%; | ||
margin-right: 10px; | ||
`; | ||
|
||
export const Greeting = styled.h2` | ||
color: ${COLORS.shrub}; | ||
font-family: Lexend; | ||
font-size: 28px; | ||
font-style: normal; | ||
font-weight: 400; | ||
line-height: normal; | ||
margin-bottom: 16px; | ||
`; | ||
|
||
export const DashboardTitle = styled.p` | ||
color: ${COLORS.shrub}; | ||
font-family: Lexend; | ||
font-size: 14px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
margin-bottom: 8px; | ||
`; | ||
|
||
export const TaskContainer = styled.div` | ||
background-color: #fff; | ||
border-radius: 10px; | ||
box-shadow: 2px 0px 8px 0px rgba(0, 0, 0, 0.1); | ||
height: 200px; | ||
margin-bottom: 8px; | ||
`; | ||
export const CalendarContainer = styled.div` | ||
background-color: #fff; | ||
border-radius: 10px; | ||
box-shadow: 2px 0px 8px 0px rgba(0, 0, 0, 0.1); | ||
height: 125px; | ||
margin-bottom: 8px; | ||
`; | ||
|
||
export const PlaceholderText = styled.p` | ||
color: ${COLORS.shrub}; | ||
font-family: Lexend; | ||
font-size: 14px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
padding: 20px; | ||
`; | ||
export const WeatherReminderWrapper = styled.div` | ||
display: flex; | ||
flex-direction: row; | ||
justify-content: space-between; | ||
gap: 8px; | ||
`; | ||
export const WeatherContainer = styled.div` | ||
background-color: #fff; | ||
border-radius: 10px; | ||
box-shadow: 2px 0px 8px 0px rgba(0, 0, 0, 0.1); | ||
height: 125px; | ||
width: 50%; | ||
margin-bottom: 8px; | ||
`; | ||
export const ReminderContainer = styled.div` | ||
background-color: #fff; | ||
border-radius: 10px; | ||
box-shadow: 2px 0px 8px 0px rgba(0, 0, 0, 0.1); | ||
height: 125px; | ||
width: 50%; | ||
margin-bottom: 8px; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React from 'react'; | ||
import { Category } from '@/types/schema'; | ||
import { Card, Text, Title } from './styles'; | ||
|
||
// Define the category type with specific values | ||
|
||
// Map category values to headers | ||
const categoryHeaders: Record<Category, string> = { | ||
'Helpful Flowers for Your Garden': 'Helpful Flowers', | ||
'Water Management': 'Water Tips', | ||
Mulching: 'Mulching Tips', | ||
Harvesting: 'Harvesting Tips', | ||
Planting: 'Planting Tips', | ||
Weeding: 'Weeding Tips', | ||
}; | ||
|
||
// Define the prop type | ||
interface TipCardProps { | ||
category: Category; | ||
body_text: string; | ||
} | ||
|
||
// Styled components | ||
|
||
export default function TipCard({ category, body_text }: TipCardProps) { | ||
return ( | ||
<Card> | ||
<Title>Tip of the Day</Title> | ||
<Text>{categoryHeaders[category]}</Text> | ||
<Text>{body_text}</Text> | ||
</Card> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import styled from 'styled-components'; | ||
import COLORS from '@/styles/colors'; | ||
|
||
export const Card = styled.div` | ||
background-color: white; | ||
box-shadow: 2px 0px 8px 0px rgba(0, 0, 0, 0.1); | ||
border-radius: 10px; | ||
padding: 24px; | ||
height: 109px; | ||
`; | ||
|
||
export const Title = styled.h2` | ||
color: ${COLORS.shrub}; | ||
font-family: Lexend; | ||
font-size: 16px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
margin-bottom: 6px; | ||
text-align: center; | ||
`; | ||
|
||
export const Text = styled.p` | ||
color: ${COLORS.midgray}; | ||
font-family: Lexend; | ||
font-size: 10px; | ||
font-style: normal; | ||
font-weight: 300; | ||
line-height: normal; | ||
margin-bottom: 6px; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters