Skip to content

Commit

Permalink
fix: game input UI
Browse files Browse the repository at this point in the history
  • Loading branch information
shiftpsh committed Jul 20, 2024
1 parent 45d258d commit 7964994
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 55 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Oxanium:[email protected]&family=Zen+Antique+Soft&display=swap"
href="https://fonts.googleapis.com/css2?family=Oxanium:[email protected]&family=Zen+Antique+Soft&family=Libre+Caslon+Text:ital,wght@0,400;0,700;1,400&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="/fonts/TAEBAEKmilkyway.css" />
Expand Down
4 changes: 4 additions & 0 deletions src/components/TitleLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const TotalStatContainer = styled.div`
align-items: flex-start;
justify-content: flex-start;
padding: 32px 0;
@media screen and (max-width: 720px) {
padding: 16px 0;
}
`;

const TotalStatWrapper = styled.div`
Expand Down
2 changes: 0 additions & 2 deletions src/components/form/JyanshiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ const JyanshiSelect = ({
}
: undefined
}
// autoSelect
autoComplete
autoHighlight
filterSelectedOptions
/>
Expand Down
115 changes: 115 additions & 0 deletions src/components/form/gameRecord/GameChipInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import styled from "@emotion/styled";
import { Input } from "@mui/base";
import { useEffect, useState } from "react";
import { color } from "../../../styles/colors";
import { fontFamilies } from "../../../styles/fonts";
import { IconPokerChip } from "@tabler/icons-react";

const ScoreBackground = styled.div`
position: relative;
${fontFamilies.libreCaslon}
font-weight: 500;
background-color: #1a1a1b;
color: #b89554;
font-size: 1.6em;
border: 1px solid ${color.silkBlueLight};
&:hover {
border: 1px solid ${color.goldLight};
}
@media (max-width: 720px) {
font-size: 1.2em;
}
`;

const InputRoot = styled.div`
flex: 1 0 0;
font-size: 1.2em;
min-width: 0;
`;

const InputField = styled.input`
width: 100%;
background: none;
padding: 0;
border: none;
color: inherit;
padding: 8px 8px 8px 1.7ch;
text-align: center;
`;

const InputAdornment = styled.span`
position: absolute;
user-select: none;
left: 8px;
bottom: 16%;
`;

const strip = (value: string) => {
const replaced = value.replace(/[^0-9-]/g, "");
if (!replaced.length) return "";
if (/^0+$/.test(replaced)) return "0";
return replaced.replace(/^0+/, "").replace(/^-0+/, "-");
};

interface Props {
value: number;
onChange?: (value: number) => void;
}

const GameChipInput = ({ value, onChange }: Props) => {
const [internalValue, setInternalValue] = useState<string>("");

useEffect(() => {
if (!value) {
if (internalValue === "-") return;
}
if (value !== +internalValue) {
setInternalValue(Math.floor(value).toString());
}
}, [internalValue, value]);

const handleChange = (newValue: string) => {
const stripped = strip(newValue).slice(0, 5);
setInternalValue(stripped);
if (onChange) {
const int = +stripped;
if (isNaN(int)) {
onChange(0);
return;
}
onChange(int);
}
};

const handleFocus = () => {
if (internalValue === "0") {
setInternalValue("");
}
};

const handleBlur = () => {
setInternalValue(Math.floor(value).toString());
};

return (
<>
<ScoreBackground>
<Input
inputMode="numeric"
slots={{ root: InputRoot, input: InputField }}
value={internalValue}
onChange={(e) => handleChange(e.target.value)}
onFocus={handleFocus}
onBlur={handleBlur}
/>
<InputAdornment>
<IconPokerChip />
</InputAdornment>
</ScoreBackground>
</>
);
};

export default GameChipInput;
4 changes: 4 additions & 0 deletions src/components/form/gameRecord/GameRecordSingleUserInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { fontFamilies } from "../../../styles/fonts";
import { Space } from "../../Space";
import { IconCheckbox, IconSquare } from "@tabler/icons-react";
import GameScoreInput from "./GameScoreInput";
import GameChipInput from "./GameChipInput";

const InputCard = styled.div<{ oya: boolean }>`
background-image: linear-gradient(
Expand Down Expand Up @@ -119,6 +120,9 @@ const GameRecordSingleUserInput = ({
{scoreType === "score" && (
<GameScoreInput value={value.score} onChange={onChangeScore} />
)}
{scoreType === "chips" && (
<GameChipInput value={value.score} onChange={onChangeScore} />
)}
</InputCard>
);
};
Expand Down
6 changes: 6 additions & 0 deletions src/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const HeaderBackground = styled.div`
display: flex;
align-items: center;
justify-content: flex-start;
@media (max-width: 720px) {
min-height: 48px;
font-size: 1.5rem;
padding: 8px 120px 8px 16px;
}
`;

interface Props extends HTMLAttributes<HTMLDivElement> {}
Expand Down
2 changes: 1 addition & 1 deletion src/components/layouts/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ export const Container = styled.div`
padding: 0 32px;
@media screen and (max-width: 720px) {
padding: 0 16px;
padding: 0;
}
`;
4 changes: 4 additions & 0 deletions src/components/layouts/DefaultLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const FullScreenContainer = styled.div`
height: calc(100vh - 72px);
overflow: hidden;
position: relative;
@media screen and (max-width: 720px) {
height: calc(100vh - 48px);
}
`;

const BACKGROUND_IMAGES = {
Expand Down
11 changes: 7 additions & 4 deletions src/components/layouts/TopBarPadding.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Space } from "../Space";
import styled from "@emotion/styled";

export const TopBarPadding = () => {
return <Space h={96} />;
};
export const TopBarPadding = styled.div`
height: 96px;
@media screen and (max-width: 720px) {
height: 64px;
}
`;
66 changes: 21 additions & 45 deletions src/pages/create/CreateLoggedIn.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,33 @@
import styled from "@emotion/styled";
import { useState } from "react";
import { Card } from "../../components/Card";
import { Space } from "../../components/Space";
import GameTypeSelect from "../../components/form/GameTypeSelect";
import GameRecordInput from "../../components/form/gameRecord/GameRecordInput";
import { GameRecordInputValues } from "../../components/form/gameRecord/types";
import { GameTypeResponse } from "../../types/GameTypeResponse";
import { resolveWind } from "../../utils/wind";

const InputRow = styled.div`
display: flex;
gap: 8px;
align-items: center;
justify-content: center;
@media screen and (max-width: 720px) {
align-items: flex-start;
flex-direction: column;
}
`;

const InputCaption = styled.div`
flex: 0 0 120px;
min-width: 0;
@media screen and (max-width: 720px) {
flex: 0 0 auto;
}
const GameTypeInputContainer = styled.div`
width: 100%;
max-width: 540px;
margin: 0 auto;
`;

const InputDetails = styled.div`
flex: 1;
min-width: 0;
const GameTypeSelectContainer = styled.div`
position: fixed;
z-index: 210;
left: 160px;
right: 0;
top: 46px;
color: white;
@media screen and (max-width: 720px) {
flex: 0 0 auto;
left: unset;
top: 22px;
right: 0px;
}
`;

const GameTypeInputContainer = styled.div`
width: 100%;
max-width: 540px;
margin: 0 auto;
`;

const CreateLoggedIn = () => {
const [selectedGameType, setSelectedGameType] =
useState<GameTypeResponse | null>(null);
Expand Down Expand Up @@ -85,22 +69,14 @@ const CreateLoggedIn = () => {

return (
<>
<GameTypeSelectContainer>
<GameTypeSelect
value={selectedGameType}
onChange={handleSelectGameType}
setToDefault
/>
</GameTypeSelectContainer>
<Card>
<InputRow>
<InputCaption>대국 유형</InputCaption>
<InputDetails>
<GameTypeSelect
value={selectedGameType}
onChange={handleSelectGameType}
setToDefault
/>
</InputDetails>
</InputRow>
<Space h={16} />
<InputRow>
<InputCaption>작사</InputCaption>
<InputDetails />
</InputRow>
<GameTypeInputContainer>
{selectedGameType && (
<GameRecordInput
Expand Down
13 changes: 11 additions & 2 deletions src/styles/fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,24 @@ const milkyway = ["Taebaek Milkyway", "sans-serif"]
.map((x) => (x === "sans-serif" ? x : `'${x}'`))
.join(", ");

const zenAntique = ["Zen Antique Soft", "sans-serif"];
const zenAntique = ["Zen Antique Soft", "sans-serif"]
.map((x) => (x === "sans-serif" ? x : `'${x}'`))
.join(", ");

const oxanium = ["Oxanium", "sans-serif"];
const oxanium = ["Oxanium", "sans-serif"]
.map((x) => (x === "sans-serif" ? x : `'${x}'`))
.join(", ");

const libreCaslon = ["Libre Caslon Text", "sans-serif"]
.map((x) => (x === "sans-serif" ? x : `'${x}'`))
.join(", ");

export const fonts = {
kimDaegon,
milkyway,
zenAntique,
oxanium,
libreCaslon,
};

export const fontFamilies = Object.fromEntries(
Expand Down

0 comments on commit 7964994

Please sign in to comment.