Skip to content

Commit

Permalink
feat: askXpert component to show users query results and the ability …
Browse files Browse the repository at this point in the history
…to tweak
  • Loading branch information
Maham Akif authored and Maham Akif committed Mar 13, 2024
1 parent 8096fea commit 0bfbb8d
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 0 deletions.
193 changes: 193 additions & 0 deletions src/components/catalogs/askXpertResultCard/AskXpertResultCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import {
Icon, Card, Stack, Form, Button, Spinner,
} from '@edx/paragon';
import { logError } from '@edx/frontend-platform/logging';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { Close } from '@edx/paragon/icons';
import askXpretImage from '../../../assets/edxXpert.png';
import EnterpriseCatalogAiCurationApiService from '../data/service';
import {
CONTENT_TYPE_COURSE,
CONTENT_TYPE_PROGRAM,
EXEC_ED_TITLE,
} from '../../../constants';

const AskXpertResultCard = ({ taskId, queryTitle, data }) => {
const [thresholdValue, setThresholdValue] = useState(0);
const [items, setItems] = useState(data);
const [loading, setLoading] = useState(false);

useEffect(() => {
setItems(data);
}, [data]);

const getXpertResultsWithThreshold = async (threshold) => {
try {
setLoading(true);
const results = await EnterpriseCatalogAiCurationApiService.getXpertResults(taskId, threshold);
const { status, data: responseData } = results;
if (status === 200 && responseData) {
setItems(responseData);
} else {
setItems([]);
}
setLoading(false);
} catch (error) {
setItems([]);
logError(error);
setLoading(false);
}
};

const handleChange = (e) => {
const threshold = Number(e.target.value);
setThresholdValue(threshold);
getXpertResultsWithThreshold(threshold);
};

const selfPacedCoursesCount = items.filter(item => item.learning_type === CONTENT_TYPE_COURSE).length;
const selfPacedProgramsCount = items.filter(item => item.learning_type === CONTENT_TYPE_PROGRAM).length;
const execEdCoursesCount = items.filter(item => item.learning_type === EXEC_ED_TITLE).length;

return (
<div>
<div className="mt-3 d-flex justify-content-center">
<Card orientation="horizontal" className="bg-primary w-100 row">
<Card.Section className="col-3">
<Card.ImageCap
src={askXpretImage}
srcAlt="xpert"
/>
</Card.Section>
<Card.Section className="col-6">
<Stack gap={3}>
<h1 className="text-white">
<FormattedMessage
id="catalogs.askXpert.result.card.heading"
defaultMessage="Xpert"
description="Heading displayed on askXpert result card"
/>
</h1>
<div className="text-white">
<FormattedMessage
id="catalogs.askXpert.result.card.label.for.results"
defaultMessage="Results: {queryTitle}"
description="Results label to display askXpert search results on askXpert result card"
values={{ queryTitle: <b>{queryTitle}</b> }}
/>
</div>
{ items && items.length > 0
? (
<div className="d-flex align-items-center text-white">
<div className="d-flex align-items-center mr-4">
{loading
? <Spinner animation="border" variant="light" className="mr-2" />
: <h1 className="text-white mr-2">{selfPacedCoursesCount}</h1>}
<span className="font-italic">
<FormattedMessage
id="catalogs.askXpert.result.card.label.for.self.paced.courses"
defaultMessage="Self-paced courses"
description="Label to display self-paced courses count on askXpert result card"
/>
</span>
</div>
<div className="d-flex align-items-center mr-4">
{loading
? <Spinner animation="border" variant="light" className="mr-2" />
: <h1 className="text-white mr-2">{selfPacedProgramsCount}</h1>}
<span className="font-italic">
<FormattedMessage
id="catalogs.askXpert.result.card.label.for.self.paced.programs"
defaultMessage="Self-paced programs"
description="Label to display self-paced programs count on askXpert result card"
/>
</span>
</div>
<div className="d-flex align-items-center">
{loading
? <Spinner animation="border" variant="light" className="mr-2" />
: <h1 className="text-white mr-2">{execEdCoursesCount}</h1>}
<span className="font-italic">
<FormattedMessage
id="catalogs.askXpert.result.card.label.for.executive.education.courses"
defaultMessage="Executive education courses"
description="Label to display executive education courses count on askXpert result card"
/>
</span>
</div>
</div>
)
: (
<p className="text-white">
<FormattedMessage
id="catalogs.askXpert.result.card.no.data.found.error.message"
defaultMessage="No course/program found against your filter criteria, please select a broader focus to get results"
description="Error message displayed when no course/program is found against the selected filter value, on askXpert result card"
/>
</p>
)}
<div className="text-white mt-4">
<Form.Group className="">
<Form.Label className="h2 text-white mb-3 font-weight-bold">
Update your results
</Form.Label>
<datalist id="values" className="d-flex justify-content-between mb-1">
<option value="0" label="Broad" className="p-0 font-weight-normal" />
<option value="0.8" label="Focused" className="p-0 font-weight-normal" />
</datalist>
<Form.Control
type="range"
role="slider"
value={thresholdValue}
onChange={handleChange}
min="0"
max="0.8"
step="0.2"
list="values"
aria-valuemin="0"
aria-valuemax="0.8"
className="m-0"
/>
</Form.Group>
</div>
</Stack>
</Card.Section>
<Card.Section className="col-3">
<div className="d-flex justify-content-end d-flex align-items-center">
<Button variant="inverse-outline-primary mr-3 btn-sm">New Search</Button>
<Icon src={Close} className="text-white" />
</div>
</Card.Section>
<Card.Section className="row d-flex justify-content-end m-0 pt-0 pb-0">
<p className="text-white">Powered by OpenAI</p>
</Card.Section>
</Card>
</div>
</div>
);
};

AskXpertResultCard.defaultProps = {
taskId: null,
queryTitle: null,
data: [],
};

AskXpertResultCard.propTypes = {
taskId: PropTypes.number,
queryTitle: PropTypes.string,
data: PropTypes.arrayOf(
PropTypes.shape({
learning_type: PropTypes.string.isRequired,
queryTitle: PropTypes.string,
card_image_url: PropTypes.string,
course_keys: PropTypes.arrayOf(PropTypes.string),
enterprise_catalog_query_queryTitles: PropTypes.arrayOf(PropTypes.string),
original_image_url: PropTypes.string,
}),
),
};

export default AskXpertResultCard;
24 changes: 24 additions & 0 deletions src/components/catalogs/askXpertResultCard/AskXpertResultCard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
input[type='range'] {
accent-color: yellow;
}

input[type='range']::-webkit-slider-runnable-track {
width: 300px;
height: 6px;
background: #fff;
border: none;
border-radius: 3px;
}

input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 16px;
width: 16px;
border-radius: 50%;
margin-top: -4px;
}

input[type='range']:focus::-webkit-slider-runnable-track {
background: #ffff;
}
1 change: 1 addition & 0 deletions src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@import './components/hero/Hero';
@import 'components/catalogSearchResults/associatedComponents/downloadCsvButton/DownloadCsvButton';
@import 'components/catalogSelectionDeck/CatalogSelectionDeck';
@import 'components/catalogs/askXpertResultCard/AskXpertResultCard';

.page-width {
max-width: 1350px;
Expand Down

0 comments on commit 0bfbb8d

Please sign in to comment.