Skip to content

Commit

Permalink
feat: server controllers for posts
Browse files Browse the repository at this point in the history
  • Loading branch information
warmachine028 committed Oct 25, 2024
1 parent 8f83783 commit 989be4c
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 108 deletions.
5 changes: 4 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
"endOfLine": "lf",
"plugins": [
"prettier-plugin-tailwindcss"
]
}
Binary file modified client/bun.lockb
Binary file not shown.
9 changes: 7 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
"dev": "bun x vite",
"build": "bun x vite build",
"lint": "eslint .",
"preview": "bun x vite preview"
"preview": "bun x vite preview",
"start": "bun x vite preview --host"
},
"dependencies": {
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-scroll-area": "^1.2.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@tanstack/react-query": "^5.59.16",
"@tanstack/react-query-devtools": "^5.59.16",
Expand Down Expand Up @@ -44,9 +46,12 @@
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.11.0",
"postcss": "^8.4.47",
"prettier-plugin-tailwindcss": "^0.6.8",
"tailwindcss": "^3.4.14",
"typescript": "~5.6.3",
"typescript-eslint": "^8.11.0",
"vite": "6.0.0-beta.4"
},
"peerDependencies": {
"typescript": "~5.6.3"
}
}
10 changes: 1 addition & 9 deletions client/src/api/posts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import axios from 'axios'
import { PostsResponse, Post } from '@/types'
import { sleep } from '@/lib/utils'

const api = axios.create({ baseURL: import.meta.env.VITE_API_URL })

Expand Down Expand Up @@ -41,17 +40,11 @@ export const deletePost = async (id: number): Promise<void> => {
}
}

// Search posts
export const searchPosts = async (query: string): Promise<PostsResponse> => {
try {
const { data } = await api.get<PostsResponse>(`/posts/search?q=${query}`)

const postsWithImages = data.posts.map((post) => ({
...post,
imageUrl: `https://picsum.photos/seed/${post.id}/800/600`
}))

return { ...data, posts: postsWithImages }
return data
} catch (error) {
throw handleApiError(error)
}
Expand All @@ -78,7 +71,6 @@ export const getPostsByUser = async (userId: number): Promise<PostsResponse> =>

export const updateReaction = async (postId: number, type: 'like' | 'dislike') => {
try {
await sleep(3000)
const { data } = await api.put(`/posts/${postId}`, { reactions: { [type]: +1 } })

return data
Expand Down
1 change: 1 addition & 0 deletions client/src/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export { ScrollArea } from './scroll-area'
export { Badge } from './badge'
export { Textarea } from './textarea'
export { Search } from './search'
export { Separator } from './separator'
16 changes: 11 additions & 5 deletions client/src/components/ui/mode-toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import { Moon, Sun } from 'lucide-react'
import { Computer, Moon, Sun } from 'lucide-react'
import { Button } from './button'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from './dropdown-menu'
import { useTheme } from '@/hooks'

export const ModeToggle = ({ variant, className }: { variant?: 'default' | 'outline'; className?: string }) => {
const { setTheme } = useTheme()

const { setTheme, theme } = useTheme()
console.log(theme)
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant={variant} size="icon" className={className} title="Toggle theme">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
{theme === 'system' ? (
<Computer />
) : (
<>
<Sun className="rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
</>
)}
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
Expand Down
1 change: 1 addition & 0 deletions client/src/components/ui/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ const Search = ({ className, iconClassName, ...props }: { iconClassName?: string
</div>
)
}
Search.displayName = 'Search'

export { Search }
29 changes: 29 additions & 0 deletions client/src/components/ui/separator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"

import { cn } from "@/lib/utils"

const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{ className, orientation = "horizontal", decorative = true, ...props },
ref
) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
"shrink-0 bg-border",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
className
)}
{...props}
/>
)
)
Separator.displayName = SeparatorPrimitive.Root.displayName

