|
1 | 1 | import React, {useEffect} from "react";
|
2 |
| -import {selectors, useAppSelector, useGetNewsPodListQuery} from "../../../state"; |
| 2 | +import {selectors, useAppSelector, useGetNewsPodListQuery, useLazyGetEventsQuery} from "../../../state"; |
3 | 3 | import {Link} from "react-router-dom";
|
4 |
| -import {Button, Col, Container, Row} from "reactstrap"; |
5 |
| -import {NewsCarousel} from "../../elements/NewsCarousel"; |
6 |
| -import {above, SITE_TITLE, useDeviceSize, useUserConsent} from "../../../services"; |
7 |
| -import {HomepageYoutubeCookieHandler} from "../../handlers/InterstitialCookieHandler"; |
| 4 | +import {Button, Card, CardBody, CardProps, CardText, CardTitle, Col, Container, Row} from "reactstrap"; |
| 5 | +import {above, EventStatusFilter, EventTypeFilter, HUMAN_STAGES, HUMAN_SUBJECTS, isLoggedIn, PHY_NAV_SUBJECTS, SITE_TITLE, STAGE, useDeviceSize} from "../../../services"; |
| 6 | +import { NewsCard } from "../../elements/cards/NewsCard"; |
| 7 | +import { ShowLoadingQuery } from "../../handlers/ShowLoadingQuery"; |
| 8 | +import { EventCard } from "../../elements/cards/EventCard"; |
8 | 9 | import { StudentDashboard } from "../../elements/StudentDashboard";
|
| 10 | +import { Subject, ShortcutResponse } from "../../../../IsaacAppTypes"; |
| 11 | +import { ListViewCardProps, ListViewCards } from "../../elements/list-groups/ListView"; |
| 12 | +import { Spacer } from "../../elements/Spacer"; |
| 13 | + |
| 14 | +interface HomepageHeroCardProps extends CardProps { |
| 15 | + title?: string; |
| 16 | + content?: string; |
| 17 | + isStudent?: boolean; |
| 18 | +} |
| 19 | + |
| 20 | +const HomepageHeroCard = ({title, content, isStudent}: HomepageHeroCardProps) => { |
| 21 | + return <Card className="homepage-hero-card border-0"> |
| 22 | + <CardBody className="p-4 pt-5 d-flex flex-column"> |
| 23 | + <div className="homepage-hero-card-tag"> |
| 24 | + {isStudent |
| 25 | + ? <> |
| 26 | + <img src="/assets/phy/icons/redesign/homepage-hero-student-flag.svg" height={"40px"} alt={"student card tag"}/> |
| 27 | + <b>STUDENTS</b> |
| 28 | + </> |
| 29 | + : <> |
| 30 | + <img src="/assets/phy/icons/redesign/homepage-hero-teacher-flag.svg" height={"40px"} alt={"teacher card tag"}/> |
| 31 | + <b>TEACHERS</b> |
| 32 | + </> |
| 33 | + } |
| 34 | + </div> |
| 35 | + <CardTitle className="mt-1" tag="h4">{title}</CardTitle> |
| 36 | + <CardText>{content}</CardText> |
| 37 | + <Spacer/> |
| 38 | + <Button className="w-max-content" tag={Link} to={isStudent ? "/login" : "/teacher_account_request"}>Create a {isStudent ? "student" : "teacher"} account</Button> |
| 39 | + </CardBody> |
| 40 | + </Card>; |
| 41 | +}; |
| 42 | + |
| 43 | +const HomepageHero = () => { |
| 44 | + const user = useAppSelector(selectors.user.orNull); |
| 45 | + const deviceSize = useDeviceSize(); |
| 46 | + if (!isLoggedIn(user)) { |
| 47 | + return <div className="homepage-hero"> |
| 48 | + {above['md'](deviceSize) && <div className="homepage-hero-img"/>} |
| 49 | + <Container className="pt-5"> |
| 50 | + <div className="w-100 w-md-50 mb-4 mb-md-5 mb-xl-6 pe-xl-5"> |
| 51 | + <div className="physics-strapline mb-3"> |
| 52 | + <h2><span className="text-green">Master Science subjects</span> by solving problems</h2> |
| 53 | + </div> |
| 54 | + From School to University – <b>Isaac</b> is a free platform for teachers and students for use in the classroom, for homework and for revision. |
| 55 | + </div> |
| 56 | + {!above['md'](deviceSize) && <div className="homepage-hero-img container-override"/>} |
| 57 | + <Row className="row-cols-1 row-cols-md-2"> |
| 58 | + <Col className="mb-3"> |
| 59 | + <HomepageHeroCard |
| 60 | + title="Build Confidence in Physics through Practice" |
| 61 | + content="Tackle interactive questions, explore varying difficulty levels, and strengthen problem-solving skills with concept guides, video lessons, and events." |
| 62 | + isStudent={true}/> |
| 63 | + </Col> |
| 64 | + <Col className="mb-3"> |
| 65 | + <HomepageHeroCard |
| 66 | + title="Support students in developing skills and achieving higher results" |
| 67 | + content="Assign, track, and manage student progress with ease—ideal for classwork, homework, or revision. Trusted by over 1,000 UK schools." |
| 68 | + isStudent={false}/> |
| 69 | + </Col> |
| 70 | + </Row> |
| 71 | + </Container> |
| 72 | + </div>; |
| 73 | + } |
| 74 | +}; |
| 75 | + |
| 76 | +type subjectCategory = {subject: string, humanSubject: string, subcategories: {humanStage: string, href: string}[]}; |
| 77 | +const subjectCategories = Object.entries(PHY_NAV_SUBJECTS).map(([subject, stages]) => { |
| 78 | + return { |
| 79 | + subject: subject, |
| 80 | + humanSubject: HUMAN_SUBJECTS[subject], |
| 81 | + subcategories: stages.map((stage) => { |
| 82 | + return { |
| 83 | + humanStage: HUMAN_STAGES[stage.valueOf()], |
| 84 | + href: `/${subject}/${stage}`, |
| 85 | + }; |
| 86 | + }) |
| 87 | + }; |
| 88 | +}); |
| 89 | + |
| 90 | +const getListViewSubjectCard = (sc: subjectCategory) => { |
| 91 | + const item: ShortcutResponse = { |
| 92 | + title: sc.humanSubject, |
| 93 | + subtitle: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris faucibus est vulputate augue tristique, sed vehicula turpis pellentesque.", |
| 94 | + }; |
| 95 | + |
| 96 | + const listViewSubjectCard: ListViewCardProps = { |
| 97 | + item: item, |
| 98 | + icon: {type: "img", icon: `/assets/phy/icons/redesign/subject-${sc.subject}.svg`}, |
| 99 | + subject: sc.subject as Subject, |
| 100 | + linkTags: sc.subcategories.map((subcat) => ({tag: subcat.humanStage, url: subcat.href})) |
| 101 | + }; |
| 102 | + |
| 103 | + return listViewSubjectCard; |
| 104 | +}; |
| 105 | + |
| 106 | +const cards = subjectCategories.map((sc) => getListViewSubjectCard(sc)); |
9 | 107 |
|
10 | 108 | export const HomepagePhy = () => {
|
11 | 109 | useEffect( () => {document.title = SITE_TITLE;}, []);
|
12 |
| - const {data: news} = useGetNewsPodListQuery({subject: "physics"}); |
| 110 | + |
13 | 111 | const user = useAppSelector(selectors.user.orNull);
|
14 |
| - const deviceSize = useDeviceSize(); |
15 |
| - const userConsent = useUserConsent(); |
| 112 | + const {data: news} = useGetNewsPodListQuery({subject: "physics"}); |
16 | 113 |
|
| 114 | + const [getEventsList, eventsQuery] = useLazyGetEventsQuery(); |
| 115 | + useEffect(() => { |
| 116 | + getEventsList({startIndex: 0, limit: 2, typeFilter: EventTypeFilter["All events"], statusFilter: EventStatusFilter["Upcoming events"], stageFilter: [STAGE.ALL]}); |
| 117 | + }, []); |
| 118 | + |
17 | 119 | return <>
|
18 |
| - {/*<WarningBanner/>*/} |
19 |
| - <StudentDashboard /> |
20 |
| - <div id="homepage" className="pb-5 px-2 px-sm-5 mx-md-5 px-lg-0"> |
21 |
| - <section id="call-to-action" className="homepageHero"> |
22 |
| - <Container className="pt-4"> |
23 |
| - <Row className="mt-sm-4"> |
24 |
| - <Col lg={5} className="physics-site-intro"> |
25 |
| - <h1 className={`physics-strapline ${above["lg"](deviceSize) ? "h2" : ""} mb-lg-3`}> |
26 |
| - {above["sm"](deviceSize) ? |
27 |
| - <>Master Physics by Solving Problems:<br /><small>from School to University!</small></> : |
28 |
| - <>Master Physics by Solving Problems</>} |
29 |
| - </h1> |
30 |
| - <p>Welcome to Isaac Physics, the free platform for teachers and students.</p> |
31 |
| - <ul> |
32 |
| - <li>Use it in the <strong>classroom</strong></li> |
33 |
| - <li>Use it for <strong>homework</strong></li> |
34 |
| - <li>Use it for <strong>revision</strong></li> |
35 |
| - </ul> |
36 |
| - </Col> |
37 |
| - <Col lg={7} className={above["lg"](deviceSize) ? `align-items-stretch d-flex flex-column` : ""}> |
38 |
| - {!(user && user.loggedIn) && <Row className="align-self-end mt-2 mt-lg-0 mb-1 mb-lg-0"> |
39 |
| - <Col className="col-6 col-lg-auto ps-lg-0 pe-1 pe-sm-2"> |
40 |
| - <Button size={above['lg'](deviceSize) || deviceSize === "xs" ? "sm" : ""} tag={Link} to="/login" color="primary" outline block |
41 |
| - > |
42 |
| - Log in |
43 |
| - </Button> |
44 |
| - </Col> |
45 |
| - <Col className="col-6 col-lg-auto ps-lg-0 ps-1 ps-sm-2"> |
46 |
| - <Button size={above['lg'](deviceSize) || deviceSize === "xs" ? "sm" : ""} tag={Link} to="/register" color="secondary" block> |
47 |
| - Sign up |
48 |
| - </Button> |
49 |
| - </Col> |
50 |
| - </Row>} |
51 |
| - <div className={`h-100 ps-lg-4 content-video-container w-100 ${user?.loggedIn ? "pt-1 pt-sm-2 pt-lg-2" : "pt-4 pt-lg-3"} ${userConsent.cookieConsent?.youtubeCookieAccepted ?? false ? "ratio-16x9" : ""}`}> |
52 |
| - <HomepageYoutubeCookieHandler /> |
53 |
| - </div> |
54 |
| - </Col> |
55 |
| - </Row> |
56 |
| - |
57 |
| - <div className="physics-site-intro mt-4 mt-lg-2"> |
58 |
| - <strong>Show me resources for...</strong> |
59 |
| - <Row className="mt-2"> |
60 |
| - <Col xs={12} lg={3} className="pe-lg-1 py-1"> |
61 |
| - <Button size={deviceSize==="xs" ? "sm" : ""} block tag={Link} to="/11_14" className="h-100 d-inline-flex align-items-center justify-content-center"> |
62 |
| - 11-14 |
63 |
| - </Button> |
64 |
| - </Col> |
65 |
| - <Col xs={12} lg={3} className="px-lg-1 py-1"> |
66 |
| - <Button size={deviceSize==="xs" ? "sm" : ""} block tag={Link} to="/gcse" className="h-100 d-inline-flex align-items-center justify-content-center"> |
67 |
| - {above["md"](deviceSize) ? |
68 |
| - "GCSE or\u00A0equivalent" : |
69 |
| - "GCSE"} |
70 |
| - </Button> |
71 |
| - </Col> |
72 |
| - <Col xs={12} lg={3} className="px-lg-1 py-1"> |
73 |
| - <Button size={deviceSize==="xs" ? "sm" : ""} block tag={Link} to="/alevel" className="h-100 d-inline-flex align-items-center justify-content-center"> |
74 |
| - {above["md"](deviceSize) ? |
75 |
| - "A\u00A0Level or\u00A0equivalent" : |
76 |
| - "A\u00A0Level"} |
77 |
| - </Button> |
78 |
| - </Col> |
79 |
| - <Col xs={12} lg={3} className="ps-lg-1 py-1"> |
80 |
| - <Button size={deviceSize==="xs" ? "sm" : ""} block tag={Link} to="/teacher_features" className="h-100 d-inline-flex align-items-center justify-content-center"> |
81 |
| - teachers |
82 |
| - </Button> |
83 |
| - </Col> |
84 |
| - </Row> |
85 |
| - </div> |
86 |
| - </Container> |
| 120 | + <div id="homepage" className="homepage pb-5"> |
| 121 | + <section id="student-dashboard"> |
| 122 | + <StudentDashboard /> |
87 | 123 | </section>
|
88 |
| - |
89 |
| - <section id="news"> |
90 |
| - <Container> |
91 |
| - <div className="h-underline mb-4 mt-4 pt-2 mt-sm-5 pt-sm-0 d-flex align-items-center"> |
92 |
| - <h2>News and features</h2> |
93 |
| - <Link to="/news" className="ms-auto">See all news</Link> |
94 |
| - </div> |
95 |
| - <Row className="eventList pt-1"> |
96 |
| - <Col> |
97 |
| - <NewsCarousel items={news} showTitle className={"mx-sm-n4"} /> |
98 |
| - </Col> |
99 |
| - </Row> |
100 |
| - </Container> |
| 124 | + <section id="homepage-hero"> |
| 125 | + {!isLoggedIn(user) && <HomepageHero />} |
101 | 126 | </section>
|
102 |
| - |
103 |
| - {!user?.loggedIn && <section className="mb-4"> |
104 |
| - <Container> |
105 |
| - <div className="mt-4 py-4 px-5 d-flex align-items-center flex-column flex-md-row border bg-white"> |
106 |
| - <h3 className="text-center text-md-start me-md-4 me-lg-0 mb-3 mb-md-0"> |
107 |
| - Sign up to track your progress |
108 |
| - </h3> |
109 |
| - <Button tag={Link} size="lg" className="ms-md-auto me-md-3 me-lg-5 btn-xl" to={"/register"}> |
110 |
| - Sign up |
111 |
| - </Button> |
112 |
| - </div> |
113 |
| - </Container> |
114 |
| - </section>} |
| 127 | + <Container> |
| 128 | + <section id="explore-learn"> |
| 129 | + <div className="mt-5"> |
| 130 | + <div className="d-flex"> |
| 131 | + <h3>Explore and learn!</h3> |
| 132 | + <div className="section-divider ms-2"/> |
| 133 | + </div> |
| 134 | + <ListViewCards cards={cards}/> |
| 135 | + </div> |
| 136 | + </section> |
| 137 | + <section id="events-news"> |
| 138 | + <Row className="mt-5 row-cols-1 row-cols-lg-2"> |
| 139 | + <div className="d-flex flex-column mt-3"> |
| 140 | + <div className="d-flex"> |
| 141 | + <h3>Upcoming Events</h3> |
| 142 | + <Link to="/events" className="news-events-link">More events</Link> |
| 143 | + <div className="section-divider"/> |
| 144 | + </div> |
| 145 | + <ShowLoadingQuery |
| 146 | + query={eventsQuery} |
| 147 | + defaultErrorTitle={"Error loading events list"} |
| 148 | + thenRender={({events}) => { |
| 149 | + return <Row className="h-100"> |
| 150 | + {events.map(event => <Col key={event.id}> |
| 151 | + <EventCard event={event} /> |
| 152 | + </Col>)} |
| 153 | + </Row>; |
| 154 | + }}/> |
| 155 | + </div> |
| 156 | + <div className="d-flex flex-column mt-3"> |
| 157 | + <div className="d-flex"> |
| 158 | + <h3>News & Features</h3> |
| 159 | + <Link to="/news" className="news-events-link">More news</Link> |
| 160 | + <div className="section-divider"/> |
| 161 | + </div> |
| 162 | + {news && <Row className="h-100"> |
| 163 | + {news.slice(0, 2).map(newsItem => <Col key={newsItem.id}> |
| 164 | + <NewsCard newsItem={newsItem} /> |
| 165 | + </Col>)} |
| 166 | + </Row>} |
| 167 | + </div> |
| 168 | + </Row> |
| 169 | + </section> |
| 170 | + </Container> |
115 | 171 | </div>
|
116 | 172 | </>;
|
117 | 173 | };
|
0 commit comments