Skip to content
Merged
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
20 changes: 20 additions & 0 deletions mock-data/ai-review-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"challengeId": "97701509-f4ee-4a03-9bd1-bad7413d2274",
"minPassingThreshold": 15,
"mode": "AI_ONLY",
"templateId": "template_001",
"autoFinalize": false,
"formula": {},
"workflows": [
{
"workflowId": "1lROGgC0jANqJL",
"weightPercent": 80,
"isGating": false
},
{
"workflowId": "J0aZLgbf9NUvnZ",
"weightPercent": 20,
"isGating": false
}
]
}
171 changes: 171 additions & 0 deletions mock-data/ai-review-templates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
{
"templates": [
{
"id": "template_001",
"challengeTrack": "Development",
"challengeType": "Challenge",
"title": "Development Code Challenge - Standard",
"description": "Standard AI review configuration for development track code challenges. Combines code quality and security checks with gating mechanism.",
"minPassingThreshold": 75.00,
"mode": "AI_GATING",
"autoFinalize": false,
"formula": {
"type": "gating",
"gates": [
{
"workflowId": "wf_001_security",
"threshold": 80,
"isMandatory": true
}
],
"scoring": {
"type": "weighted",
"weights": {
"wf_001_security": 0.4,
"wf_002_quality": 0.6
}
}
},
"workflows": [
{
"id": "tcwf_001",
"configId": "template_001",
"workflowId": "wf_001_security",
"weightPercent": 40.00,
"isGating": true,
"workflow": {
"id": "wf_001_security",
"name": "Security Code Review",
"description": "Analyzes code for security vulnerabilities",
"scorecardId": "scorecard_sec_001"
}
},
{
"id": "tcwf_002",
"configId": "template_001",
"workflowId": "wf_002_quality",
"weightPercent": 60.00,
"isGating": false,
"workflow": {
"id": "wf_002_quality",
"name": "Code Quality Check",
"description": "Evaluates code quality metrics",
"scorecardId": "scorecard_quality_001"
}
}
],
"createdAt": "2026-01-15T10:30:00Z",
"createdBy": "admin_user_001",
"updatedAt": "2026-02-10T14:20:00Z",
"updatedBy": "admin_user_002"
},
{
"id": "template_002",
"challengeTrack": "Design",
"challengeType": "Challenge",
"title": "Design Challenge - AI Only",
"description": "AI-only review for design challenges. No human review required - AI makes final decisions.",
"minPassingThreshold": 70.00,
"mode": "AI_ONLY",
"autoFinalize": true,
"formula": {
"type": "weighted",
"weights": {
"wf_003_design": 0.5,
"wf_004_usability": 0.5
}
},
"workflows": [
{
"id": "tcwf_003",
"configId": "template_002",
"workflowId": "wf_003_design",
"weightPercent": 50.00,
"isGating": false,
"workflow": {
"id": "wf_003_design",
"name": "Design Review",
"description": "Reviews design assets and composition",
"scorecardId": "scorecard_design_001"
}
},
{
"id": "tcwf_004",
"configId": "template_002",
"workflowId": "wf_004_usability",
"weightPercent": 50.00,
"isGating": false,
"workflow": {
"id": "wf_004_usability",
"name": "Usability Assessment",
"description": "Evaluates usability and UX principles",
"scorecardId": "scorecard_usability_001"
}
}
],
"createdAt": "2026-01-20T09:00:00Z",
"createdBy": "admin_user_001",
"updatedAt": "2026-02-05T16:45:00Z",
"updatedBy": "admin_user_001"
},
{
"id": "template_003",
"challengeTrack": "Data Science",
"challengeType": "Marathon Match",
"title": "Data Science Challenge - Gating",
"description": "Data science challenge with AI gating for submissions. AI filters low-quality submissions; humans review the rest.",
"minPassingThreshold": 80.00,
"mode": "AI_GATING",
"autoFinalize": false,
"formula": {
"type": "gating",
"gates": [
{
"workflowId": "wf_005_accuracy",
"threshold": 75,
"isMandatory": true
}
],
"scoring": {
"type": "weighted",
"weights": {
"wf_005_accuracy": 0.5,
"wf_006_methodology": 0.5
}
}
},
"workflows": [
{
"id": "tcwf_005",
"configId": "template_003",
"workflowId": "wf_005_accuracy",
"weightPercent": 50.00,
"isGating": true,
"workflow": {
"id": "wf_005_accuracy",
"name": "Model Accuracy Validator",
"description": "Validates machine learning model accuracy",
"scorecardId": "scorecard_accuracy_001"
}
},
{
"id": "tcwf_006",
"configId": "template_003",
"workflowId": "wf_006_methodology",
"weightPercent": 50.00,
"isGating": false,
"workflow": {
"id": "wf_006_methodology",
"name": "Methodology Review",
"description": "Reviews data science methodology",
"scorecardId": "scorecard_methodology_001"
}
}
],
"createdAt": "2026-02-01T11:15:00Z",
"createdBy": "admin_user_002",
"updatedAt": "2026-02-15T13:30:00Z",
"updatedBy": "admin_user_002"
}
]
}
6 changes: 6 additions & 0 deletions src/components/Buttons/OutlineButton/Outline.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,10 @@
color: $tc-gray-40;
}
}

