feat/ratings
Arik Chakma 3 months ago
parent 8e4baa02b1
commit dd71900f8b
  1. 146
      src/components/Rating/Rating.tsx
  2. 14
      src/components/TeamsList.tsx

@ -0,0 +1,146 @@
import { useState } from 'react';
import { cn } from '../../lib/classname';
type StarValue = 0 | 0.5 | 1;
type RatingProps = {
ratings?: number;
size?: number;
};
export function Rating(props: RatingProps) {
const { ratings = 0, size } = props;
const [stars, setStars] = useState(
Array.from({ length: 5 }, (_, i) => {
const rating = Math.floor(ratings);
if (i < rating) {
return 1;
}
if (i === rating && ratings % 1 !== 0) {
return 0.5;
}
return 0;
}),
);
const [dynamicStars, setDynamicStars] = useState(stars);
return (
<div className="mt-4 flex">
{dynamicStars.map((star, counter) => (
<RatingStar
key={`star-${counter}`}
value={star}
onValueChange={(value) => {
const newStars = [...stars];
newStars.fill(1, 0, counter);
newStars[counter] = value;
newStars.fill(0, counter + 1);
setDynamicStars(newStars);
}}
onClick={(value) => {
const newStars = [...stars];
newStars.fill(1, 0, counter);
newStars[counter] = value;
newStars.fill(0, counter + 1);
setStars(newStars);
setDynamicStars(newStars);
}}
onMouseLeave={() => {
setDynamicStars(stars);
}}
/>
))}
</div>
);
}
type RatingStarProps = {
value: StarValue;
onValueChange?: (value: StarValue) => void;
onMouseLeave?: () => void;
onClick: (value: StarValue) => void;
startSize?: number;
};
export function RatingStar(props: RatingStarProps) {
const { value, onValueChange, onClick, onMouseLeave, startSize = 20 } = props;
return (
<span
onMouseMove={(e) => {
e.preventDefault();
e.stopPropagation();
const rect = e.currentTarget.getBoundingClientRect();
const mid = rect.width / 2;
const value = e.clientX < rect.left + mid ? 0.5 : 1;
onValueChange?.(value);
}}
onMouseEnter={(e) => {
e.preventDefault();
e.stopPropagation();
const rect = e.currentTarget.getBoundingClientRect();
const mid = rect.width / 2;
const value = e.clientX < rect.left + mid ? 0.5 : 1;
onValueChange?.(value);
}}
onMouseLeave={onMouseLeave}
onClick={() => {
onClick(value);
}}
className="relative block cursor-pointer"
style={{
width: `${startSize}px`,
height: `${startSize}px`,
}}
>
<span
className={cn(
'absolute overflow-hidden',
value === 0.5 ? 'w-1/2' : 'w-0',
)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="fill-red"
style={{
width: `${startSize}px`,
height: `${startSize}px`,
}}
>
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
</svg>
</span>
<span className="absolute">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={cn('', value === 1 ? 'fill-red' : 'fill-none')}
style={{
width: `${startSize}px`,
height: `${startSize}px`,
}}
>
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
</svg>
</span>
</span>
);
}

@ -4,6 +4,7 @@ import { useAuth } from '../hooks/use-auth';
import { pageProgressMessage } from '../stores/page';
import { useToast } from '../hooks/use-toast';
import { type UserTeamItem } from './TeamDropdown/TeamDropdown';
import { Rating } from './Rating/Rating';
export function TeamsList() {
const [teamList, setTeamList] = useState<UserTeamItem[]>([]);
@ -11,7 +12,7 @@ export function TeamsList() {
const toast = useToast();
async function getAllTeam() {
const { response, error } = await httpGet<UserTeamItem[]>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`
`${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`,
);
if (error || !response) {
toast.error(error?.message || 'Something went wrong');
@ -35,6 +36,17 @@ export function TeamsList() {
<p className="mt-2 text-gray-400">
Here are the teams you are part of
</p>
<Rating ratings={0.5} />
<Rating ratings={1} />
<Rating ratings={1.5} />
<Rating ratings={2} />
<Rating ratings={2.5} />
<Rating ratings={3} />
<Rating ratings={3.5} />
<Rating ratings={4} />
<Rating ratings={4.5} />
<Rating ratings={5} />
</div>
<ul className="mb-3 flex flex-col gap-1">
<li>

Loading…
Cancel
Save