mirror of
https://github.com/urbit/shrub.git
synced 2025-01-01 17:16:47 +03:00
add / edit card.js toggle
This commit is contained in:
parent
9e4a192fa5
commit
8ec9031be3
@ -1,10 +1,182 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Sigil } from './icons/sigil';
|
||||
import { uxToHex } from '/lib/util';
|
||||
|
||||
import { api } from '/api';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
|
||||
export class ContactCard extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
edit: false,
|
||||
colorToSet: ""
|
||||
}
|
||||
this.editToggle = this.editToggle.bind(this);
|
||||
this.sigilColorSet = this.sigilColorSet.bind(this);
|
||||
}
|
||||
|
||||
editToggle() {
|
||||
let editSwitch = this.state.edit;
|
||||
editSwitch = !editSwitch;
|
||||
this.setState({edit: editSwitch});
|
||||
}
|
||||
|
||||
sigilColorSet(event) {
|
||||
//TODO regex for complete hex value and submit as change
|
||||
this.setState({colorToSet: event.target.value});
|
||||
}
|
||||
|
||||
shipParser(ship) {
|
||||
switch(ship.length) {
|
||||
case 3: return "Galaxy";
|
||||
case 6: return "Star";
|
||||
case 13: return "Planet";
|
||||
case 56: return "Comet";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
renderEditCard() {
|
||||
//TODO if the path is our special invite flow path, autofill the details from /~/default's version of your contact, not this one
|
||||
let shipType = this.shipParser(this.props.ship);
|
||||
|
||||
let currentColor = (this.props.contact.color) ? this.props.contact.color : "0x0";
|
||||
let hexColor = uxToHex(currentColor);
|
||||
|
||||
let sigilColor = ""
|
||||
|
||||
if (this.props.contact.avatar === "TODO") { //TODO change to empty string once we have avatars
|
||||
sigilColor = (
|
||||
<div className="tl mt4 mb4 w-auto ml-auto mr-auto"
|
||||
style={{ width: "fit-content" }}>
|
||||
<p className="f9 gray2 lh-copy">Sigil Color</p>
|
||||
<textarea
|
||||
className="b--gray4 black f7 ba db pl2"
|
||||
onChange={this.sigilColorSet}
|
||||
defaultValue={"#" + hexColor}
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 14,
|
||||
width: 114
|
||||
}}></textarea>
|
||||
</div>
|
||||
)
|
||||
//TODO The fields to actually edit, using the api hooks for those atomic actions
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-100 flex justify-center pa4 pa0-xl pt4-xl">
|
||||
<div className="w-100 mw6 tc">
|
||||
<Sigil ship={this.props.ship} size={128} color={hexColor} />
|
||||
{sigilColor}
|
||||
<button className="f9 b--black ba pa2">Upload an Image</button>
|
||||
|
||||
<div className="w-100 pt8 lh-copy tl">
|
||||
<p className="f9 gray2">Ship Name</p>
|
||||
<p className="f8 mono">~{this.props.ship}</p>
|
||||
<p className="f9 gray2 mt3">Ship Type</p>
|
||||
<p className="f8">{shipType}</p>
|
||||
|
||||
<hr className="mv8 gray4 b--gray4 bb-0 b--solid" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderCard() {
|
||||
let shipType = this.shipParser(this.props.ship);
|
||||
let currentColor = (this.props.contact.color) ? this.props.contact.color : "0x0";
|
||||
let hexColor = uxToHex(currentColor);
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-100 flex justify-center pa4 pa0-xl pt4-xl">
|
||||
<div className="w-100 mw6 tc">
|
||||
{/*TODO default to sigil, but show avatar if exists for contact */}
|
||||
<Sigil ship={this.props.ship} size={128} color={hexColor} />
|
||||
<div className="w-100 pt8 lh-copy tl">
|
||||
<p className="f9 gray2">Ship Name</p>
|
||||
<p className="f8 mono">~{this.props.ship}</p>
|
||||
<p className="f9 gray2 mt3">Ship Type</p>
|
||||
<p className="f8">{shipType}</p>
|
||||
|
||||
<hr className="mv8 gray4 b--gray4 bb-0 b--solid" />
|
||||
<div>
|
||||
{(() => {
|
||||
if (this.props.contact.nickname) {
|
||||
return (
|
||||
<div>
|
||||
<p className="f9 gray2">Nickname</p>
|
||||
<p className="f8">{this.props.contact.nickname}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (this.props.contact.email) {
|
||||
return (
|
||||
<div>
|
||||
<p className="f9 gray2">Email</p>
|
||||
<p className="f8">{this.props.contact.email}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (this.props.contact.phone) {
|
||||
return (
|
||||
<div>
|
||||
<p className="f9 gray2">Phone</p>
|
||||
<p className="f8">{this.props.contact.phone}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (this.props.contact.website) {
|
||||
return (
|
||||
<div>
|
||||
<p className="f9 gray2">Website</p>
|
||||
<p className="f8">{this.props.contact.website}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (this.props.contact.notes) {
|
||||
return (
|
||||
<div>
|
||||
<p className="f9 gray2">Notes</p>
|
||||
<p className="f8">{this.props.contact.notes}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
let ourOption = (this.props.ship === window.ship)
|
||||
? "dib"
|
||||
: "dn";
|
||||
|
||||
let localOption = ((this.props.ship === window.ship) && (this.props.path === "/~/default"))
|
||||
? "dib"
|
||||
: "dn";
|
||||
|
||||
let editInfoText = (this.state.edit)
|
||||
? "Finish Editing"
|
||||
: "Edit Contact Info";
|
||||
|
||||
let adminOption = (this.props.path.includes(window.ship) && (this.props.ship !== window.ship))
|
||||
? "dib"
|
||||
: "dn";
|
||||
|
||||
let card = (this.state.edit)
|
||||
? this.renderEditCard()
|
||||
: this.renderCard();
|
||||
|
||||
//TODO "Share card" if it's /me -> sends to /~/default of recipient
|
||||
return (
|
||||
<div className="h-100 w-100 overflow-x-hidden">
|
||||
@ -12,18 +184,19 @@ export class ContactCard extends Component {
|
||||
<Link to="/~contacts/">{"⟵"}</Link>
|
||||
</div>
|
||||
<div className="w-100 bb b--gray4">
|
||||
<button className="ml3 mt2 mb2 f9 pa2 ba br3 b--black">Edit Contact Info</button>
|
||||
</div>
|
||||
<div className="w-100 flex justify-center pa4 pa0-xl pt4-xl">
|
||||
<div className="w-100 mw6 tc">
|
||||
{/*TODO default to sigil, but show avatar if exists for contact */}
|
||||
<Sigil ship={this.props.ship} size={128} color={this.props.contact.color}/>
|
||||
<div className="w-100 pt8 lh-copy tl">
|
||||
<p className="f9 gray2">Ship Name</p>
|
||||
<p className="f8 mono">~{this.props.ship}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={this.editToggle}
|
||||
className={`ml3 mt2 mb2 f9 pa2 ba br3 pointer b--black ` + ourOption}>
|
||||
{editInfoText}
|
||||
</button>
|
||||
<button className={`ml3 mt2 mb2 f9 pa2 ba br3 b--black ` + localOption}>
|
||||
Share Contact Info
|
||||
</button>
|
||||
<button className={`ml3 mt2 mb2 f9 pa2 ba red2 br3 b--red2 ` + adminOption}>
|
||||
Remove from Group
|
||||
</button>
|
||||
</div>
|
||||
{card}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import urbitOb from 'urbit-ob';
|
||||
export class NewScreen extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
||||
this.state = {
|
||||
groupName: '',
|
||||
invites: '',
|
||||
@ -15,30 +15,30 @@ export class NewScreen extends Component {
|
||||
groupNameError: false,
|
||||
inviteError: false
|
||||
};
|
||||
|
||||
|
||||
this.groupNameChange = this.groupNameChange.bind(this);
|
||||
this.invChange = this.invChange.bind(this);
|
||||
// this.colorChange = this.colorChange.bind(this);
|
||||
}
|
||||
|
||||
|
||||
groupNameChange(event) {
|
||||
this.setState({
|
||||
groupName: event.target.value
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
invChange(event) {
|
||||
this.setState({
|
||||
invites: event.target.value
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// colorChange(event) {
|
||||
// this.setState({
|
||||
// color: event.target.value
|
||||
// });
|
||||
// }
|
||||
|
||||
|
||||
onClickCreate() {
|
||||
const { props, state } = this;
|
||||
if (!state.groupName) {
|
||||
@ -49,21 +49,21 @@ export class NewScreen extends Component {
|
||||
return;
|
||||
}
|
||||
let group = `/~${window.ship}` + `/${state.groupName}`;
|
||||
|
||||
|
||||
let aud = [];
|
||||
let isValid = true;
|
||||
|
||||
|
||||
if (state.invites.length > 2) {
|
||||
aud = state.invites.split(',')
|
||||
.map((mem) => `~${deSig(mem.trim())}`);
|
||||
|
||||
|
||||
aud.forEach((mem) => {
|
||||
if (!urbitOb.isValidPatp(mem)) {
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (!isValid) {
|
||||
this.setState({
|
||||
inviteError: true,
|
||||
@ -71,7 +71,7 @@ export class NewScreen extends Component {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (this.textarea) {
|
||||
this.textarea.value = '';
|
||||
}
|
||||
@ -90,96 +90,97 @@ export class NewScreen extends Component {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
|
||||
let groupNameErrElem = (<span />);
|
||||
if (this.state.groupNameError) {
|
||||
groupNameErrElem = (
|
||||
<span className="f9 inter red2 ml3 mt1 db">
|
||||
Group must have a valid name.
|
||||
Group must have a valid name.
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
let invErrElem = (<span />);
|
||||
if (this.state.inviteError) {
|
||||
invErrElem = (
|
||||
<span className="f9 inter red2 ml3 mb5 db">
|
||||
);
|
||||
}
|
||||
|
||||
let invErrElem = (<span />);
|
||||
if (this.state.inviteError) {
|
||||
invErrElem = (
|
||||
<span className="f9 inter red2 ml3 mb5 db">
|
||||
Invites must be validly formatted ship names.
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-100 w-100 flex flex-column overflow-y-scroll">
|
||||
<div className="w-100 dn-m dn-l dn-xl inter pt1 pb6 pl3 pt3 f8">
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-100 w-100 flex flex-column overflow-y-scroll">
|
||||
<div className="w-100 dn-m dn-l dn-xl inter pt1 pb6 pl3 pt3 f8">
|
||||
<Link to="/~contacts/">{"⟵ All Groups"}</Link>
|
||||
</div>
|
||||
<div className="w-100 w-50-l w-50-xl mb4 pr6 pr0-l pr0-xl">
|
||||
</div>
|
||||
<div className="w-100 w-50-l w-50-xl mb4 pr6 pr0-l pr0-xl">
|
||||
<h2 className="f8 pl3 pt4">Create New Group</h2>
|
||||
<h2 className="f8 pl3 pt6">Group Name</h2>
|
||||
<p className="f9 pl3 gray2 lh-copy">Alphanumeric characters and hyphens only</p>
|
||||
<textarea
|
||||
className="f7 ba b--gray3 w-100 pa3 ml3 mt2"
|
||||
rows={1}
|
||||
placeholder="example-group-name"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 14
|
||||
}}
|
||||
onChange={this.groupNameChange}/>
|
||||
className="f7 ba b--gray3 w-100 pa3 ml3 mt2"
|
||||
rows={1}
|
||||
placeholder="example-group-name"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 14
|
||||
}}
|
||||
onChange={this.groupNameChange}/>
|
||||
{groupNameErrElem}
|
||||
{/* <h2 className="f8 pl3 pt6">Group Avatar</h2>
|
||||
<p className="f9 pl3 gray2 lh-copy">
|
||||
Select a color to represent your group
|
||||
Select a color to represent your group
|
||||
</p>
|
||||
<textarea
|
||||
className="f7 ba b--gray3 w-50 w-25-xl pa3 ml3 mt2"
|
||||
rows={1}
|
||||
placeholder="#000000"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 14
|
||||
}}
|
||||
/> */}
|
||||
<h2 className="f8 pl3 pt6">Add Group Members</h2>
|
||||
<p className="f9 pl3 gray2 lh-copy">
|
||||
Invite ships to your group
|
||||
</p>
|
||||
<div className="relative">
|
||||
<textarea
|
||||
className="f8 ba b--gray3 w-100 pa3 pl3 ml3 mt2 mb2"
|
||||
rows={1}
|
||||
placeholder="~zod, ~dopzod, ~ravmel-ropdyl"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 15
|
||||
}}
|
||||
onChange={this.invChange}/>
|
||||
{invErrElem}
|
||||
{/* <span className="f5 gray3 absolute"
|
||||
style={{transform: "rotate(-45deg)",
|
||||
left: 21,
|
||||
top: 18}}>
|
||||
⚲
|
||||
</span> */}
|
||||
</div>
|
||||
<button
|
||||
onClick={this.onClickCreate.bind(this)}
|
||||
className="ml3 f8 ba pa2 b--green2 green2 pointer">
|
||||
Start Group
|
||||
</button>
|
||||
<Link to="/~contacts">
|
||||
<button className="f8 ml3 ba pa2 b--black pointer">Cancel</button>
|
||||
</Link>
|
||||
</div>
|
||||
className="f7 ba b--gray3 w-50 w-25-xl pa3 ml3 mt2"
|
||||
rows={1}
|
||||
placeholder="#000000"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 14
|
||||
}}
|
||||
/> */}
|
||||
<h2 className="f8 pl3 pt6">Add Group Members</h2>
|
||||
<p className="f9 pl3 gray2 lh-copy">
|
||||
Invite ships to your group
|
||||
</p>
|
||||
<div className="relative">
|
||||
<textarea
|
||||
className="f8 ba b--gray3 w-100 pa3 pl3 ml3 mt2 mb2"
|
||||
rows={1}
|
||||
placeholder="~zod, ~dopzod, ~ravmel-ropdyl"
|
||||
style={{
|
||||
resize: "none",
|
||||
height: 48,
|
||||
paddingTop: 15
|
||||
}}
|
||||
onChange={this.invChange}/>
|
||||
{invErrElem}
|
||||
{/* <span className="f5 gray3 absolute"
|
||||
style={{transform: "rotate(-45deg)",
|
||||
left: 21,
|
||||
top: 18}}>
|
||||
⚲
|
||||
</span> */}
|
||||
</div>
|
||||
);
|
||||
<button
|
||||
onClick={this.onClickCreate.bind(this)}
|
||||
className="ml3 f8 ba pa2 b--green2 green2 pointer">
|
||||
Start Group
|
||||
</button>
|
||||
<Link to="/~contacts">
|
||||
<button className="f8 ml3 ba pa2 b--black pointer">Cancel</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default NewScreen
|
||||
|
||||
export default NewScreen
|
||||
|
Loading…
Reference in New Issue
Block a user