Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 19 additions & 10 deletions src/components/ChallengeEditor/CheckpointPrizes-Field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,32 @@ import { getPrizeType } from '../../../util/prize'
const CheckpointPrizesField = ({ challenge, onUpdateOthers, readOnly }) => {
const type = PRIZE_SETS_TYPE.CHECKPOINT_PRIZES
const prizeSets = _.get(challenge, 'prizeSets') || []
const checkpointPrize = prizeSets.find(p => p.type === type) || { type: PRIZE_SETS_TYPE.CHECKPOINT_PRIZES, prizes: [], 'description': 'Checkpoint Prizes' }
const number = _.get(checkpointPrize, 'prizes.length') || DEFAULT_CHECKPOINT_PRIZE_COUNT
const amount = _.get(checkpointPrize, 'prizes.length') ? checkpointPrize.prizes[0].value : DEFAULT_CHECKPOINT_PRIZE
const prizeType = _.get(checkpointPrize, 'prizes[0].type') || getPrizeType(prizeSets)

// Determine the currency type from the main challenge prizes (PLACEMENT)
const mainChallengeCurrencyType = getPrizeType(prizeSets)

const checkpointPrizeSet = prizeSets.find(p => p.type === type) || { type: PRIZE_SETS_TYPE.CHECKPOINT_PRIZES, prizes: [], 'description': 'Checkpoint Prizes' }
const number = _.get(checkpointPrizeSet, 'prizes.length') || DEFAULT_CHECKPOINT_PRIZE_COUNT
const amount = _.get(checkpointPrizeSet, 'prizes.length') ? checkpointPrizeSet.prizes[0].value : DEFAULT_CHECKPOINT_PRIZE

// update the check point prize with default values if it's not already defined
if (_.get(checkpointPrize, 'prizes.length') === 0) {
// or if the prize type is not CHECKPOINT (e.g., legacy data might have USD/POINT)
if (_.get(checkpointPrizeSet, 'prizes.length') === 0 || _.get(checkpointPrizeSet, 'prizes[0].type') !== CHALLENGE_PRIZE_TYPE.CHECKPOINT) {
onChange(number, amount)
}

function onChange (number, amount) {
checkpointPrize.prizes = _.range(validateValue(number, VALIDATION_VALUE_TYPE.INTEGER))
.map(i => ({ type: prizeType, value: +validateValue(amount, VALIDATION_VALUE_TYPE.INTEGER) }))
onUpdateOthers({ field: 'prizeSets', value: [...prizeSets.filter(p => p.type !== type), +number && checkpointPrize].filter(p => p) })
checkpointPrizeSet.prizes = _.range(validateValue(number, VALIDATION_VALUE_TYPE.INTEGER))
.map(i => ({
type: CHALLENGE_PRIZE_TYPE.CHECKPOINT, // Set the prize type to CHECKPOINT
value: +validateValue(amount, VALIDATION_VALUE_TYPE.INTEGER)
}))
// Filter out the old checkpoint prize set and add the updated one
onUpdateOthers({ field: 'prizeSets', value: [...prizeSets.filter(p => p.type !== type), +number && checkpointPrizeSet].filter(p => p) })
}

const symbol = prizeType === CHALLENGE_PRIZE_TYPE.POINT ? 'Pts' : '$'
// Use the main challenge currency type for display symbol
const symbol = mainChallengeCurrencyType === CHALLENGE_PRIZE_TYPE.POINT ? 'Pts' : '$'

return (
<>
Expand All @@ -54,7 +63,7 @@ const CheckpointPrizesField = ({ challenge, onUpdateOthers, readOnly }) => {
<div>
<div className={styles.checkpointPrizeInputContainer}>
<div className={styles.checkpointPrizeAmountContainer}>
{prizeType === CHALLENGE_PRIZE_TYPE.POINT
{mainChallengeCurrencyType === CHALLENGE_PRIZE_TYPE.POINT
? <span className={styles.pointsLabel}>Pts</span>
: <FontAwesomeIcon className={styles.dollarIcon} icon={faDollarSign} />}
</div>
Expand Down
82 changes: 64 additions & 18 deletions src/util/prize.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,75 @@
import _ from 'lodash'
import { CHALLENGE_PRIZE_TYPE, PRIZE_SETS_TYPE } from '../config/constants'

const PRIZE_SETS_WITH_TYPE = [
PRIZE_SETS_TYPE.CHALLENGE_PRIZES,
PRIZE_SETS_TYPE.REVIEWER_PAYMENT,
PRIZE_SETS_TYPE.CHECKPOINT_PRIZES
]
/**
* Get prize type (USD or POINT) from prize sets.
* It prioritizes PLACEMENT prize set, then COPILOT_PAYMENT.
* If no specific prize type is found, it defaults to USD.
*
* @param {Array} prizeSets prize sets
* @returns {String} prize type (USD or POINT)
*/
export function getPrizeType (prizeSets) {
if (!prizeSets || !prizeSets.length) {
return CHALLENGE_PRIZE_TYPE.USD
}

export const getPrizeType = (prizeSets = []) => {
const placementSet = (prizeSets || []).find(p => p.type === PRIZE_SETS_TYPE.CHALLENGE_PRIZES)
const prizeType = placementSet && placementSet.prizes && placementSet.prizes[0] && placementSet.prizes[0].type
return prizeType || CHALLENGE_PRIZE_TYPE.USD
}
// Prioritize PLACEMENT prize set for overall challenge currency type
const placementPrizeSet = prizeSets.find(p => p.type === PRIZE_SETS_TYPE.CHALLENGE_PRIZES)
if (placementPrizeSet && placementPrizeSet.prizes && placementPrizeSet.prizes.length) {
// Ensure the type is USD or POINT, not CHECKPOINT
const type = placementPrizeSet.prizes[0].type
if (type === CHALLENGE_PRIZE_TYPE.USD || type === CHALLENGE_PRIZE_TYPE.POINT) {
return type
}
}

// Fallback to COPILOT_PAYMENT if no PLACEMENT or invalid type
const copilotPrizeSet = prizeSets.find(p => p.type === PRIZE_SETS_TYPE.COPILOT_PAYMENT)
if (copilotPrizeSet && copilotPrizeSet.prizes && copilotPrizeSet.prizes.length) {
const type = copilotPrizeSet.prizes[0].type
if (type === CHALLENGE_PRIZE_TYPE.USD || type === CHALLENGE_PRIZE_TYPE.POINT) {
return type
}
}

// If no PLACEMENT or COPILOT_PAYMENT, check other prize sets, but still only return USD/POINT
for (const prizeSet of prizeSets) {
if (prizeSet.prizes && prizeSet.prizes.length) {
const type = prizeSet.prizes[0].type
if (type === CHALLENGE_PRIZE_TYPE.USD || type === CHALLENGE_PRIZE_TYPE.POINT) {
return type
}
} else if (prizeSet.type === CHALLENGE_PRIZE_TYPE.USD || prizeSet.type === CHALLENGE_PRIZE_TYPE.POINT) {
// Handle cases where prizeSet itself is a simple prize object (less common for top-level prizeSets)
return prizeSet.type
}
}

export const mapPrizesWithType = (prizes = [], prizeType = CHALLENGE_PRIZE_TYPE.USD) => {
return (prizes || []).map(prize => ({ ...prize, type: prizeType }))
return CHALLENGE_PRIZE_TYPE.USD
}

export const applyPrizeTypeToPrizeSets = (prizeSets = [], prizeType = CHALLENGE_PRIZE_TYPE.USD) => {
return (prizeSets || []).map(set => {
if (PRIZE_SETS_WITH_TYPE.includes(set.type)) {
/**
* Apply prize type (USD or POINT) to all prizes in prize sets.
*
* @param {Array} prizeSets prize sets
* @param {String} prizeType prize type (USD or POINT)
* @returns {Array} updated prize sets
*/
export function applyPrizeTypeToPrizeSets (prizeSets, prizeType) {
return _.map(prizeSets, (prizeSet) => {
// Only update PLACEMENT and COPILOT_PAYMENT prize types
if (prizeSet.type === PRIZE_SETS_TYPE.CHALLENGE_PRIZES || prizeSet.type === PRIZE_SETS_TYPE.COPILOT_PAYMENT) {
return {
...set,
prizes: mapPrizesWithType(set.prizes, prizeType)
...prizeSet,
prizes: _.map(prizeSet.prizes, (prize) => ({
...prize,
type: prizeType
}))
}
}
return set
// For CHECKPOINT_PRIZES, the internal prize type should remain CHALLENGE_PRIZE_TYPE.CHECKPOINT
// We assume the value is already in the correct currency based on the main challenge prize type.
return prizeSet
})
}