@@ -17,6 +17,7 @@ import { Cross1Icon } from "@radix-ui/react-icons";
17
17
import { Skeleton } from "../ui/skeleton" ;
18
18
import { useNavigate , useParams } from "react-router-dom" ;
19
19
import ReactMarkdown from 'react-markdown' ;
20
+ import { toast } from "sonner" ;
20
21
21
22
interface Project {
22
23
projectId : string ;
@@ -38,6 +39,7 @@ const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5000';
38
39
export function ProjectCard ( { project, onProjectChange } : ProjectProps ) {
39
40
const [ isStarred , setIsStarred ] = useState ( false ) ;
40
41
const [ starCount , setStarCount ] = useState ( project . starCount ) ;
42
+ const [ isStarRequestInProgress , setIsStarRequestInProgress ] = useState ( false ) ; // State to handle star request
41
43
const username = localStorage . getItem ( 'devhub_username' ) ; // Logged-in user
42
44
const { username : paramsUsername } = useParams < { username : string } > ( ) ; // Extract username from URL
43
45
@@ -59,10 +61,12 @@ export function ProjectCard({ project, onProjectChange }: ProjectProps) {
59
61
} , [ project . projectId ] ) ;
60
62
61
63
const handleStarClick = async ( ) => {
62
- if ( isStarred ) return ; // Prevent multiple stars
64
+ if ( isStarred || isStarRequestInProgress ) return ; // Prevent multiple stars and requests
65
+
66
+ setIsStarRequestInProgress ( true ) ; // Start request
63
67
64
68
try {
65
- const response = await fetch ( `${ backendUrl } /profile/${ paramsUsername } /projects/${ project . projectId } /star` , {
69
+ const response = await fetch ( `${ backendUrl } /profile/${ username } /projects/${ project . projectId } /star` , {
66
70
method : "POST" ,
67
71
headers : { "Content-Type" : "application/json" } ,
68
72
} ) ;
@@ -71,11 +75,18 @@ export function ProjectCard({ project, onProjectChange }: ProjectProps) {
71
75
setStarCount ( ( prevCount ) => prevCount + 1 ) ;
72
76
setIsStarred ( true ) ;
73
77
localStorage . setItem ( `starred_${ project . projectId } ` , "true" ) ;
78
+
79
+ // Show success toast
80
+ toast . success ( "Project starred!" ) ;
74
81
} else {
75
82
console . error ( "Failed to star the project" ) ;
83
+ toast . error ( "Failed to star the project" ) ;
76
84
}
77
85
} catch ( error ) {
78
86
console . error ( "Error starring the project:" , error ) ;
87
+ toast . error ( "Failed to star the project" ) ;
88
+ } finally {
89
+ setIsStarRequestInProgress ( false ) ; // End request
79
90
}
80
91
} ;
81
92
@@ -97,21 +108,23 @@ export function ProjectCard({ project, onProjectChange }: ProjectProps) {
97
108
>
98
109
{ project . title }
99
110
</ CardTitle >
100
- < ReactMarkdown > { project . description } </ ReactMarkdown >
111
+ < ReactMarkdown >
112
+ { project . description . split ( ' ' ) . slice ( 0 , 5 ) . join ( ' ' ) + ( project . description . split ( ' ' ) . length > 5 ? '...' : '' ) }
113
+ </ ReactMarkdown >
101
114
</ div >
102
115
< div className = "flex items-center rounded-md bg-secondary text-secondary-foreground" >
103
116
< Button
104
117
variant = "secondary"
105
- className = " shadow-none"
118
+ className = "shadow-none"
106
119
onClick = { handleStarClick }
107
- disabled = { isStarred }
120
+ disabled = { isStarred || isStarRequestInProgress } // Disable during star request
108
121
>
109
122
{ isStarred ? (
110
123
< FilledStarIcon className = "mr-2 h-4 w-4 text-yellow-400" />
111
124
) : (
112
125
< StarIcon className = "mr-2 h-4 w-4" />
113
126
) }
114
- Star
127
+ { isStarRequestInProgress ? "Starring..." : " Star" } { /* Show loading text */ }
115
128
</ Button >
116
129
</ div >
117
130
</ CardHeader >
0 commit comments