11import { createPortal } from 'react-dom' ;
2- import { useSelector } from 'react-redux' ;
32import PropTypes from 'prop-types' ;
4-
5- import { Xpert } from '@edx/frontend-lib-learning-assistant' ;
6- import { getConfig } from '@edx/frontend-platform' ;
7-
8- import { ALLOW_UPSELL_MODES , VERIFIED_MODES } from '@src/constants' ;
9- import { useModel } from '../../../generic/model-store' ;
3+ import { PluginSlot } from '@openedx/frontend-plugin-framework' ;
4+ import { getAuthenticatedUser } from '@edx/frontend-platform/auth' ;
105
116const Chat = ( {
127 enabled,
138 enrollmentMode,
149 isStaff,
1510 courseId,
16- contentToolsEnabled,
1711 unitId,
1812} ) => {
19- const {
20- activeAttempt, exam,
21- } = useSelector ( state => state . specialExams ) ;
22- const course = useModel ( 'coursewareMeta' , courseId ) ;
23-
24- // If is disabled or taking an exam, we don't show the chat.
25- if ( ! enabled || activeAttempt ?. attempt_id || exam ?. id ) { return null ; }
26-
27- // If is not staff and doesn't have an enrollment, we don't show the chat.
28- if ( ! isStaff && ! enrollmentMode ) { return null ; }
29-
30- const verifiedMode = VERIFIED_MODES . includes ( enrollmentMode ) ; // Enrollment verified
31- const auditMode = (
32- ! isStaff
33- && ! verifiedMode
34- && ALLOW_UPSELL_MODES . includes ( enrollmentMode ) // Can upgrade course
35- && getConfig ( ) . ENABLE_XPERT_AUDIT
36- ) ;
37- // If user has no access, we don't show the chat.
38- if ( ! isStaff && ! ( verifiedMode || auditMode ) ) { return null ; }
39-
40- // Date validation
41- const {
42- accessExpiration,
43- start,
44- end,
45- } = course ;
46-
47- const utcDate = ( new Date ( ) ) . toISOString ( ) ;
48- const expiration = accessExpiration ?. expirationDate || utcDate ;
49- const validDate = (
50- ( start ? start <= utcDate : true )
51- && ( end ? end >= utcDate : true )
52- && ( auditMode ? expiration >= utcDate : true )
53- ) ;
54- // If date is invalid, we don't show the chat.
55- if ( ! validDate ) { return null ; }
56-
57- // Use a portal to ensure that component overlay does not compete with learning MFE styles.
13+ const { userId } = getAuthenticatedUser ( ) ;
14+
15+ // If chat is disabled, don't show anything
16+ if ( ! enabled ) {
17+ return null ;
18+ }
19+
20+ // Provide minimal, generic context - no feature-specific flags
21+ const pluginContext = {
22+ courseId,
23+ unitId,
24+ userId,
25+ isStaff,
26+ enrollmentMode,
27+ } ;
28+
29+ // Use generic plugin slot ID (location-based, not feature-specific)
30+ // Plugins will query their own requirements from Redux/config
5831 return createPortal (
59- < Xpert
60- courseId = { courseId }
61- contentToolsEnabled = { contentToolsEnabled }
62- unitId = { unitId }
63- isUpgradeEligible = { auditMode }
32+ < PluginSlot
33+ id = "learner_tools_slot"
34+ pluginProps = { pluginContext }
6435 /> ,
6536 document . body ,
6637 ) ;
@@ -71,7 +42,6 @@ Chat.propTypes = {
7142 enabled : PropTypes . bool . isRequired ,
7243 enrollmentMode : PropTypes . string ,
7344 courseId : PropTypes . string . isRequired ,
74- contentToolsEnabled : PropTypes . bool . isRequired ,
7545 unitId : PropTypes . string . isRequired ,
7646} ;
7747
0 commit comments