diff options
| -rw-r--r-- | pages/_app.tsx | 1 | ||||
| -rw-r--r-- | pages/user.tsx | 456 | ||||
| -rw-r--r-- | styles/global.css | 16 | ||||
| -rw-r--r-- | styles/user.css | 46 | ||||
| -rw-r--r-- | styles/utility.css | 4 | 
5 files changed, 256 insertions, 267 deletions
diff --git a/pages/_app.tsx b/pages/_app.tsx index 7cdb8e3..db62fa8 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -16,6 +16,7 @@ import '../styles/index.css';  import '../styles/loginregister.css';  import '../styles/search.css';  import '../styles/settings.css'; +import '../styles/user.css';  export default function VierOpEenRijWebsite({ Component, pageProps }) {  	return <div> diff --git a/pages/user.tsx b/pages/user.tsx index 4f7331c..e1c3674 100644 --- a/pages/user.tsx +++ b/pages/user.tsx @@ -1,6 +1,6 @@  import Icon from '@mdi/react';  import axios from 'axios'; -import { Children, ReactNode, useContext, useEffect, useState } from 'react'; +import { ReactNode, useContext, useEffect, useState } from 'react';  import { userGames, userInfo } from '../api/api';  import { AccountAvatar } from '../components/account'; @@ -35,60 +35,18 @@ function InfoModule(props: {  	label: string;  	icon: ReactNode;  }) { -	return <div -		style={{ -			position: 'relative', -			height: '100%', -		}} -	> -		<div -			style={{ -				position: 'absolute', -				left: '50%', -				transform: 'translateX(-50%)', -			}} -		> +	return <div className='infoModule posrel'> +		<div className='iconWrapper posabs'>  			{props.icon}  		</div> -		<div -			style={{ -				position: 'absolute', -				top: 24 + 6, -				left: 0, -				right: 0, -				bottom: 0, -			}} -		> -			<span -				style={{ -					position: 'absolute', -					top: '50%', -					transform: 'translateY(-50%)', -					width: '100%', -					textAlign: 'center', -				}} -			> +		<div className='labelWrapper posabs h0 b0'> +			<span className='label posabs center fullwidth'>  				{props.label}  			</span>  		</div>  	</div>;  } -function InfoSection(props: { children: ReactNode; }) { -	return <Vierkant fullwidth> -		<div -			style={{ -				display: 'grid', -				gridTemplateColumns: `repeat(${Children.count(props.children)}, 1fr)`, -				gridGap: 12, -				height: 64, -			}} -		> -			{props.children} -		</div> -	</Vierkant>; -} -  export default function AccountPage() {  	var server = typeof window === 'undefined';  	var loggedIn = !server && document.cookie.includes('token'); @@ -167,226 +125,222 @@ export default function AccountPage() {  		<NavBar />  		<CenteredPage width={802}>  			<PageTitle>Profiel</PageTitle> -			<Vierkant fullwidth> -				<AccountAvatar size={128} id={user?.id || ''} /> -				<div -					style={{ -						display: 'inline-block', -						verticalAlign: 'top', -						marginLeft: 12, -						width: 'calc(100% - 128px - 12px)', -					}} -				> -					<h2 style={{ fontSize: 32 }}>{user?.username}</h2> -					<p -						id='status' -						contentEditable={editingStatus ? 'true' : 'false'} -						style={{ -							marginTop: 6, -							transitionDuration: '.3s', -						}} -						suppressContentEditableWarning={true} -					> -						{user?.status} -					</p> -				</div> -				<div -					style={{ -						position: 'absolute', -						backgroundColor: 'var(--background)', -						height: '40px', -						bottom: 24, -						left: 24 + 12 + 128, -						right: 24, -					}} -				> -					{loggedIn && <div> -						{ownPage -							? <div> -								<IconLabelButton icon={<SettingsOutlinedIcon />} href='/settings' text='Instellingen' /> -								{!editingStatus -									? <IconLabelButton -										icon={<EditOutlinedIcon />} -										text='Status bewerken' -										onclick={() => setEditingStatus(true)} +			<Vierkant className='accountHeader w100m2m pad-l'> +				<div className='inner posrel'> +					<AccountAvatar size={128} id={user?.id || ''} /> +					<div className='userInfo dispinbl valigntop'> +						<h2 className='username'>{user?.username}</h2> +						<p +							id='status' +							className='status round-t' +							contentEditable={editingStatus ? 'true' : 'false'} +							suppressContentEditableWarning={true} +						> +							{user?.status} +						</p> +					</div> +					<div className='posabs b0 r0'> +						{loggedIn && <div> +							{ownPage +								? <div> +									<IconLabelButton +										icon={<SettingsOutlinedIcon />} +										href='/settings' +										text='Instellingen'  									/> -									: <IconLabelButton -										icon={<DoneOutlinedIcon />} -										text='Status opslaan' -										onclick={() => { -											setEditingStatus(false); -											axios.request({ -												method: 'post', -												url: `/api/user/status`, -												headers: { 'content-type': 'application/json' }, -												data: { 'status': document.getElementById('status').innerText }, -											}); -										}} -									/>} -							</div> -							: <div> -								{(() => { -									var icon = { -										'blocked': <Icon size={1} path={mdiAccountCancelOutline} />, -									}[relation] || <Icon size={1} path={mdiAccountCancelOutline} />; +									{!editingStatus +										? <IconLabelButton +											icon={<EditOutlinedIcon />} +											text='Status bewerken' +											onclick={() => setEditingStatus(true)} +										/> +										: <IconLabelButton +											icon={<DoneOutlinedIcon />} +											text='Status opslaan' +											onclick={() => { +												setEditingStatus(false); +												axios.request({ +													method: 'post', +													url: `/api/user/status`, +													headers: { 'content-type': 'application/json' }, +													data: { 'status': document.getElementById('status').innerText }, +												}); +											}} +										/>} +								</div> +								: <div> +									{(() => { +										var icon = { +											'blocked': <Icon size={1} path={mdiAccountCancelOutline} />, +										}[relation] || <Icon size={1} path={mdiAccountCancelOutline} />; -									var text = { -										'blocked': 'Deblokkeren', -									}[relation] || 'Blokkeren'; +										var text = { +											'blocked': 'Deblokkeren', +										}[relation] || 'Blokkeren'; -									return <IconLabelButton -										icon={icon} -										text={text} -										onclick={() => { -											var nextRelation = { -												'blocked': { -													'endpoint': '/api/social/unblock', -													'action': `${user.username} gedeblokkeerd`, -													'relation': 'none', +										return <IconLabelButton +											icon={icon} +											text={text} +											onclick={() => { +												var nextRelation = { +													'blocked': { +														'endpoint': '/api/social/unblock', +														'action': `${user.username} gedeblokkeerd`, +														'relation': 'none', +														'icon': <Icon size={1} path={mdiAccountCancelOutline} />, +													}, +												}[relation] || { +													'endpoint': '/api/social/block', +													'action': `${user.username} geblokkeerd`, +													'relation': 'blocked',  													'icon': <Icon size={1} path={mdiAccountCancelOutline} />, -												}, -											}[relation] || { -												'endpoint': '/api/social/block', -												'action': `${user.username} geblokkeerd`, -												'relation': 'blocked', -												'icon': <Icon size={1} path={mdiAccountCancelOutline} />, -											}; +												}; -											axios.request({ -												method: 'post', -												url: nextRelation.endpoint, -												headers: { 'content-type': 'application/json' }, -												data: { 'id': user?.id }, -											}) -												.then(() => { -													toast({ -														message: nextRelation.action, -														type: 'confirmation', -														icon: nextRelation.icon, +												axios.request({ +													method: 'post', +													url: nextRelation.endpoint, +													headers: { 'content-type': 'application/json' }, +													data: { 'id': user?.id }, +												}) +													.then(() => { +														toast({ +															message: nextRelation.action, +															type: 'confirmation', +															icon: nextRelation.icon, +														}); +														setRelation(nextRelation.relation);  													}); -													setRelation(nextRelation.relation); -												}); -										}} -									/>; -								})()} -								{(() => { -									var icon = { -										'friends': <Icon size={1} path={mdiAccountMinusOutline} />, -										'outgoing': <Icon size={1} path={mdiAccountRemoveOutline} />, -										'incoming': <PersonAddOutlinedIcon />, -									}[relation] || <PersonAddOutlinedIcon />; +											}} +										/>; +									})()} +									{(() => { +										var icon = { +											'friends': <Icon size={1} path={mdiAccountMinusOutline} />, +											'outgoing': <Icon size={1} path={mdiAccountRemoveOutline} />, +											'incoming': <PersonAddOutlinedIcon />, +										}[relation] || <PersonAddOutlinedIcon />; -									var text = { -										'friends': 'Vriend verwijderen', -										'outgoing': 'Vriendschapsverzoek annuleren', -										'incoming': 'Vriendschapsverzoek accepteren', -									}[relation] || 'Vriendschapsverzoek sturen'; +										var text = { +											'friends': 'Vriend verwijderen', +											'outgoing': 'Vriendschapsverzoek annuleren', +											'incoming': 'Vriendschapsverzoek accepteren', +										}[relation] || 'Vriendschapsverzoek sturen'; -									return <IconLabelButton -										icon={icon} -										text={text} -										onclick={() => { -											var nextRelation = { -												'friends': { -													'endpoint': '/api/social/remove', -													'action': `${user.username} succesvol verwijderd als vriend`, -													'relation': 'none', -													'icon': <Icon size={1} path={mdiAccountMinusOutline} />, -												}, -												'outgoing': { -													'endpoint': '/api/social/remove', -													'action': `Vriendschapsverzoek naar ${user.username} geannuleerd`, -													'relation': 'none', -													'icon': <Icon size={1} path={mdiAccountMinusOutline} />, -												}, -												'incoming': { -													'endpoint': '/api/social/accept', -													'action': `Vriendschapsverzoek van ${user.username} geaccepteerd`, -													'relation': 'friends', +										return <IconLabelButton +											icon={icon} +											text={text} +											onclick={() => { +												var nextRelation = { +													'friends': { +														'endpoint': '/api/social/remove', +														'action': `${user.username} succesvol verwijderd als vriend`, +														'relation': 'none', +														'icon': <Icon size={1} path={mdiAccountMinusOutline} />, +													}, +													'outgoing': { +														'endpoint': '/api/social/remove', +														'action': +															`Vriendschapsverzoek naar ${user.username} geannuleerd`, +														'relation': 'none', +														'icon': <Icon size={1} path={mdiAccountMinusOutline} />, +													}, +													'incoming': { +														'endpoint': '/api/social/accept', +														'action': +															`Vriendschapsverzoek van ${user.username} geaccepteerd`, +														'relation': 'friends', +														'icon': <PersonAddOutlinedIcon />, +													}, +												}[relation] || { +													'endpoint': '/api/social/request', +													'action': `Vriendschapsverzoek gestuurd naar ${user.username}`, +													'relation': 'outgoing',  													'icon': <PersonAddOutlinedIcon />, -												}, -											}[relation] || { -												'endpoint': '/api/social/request', -												'action': `Vriendschapsverzoek gestuurd naar ${user.username}`, -												'relation': 'outgoing', -												'icon': <PersonAddOutlinedIcon />, -											}; +												}; -											axios.request({ -												method: 'post', -												url: nextRelation.endpoint, -												headers: { 'content-type': 'application/json' }, -												data: { 'id': user?.id }, -											}) -												.then(() => { -													toast({ -														message: nextRelation.action, -														type: 'confirmation', -														icon: nextRelation.icon, +												axios.request({ +													method: 'post', +													url: nextRelation.endpoint, +													headers: { 'content-type': 'application/json' }, +													data: { 'id': user?.id }, +												}) +													.then(() => { +														toast({ +															message: nextRelation.action, +															type: 'confirmation', +															icon: nextRelation.icon, +														}); +														setRelation(nextRelation.relation);  													}); -													setRelation(nextRelation.relation); -												}); -										}} -									/>; -								})()} -							</div>} -					</div>} +											}} +										/>; +									})()} +								</div>} +						</div>} +					</div>  				</div>  			</Vierkant> -			<InfoSection> -				<InfoModule -					icon={<Icon size={1} path={mdiCheckboxBlankCircle} color='var(--disk-b-text)' />} -					label='Online' -				/> -				<InfoModule -					icon={<AssignmentIndOutlinedIcon />} -					label={(() => { -						var memberSince = 'Lid sinds'; +			<Vierkant className='infosection pad-l w100m2m'> +				<div className='inner sidebyside'> +					<InfoModule +						icon={<Icon size={1} path={mdiCheckboxBlankCircle} className='outcome win' />} +						label='Online' +					/> +					<InfoModule +						icon={<AssignmentIndOutlinedIcon />} +						label={(() => { +							var memberSince = 'Lid sinds'; -						var registered = new Date(user?.registered); -						memberSince += ' ' + registered.toLocaleString('nl-nl', { month: 'long', day: 'numeric' }); +							var registered = new Date(user?.registered); +							memberSince += ' ' + registered.toLocaleString('nl-nl', { month: 'long', day: 'numeric' }); -						var currentYear = new Date().getFullYear(); -						var memberYear = registered.getFullYear(); -						if (currentYear != memberYear) memberSince += ' ' + memberYear; +							var currentYear = new Date().getFullYear(); +							var memberYear = registered.getFullYear(); +							if (currentYear != memberYear) memberSince += ' ' + memberYear; -						return memberSince; -					})()} -				/> -				<InfoModule -					icon={<PeopleOutlineOutlinedIcon />} -					label={(() => { -						var label = user?.friends.toString() + ' '; -						label += user?.friends == 1 ? 'vriend' : 'vrienden'; -						return label; -					})()} -				/> -				<InfoModule icon={<Icon size={1} path={mdiEarth} />} label='Nederland' /> -			</InfoSection> -			<InfoSection> -				<InfoModule -					icon={<ArrowUpwardOutlinedIcon style={{ color: 'var(--disk-b-text)' }} />} -					label={gameInfo?.totals.win + ' keer gewonnen'} -				/> -				<InfoModule -					icon={<Icon size={1} path={mdiEqual} />} -					label={gameInfo?.totals.draw + ' keer gelijkspel'} -				/> -				<InfoModule -					icon={<ArrowDownwardOutlinedIcon style={{ color: 'var(--disk-a-text)' }} />} -					label={gameInfo?.totals.lose + ' keer verloren'} -				/> -				<InfoModule icon={<Icon size={1} path={mdiClipboardTextOutline} />} label={'Score: ' + user?.rating} /> -				<InfoModule -					icon={<Icon size={1} path={mdiGamepadSquareOutline} />} -					label={(() => { -						var label = gameInfo?.totals.games.toString() + ' '; -						label += gameInfo?.totals.games == 1 ? 'potje' : 'potjes'; -						return label; -					})()} -				/> -			</InfoSection> -			<Vierkant> +							return memberSince; +						})()} +					/> +					<InfoModule +						icon={<PeopleOutlineOutlinedIcon />} +						label={(() => { +							var label = user?.friends.toString() + ' '; +							label += user?.friends == 1 ? 'vriend' : 'vrienden'; +							return label; +						})()} +					/> +					<InfoModule icon={<Icon size={1} path={mdiEarth} />} label='Nederland' /> +				</div> +			</Vierkant> +			<Vierkant className='infosection pad-l w100m2m sidebyside'> +				<div className='inner sidebyside'> +					<InfoModule +						icon={<ArrowUpwardOutlinedIcon className='outcome win' />} +						label={gameInfo?.totals.win + ' keer gewonnen'} +					/> +					<InfoModule +						icon={<Icon size={1} path={mdiEqual} className='subtile' />} +						label={gameInfo?.totals.draw + ' keer gelijkspel'} +					/> +					<InfoModule +						icon={<ArrowDownwardOutlinedIcon className='outcome lose' />} +						label={gameInfo?.totals.lose + ' keer verloren'} +					/> +					<InfoModule +						icon={<Icon size={1} path={mdiClipboardTextOutline} />} +						label={'Score: ' + user?.rating} +					/> +					<InfoModule +						icon={<Icon size={1} path={mdiGamepadSquareOutline} />} +						label={(() => { +							var label = gameInfo?.totals.games.toString() + ' '; +							label += gameInfo?.totals.games == 1 ? 'potje' : 'potjes'; +							return label; +						})()} +					/> +				</div> +			</Vierkant> +			<Vierkant className='pad-l'>  				<RecentGames games={gameInfo?.games} />  			</Vierkant>  		</CenteredPage> diff --git a/styles/global.css b/styles/global.css index b6ed028..f70b6bd 100644 --- a/styles/global.css +++ b/styles/global.css @@ -141,19 +141,3 @@ input::placeholder {  /* material-ui default state */  svg.MuiSvgIcon-root { transition: none !important; } -/* editable field status */ -*[contenteditable] { border-color: var(--background-alt); } -*[contenteditable="true"]:focus { border-color: var(--disk-a); } -*[contenteditable="true"] { -	background-color: var(--page-background); -	color: var(--text-alt); -	padding: 6px; -	border-radius: 6px; -	border-style: solid; -	border-width: 2px; -} - -.outcome.win { color: var(--disk-a-alt); } -.outcome.lose { color: var(--disk-b-alt); } -.outcome.draw { color: var(--gray-600); } - diff --git a/styles/user.css b/styles/user.css new file mode 100644 index 0000000..d66fa94 --- /dev/null +++ b/styles/user.css @@ -0,0 +1,46 @@ +.infosection .inner { +	height: 64px; +} + +/* editable field status */ +*[contenteditable] { +	box-shadow: inset 0 0 0 0px var(--foreground); +} +*[contenteditable="true"]:focus { +	box-shadow: inset 0 0 0 2px var(--accent); +} +*[contenteditable="true"] { +	background-color: var(--background); +	color: var(--text-alt); +	padding: 8px; +	box-shadow: inset 0 0 0 2px var(--foreground); +} + +.accountHeader .userInfo { +	margin-left: var(--spacing-medium); +	width: calc(100% - 128px - var(--spacing-medium)); +} + +.accountHeader .userInfo .username { +	font-size: 2rem; +} + +.accountHeader .userInfo .status { +	transition-duration: .3s; +	margin-top: var(--spacing-small); +} + +.infoModule .iconWrapper { +	left: 50%; +	transform: translateX(-50%); +} + +.infoModule .labelWrapper { +	top: calc(24px + var(--spacing-small)); +} + +.infoModule .labelWrapper .label { +	top: 50%; +	transform: translateY(-50%); +} + diff --git a/styles/utility.css b/styles/utility.css index 7f5ebbd..be982f8 100644 --- a/styles/utility.css +++ b/styles/utility.css @@ -18,6 +18,10 @@  .fg-100 { color: var(--gray-100); }  .fg-900 { color: var(--gray-900); } +.outcome.win { color: var(--disk-a-alt); } +.outcome.lose { color: var(--disk-b-alt); } +.outcome.draw { color: var(--gray-600); } +  .posabs { position: absolute; }  .posrel { position: relative; }  .posfix { position: fixed; }  |