export { Separator }
2 changes: 2 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ a:hover {
body {
margin: 0;
display: flex;
align-items: center;
justify-content: center;
place-items: center;
min-width: 320px;
min-height: 100vh;
Expand Down
16 changes: 8 additions & 8 deletions client/src/pages/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const PostsCard = () => {
<CardHeader className="bg-primary text-primary-foreground sticky top-0 z-10">
<div className="flex items-center justify-between">
<CardTitle className="text-2xl font-bold">Posts</CardTitle>
<div className="space-x-2 *:bg-primary">
<div className="*:bg-primary space-x-2">
<Button asChild variant="outline" size="icon" title="Home">
<Link to="/" className="text-inherit">
<House />
Expand Down Expand Up @@ -63,18 +63,18 @@ const PostsCard = () => {
</div>
<ScrollArea className="h-[calc(100vh-20rem)]">
{status === 'pending' ? (
<div className="flex justify-center items-center h-full">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
<div className="flex h-full items-center justify-center">
<Loader2 className="text-primary size-8 animate-spin" />
</div>
) : status === 'error' ? (
<p className="text-center text-destructive">Error fetching posts</p>
<p className="text-destructive text-center">Error fetching posts</p>
) : (
<AnimatePresence>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="grid grid-cols-1 md:grid-cols-2 gap-6 auto-rows-max"
className="grid auto-rows-max grid-cols-1 gap-6 md:grid-cols-2"
>
{results.map((post) => (
<Post key={post.id} post={post} />
Expand All @@ -83,8 +83,8 @@ const PostsCard = () => {
</AnimatePresence>
)}
{isFetchingNextPage && (
<div className="flex justify-center mt-4">
<Loader2 className="h-6 w-6 animate-spin text-primary" />
<div className="mt-4 flex justify-center">
<Loader2 className="text-primary size-6 animate-spin" />
</div>
)}
<div ref={ref} className="h-1" />
Expand All @@ -97,7 +97,7 @@ const PostsCard = () => {
const Posts = () => {
return (
<div className="container mx-auto space-y-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
<div className="md:col-span-2">
<PostsCard />
</div>
Expand Down
30 changes: 13 additions & 17 deletions client/src/pages/Todos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,21 @@ export default function Todos() {
<CardContent className="p-6">
<ScrollArea className="h-[400px] pr-4">
{status === 'pending' ? (
<div className="flex justify-center items-center h-full">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
<div className="flex h-full items-center justify-center">
<Loader2 className="text-primary size-8 animate-spin" />
</div>
) : status === 'error' ? (
<p className="text-center text-destructive">Error fetching todos</p>
<p className="text-destructive text-center">Error fetching todos</p>
) : (
<ul className="space-y-3">
{data.pages.map((page, i) => (
<ul key={i} className="space-y-3">
{page.todos.map((todo) => (
<li
key={todo.id}
className="flex items-center justify-between p-3 bg-muted rounded-lg transition-all duration-200 hover:shadow-md"
className="bg-muted flex items-center justify-between rounded-lg p-3 transition-all duration-200 hover:shadow-md"
>
<div className="flex items-center space-x-3 flex-grow">
<div className="flex flex-grow items-center space-x-3">
<Checkbox
id={`todo-${todo.id}`}
checked={todo.completed}
Expand All @@ -115,7 +115,7 @@ export default function Todos() {
<label
htmlFor={`todo-${todo.id}`}
className={`flex-grow cursor-pointer ${
todo.completed ? 'line-through text-muted-foreground' : ''
todo.completed ? 'text-muted-foreground line-through' : ''
}`}
>
{todo.title}
Expand All @@ -127,7 +127,7 @@ export default function Todos() {
onClick={() => handleDeleteTodo(todo.id)}
className="text-destructive hover:text-destructive hover:bg-destructive/10"
>
<Trash2 className="h-4 w-4" />
<Trash2 className="size-4" />
</Button>
</li>
))}
Expand All @@ -136,8 +136,8 @@ export default function Todos() {
</ul>
)}
{isFetchingNextPage && (
<div className="flex justify-center mt-4">
<Loader2 className="h-6 w-6 animate-spin text-primary" />
<div className="mt-4 flex justify-center">
<Loader2 className="text-primary size-6 animate-spin" />
</div>
)}
<div ref={ref} className="h-1" />
Expand All @@ -155,15 +155,11 @@ export default function Todos() {
<Button
type="submit"
disabled={addMutation.isPending}
className="bg-primary text-primary-foreground"
className="bg-primary text-primary-foreground *:mr-2 *:size-4"
size="icon"
>
{addMutation.isPending ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<>
<Plus className="h-4 w-4 mr-2" /> Add
</>
)}
{addMutation.isPending ? <Loader2 className="animate-spin" /> : <Plus />}
Add
</Button>
</form>
</CardFooter>
Expand Down
Loading

0 comments on commit 989be4c

Please sign in to comment.