feat: integrate StarRating component into MediaFormModal for improved rating input
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
import type { Media } from './interfaces';
|
import type { Media } from './interfaces';
|
||||||
import { fade, scale } from 'svelte/transition';
|
import { fade, scale } from 'svelte/transition';
|
||||||
import DatePicker from './DatePicker.svelte';
|
import DatePicker from './DatePicker.svelte';
|
||||||
|
import StarRating from './StarRating.svelte';
|
||||||
|
|
||||||
let {show, mode, submitMedia, handleClose, media: initialMedia, itemType} = $props();
|
let {show, mode, submitMedia, handleClose, media: initialMedia, itemType} = $props();
|
||||||
let media: Media = $state({
|
let media: Media = $state({
|
||||||
@@ -114,17 +115,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-between items-center gap-6">
|
<div class="flex start items-center gap-6">
|
||||||
<label class="font-medium text-gray-700 whitespace-nowrap" for="rating">评分</label>
|
<label for="score" class="font-medium text-gray-700 whitespace-nowrap">评分</label>
|
||||||
<input
|
<StarRating
|
||||||
id="rating"
|
value={media.rating}
|
||||||
type="number"
|
onSelect={(score: number) => media.rating = score}
|
||||||
min="0"
|
|
||||||
max="10"
|
|
||||||
step="0.5"
|
|
||||||
bind:value={media.rating}
|
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
aria-label="输入评分,范围0-10"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if media.type === 'game' || media.type === 'other'}
|
{#if media.type === 'game' || media.type === 'other'}
|
||||||
|
|||||||
38
src/lib/StarRating.svelte
Normal file
38
src/lib/StarRating.svelte
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
let { value = 0, maxStars = 10, onSelect } = $props();
|
||||||
|
let hoverValue = $state(0);
|
||||||
|
|
||||||
|
function handleStarClick(index: number) {
|
||||||
|
onSelect(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleStarHover(index: number) {
|
||||||
|
hoverValue = index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseLeave() {
|
||||||
|
hoverValue = 0;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-1" onmouseleave={handleMouseLeave} role="presentation">
|
||||||
|
{#each Array(maxStars) as _, i}
|
||||||
|
<div
|
||||||
|
class="text-l focus:outline-none transition-colors duration-200 cursor-pointer"
|
||||||
|
class:text-yellow-400={i <(hoverValue || value)}
|
||||||
|
class:text-gray-300={i >= (hoverValue || value)}
|
||||||
|
onclick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
handleStarClick(i);
|
||||||
|
}}
|
||||||
|
onmouseenter={() => handleStarHover(i)}
|
||||||
|
role="presentation"
|
||||||
|
>
|
||||||
|
★
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{#if value > 0}
|
||||||
|
<span class="ml-2 text-sm text-gray-600">{value}分</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user