Skip to content

Commit

Permalink
feat: 完善 CityPicker
Browse files Browse the repository at this point in the history
  • Loading branch information
lijinke666 committed Oct 1, 2018
1 parent c77e261 commit 9af9f79
Show file tree
Hide file tree
Showing 13 changed files with 532 additions and 187 deletions.
94 changes: 94 additions & 0 deletions components/cityPicker/CityPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import cls from "classnames";
import CityPickerCore from "./CityPickerCore";
import Input from "../input";
import { DownIcon } from "../icon";

export default class CityPicker extends PureComponent {
state = {
visible: false
};
static defaultProps = {
prefixCls: "cuke-city-picker",
cityList: [],
disabled: false,
placeholder: "请选择"
};
static propTypes = {
cityList: PropTypes.arrayOf(
PropTypes.shape({
group: PropTypes.string.isRequired,
resources: PropTypes.arrayOf(PropTypes.object)
})
).isRequired,
disabled: PropTypes.bool,
placeholder: PropTypes.string,
onCityGroupChange: PropTypes.func,
onCityChange: PropTypes.func
};
state = {
selectedCityGroup: "热门",
selectedCityName: ""
};

onCityGroupChange = selectedCityGroup => {
if (this.props.onCityGroupChange) {
this.props.onCityGroupChange(selectedCityGroup);
}
};
onCityChange = selectedCity => {
this.setState({ visible: false, selectedCityName: selectedCity.name });

if (this.props.onCityChange) {
this.props.onCityChange(selectedCity);
}
};

onOpenCityPicker = () => {
this.setState({ visible: true });
};

onCloseCityPicker = () => {
// this.setState({visible: false})
};
render() {
const {
cityList,
prefixCls,
disabled,
placeholder,
className,
...attr
} = this.props;
const { visible, selectedCityName } = this.state;
return (
<div className={cls(`${prefixCls}`, className)} {...attr}>
<div className={cls(`${prefixCls}-inner`)}>
<Input
disabled={disabled}
readonly
placeholder={placeholder}
className={cls(`${prefixCls}-input`)}
onFocus={this.onOpenCityPicker}
onBlur={this.onCloseCityPicker}
value={selectedCityName}
/>
<DownIcon className={`${prefixCls}-arrow`} />
</div>
<div
className={cls(`${prefixCls}-content`, {
[`${prefixCls}-open`]: visible,
[`${prefixCls}-close`]: !visible
})}
>
<CityPickerCore
cityList={cityList}
onCityChange={this.onCityChange}
onCityGroupChange={this.onCityGroupChange}
/>
</div>
</div>
);
}
}
96 changes: 96 additions & 0 deletions components/cityPicker/CityPickerCore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import cls from "classnames";

