-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from SpaceTurtle-Dao/feature/feed
Implemented Feed Page
- Loading branch information
Showing
6 changed files
with
306 additions
and
120 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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 |
---|---|---|
@@ -1,3 +1,42 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
@tailwind utilities; | ||
|
||
@layer base { | ||
:root { | ||
--background: 0 0% 100%; | ||
--foreground: 240 10% 3.9%; | ||
--card: 0 0% 100%; | ||
--card-foreground: 240 10% 3.9%; | ||
--popover: 0 0% 100%; | ||
--popover-foreground: 240 10% 3.9%; | ||
--primary: 240 5.9% 10%; | ||
--primary-foreground: 0 0% 98%; | ||
--secondary: 240 4.8% 95.9%; | ||
--secondary-foreground: 240 5.9% 10%; | ||
--muted: 240 4.8% 95.9%; | ||
--muted-foreground: 240 3.8% 45%; | ||
--accent: 240 4.8% 95.9%; | ||
--accent-foreground: 240 5.9% 10%; | ||
--destructive: 0 72% 51%; | ||
--destructive-foreground: 0 0% 98%; | ||
--border: 240 5.9% 90%; | ||
--input: 240 5.9% 90%; | ||
--ring: 240 5.9% 10%; | ||
--radius: 0.5rem; | ||
} | ||
} | ||
|
||
@layer base { | ||
* { | ||
@apply border-border; | ||
} | ||
|
||
body { | ||
@apply bg-background text-foreground font-body; | ||
} | ||
|
||
h1, h2, h3, h4, h5, h6 { | ||
@apply font-heading; | ||
} | ||
} |
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 |
---|---|---|
@@ -1,63 +1,75 @@ | ||
<!-- Feed.svelte --> | ||
<script> | ||
import { onMount } from "svelte"; | ||
import Tweet from "./Post.svelte"; | ||
let tweets = [ | ||
{ | ||
id: "1", | ||
username: "johnDoe", | ||
text: "Just learned Svelte! #SvelteLearning", | ||
likes: 10, | ||
retweets: 5, | ||
}, | ||
{ | ||
id: "2", | ||
username: "janeSmith", | ||
text: "I'm loving this Svelte tutorial! #SvelteTutorials", | ||
likes: 20, | ||
retweets: 10, | ||
}, | ||
{ | ||
id: "3", | ||
username: "janeSmith", | ||
text: "I'm loving this Svelte tutorial! #SvelteTutorials", | ||
likes: 20, | ||
retweets: 10, | ||
}, | ||
]; | ||
onMount(() => { | ||
// fetch tweets from API or database here | ||
// for demonstration purposes, we'll just use the pre-defined array | ||
console.log("tweets:", tweets); | ||
<script lang="ts"> | ||
//@ts-nocheck | ||
import { onMount } from 'svelte'; | ||
import Tweet from './Tweet.svelte'; | ||
import { fetchMemes, fetchMemesByIds } from './ao/mememaker'; | ||
let tweets = []; | ||
onMount(async () => { | ||
try { | ||
const fetchedMemes = await fetchMemes("1", "100"); | ||
tweets = fetchedMemes.map(meme => ({ | ||
id: meme.Pool, | ||
avatarSrc: meme.Profile?.Image ? `https://arweave.net/${meme.Profile.Image}` : '/default-avatar.png', | ||
username: meme.Profile?.Name || 'Anonymous', | ||
handle: `@${meme.Creator.slice(0, 12)}`, | ||
time: formatTime(meme.createdAt), | ||
content: meme.Post.Content, | ||
likes: meme.Pumps, | ||
retweets: meme.Replies, | ||
price: meme.Analytics.Price, | ||
marketCap: meme.Analytics.MarketCap | ||
})); | ||
} catch (error) { | ||
console.error('Error fetching memes:', error); | ||
} | ||
}); | ||
// function handleTweetLike(tweetId) { | ||
// const tweet = tweets.find((t) => t.id === tweetId); | ||
// if (tweet) { | ||
// tweet.likes++; | ||
// } | ||
// } | ||
// function handleTweetRetweet(tweetId) { | ||
// const tweet = tweets.find((t) => t.id === tweetId); | ||
// if (tweet) { | ||
// tweet.retweets++; | ||
// } | ||
// } | ||
</script> | ||
|
||
<div> | ||
{#each tweets as tweet} | ||
<Tweet | ||
id={tweet.id} | ||
username={tweet.username} | ||
text={tweet.text} | ||
likes={tweet.likes} | ||
retweets={tweet.retweets} | ||
onLike={() => {}} | ||
onRetweet={() => {}} | ||
/> | ||
function formatTime(timestamp) { | ||
const now = Date.now(); | ||
const diff = now - timestamp; | ||
const minutes = Math.floor(diff / 60000); | ||
const hours = Math.floor(minutes / 60); | ||
const days = Math.floor(hours / 24); | ||
if (days > 0) return `${days}d`; | ||
if (hours > 0) return `${hours}h`; | ||
if (minutes > 0) return `${minutes}m`; | ||
return 'Just now'; | ||
} | ||
function handleTweetLike(tweetId) { | ||
const tweet = tweets.find((t) => t.id === tweetId); | ||
if (tweet) { | ||
tweet.likes++; | ||
} | ||
} | ||
function handleTweetRetweet(tweetId) { | ||
const tweet = tweets.find((t) => t.id === tweetId); | ||
if (tweet) { | ||
tweet.retweets++; | ||
} | ||
} | ||
</script> | ||
|
||
<div class="flex flex-col items-center max-w-2xl mx-auto px-4 py-8 space-y-6"> | ||
{#each tweets as tweet (tweet.id)} | ||
<div class="w-full bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow duration-300 ease-in-out"> | ||
<Tweet | ||
avatarSrc={tweet.avatarSrc} | ||
username={tweet.username} | ||
handle={tweet.handle} | ||
time={tweet.time} | ||
content={tweet.content} | ||
likes={tweet.likes} | ||
retweets={tweet.retweets} | ||
onLike={() => handleTweetLike(tweet.id)} | ||
onRetweet={() => handleTweetRetweet(tweet.id)} | ||
price={tweet.price} | ||
marketCap={tweet.marketCap} | ||
/> | ||
</div> | ||
{/each} | ||
</div> | ||
</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,84 @@ | ||
<script> | ||
import { MessageCircleIcon, RepeatIcon, HeartIcon, ShareIcon, DollarSignIcon, TrendingUpIcon } from 'lucide-svelte'; | ||
import Card from '$lib/components/ui/ui/card/card.svelte'; | ||
import Avatar from '$lib/components/ui/ui/avatar/avatar.svelte'; | ||
import Button from './components/ui/ui/button/button.svelte'; | ||
export let avatarSrc = '/placeholder-user.jpg'; | ||
export let username = 'User'; | ||
export let handle = '@user'; | ||
export let time = '1h'; | ||
export let content = 'Tweet content here'; | ||
export let imageSrc = ''; | ||
export let showImage = false; | ||
export let likes = 0; | ||
export let retweets = 0; | ||
export let price = 0; | ||
export let marketCap = 0; | ||
export let onLike = () => {}; | ||
export let onRetweet = () => {}; | ||
$: formattedPrice = price.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); | ||
$: formattedMarketCap = marketCap.toLocaleString('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }); | ||
</script> | ||
|
||
<Card class="max-w-full md:max-w-lg"> | ||
<div class="p-4"> | ||
<div class="flex items-start gap-4"> | ||
<a href="/" class="flex-shrink-0"> | ||
<Avatar class="h-10 w-10 rounded-full"> | ||
<img src={avatarSrc} alt={`Avatar of ${username}`} /> | ||
<span>{username.charAt(0)}</span> | ||
</Avatar> | ||
</a> | ||
<div class="flex-1 space-y-2"> | ||
<div class="flex items-center gap-2"> | ||
<a href="/" class="font-medium">{username}</a> | ||
<span class="text-sm text-muted-foreground">{handle} · {time}</span> | ||
</div> | ||
<p class="text-sm"> | ||
{content} | ||
</p> | ||
{#if showImage} | ||
<!-- svelte-ignore a11y-img-redundant-alt --> | ||
<img | ||
src={imageSrc} | ||
alt="Tweet image" | ||
class="rounded-md object-cover w-full" | ||
style="aspect-ratio: 600/400; object-fit: cover;" | ||
/> | ||
{/if} | ||
<div class="flex items-center gap-4 text-sm text-muted-foreground"> | ||
<div class="flex items-center gap-1"> | ||
<DollarSignIcon class="h-4 w-4" /> | ||
<span>Price: {formattedPrice}</span> | ||
</div> | ||
<div class="flex items-center gap-1"> | ||
<TrendingUpIcon class="h-4 w-4" /> | ||
<span>Market Cap: {formattedMarketCap}</span> | ||
</div> | ||
</div> | ||
<div class="flex items-center gap-4"> | ||
<Button variant="ghost" size="icon" on:click={onLike}> | ||
<HeartIcon class="h-5 w-5" /> | ||
<span class="sr-only">Like</span> | ||
<span>{likes}</span> | ||
</Button> | ||
<Button variant="ghost" size="icon" on:click={onRetweet}> | ||
<RepeatIcon class="h-5 w-5" /> | ||
<span class="sr-only">Retweet</span> | ||
<span>{retweets}</span> | ||
</Button> | ||
<Button variant="ghost" size="icon"> | ||
<MessageCircleIcon class="h-5 w-5" /> | ||
<span class="sr-only"> Comment</span> | ||
</Button> | ||
<Button variant="ghost" size="icon"> | ||
<ShareIcon class="h-5 w-5" /> | ||
<span class="sr-only">Share</span> | ||
</Button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</Card> |
Oops, something went wrong.