Skip to content

Commit

Permalink
Refactor petition-related components and actions
Browse files Browse the repository at this point in the history
Consolidate petition actions into a single file and update imports accordingly. Deleted redundant components and cleaned up petition handling logic for better maintainability.

Took 30 minutes
  • Loading branch information
mikepsinn committed Nov 20, 2024
1 parent adf75e3 commit c61aa96
Show file tree
Hide file tree
Showing 14 changed files with 209 additions and 78 deletions.
55 changes: 55 additions & 0 deletions app/dfda/right-to-trial-act/components/DFDASignPetitionButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use client'

import { SignPetitionButton } from '@/app/petitions/components/SignPetitionButton'
import { useEffect, useState } from 'react'
import { useSession } from 'next-auth/react'
import { checkPetitionSignature } from '@/app/petitions/petitionActions'

const neoBrutalistStyles = {
button: "border-4 border-black p-4 text-lg font-bold transition-all hover:translate-x-1 hover:translate-y-1 hover:shadow-none bg-white shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] text-black min-w-[200px] min-h-[60px] rounded-none",
signed: "border-4 border-black p-4 text-lg font-bold bg-pink-400 shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] hover:bg-pink-500 text-white min-w-[200px] min-h-[60px] rounded-none"
}

export function DFDASignPetitionButton() {
const { data: session } = useSession()
const [hasSigned, setHasSigned] = useState(false)

useEffect(() => {
let mounted = true

async function checkSignature() {
if (!session?.user?.id) {
if (mounted) setHasSigned(false)
return
}

try {
const hasSignature = await checkPetitionSignature('right-to-trial-act')
if (mounted) setHasSigned(hasSignature)
} catch (error) {
console.error('Failed to check signature status:', error)
if (mounted) setHasSigned(false)
}
}

checkSignature()

return () => {
mounted = false
}
}, [session?.user?.id])

return (
<SignPetitionButton
petitionId="right-to-trial-act"
hasSigned={hasSigned}
status="ACTIVE"
className={neoBrutalistStyles.button}
signedClassName={neoBrutalistStyles.signed}
onSignatureChange={() => {
// Toggle the hasSigned state immediately for better UX
setHasSigned(prev => !prev)
}}
/>
)
}
6 changes: 3 additions & 3 deletions app/dfda/right-to-trial-act/components/PetitionSection.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { GitHubEditButton } from './GitHubEditButton'
import { SignPetitionButton } from './SignPetitionButton'
import { DFDASignPetitionButton } from './DFDASignPetitionButton'

