Skip to content

Commit

Permalink
Merge branch 'dev' into feature/#60
Browse files Browse the repository at this point in the history
  • Loading branch information
Seogeurim committed Dec 28, 2021
2 parents aec41c7 + adadb2e commit 6394494
Show file tree
Hide file tree
Showing 10 changed files with 412 additions and 9 deletions.
14 changes: 8 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ErrorBoundary from './components/common/ErrorBoundary';
import Uri from './constants/uri';
import HomePage from './pages/HomePage';
import NotFoundPage from './pages/NotFoundPage';
import ServiceEditPage from './pages/ServiceEditPage';
import ServicePage from './pages/ServicePage';
import SigninPage from './pages/SigninPage';
import SignupPage from './pages/SignupPage';
Expand All @@ -20,12 +21,6 @@ const App: FC = () => {
<ErrorBoundary>
<Switch>
<Route path={Uri.home} exact component={HomePage} />
<PrivateRoute
path={Uri.service}
exact
component={ServicePage}
isAccessible={isAuthenticated}
/>
<PrivateRoute
path={Uri.signup}
exact
Expand All @@ -38,6 +33,13 @@ const App: FC = () => {
component={SigninPage}
isAccessible={!isAuthenticated}
/>
<PrivateRoute
path={Uri.service}
exact
component={ServicePage}
isAccessible={isAuthenticated}
/>
<Route path={Uri.serviceEdit} exact component={ServiceEditPage} />
<Route component={NotFoundPage} />
</Switch>
</ErrorBoundary>
Expand Down
Binary file added src/assets/images/theme1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/theme2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
203 changes: 203 additions & 0 deletions src/components/service/ServiceEditForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import React, { FC, useCallback, useEffect, useState } from 'react';

import defaultProfileImg from '@/assets/images/logo.png';
import theme1Img from '@/assets/images/theme1.png';
import theme2Img from '@/assets/images/theme2.png';
import { ServiceInfo } from '@/types/service';

import {
formBodyStyle,
formHeaderStyle,
inputFormStyle,
radioFormStyle,
} from './style';

type ServiceEditFormProps = {
serviceInfo: ServiceInfo;
};

type ServiceEditFormInput = {
name: string;
description: string;
domain: string;
firstQuestion: string;
theme: string;
};

type ImageInput = {
preview: string;
raw: File | null;
};

const ServiceEditForm: FC<ServiceEditFormProps> = ({ serviceInfo }) => {
const {
name,
clientId,
description,
domain,
firstQuestion,
theme,
profileImg,
} = serviceInfo;

const [inputs, setInputs] = useState<ServiceEditFormInput>({
name,
description,
domain,
firstQuestion,
theme: theme.toString(),
});
const [image, setImage] = useState<ImageInput>({
preview: profileImg || defaultProfileImg,
raw: null,
});
const [isBtnActive, setIsBtnActive] = useState<boolean>(false);

useEffect(() => {
setIsBtnActive(
name !== inputs.name ||
description !== inputs.description ||
domain !== inputs.domain ||
firstQuestion !== inputs.firstQuestion ||
theme.toString() !== inputs.theme ||
profileImg !== image.preview,
);
}, [inputs, image]);

const onChange = useCallback(
(e) => {
setInputs({
...inputs,
[e.target.name]: e.target.value,
});
},
[inputs],
);

const onSubmit = () => {
// TODO: 서비스 수정 API 연결
};

const onChangeImgFile = (e) => {
if (e.target.files.length) {
setImage({
preview: URL.createObjectURL(e.target.files[0]),
raw: e.target.files[0],
});
}
};

return (
<form onSubmit={onSubmit}>
<div css={formHeaderStyle}>
<label htmlFor="service-profile">
<input
accept="image/*"
type="file"
name="image"
id="service-profile"
hidden
onChange={onChangeImgFile}
/>
<img src={image.preview} alt="service profile" />
</label>
<div>
<span>Client ID: {clientId}</span>
<h2>{inputs.name}</h2>
</div>
<button type="submit" disabled={!isBtnActive}>
SAVE
</button>
</div>
<div css={formBodyStyle}>
<label
htmlFor="service-name"
css={(cssTheme) => inputFormStyle(cssTheme, name !== inputs.name)}
>
Name :
<input
value={inputs.name}
type="text"
id="service-name"
name="name"
onChange={onChange}
/>
</label>
<label
htmlFor="service-description"
css={(cssTheme) =>
inputFormStyle(cssTheme, description !== inputs.description)
}
>
Description :
<input
value={inputs.description}
type="text"
id="service-description"
name="description"
onChange={onChange}
/>
</label>
<label
htmlFor="service-domain"
css={(cssTheme) => inputFormStyle(cssTheme, domain !== inputs.domain)}
>
Domain :
<input
value={inputs.domain}
type="text"
id="service-domain"
name="domain"
onChange={onChange}
/>
</label>
<label
htmlFor="service-first-question"
css={(cssTheme) =>
inputFormStyle(cssTheme, firstQuestion !== inputs.firstQuestion)
}
>
First Question :
<input
value={inputs.firstQuestion}
type="text"
id="service-first-question"
name="firstQuestion"
onChange={onChange}
/>
</label>
<fieldset css={radioFormStyle}>
<legend>Theme : </legend>
<label htmlFor="theme-1">
<input
type="radio"
id="theme-1"
name="theme"
value="1"
checked={inputs.theme === '1'}
onChange={onChange}
/>
Color Theme 1
<img src={theme1Img} alt="theme-1" />
<span />
</label>
<label htmlFor="theme-2">
<input
type="radio"
id="theme-2"
name="theme"
value="2"
checked={inputs.theme === '2'}
onChange={onChange}
/>
Color Theme 2
<img src={theme2Img} alt="theme-1" />
<span />
</label>
</fieldset>
</div>
</form>
);
};

export default ServiceEditForm;
146 changes: 146 additions & 0 deletions src/components/service/ServiceEditForm/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { SerializedStyles, Theme, css } from '@emotion/react';

export const formHeaderStyle = (theme: Theme): SerializedStyles => css`
font-family: ${theme.fontCoding};
display: flex;
align-items: center;
margin: 20px 50px;
img {
width: 80px;
height: 80px;
margin-right: 20px;
border-radius: 50%;
border: 2px solid ${theme.colorPrimary};
object-fit: cover;
cursor: pointer;
}
> div {
span {
color: ${theme.colorGray3};
font-size: 14px;
}
h2 {
margin-top: 6px;
color: ${theme.colorPrimary};
font-family: ${theme.fontCodingBold};
font-size: 32px;
}
}
button {
height: fit-content;
padding: 6px 20px;
margin-left: auto;
border: none;
border-radius: 10px;
background-color: ${theme.colorSuccess};
color: ${theme.colorWhite};
font-size: 18px;
&:hover,
&:disabled {
opacity: 0.8;
}
}
`;

export const formBodyStyle = css`
display: flex;
flex-direction: column;
margin: 40px;
`;

export const inputFormStyle = (
theme: Theme,
isEdited: boolean,
): SerializedStyles => css`
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
color: ${theme.colorGray1};
font-weight: 700;
font-size: 16px;
input {
width: 80%;
padding: 10px 5px;
background: none;
border: none;
border-bottom: 2px solid ${theme.colorGray2};
color: ${isEdited ? theme.colorGray2 : theme.colorGray3};
font-weight: 600;
font-size: 16px;
&:focus {
outline: none;
}
}
`;

export const radioFormStyle = (theme: Theme): SerializedStyles => css`
display: flex;
border: none;
padding: 0;
margin: 0;
legend {
width: 20%;
padding: 0;
margin-right: 10px;
float: right;
color: ${theme.colorGray1};
font-weight: 700;
font-size: 16px;
}
label {
position: relative;
padding-left: 25px;
margin-right: 30px;
color: ${theme.colorGray2};
font-weight: 600;
cursor: pointer;
img {
display: block;
width: 300px;
margin-left: -40px;
}
input {
position: absolute;
top: 3px;
left: -3px;
opacity: 0;
&:checked ~ span {
background-color: ${theme.colorGray3};
}
&:checked ~ span:after {
display: block;
}
}
span {
position: absolute;
top: 5px;
left: 0;
height: 12px;
width: 12px;
background-color: ${theme.colorWhite};
border: 2px solid ${theme.colorGray3};
border-radius: 50%;
&:after {
content: '';
position: absolute;
display: none;
}
}
}
`;
2 changes: 1 addition & 1 deletion src/constants/uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ enum Uri {
signin = '/signin',
signup = '/signup',
service = '/service',
count = '/count',
serviceEdit = '/service-edit',
}

export default Uri;
Loading

0 comments on commit 6394494

Please sign in to comment.