Projects STRLCPY gradejs Commits 273ee362
🤬
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/layouts/Home/Home.tsx
    skipped 7 lines
    8 8  import CardGroup from '../../ui/CardGroup/CardGroup';
    9 9   
    10 10  type Props = {
     11 + loading?: boolean;
     12 + onSubmit?: (site: string) => void;
    11 13   suggestions?: string[];
    12 14  };
    13 15   
    14  -export default function Home({ suggestions }: Props) {
     16 +export default function Home({ suggestions, loading, onSubmit }: Props) {
    15 17   // TODO: mock data, remove later
    16 18   const popularCards: CardProps[] = [
    17 19   {
    skipped 130 lines
    148 150   
    149 151   return (
    150 152   <>
    151  - <Hero suggestions={suggestions} />
     153 + <Hero suggestions={suggestions} onSubmit={onSubmit} loading={loading} />
    152 154   
    153 155   <Container>
    154 156   <CardGroups>
    skipped 23 lines
  • ■ ■ ■ ■
    packages/web/src/components/layouts/SearchResults/SearchResults.tsx
    skipped 259 lines
    260 260   </aside>
    261 261   
    262 262   <div className={styles.packages}>
    263  - <PackagePreview
    264  - name='@team-griffin/react-heading-section'
    265  - version='3.0.0 - 4.16.4'
    266  - />
     263 + <PackagePreview name='@team-griffin/react-heading-section' version='3.0.0 - 4.16.4' />
    267 264   <PackagePreview
    268 265   name='@team-griffin/react-heading-section@team-griffin/react-heading-section'
    269 266   version='3.0.0 - 4.16.4'
    skipped 20 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/pages/Home.tsx
    1  -import React from 'react';
    2  -import { Home } from 'components/layouts';
     1 +import React, { useCallback, useEffect } from 'react';
     2 +import { Error, Home } from 'components/layouts';
     3 +import { trackCustomEvent } from '../../services/analytics';
     4 +import {
     5 + useAppDispatch,
     6 + parseWebsite,
     7 + resetError,
     8 + useAppSelector,
     9 + homeDefaultSelector,
     10 +} from '../../store';
     11 +import { useNavigate } from 'react-router-dom';
    3 12   
    4  -// TODO: add proper logic here when API integration will take place
    5 13  export function HomePage() {
    6  - return <Home />;
     14 + const navigate = useNavigate();
     15 + const dispatch = useAppDispatch();
     16 + const state = useAppSelector(homeDefaultSelector);
     17 + 
     18 + // TODO: properly handle history/routing
     19 + useEffect(() => {
     20 + if (!state.isLoading && !state.isFailed && state.hostname) {
     21 + navigate(`/w/${state.hostname}`, { replace: true });
     22 + }
     23 + });
     24 + 
     25 + const handleDetectStart = useCallback(async (address: string) => {
     26 + trackCustomEvent('HomePage', 'WebsiteSubmitted');
     27 + // TODO: error state of input field, e.g. when empty
     28 + if (!address.startsWith('http://') && !address.startsWith('https://')) {
     29 + address = 'https://' + address;
     30 + }
     31 + await dispatch(parseWebsite(address));
     32 + }, []);
     33 + 
     34 + if (state.isFailed) {
     35 + return (
     36 + <Error
     37 + host={state.hostname}
     38 + onReportClick={() => {
     39 + trackCustomEvent('HomePage', 'ClickReport');
     40 + }}
     41 + onRetryClick={() => {
     42 + trackCustomEvent('HomePage', 'ClickRetry');
     43 + dispatch(resetError());
     44 + }}
     45 + />
     46 + );
     47 + }
     48 + 
     49 + return <Home onSubmit={handleDetectStart} loading={state.isLoading} />;
    7 50  }
    8 51   
  • packages/web/src/components/ui/Button/Button.tsx
    Content is identical
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Hero/Hero.stories.tsx
    skipped 19 lines
    20 20   
    21 21  export const Loading = Template.bind({});
    22 22  Loading.args = {
    23  - inputText:
    24  - 'https://github.com/remix-run/react-router/blob/main/packages/react-router/index.ts#L85',
    25 23   loading: true,
    26 24   suggestions: ['tinkoff.ru', 'pinterest.com', 'github.com', 'gradejs.com', 'npmjs.com'],
    27 25  };
    skipped 1 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/components/ui/Hero/Hero.tsx
    1  -import React from 'react';
     1 +import React, { useState } from 'react';
    2 2  import styles from './Hero.module.scss';
    3 3  import Container from '../Container/Container';
    4 4  import Chip from '../Chip/Chip';
    skipped 1 lines
    6 6  import { Icon } from '../Icon/Icon';
    7 7   
    8 8  export type HeroProps = {
    9  - inputText?: string;
    10 9   loading?: boolean;
    11 10   suggestions?: string[];
     11 + onSubmit?: (site: string) => void;
    12 12  };
    13 13   
    14  -export default function Hero({ inputText, suggestions, loading = false }: HeroProps) {
     14 +export default function Hero({ suggestions, onSubmit = () => {}, loading = false }: HeroProps) {
     15 + const [inputText, setInputText] = useState('');
    15 16   return (
    16 17   <section className={styles.hero}>
    17 18   <Header variant='homepage' />
    skipped 7 lines
    25 26   </p>
    26 27   
    27 28   <div className={styles.search}>
    28  - <input
    29  - type='text'
    30  - className={styles.input}
    31  - value={inputText}
    32  - placeholder='Start analyzing...'
    33  - />
    34  - <button type='submit' className={styles.submit}>
    35  - {/* TODO: use SVG loading component */}
    36  - {!loading ? (
    37  - <Icon
    38  - kind='arrow'
    39  - className={styles.submitIcon}
    40  - width={32}
    41  - height={32}
    42  - color='#fff'
    43  - />
    44  - ) : (
    45  - <span className={styles.loader} />
    46  - )}
    47  - </button>
     29 + <form
     30 + onSubmit={(e) => {
     31 + onSubmit(inputText);
     32 + e.preventDefault();
     33 + return false;
     34 + }}
     35 + >
     36 + <input
     37 + type='text'
     38 + className={styles.input}
     39 + value={inputText}
     40 + onChange={(e) => setInputText(e.currentTarget.value)}
     41 + placeholder='Start analyzing...'
     42 + />
     43 + <button type='submit' className={styles.submit}>
     44 + {/* TODO: use SVG loading component */}
     45 + {!loading ? (
     46 + <Icon
     47 + kind='arrow'
     48 + className={styles.submitIcon}
     49 + width={32}
     50 + height={32}
     51 + color='#fff'
     52 + />
     53 + ) : (
     54 + <span className={styles.loader} />
     55 + )}
     56 + </button>
     57 + </form>
    48 58   </div>
    49 59   
    50 60   {suggestions && (
    skipped 14 lines
  • ■ ■ ■ ■ ■ ■
    packages/web/src/store/slices/home.ts
    1  -import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
     1 +import { createSlice, createAsyncThunk, SerializedError } from '@reduxjs/toolkit';
    2 2  import { client } from '../../services/apiClient';
    3 3  import { RootState } from '../';
    4 4   
    skipped 7 lines
    12 12   isLoading: false,
    13 13   isFailed: false,
    14 14   hostname: '',
     15 + loadError: null as SerializedError | null,
    15 16   },
    16 17   reducers: {
    17 18   resetError(state) {
    skipped 7 lines
    25 26   state.hostname = new URL(action.meta.arg).hostname;
    26 27   state.isLoading = true;
    27 28   state.isFailed = false;
     29 + state.loadError = null;
    28 30   })
    29 31   .addCase(parseWebsite.fulfilled, (state) => {
    30 32   state.isLoading = false;
    31 33   })
    32  - .addCase(parseWebsite.rejected, (state) => {
     34 + .addCase(parseWebsite.rejected, (state, action) => {
    33 35   state.isFailed = true;
    34 36   state.isLoading = false;
     37 + state.loadError = action.error;
    35 38   });
    36 39   },
    37 40  });
    skipped 6 lines
Please wait...
Page is in error, reload to recover