Commit 8e472db1 authored by Sam Gluck's avatar Sam Gluck
Browse files

- Change Username field of User to Name;

- Reduce amount scrolled when moving to step 2 of sign up;
- Move Languages above Interests in step 2 of sign up;
- Add "Bio" field to step 1 of sign up and to the User type;
- Add "real" tags to the Interests section of sign up step 2;
parent d501c600
...@@ -8,8 +8,9 @@ import { NotificationType } from '../components/elements/Notification/Notificati ...@@ -8,8 +8,9 @@ import { NotificationType } from '../components/elements/Notification/Notificati
export const DUMMY_USER = { export const DUMMY_USER = {
__typename: 'User', __typename: 'User',
id: 0, id: 0,
username: 'MoodlerJoe', name: 'Moodler Joe',
email: 'moodlerjoe@example.com', email: 'moodlerjoe@example.com',
bio: 'I <3 Moodle',
emojiId: '', emojiId: '',
role: '', role: '',
location: '', location: '',
......
export default ` export default `
type User { type User {
id: Int! id: Int!
username: String! name: String!
email: String! email: String!
bio: String!
emojiId: String! emojiId: String!
role: String! role: String!
location: String! location: String!
......
...@@ -100,8 +100,8 @@ export default withTheme( ...@@ -100,8 +100,8 @@ export default withTheme(
top: '-2px' top: '-2px'
}} }}
src={avatar} src={avatar}
alt={user.data.username} alt={user.data.name}
title={`Hi, ${user.data.username}!`} title={`Hi, ${user.data.name}!`}
/> />
</Avatar> </Avatar>
</MenuNavItem> </MenuNavItem>
......
...@@ -27,7 +27,7 @@ const UserMenu = styled.div` ...@@ -27,7 +27,7 @@ const UserMenu = styled.div`
export default ({ user }) => { export default ({ user }) => {
return ( return (
<UserMenu> <UserMenu>
<UserLink title="Go to Edit profile" to={`/user/${user.username}`}> <UserLink title="Go to Edit profile" to={`/user`}>
<FontAwesomeIcon icon={faPencilAlt} /> &nbsp;Edit profile <FontAwesomeIcon icon={faPencilAlt} /> &nbsp;Edit profile
</UserLink> </UserLink>
<br /> <br />
......
...@@ -4,7 +4,7 @@ query GetUserQuery { ...@@ -4,7 +4,7 @@ query GetUserQuery {
isAuthenticated isAuthenticated
data { data {
id id
username name
email email
emojiId emojiId
role role
......
...@@ -82,12 +82,12 @@ interface LoginState { ...@@ -82,12 +82,12 @@ interface LoginState {
} }
type CredentialsObject = { type CredentialsObject = {
username: string; email: string;
password: string; password: string;
}; };
const DEMO_CREDENTIALS = { const DEMO_CREDENTIALS = {
username: 'moodle', email: 'moodle@moodle.net',
password: 'moodle' password: 'moodle'
}; };
...@@ -101,11 +101,11 @@ class Login extends React.Component<LoginProps, LoginState> { ...@@ -101,11 +101,11 @@ class Login extends React.Component<LoginProps, LoginState> {
static validateCredentials(credentials: CredentialsObject) { static validateCredentials(credentials: CredentialsObject) {
const validation: ValidationObject[] = []; const validation: ValidationObject[] = [];
if (!credentials.username.length) { if (!credentials.email.length) {
validation.push({ validation.push({
field: ValidationField.username, field: ValidationField.email,
type: ValidationType.error, type: ValidationType.error,
message: 'The username field cannot be empty' message: 'The email field cannot be empty'
} as ValidationObject); } as ValidationObject);
} }
if (!credentials.password.length) { if (!credentials.password.length) {
...@@ -144,7 +144,7 @@ class Login extends React.Component<LoginProps, LoginState> { ...@@ -144,7 +144,7 @@ class Login extends React.Component<LoginProps, LoginState> {
// TODO implement real auth when we know what the backend looks like // TODO implement real auth when we know what the backend looks like
setTimeout(async () => { setTimeout(async () => {
if ( if (
credentials.username !== DEMO_CREDENTIALS.username || credentials.email !== DEMO_CREDENTIALS.email ||
credentials.password !== DEMO_CREDENTIALS.password credentials.password !== DEMO_CREDENTIALS.password
) { ) {
this.setState({ this.setState({
......
...@@ -38,13 +38,13 @@ type LoginFormProps = { ...@@ -38,13 +38,13 @@ type LoginFormProps = {
}; };
type LoginFormState = { type LoginFormState = {
username: string; email: string;
password: string; password: string;
}; };
export default class extends React.Component<LoginFormProps, LoginFormState> { export default class extends React.Component<LoginFormProps, LoginFormState> {
state = { state = {
username: '', email: '',
password: '' password: ''
}; };
...@@ -95,22 +95,20 @@ export default class extends React.Component<LoginFormProps, LoginFormState> { ...@@ -95,22 +95,20 @@ export default class extends React.Component<LoginFormProps, LoginFormState> {
<Row> <Row>
<Col> <Col>
<TextField> <TextField>
<Label>Username:</Label> <Label>Email address:</Label>
<TextInput <TextInput
placeholder="Enter your username" placeholder="Enter your email address"
value={this.state.username} value={this.state.email}
validation={this.getValidation(ValidationField.username)} validation={this.getValidation(ValidationField.email)}
onChange={(evt: any) => { onChange={(evt: any) => {
this.setState({ this.setState({
username: evt.target.value email: evt.target.value
}); });
onInputChange(ValidationField.username, evt.target.value); onInputChange(ValidationField.email, evt.target.value);
}} }}
/> />
<Message <Message validation={this.getValidation(ValidationField.email)}>
validation={this.getValidation(ValidationField.username)} {this.getValidationMessage(ValidationField.email)}
>
{this.getValidationMessage(ValidationField.username)}
</Message> </Message>
</TextField> </TextField>
<Spacer /> <Spacer />
......
...@@ -6,7 +6,7 @@ export enum ValidationType { ...@@ -6,7 +6,7 @@ export enum ValidationType {
} }
export enum ValidationField { export enum ValidationField {
username, email,
password password
} }
......
...@@ -31,7 +31,7 @@ const Sidebar = styled.div` ...@@ -31,7 +31,7 @@ const Sidebar = styled.div`
const stepScrollTo = { const stepScrollTo = {
1: 0, 1: 0,
2: 650 2: 450
}; };
//TODO this should be offloaded to an API //TODO this should be offloaded to an API
...@@ -91,22 +91,30 @@ const Step2Section = styled.div<any>` ...@@ -91,22 +91,30 @@ const Step2Section = styled.div<any>`
transition: opacity 1.75s linear; transition: opacity 1.75s linear;
`; `;
const TagsNoneSelected = ({ what }) => {
return (
<div style={{ paddingTop: '8px', color: 'grey' }}>No {what} selected</div>
);
};
const Interests = ({ active, interests, onTagClick }) => ( const Interests = ({ active, interests, onTagClick }) => (
<Step2Section active={active}> <Step2Section active={active}>
<H4>Interests</H4> <H4>Interests</H4>
<TagContainer> <TagContainer>
{interests.length {interests.length ? (
? interests.map(interest => ( interests.map(interest => (
<Tag <Tag
focused focused
closeable closeable
key={interest} key={interest}
onClick={() => onTagClick(interest)} onClick={() => onTagClick(interest)}
> >
{interest} {interest}
</Tag> </Tag>
)) ))
: 'None selected'} ) : (
<TagsNoneSelected what="interests" />
)}
</TagContainer> </TagContainer>
<Button onClick={() => alert('add interest clicked')}>Add interest</Button> <Button onClick={() => alert('add interest clicked')}>Add interest</Button>
</Step2Section> </Step2Section>
...@@ -116,18 +124,20 @@ const Languages = ({ active, languages }) => ( ...@@ -116,18 +124,20 @@ const Languages = ({ active, languages }) => (
<Step2Section active={active}> <Step2Section active={active}>
<H4>Languages</H4> <H4>Languages</H4>
<TagContainer> <TagContainer>
{languages.length {languages.length ? (
? languages.map(lang => ( languages.map(lang => (
<Tag <Tag
focused focused
closeable closeable
key={lang} key={lang}
onClick={() => alert('lang clicked')} onClick={() => alert('lang clicked')}
> >
{lang} {lang}
</Tag> </Tag>
)) ))
: 'None selected'} ) : (
<TagsNoneSelected what="languages" />
)}
</TagContainer> </TagContainer>
<Button onClick={() => alert('add lang clicked')}>Add language</Button> <Button onClick={() => alert('add lang clicked')}>Add language</Button>
</Step2Section> </Step2Section>
...@@ -136,13 +146,16 @@ const Languages = ({ active, languages }) => ( ...@@ -136,13 +146,16 @@ const Languages = ({ active, languages }) => (
export default class SignUp extends React.Component<SignUpProps, SignUpState> { export default class SignUp extends React.Component<SignUpProps, SignUpState> {
static stepComponents = [Step1, Step2]; static stepComponents = [Step1, Step2];
// container of the user profile, ref. is used
// to scroll container on sign up step change
_profileElem: HTMLElement; _profileElem: HTMLElement;
state: SignUpState = { state: SignUpState = {
currentStep: -1, currentStep: -1,
user: { user: {
username: '', name: '',
email: '', email: '',
bio: '',
emojiId: generateEmojiId(), emojiId: generateEmojiId(),
avatarImage: undefined, avatarImage: undefined,
profileImage: undefined, profileImage: undefined,
...@@ -159,7 +172,7 @@ export default class SignUp extends React.Component<SignUpProps, SignUpState> { ...@@ -159,7 +172,7 @@ export default class SignUp extends React.Component<SignUpProps, SignUpState> {
this.state.currentStep = Number(props.match.params.step); this.state.currentStep = Number(props.match.params.step);
if (!this.state.user.username && this.state.currentStep > 1) { if (!this.state.user.name && this.state.currentStep > 1) {
this.state.redirect = '/sign-up/1'; this.state.redirect = '/sign-up/1';
return; return;
} }
...@@ -351,7 +364,7 @@ export default class SignUp extends React.Component<SignUpProps, SignUpState> { ...@@ -351,7 +364,7 @@ export default class SignUp extends React.Component<SignUpProps, SignUpState> {
</Row> </Row>
{this.getStepComponent()} {this.getStepComponent()}
<Row style={{ flexGrow: 1 }} /> <Row style={{ flexGrow: 1 }} />
<Row> <Row style={{ minHeight: '42px', marginTop: '10px' }}>
{this.getNextStepName() ? ( {this.getNextStepName() ? (
<Col <Col
style={{ style={{
...@@ -384,15 +397,15 @@ export default class SignUp extends React.Component<SignUpProps, SignUpState> { ...@@ -384,15 +397,15 @@ export default class SignUp extends React.Component<SignUpProps, SignUpState> {
body={({ containerProps }) => { body={({ containerProps }) => {
return ( return (
<SignUpProfileSection {...containerProps}> <SignUpProfileSection {...containerProps}>
<Languages
active={this.state.currentStep > 1}
languages={this.state.user.languages}
/>
<Interests <Interests
onTagClick={interest => this.toggleUserInterest(interest)} onTagClick={interest => this.toggleUserInterest(interest)}
active={this.state.currentStep > 1} active={this.state.currentStep > 1}
interests={this.state.user.interests} interests={this.state.user.interests}
/> />
<Languages
active={this.state.currentStep > 1}
languages={this.state.user.languages}
/>
</SignUpProfileSection> </SignUpProfileSection>
); );
}} }}
......
...@@ -5,6 +5,7 @@ import { Col, Row } from '@zendeskgarden/react-grid'; ...@@ -5,6 +5,7 @@ import { Col, Row } from '@zendeskgarden/react-grid';
import H6 from '../../components/typography/H6/H6'; import H6 from '../../components/typography/H6/H6';
import P from '../../components/typography/P/P'; import P from '../../components/typography/P/P';
import TextInput from '../../components/inputs/Text/Text'; import TextInput from '../../components/inputs/Text/Text';
import TextArea from '../../components/inputs/TextArea/Textarea';
import Button from '../../components/elements/Button/Button'; import Button from '../../components/elements/Button/Button';
import LanguageSelect from '../../components/inputs/LanguageSelect/LanguageSelect'; import LanguageSelect from '../../components/inputs/LanguageSelect/LanguageSelect';
import styled from '../../themes/styled'; import styled from '../../themes/styled';
...@@ -32,11 +33,11 @@ export default ({ user, randomizeEmojiId, linkUserState }) => { ...@@ -32,11 +33,11 @@ export default ({ user, randomizeEmojiId, linkUserState }) => {
details below to build it. details below to build it.
</P> </P>
<TextField> <TextField>
<Label>Username</Label> <Label>Name</Label>
<TextInput <TextInput
value={user.username} value={user.name}
onChange={linkUserState('username')} onChange={linkUserState('name')}
placeholder="e.g. joebloggs84" placeholder="e.g. Moodler Joe"
maxLength={20} maxLength={20}
/> />
</TextField> </TextField>
...@@ -66,11 +67,21 @@ export default ({ user, randomizeEmojiId, linkUserState }) => { ...@@ -66,11 +67,21 @@ export default ({ user, randomizeEmojiId, linkUserState }) => {
<TextInput <TextInput
value={user.email} value={user.email}
onChange={linkUserState('email')} onChange={linkUserState('email')}
placeholder="e.g. joebloggs@example.com" placeholder="e.g. joe@moodle.net"
maxLength={100} maxLength={100}
/> />
</TextField> </TextField>
<Spacer /> <Spacer />
<TextField>
<Label>Bio</Label>
<TextArea
value={user.bio}
onChange={linkUserState('bio')}
placeholder="Tell us a bit about yourself"
maxLength={250}
/>
</TextField>
<Spacer />
<TextField> <TextField>
<Label>Language</Label> <Label>Language</Label>
<LanguageSelect fullWidth={true} /> <LanguageSelect fullWidth={true} />
......
...@@ -10,14 +10,18 @@ import styled from '../../themes/styled'; ...@@ -10,14 +10,18 @@ import styled from '../../themes/styled';
import User from '../../types/User'; import User from '../../types/User';
//TODO get tags from the API //TODO get tags from the API
const words = `offer,segment,slave,duck,instant,market,degree,populate,chick,dear,enemy,reply,drink,occur,support,shell,neck`.split( const words = `Applied Sciences, K12, Performing Arts, Humanities, Higher Education, Social Sciences, Vocational Education, Professional Education, Formal Sciences, Natural Sciences, Visual Arts`
',' .split(',')
); .map(s => s.trim());
const InterestsSearchResultsContainer = styled.div` const InterestsSearchResultsContainer = styled.div`
margin: 20px 0 0 0; margin: 20px 0 0 0;
`; `;
const OverflowCol = styled(Col)`
overflow: auto;
`;
function InterestsSearchResults({ status, count, result, children }) { function InterestsSearchResults({ status, count, result, children }) {
if (status === SearchStatus.complete) { if (status === SearchStatus.complete) {
return ( return (
...@@ -115,7 +119,7 @@ export default class extends React.Component<Step2Props, Step2State> { ...@@ -115,7 +119,7 @@ export default class extends React.Component<Step2Props, Step2State> {
return ( return (
<> <>
<Row> <Row>
<Col> <OverflowCol>
<H6 style={{ borderBottom: '1px solid lightgrey' }}> <H6 style={{ borderBottom: '1px solid lightgrey' }}>
<span style={{ color: 'darkgrey', fontSize: '.7em' }}>2.</span>{' '} <span style={{ color: 'darkgrey', fontSize: '.7em' }}>2.</span>{' '}
Your Interests Your Interests
...@@ -156,7 +160,7 @@ export default class extends React.Component<Step2Props, Step2State> { ...@@ -156,7 +160,7 @@ export default class extends React.Component<Step2Props, Step2State> {
</Tag> </Tag>
))} ))}
</TagContainer> </TagContainer>
</Col> </OverflowCol>
</Row> </Row>
</> </>
); );
......
...@@ -189,10 +189,7 @@ export default function(props: UserProfileProps) { ...@@ -189,10 +189,7 @@ export default function(props: UserProfileProps) {
<UserDetails> <UserDetails>
<H6>{props.user.emojiId}</H6> <H6>{props.user.emojiId}</H6>
<H6> <H6>
<FadedFallbackText <FadedFallbackText value={props.user.name} fallback="Moodler Joe" />
value={props.user.username}
fallback="joebloggs84"
/>
</H6> </H6>
<H6> <H6>
<FadedFallbackText value={props.user.role} fallback="Head Teacher" /> <FadedFallbackText value={props.user.role} fallback="Head Teacher" />
......
export default interface User { export default interface User {
username: string; name: string;
email: string; email: string;
bio: string;
emojiId: string; emojiId: string;
avatarImage?: string; avatarImage?: string;
profileImage?: string; profileImage?: string;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment