--- /dev/null
+---
+import { getCollection } from 'astro:content';
+
+const reviews = await getCollection('reviews');
+const ratings = [1, 2, 3, 4, 5] as const;
+const counts = [0, 0, 0, 0, 0];
+
+for (const { data } of reviews) {
+ counts[data.rating - 1]++;
+}
+
+const maxCount = Math.max(...counts, 1);
+
+const chartData = ratings.map((rating, index) => ({
+ name: rating,
+ count: counts[index],
+ percent: (counts[index] / maxCount) * 100,
+}));
+---
+
+<ul class="rating-distribution">
+ {
+ chartData.map((entry) => (
+ <li class="rating-column">
+ <div class="rating-bar">
+ <span class="rating-bar-fill" style={`height: ${entry.percent}%`} />
+ </div>
+ <span class="rating-label">{entry.name}</span>
+ </li>
+ ))
+ }
+</ul>
+
+<style>
+ .rating-distribution {
+ list-style: none;
+ padding-inline-start: 0;
+ display: grid;
+ grid-template-columns: repeat(5, minmax(0, 1fr));
+ gap: clamp(1rem, 2vw, 2rem);
+ align-items: end;
+ }
+
+ .rating-column {
+ display: grid;
+ grid-template-rows: 1fr auto;
+ }
+
+ .rating-bar {
+ display: flex;
+ align-items: end;
+ width: 100%;
+ height: clamp(4rem, 24vw, 8rem);
+ border: 1px solid var(--color-text);
+ overflow: hidden;
+ }
+
+ .rating-bar-fill {
+ width: 100%;
+ background-color: var(--color-text);
+ }
+
+ .rating-label {
+ justify-self: center;
+ }
+</style>
+++ /dev/null
----
-import { getCollection } from 'astro:content';
-
-const reviews = await getCollection('reviews');
-
-const ratingCounts: Record<number, number> = {
- 1: 0,
- 2: 0,
- 3: 0,
- 4: 0,
- 5: 0,
-};
-
-reviews.forEach((review) => {
- ratingCounts[review.data.rating]++;
-});
-
-const maxCount = Math.max(...Object.values(ratingCounts), 1);
-
-const chartData = Object.entries(ratingCounts).map(([rating, count]) => ({
- name: rating,
- count,
-}));
----
-
-<ul class="rating-distribution" aria-label="Rating distribution">
- {
- chartData.map((entry) => (
- <li class="rating-column">
- <span class="rating-count">{entry.count}</span>
- <meter
- class="rating-meter"
- min="0"
- max={maxCount}
- value={entry.count}
- aria-label={`${entry.name} stars: ${entry.count} reviews`}
- >
- {entry.count} of {maxCount}
- </meter>
- <span class="rating-label">{entry.name}</span>
- </li>
- ))
- }
-</ul>
-
-<style>
- .rating-distribution {
- list-style: none;
- padding: 0;
- display: grid;
- grid-template-columns: repeat(5, minmax(0, 1fr));
- color: var(--color-text);
- font-family: var(--font-sans);
- }
-
- .rating-column {
- display: grid;
- grid-template-rows: auto auto auto;
- gap: 0.5rem;
- justify-items: center;
- }
-
- .rating-count {
- font-style: italic;
- }
-
- .rating-label {
- font-weight: 600;
- }
-
- .rating-meter {
- display: block;
- width: 4rem;
- height: 8rem;
- margin: 0;
- padding: 0;
- writing-mode: vertical-lr;
- -moz-orient: vertical;
- appearance: none;
- border: 1px solid var(--color-text);
- background: color-mix(in srgb, var(--color-text) 20%, var(--color-bg));
- overflow: hidden;
- }
-
- .rating-meter::-webkit-meter-bar {
- background: color-mix(in srgb, var(--color-text) 20%, var(--color-bg));
- }
-
- .rating-meter::-webkit-meter-optimum-value,
- .rating-meter::-webkit-meter-suboptimum-value,
- .rating-meter::-webkit-meter-even-less-good-value {
- background: var(--color-text);
- }
-
- .rating-meter::-moz-meter-bar {
- background: var(--color-text);
- }
-</style>
---
import { getCollection } from 'astro:content';
import Base from '@layouts/base.astro';
-import RatingDistribution from '@components/ratingdistribution/component.astro';
+import RatingDistribution from '@components/ratingdistribution.astro';
import Rating from '@components/ui/rating.astro';
import sortByDate from '@utils/sortByDate';
import generateContentUrl from '@utils/generateContentUrl';