export default class CityPickerCore extends PureComponent {
static defaultProps = {
prefixCls: "cuke-city-picker-core",
cityList: []
};
static propTypes = {
cityList: PropTypes.arrayOf(
PropTypes.shape({
group: PropTypes.string.isRequired,
resources: PropTypes.arrayOf(PropTypes.object)
})
).isRequired,
onCityGroupChange: PropTypes.func,
onCityChange: PropTypes.func
};
state = {
selectedCityGroup: "热门",
selectedCityName: ""
};

onCityGroupChange = selectedCityGroup => () => {
this.setState({ selectedCityGroup });

if (this.props.onCityGroupChange) {
this.props.onCityGroupChange(selectedCityGroup);
}
};
onCityChange = selectedCity => () => {
this.setState({ selectedCityName: selectedCity.name });
if (this.props.onCityChange) {
this.props.onCityChange(selectedCity);
}
};

render() {
const {
cityList,
prefixCls,
className,
onCityGroupChange, //eslint-disable-line
onCityChange, //eslint-disable-line
...attr
} = this.props;
const { selectedCityGroup, selectedCityName } = this.state;
const cityGroups =
cityList.length >= 1 ? cityList.map(({ group }) => group) : [];

return (
<div className={cls(`${prefixCls}`, className)} {...attr}>
<div className={cls(`${prefixCls}-panel`)}>
<div className={cls(`${prefixCls}-panel-header`)}>
<ul className={cls(`${prefixCls}-panel-header-wrap`)}>
{cityGroups.map((cityGroup, i) => {
return (
<li
onClick={this.onCityGroupChange(cityGroup)}
className={cls("item", {
active: selectedCityGroup === cityGroup
})}
key={i}
>
<span>{cityGroup}</span>
</li>
);
})}
</ul>
</div>
<div className={cls(`${prefixCls}-panel-content`)}>
<ul className={cls(`${prefixCls}-panel-content-wrap`)}>
{cityList.length >= 1 &&
cityList
.find(item => item.group === selectedCityGroup)
.resources.map((city, i) => {
return (
<li
className={cls("city", {
selected: selectedCityName === city.name
})}
key={i}
onClick={this.onCityChange(city)}
>
{city.name}
</li>
);
})}
</ul>
</div>
</div>
</div>
);
}
}
61 changes: 61 additions & 0 deletions components/cityPicker/__tests__/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<CityPicker/> should render CityPicker 1`] = `
<div
class="cuke-city-picker"
>
<div
class="cuke-city-picker-inner"
>
<input
class="cuke-input cuke-city-picker-input"
placeholder="请选择"
readonly=""
type="text"
value=""
/>
<svg
attr="[object Object]"
class="undefined cuke-city-picker-arrow"
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
>
<polyline
points="6 9 12 15 18 9"
/>
</svg>
</div>
<div
class="cuke-city-picker-content cuke-city-picker-close"
>
<div
class="cuke-city-picker-core"
>
<div
class="cuke-city-picker-core-panel"
>
<div
class="cuke-city-picker-core-panel-header"
>
<ul
class="cuke-city-picker-core-panel-header-wrap"
/>
</div>
<div
class="cuke-city-picker-core-panel-content"
>
<ul
class="cuke-city-picker-core-panel-content-wrap"
/>
</div>
</div>
</div>
</div>
</div>
`;
34 changes: 34 additions & 0 deletions components/cityPicker/__tests__/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import assert from "power-assert";
import React from "react";
import { render, shallow } from "enzyme";
import toJson from "enzyme-to-json";
import CityPicker from "../index";
import Input from "../../input";
import CityPickerCore from "../CityPickerCore";

describe("<CityPicker/>", () => {
it("should render CityPicker", () => {
const wrapper = render(<CityPicker />);
expect(toJson(wrapper)).toMatchSnapshot();
});

it("should render Input when render CityPicker", () => {
const wrapper = shallow(<CityPicker />);
assert(wrapper.find(Input).length === 1);
});

it("should render CityPickerCore when render CityPicker", () => {
const wrapper = shallow(<CityPicker />);
assert(wrapper.find(CityPickerCore).length === 1);
});

it("should render cuke-city-picker classnames", () => {
const wrapper = shallow(<CityPicker />);
assert(wrapper.find(".cuke-city-picker").length === 1);
});

it("should render cuke-city-picker-core classnames", () => {
const wrapper = shallow(<CityPickerCore />);
assert(wrapper.find(".cuke-city-picker-core").length === 1);
});
});
80 changes: 4 additions & 76 deletions components/cityPicker/index.js
Original file line number Diff line number Diff line change
@@ -1,78 +1,6 @@
import React, { PureComponent } from "react";
import cls from "classnames";
import CityPickerCore from "./CityPickerCore";
import CityPicker from "./CityPicker";

export default class CityPicker extends PureComponent {
static defaultProps = {
prefixCls: "cuke-city-picker",
cityList: []
};
state = {
selectedCityGroup: "热门",
selectedCityName: ""
};
CityPicker.CityPickerCore = CityPickerCore;

onCityGroupChange = selectedCityGroup => () => {
this.setState({ selectedCityGroup });

if (this.props.onCityGroupChange) {
this.props.onCityGroupChange(selectedCityGroup);
}
};
onCityChange = selectedCity => () => {
this.setState({ selectedCityName: selectedCity.name });
if (this.props.onCityChange) {
this.props.onCityChange(selectedCity);
}
};

render() {
const { cityList, prefixCls } = this.props;
const { selectedCityGroup, selectedCityName } = this.state;
const cityGroups =
cityList.length >= 1 ? cityList.map(({ group }) => group) : [];

return (
<div className={`${prefixCls}`}>
<div className={cls(`${prefixCls}-panel`)}>
<div className={cls(`${prefixCls}-panel-header`)}>
<ul className={cls(`${prefixCls}-panel-header-wrap`)}>
{cityGroups.map((cityGroup, i) => {
return (
<li
onClick={this.onCityGroupChange(cityGroup)}
className={cls("item", {
active: selectedCityGroup === cityGroup
})}
key={i}
>
<span>{cityGroup}</span>
</li>
);
})}
</ul>
</div>
<div className={cls(`${prefixCls}-panel-content`)}>
<ul className={cls(`${prefixCls}-panel-content-wrap`)}>
{cityList.length >= 1 &&
cityList
.find(item => item.group === selectedCityGroup)
.resources.map((city, i) => {
return (
<li
className={cls("city", {
selected: selectedCityName === city.name
})}
key={i}
onClick={this.onCityChange(city)}
>
{city.name}
</li>
);
})}
</ul>
</div>
</div>
</div>
);
}
}
export default CityPicker;
Loading

0 comments on commit 9af9f79

Please sign in to comment.