Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Challenge sales "Leaderboard" widget #1596 #1597

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
771a356
Leaderboard creation && edition
ithiame Nov 29, 2024
cfeb89a
Leaderboard creation && edition
ithiame Nov 29, 2024
58ef3f3
Leaderboard creation && edition
ithiame Nov 29, 2024
8c3a029
Leaderboard creation && edition
ithiame Nov 29, 2024
53f04c6
Leaderboard creation && edition
ithiame Nov 29, 2024
a529111
Widget creation and CMS Integration
ithiame Nov 29, 2024
be4f152
Widget creation and CMS Integration
ithiame Nov 29, 2024
df252e7
Widget creation and CMS Integration
ithiame Nov 29, 2024
d299f60
Widget creation and CMS Integration
ithiame Nov 29, 2024
6813ab6
Widget creation and CMS Integration
ithiame Nov 29, 2024
5d0198e
Compact design increment on paid
ithiame Nov 30, 2024
957f05c
Compact design increment on paid
ithiame Nov 30, 2024
b6e1c9d
Compact design increment on paid
ithiame Nov 30, 2024
3e6e9cf
Url to product && event tracking
ithiame Nov 30, 2024
fd78d0c
Fix goal = zero
ithiame Nov 30, 2024
480cd69
add product id on event tracking
ithiame Nov 30, 2024
e5e1d96
add product id on event tracking
ithiame Nov 30, 2024
f723315
Merge branch 'main' into leaderboard-challenge
Tirodem Nov 30, 2024
7c9e783
Documentation leaderboard
ithiame Dec 2, 2024
71ce8fa
Merge branch 'leaderboard-challenge' of https://github.com/B2Bitcoin/…
ithiame Dec 2, 2024
522dfdc
Documentation leaderboard
ithiame Dec 2, 2024
2d32910
leadeboard documentation
ithiame Dec 2, 2024
69cd8d5
leadeboard documentation
ithiame Dec 2, 2024
3b944cb
leadeboard documentation
ithiame Dec 2, 2024
2708a53
leadeboard documentation
ithiame Dec 2, 2024
0ab0d16
add suggested changes
ithiame Dec 9, 2024
d4bd92e
add suggested changes
ithiame Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/fr/leaderboard-widget.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Leaderboard Widget Documentation

Accessible sur **Admin** > **Widgets** > **Leaderboards**, cette section permet d'afficher un tableau de classement dans votre be-bop.

![image](https://github.com/user-attachments/assets/d9de6d66-d5ac-4f10-9d26-ab1a923946a4)

## Ajouter un leaderboard

Pour ajouter un leaderbord cliquez sur **add leaderboard**

### 1. **Leadeboard name **

Le nom du leaderboard. Un titre court et descriptif qui résume l'objectif du leaderboard.

### 2. **Mode**

Le mode du leaderboard qui peut etre un nombre d'articles vendu (**TotalProducts**) ou une somme d'argent à collecté (**MoneyAmount**)

### 3. Currency

Un champ **currency** si le mode est **MoneyAmount** qui represente la devise. Utilisé pour l'affichage.

### 4. **Beginning date **

La date à laquelle le leaderboard commence.

### 5. **Ending date**

La date limite de fin du leaderboard.

### 6. **Products**

Une liste de produits dont la vente fait evoluer le leaderboard.

## Intégration leaderboard dans CMS

Pour ajouter un leaderboard dans une page ou zone CMS vous pouvez utiliser `[Leaderboard=slug]`

![image](https://github.com/user-attachments/assets/af0565ec-a927-46fe-9fa4-1bf0039e0b89)

Et ça sera affiché comme suit :

![image](https://github.com/user-attachments/assets/551b7283-edb6-41eb-8d13-1c220c530839)
23 changes: 22 additions & 1 deletion src/lib/components/CmsDesign.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@
CmsTokens,
CmsContactForm,
CmsCountdown,
CmsGallery
CmsGallery,
CmsLeaderboard
} from '$lib/server/cms';
import SpecificationWidget from './SpecificationWidget.svelte';
import ContactForm from './ContactForm.svelte';
import { mapKeys } from '$lib/utils/mapKeys';
import CountdownWidget from './CountdownWidget.svelte';
import GalleryWidget from './GalleryWidget/GalleryWidget.svelte';
import { page } from '$app/stores';
import LeaderBoardWidget from './LeaderBoardWidget.svelte';
import CurrencyCalculator from './CurrencyCalculator.svelte';

export let products: CmsProduct[];
Expand All @@ -45,6 +47,7 @@
export let websiteLink: string | undefined;
export let brandName: string | undefined;
export let galleries: CmsGallery[];
export let leaderboards: CmsLeaderboard[];

let classNames = '';
export { classNames as class };
Expand All @@ -64,6 +67,10 @@
digitalFiles.map((digitalFile) => [digitalFile.productId, digitalFile])
);
$: challengeById = Object.fromEntries(challenges.map((challenge) => [challenge._id, challenge]));
$: leaderboardById = Object.fromEntries(
leaderboards.map((leaderboard) => [leaderboard._id, leaderboard])
);

$: sliderById = Object.fromEntries(sliders.map((slider) => [slider._id, slider]));
$: tagById = Object.fromEntries(tags.map((tag) => [tag._id, tag]));
$: picturesByTag = groupBy(
Expand Down Expand Up @@ -182,6 +189,13 @@
: ''}{token.height ? `height: ${token.height}px;` : ''}"
/>
<PictureComponent picture={pictureById[token.slug]} class="my-5 lg:hidden block" />
{:else if token.type === 'leaderboardWidget'}
<LeaderBoardWidget
leaderboard={leaderboardById[token.slug]}
{pictures}
{products}
class="not-prose"
/>
{:else if token.type === 'currencyCalculatorWidget'}
<CurrencyCalculator />
{:else if token.type === 'html'}
Expand Down Expand Up @@ -258,6 +272,13 @@
/>
{:else if token.type === 'pictureWidget'}
<PictureComponent picture={pictureById[token.slug]} class="my-5" />
{:else if token.type === 'leaderboardWidget'}
<LeaderBoardWidget
leaderboard={leaderboardById[token.slug]}
{pictures}
{products}
class="not-prose"
/>
{:else if token.type === 'currencyCalculatorWidget'}
<CurrencyCalculator />
{:else if token.type === 'html'}
Expand Down
7 changes: 6 additions & 1 deletion src/lib/components/CmsPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
CmsSpecification,
CmsContactForm,
CmsCountdown,
CmsGallery
CmsGallery,
CmsLeaderboard
} from '$lib/server/cms';
import CmsDesign from './CmsDesign.svelte';