export function PetitionSection() {
return (
Expand All @@ -10,8 +10,8 @@ export function PetitionSection() {
<p className="text-xl mb-8 text-black">
Sign the petition to support the Right to Trial Act and help end the suffering of billions of people.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<SignPetitionButton />
<div className="inline-flex gap-4 justify-center">
<DFDASignPetitionButton />
<GitHubEditButton />
</div>
</div>
Expand Down
26 changes: 0 additions & 26 deletions app/dfda/right-to-trial-act/components/SignPetitionButton.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions app/dfda/right-to-trial-act/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Metadata } from 'next'
import { getMarkdownContent } from '@/lib/content/getMarkdownContent'
import { PetitionSection } from './components/PetitionSection'
import { FloatingPetitionButton } from './components/FloatingPetitionButton'
import { SignPetitionButton } from './components/SignPetitionButton'
import { DFDASignPetitionButton } from './components/DFDASignPetitionButton'
import CureAccelerationAct from './components/right-to-trial-act'
import { GitHubEditButton } from './components/GitHubEditButton'

Expand Down Expand Up @@ -50,7 +50,7 @@ export default async function RightToTrialPage() {
{/* Bottom Petition Section */}
<div className="mt-16 text-center border-t-4 pt-12">
<h3 className="text-2xl font-serif mb-6">Add Your Name to Support This Act</h3>
<SignPetitionButton /> <GitHubEditButton />
<DFDASignPetitionButton /> <GitHubEditButton />
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/petitions/components/Comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState } from 'react'
import { useSession } from 'next-auth/react'
import { LoginPromptButton } from '@/components/LoginPromptButton'
import { addComment } from '../actions'
import { addComment } from '../petitionActions'
import { Button } from '@/components/ui/button'
import { Textarea } from '@/components/ui/textarea'
import { PetitionComment, User } from "@prisma/client"
Expand Down
2 changes: 1 addition & 1 deletion app/petitions/components/CreatePetitionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { useState } from "react"
import { createPetition, generatePetition } from "../actions"
import { createPetition, generatePetition } from "../petitionActions"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
Expand Down
2 changes: 1 addition & 1 deletion app/petitions/components/FollowButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from 'react'
import { useSession } from 'next-auth/react'
import { LoginPromptButton } from '@/components/LoginPromptButton'
import { Button } from '@/components/ui/button'
import { followPetition, unfollowPetition } from '../actions'
import { followPetition, unfollowPetition } from '../petitionActions'

export function FollowButton({
petitionId,
Expand Down
2 changes: 1 addition & 1 deletion app/petitions/components/FollowSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState } from 'react'
import { Switch } from "@/components/ui/switch"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { updateFollowSettings } from '../actions'
import { updateFollowSettings } from '../petitionActions'
import { EmailFrequency } from "@prisma/client"

interface FollowSettings {
Expand Down
2 changes: 1 addition & 1 deletion app/petitions/components/ImageUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useState } from 'react'
import { Button } from "@/components/ui/button"
import { uploadImage } from '../actions'
import { uploadImage } from '../petitionActions'

interface ImageUploadProps {
onUploadComplete: (url: string) => void
Expand Down
2 changes: 1 addition & 1 deletion app/petitions/components/PetitionAdminControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { createPetitionUpdate } from "../actions"
import { createPetitionUpdate } from "../petitionActions"
import { UpdatesTimeline } from "./UpdatesTimeline"
import { Petition, PetitionStatusUpdate } from "@prisma/client"

Expand Down
75 changes: 48 additions & 27 deletions app/petitions/components/SignPetitionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
'use client'

import { signPetition } from "@/app/petitions/actions"
import { signPetition, unsignPetition } from "@/app/petitions/petitionActions"
import { useSession } from "next-auth/react"
import { useState } from "react"
import { LoginPromptButton } from "@/components/LoginPromptButton"
import { Button } from "@/components/ui/button"
import { useToast } from "@/components/ui/use-toast"
import { PetitionStatus } from "@prisma/client"
import { cn } from "@/lib/utils"

interface SignPetitionButtonProps {
petitionId: string
hasSigned: boolean
status?: PetitionStatus
className?: string
signedClassName?: string
onSignatureChange?: () => void
}

export function SignPetitionButton({
petitionId,
hasSigned,
status = 'ACTIVE'
hasSigned: initialHasSigned,
status = 'ACTIVE',
className,
signedClassName,
onSignatureChange
}: SignPetitionButtonProps) {
const { data: session } = useSession()
const [signing, setSigning] = useState(false)
const [hasSigned, setHasSigned] = useState(initialHasSigned)
const { toast } = useToast()

if (hasSigned) {
return <div className="text-green-600 font-medium">✓ You've signed this petition</div>
}

if (!session) {
return <LoginPromptButton buttonText="Sign in to sign this petition" buttonVariant="default" />
}
Expand All @@ -35,31 +39,48 @@ export function SignPetitionButton({
return <div className="text-gray-600">This petition is {status.toLowerCase()}</div>
}

const handleClick = async () => {
setSigning(true)
try {
if (hasSigned) {
await unsignPetition(petitionId)
setHasSigned(false)
toast({
title: "Signature removed",
description: "You have removed your signature from this petition.",
})
} else {
await signPetition(petitionId)
setHasSigned(true)
toast({
title: "Petition signed!",
description: "Thank you for your support. Check your email for next steps.",
})
}
onSignatureChange?.()
} catch (error) {
console.error('Failed to update petition signature:', error)
setHasSigned(!hasSigned)
toast({
title: `Failed to ${hasSigned ? 'remove' : 'add'} signature`,
description: error instanceof Error ? error.message : 'An unexpected error occurred',
variant: "destructive",
})
} finally {
setSigning(false)
}
}

return (
<Button
size="lg"
disabled={signing}
onClick={async () => {
setSigning(true)
try {
await signPetition(petitionId)
toast({
title: "Petition signed!",
description: "Thank you for your support. Check your email for next steps.",
})
} catch (error) {
console.error('Failed to sign petition:', error)
toast({
title: "Failed to sign petition",
description: error instanceof Error ? error.message : 'An unexpected error occurred',
variant: "destructive",
})
} finally {
setSigning(false)
}
}}
variant={hasSigned ? "outline" : "default"}
className={cn(className, hasSigned && signedClassName)}
onClick={handleClick}
>
{signing ? 'Signing...' : 'Sign this petition'}
{signing ? (hasSigned ? 'Removing...' : 'Signing...') :
(hasSigned ? '✓ Remove signature' : 'Sign this petition')}
</Button>
)
}
28 changes: 20 additions & 8 deletions app/petitions/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getServerSession } from "next-auth/next"
import { prisma } from "@/lib/prisma"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { PlusIcon } from "lucide-react"
import { PlusIcon, PencilIcon } from "lucide-react"
import { LoginPromptButton } from "@/components/LoginPromptButton"
import { Card, CardContent } from "@/components/ui/card"

Expand All @@ -14,7 +14,10 @@ export default async function PetitionsPage() {
select: { signatures: true }
},
creator: {
select: { name: true }
select: {
name: true,
email: true
}
}
},
orderBy: { createdAt: 'desc' }
Expand All @@ -41,10 +44,7 @@ export default async function PetitionsPage() {

<div className="space-y-6">
{petitions.map((petition) => (
<Link
key={petition.id}
href={`/petitions/${petition.id}`}
>
<div key={petition.id} className="group">
<Card className="hover:bg-muted/50 transition-colors">
<div className="flex flex-col md:flex-row">
{petition.imageUrl && (
Expand All @@ -57,7 +57,19 @@ export default async function PetitionsPage() {
</div>
)}
<CardContent className={`flex-1 ${petition.imageUrl ? "pt-4 md:pt-6" : "pt-6"}`}>
<h2 className="text-2xl font-semibold mb-3">{petition.title}</h2>
<div className="flex justify-between items-start gap-4">
<Link href={`/petitions/${petition.id}`}>
<h2 className="text-2xl font-semibold mb-3 hover:underline">{petition.title}</h2>
</Link>
{session?.user?.email === petition.creator.email && (
<Link href={`/petitions/${petition.id}/edit`}>
<Button variant="ghost" size="sm" className="opacity-0 group-hover:opacity-100 transition-opacity">
<PencilIcon className="h-4 w-4 mr-2" />
Edit
</Button>
</Link>
)}
</div>
<p className="text-muted-foreground mb-4 line-clamp-2">{petition.summary}</p>
<div className="flex justify-between items-center text-sm text-muted-foreground">
<span>{petition._count.signatures} signatures</span>
Expand All @@ -66,7 +78,7 @@ export default async function PetitionsPage() {
</CardContent>
</div>
</Card>
</Link>
</div>
))}
</div>
</div>
Expand Down
Loading

0 comments on commit c61aa96

Please sign in to comment.