&.minWidth {
width: min-content;
padding-left: 16px;
padding-right: 16px;
}
}
5 changes: 3 additions & 2 deletions src/components/Buttons/OutlineButton/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cn from 'classnames'
import styles from './Outline.module.scss'
import _ from 'lodash'

const OutlineButton = ({ type, text, link, onClick, url, className, submit, disabled, target = 'self', rel }) => {
const OutlineButton = ({ type, text, link, onClick, url, className, submit, disabled, target = 'self', rel, minWidth = false }) => {
const containerClassName = cn(styles.container, styles[type], className)

const handleUrlClick = (event) => {
Expand Down Expand Up @@ -34,7 +34,7 @@ const OutlineButton = ({ type, text, link, onClick, url, className, submit, disa
return (
<button
type={submit ? 'submit' : 'button'}
className={cn(containerClassName, disabled && styles.disable)}
className={cn(containerClassName, disabled && styles.disable, minWidth && styles.minWidth)}
onClick={submit ? null : onClick}
disabled={disabled}
>
Expand Down Expand Up @@ -67,6 +67,7 @@ const OutlineButton = ({ type, text, link, onClick, url, className, submit, disa
}

OutlineButton.propTypes = {
minWidth: PropTypes.bool,
type: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
link: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react'
import PropTypes from 'prop-types'
import styles from './AiWorkflowCard.module.scss'

const AIWorkflowCard = ({ workflow, scorecardId, description, onRemove, readOnly = false }) => {
return (
<div className={styles.workflowCard}>
<div className={styles.workflowcardHeader}>
<div className={styles.workflowInfo}>
<div className={styles.workflowName}>
<span className={styles.workflowIcon}>🤖</span>
<span className={styles.workflowTitle}>{workflow.name}</span>
</div>
</div>
{!readOnly && onRemove && (
<button
className={styles.workflowRemoveBtn}
onClick={onRemove}
title='Remove workflow'
aria-label='Remove workflow'
>
</button>
)}
</div>

<div className={styles.workflowcardContent}>
{description && (
<div className={styles.workflowDescription}>
<strong>Description:</strong>
<p>{description}</p>
</div>
)}

{scorecardId && (
<div className={styles.workflowScorecard}>
<strong>Scorecard:</strong>
{scorecardId}
</div>
)}
</div>
</div>
)
}

AIWorkflowCard.propTypes = {
workflow: PropTypes.shape({
id: PropTypes.string,
name: PropTypes.string.isRequired
}).isRequired,
scorecardId: PropTypes.string,
description: PropTypes.string,
onRemove: PropTypes.func,
readOnly: PropTypes.bool
}

export default AIWorkflowCard
Loading
Loading