Expand Down Expand Up @@ -43,6 +44,8 @@
export let contactForms: CmsContactForm[];
export let countdowns: CmsCountdown[];
export let galleries: CmsGallery[];
export let leaderboards: CmsLeaderboard[];

const { t } = useI18n();
</script>

Expand Down Expand Up @@ -76,6 +79,7 @@
{brandName}
{countdowns}
{galleries}
{leaderboards}
class="body body-mainPlan"
/>
{:else}
Expand All @@ -102,6 +106,7 @@
{brandName}
{countdowns}
{galleries}
{leaderboards}
class="body"
/>
</main>
Expand Down
9 changes: 6 additions & 3 deletions src/lib/components/GoalProgress.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
export let text: string;
export let goal: number;
export let progress: number;
export let leaderboard = false;
let className = '';
export { className as class };

$: percentage = (progress * 100) / goal;
$: percentage = goal !== 0 ? (progress * 100) / goal : 0;
$: newPercentage = (goal * 100) / progress;
</script>

Expand All @@ -15,7 +16,7 @@
? 'bg-green-500'
: 'bg-gradient-to-r from-red-500 to-green-500 via-yellow-500'}"
>
{#if percentage < 100}
{#if percentage <= 100}
<div
data-text={text}
style="background-position: {percentage}% 0%"
Expand All @@ -33,7 +34,9 @@
</div>
<div
class="absolute inset-0 rounded-[3px] flex justify-end {percentage >= 100
? 'bg-green-500'
? leaderboard
? 'bg-gradient-to-r from-red-500 to-green-500 via-yellow-500'
: 'bg-green-500'
: ''}"
style={percentage >= 100 ? `width: calc(${Math.round(newPercentage)}%);` : ''}
>
Expand Down
60 changes: 60 additions & 0 deletions src/lib/components/LeaderBoardWidget.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script lang="ts">
import GoalProgress from './GoalProgress.svelte';
import { useI18n } from '$lib/i18n';
import type { Leaderboard } from '$lib/types/Leaderboard';
import type { Product } from '$lib/types/Product';
import type { Picture } from '$lib/types/Picture';
import { groupBy } from 'lodash-es';
import type { SetRequired } from 'type-fest';
import PictureComponent from './Picture.svelte';

let className = '';
export { className as class };
export let leaderboard: Pick<
Leaderboard,
'_id' | 'name' | 'progress' | 'endsAt' | 'mode' | 'beginsAt'
>;
export let products: Pick<Product, '_id' | 'name' | 'shortDescription'>[];
export let pictures: Picture[];
const { locale } = useI18n();
$: productById = Object.fromEntries(products.map((product) => [product._id, product]));
$: picturesByProduct = groupBy(
pictures.filter((picture): picture is SetRequired<Picture, 'productId'> => !!picture.productId),
'productId'
);
leaderboard.progress.sort((a, b) => b.amount - a.amount);
</script>

{#each leaderboard.progress as progress}
<div class="flex items-center {className}">
<div class="flex items-center flex-row gap-4">
<a href="/product/{progress.productId}">
<PictureComponent
picture={picturesByProduct[productById[progress.productId]._id][0]}
class="max-w-[68px] max-h-[68px]"
/>
</a>
<div class="flex flex-col">
<a href="/product/{progress.productId}" class="font-medium text-[22px] body-title">
{productById[progress.productId].name}
</a>
<p class="hidden lg:contents">{productById[progress.productId].shortDescription}</p>
</div>
</div>
</div>
<GoalProgress
class="font-bold body-title"
text={leaderboard.mode === 'moneyAmount'
? Number(Math.max(0, progress.amount))
.toLocaleString($locale, {
style: 'currency',
currency: progress.currency,
minimumFractionDigits: 0
})
.toString()
: Math.max(progress.amount, 0).toString()}
goal={leaderboard.progress[0].amount}
progress={progress.amount}
leaderboard={true}
/>
{/each}
Loading
Loading