Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions apps/web/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/App.css",
"baseColor": "stone",
"cssVariables": false
},
"aliases": {
"components": "./src/components",
"utils": "./src/lib/utils",
"ui": "./src/components/ui"
}
}
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"react-redux": "^9.2.0",
"react-router-dom": "^6.15.0",
"recharts": "^2.5.0",
"tailwind-merge": "^3.5.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
Expand Down
117 changes: 117 additions & 0 deletions apps/web/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,123 @@
@tailwind components;
@tailwind utilities;

@layer base {
html,
body,
#root {
min-height: 100%;
}

body {
margin: 0;
background: #edf0e6;
}

::selection {
background: #b9c8a3;
color: #28362c;
}
}

.calm-shell {
font-family: 'Avenir Next', 'Trebuchet MS', sans-serif;
}

.calm-shell .font-serif {
font-family: 'Iowan Old Style', 'Palatino Linotype', Palatino, serif;
}

.calm-orb {
position: absolute;
border-radius: 9999px;
filter: blur(2px);
pointer-events: none;
}

.calm-orb-one {
top: 70px;
right: -160px;
width: 430px;
height: 430px;
background: rgb(244 168 143 / 22%);
}

.calm-orb-two {
bottom: 120px;
left: -180px;
width: 470px;
height: 470px;
background: rgb(185 200 163 / 33%);
}

.calm-shell section > *,
.calm-shell main > * {
animation: calm-arrive 480ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.calm-shell section > *:nth-child(2),
.calm-shell main > *:nth-child(2) {
animation-delay: 70ms;
}

.calm-shell main > *:nth-child(3) {
animation-delay: 120ms;
}

.calm-shell main > *:nth-child(4) {
animation-delay: 170ms;
}

.calm-shell header .btn-circle,
.calm-shell header .btn-sm {
min-height: 2.5rem;
height: 2.5rem;
border: 0;
border-radius: 9999px;
background: transparent;
color: #28362c;
}

.calm-shell header .btn-circle {
width: 2.5rem;
}

.calm-shell header .dropdown-content {
border: 1px solid rgb(40 54 44 / 15%);
border-radius: 1.5rem;
background: #fffdf6;
color: #28362c;
}

.calm-log-editor {
background-image: repeating-linear-gradient(
to bottom,
transparent 0,
transparent 27px,
rgb(40 54 44 / 7%) 27px,
rgb(40 54 44 / 7%) 28px
);
background-position-y: 16px;
}

@keyframes calm-arrive {
from {
opacity: 0;
transform: translateY(10px) scale(0.995);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}

@media (prefers-reduced-motion: reduce) {
.calm-shell section > *,
.calm-shell main > * {
animation: none;
}
}

@keyframes shake {
0% {
transform: translateX(0);
Expand Down
57 changes: 45 additions & 12 deletions apps/web/src/components/charts/AvailableRestTimeChart/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Area,
AreaChart,
CartesianGrid,
ReferenceLine,
ResponsiveContainer,
Tooltip,
XAxis,
Expand Down Expand Up @@ -31,46 +32,78 @@ export const AvailableRestTimeChart = ({

const gradientId = 'availableRestTimeSplitColor';

if (data.length < 2) {
return (
<div className="flex h-full min-h-44 items-center justify-center rounded-3xl border border-dashed border-[#28362c]/15 bg-white/35 px-8 text-center text-xs text-[#28362c]/35">
기록을 두 개 이상 남기면 오늘의 시간 온도가 보여요
</div>
);
}

return (
<ResponsiveContainer className="min-h-0">
<ResponsiveContainer className="min-h-0" width="100%" height="100%">
<AreaChart
data={data}
margin={{
top: 30,
right: 30,
left: 0,
bottom: 30,
top: 26,
right: 18,
left: -12,
bottom: 8,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<CartesianGrid
stroke="#dfe3d7"
strokeDasharray="3 6"
vertical={false}
/>
<XAxis
dataKey="offset"
type="number"
tick={{ fontSize: 16 }}
axisLine={false}
tickLine={false}
tick={{ fontSize: 10, fill: '#75806f' }}
tickFormatter={minutesToTimeString}
domain={[minXAxisDomain, maxXAxisDomain]}
/>
<YAxis
tick={{ fontSize: 16 }}
axisLine={false}
tickLine={false}
tick={{ fontSize: 10, fill: '#75806f' }}
domain={yAxisConfig.domain}
ticks={yAxisConfig.ticks}
tickFormatter={(value) => `${value}`}
/>
<Tooltip
labelFormatter={minutesToTimeString}
formatter={(value: number | string) => [`${value}분`, '초과 휴식']}
formatter={(value: number | string) => [`${value}분`, '소비 − 생산']}
contentStyle={{
border: '1px solid rgba(40,54,44,.12)',
borderRadius: 18,
boxShadow: '0 14px 35px rgba(40,54,44,.10)',
fontSize: 11,
}}
/>
<ReferenceLine y={0} stroke="#8b9684" strokeDasharray="3 5" />
<defs>
<linearGradient id={gradientId} x1="0" y1="0" x2="0" y2="1">
<stop offset={gradientOffset} stopColor="red" stopOpacity={1} />
<stop offset={gradientOffset} stopColor="green" stopOpacity={1} />
<stop
offset={gradientOffset}
stopColor="#f4a88f"
stopOpacity={0.78}
/>
<stop
offset={gradientOffset}
stopColor="#b9c8a3"
stopOpacity={0.72}
/>
</linearGradient>
</defs>
<Area
type="monotone"
dataKey="need"
unit="min"
stroke="#000"
stroke="#52624e"
strokeWidth={1.5}
fill={`url(#${gradientId})`}
/>
{getPoints(data)}
Expand Down
10 changes: 5 additions & 5 deletions apps/web/src/components/charts/AvailableRestTimeChart/points.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const getPoints = (data: ChartDataPoint[]) => {
const points: ReactElement[] = [];

if (highPoint) {
const color = highPoint.need >= 0 ? 'red' : 'green';
const color = highPoint.need >= 0 ? '#d87f62' : '#718466';
points.push(
<ReferenceDot
key="high"
Expand All @@ -34,7 +34,7 @@ export const getPoints = (data: ChartDataPoint[]) => {
}

if (lowPoint) {
const color = lowPoint.need >= 0 ? 'red' : 'green';
const color = lowPoint.need >= 0 ? '#d87f62' : '#718466';
points.push(
<ReferenceDot
key="low"
Expand Down Expand Up @@ -117,7 +117,7 @@ function isNearPoint(
type CurrentPointConfig = {
point: ChartDataPoint | null;
shouldShow: boolean;
color: 'red' | 'green';
color: string;
position: 'top' | 'bottom';
};

Expand All @@ -131,14 +131,14 @@ function getCurrentPointConfig(
return {
point: null,
shouldShow: false,
color: 'red',
color: '#d87f62',
position: 'top',
};
}

const shouldShow =
!isNearPoint(currPoint, highPoint) && !isNearPoint(currPoint, lowPoint);
const color = currPoint.need >= 0 ? 'red' : 'green';
const color = currPoint.need >= 0 ? '#d87f62' : '#718466';
const position = currPoint.need >= 0 ? 'top' : 'bottom';

return { point: currPoint, shouldShow, color, position };
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/components/charts/DayRatioBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const DayRatioBar = ({ logs }: { logs: Log[] }) => {

if (isEmpty || totalDuration <= 0) {
return (
<div className="flex h-3 w-full min-w-0 overflow-hidden rounded-full bg-gray-200" />
<div className="flex h-2 w-full min-w-0 overflow-hidden rounded-full bg-[#e4e7dc]" />
);
}

Expand Down Expand Up @@ -36,14 +36,14 @@ export const DayRatioBar = ({ logs }: { logs: Log[] }) => {

return (
<div
className="isolate flex h-3 w-full min-w-0 transform-gpu flex-nowrap overflow-hidden rounded-full bg-gray-100"
className="isolate flex h-2 w-full min-w-0 transform-gpu flex-nowrap overflow-hidden rounded-full bg-[#e4e7dc]"
style={{ WebkitMaskImage: '-webkit-radial-gradient(white, black)' }}
>
{blocks.map((block, idx) => (
<div
key={idx}
className={`transition-all duration-500 ease-in-out ${
block.type === 'productive' ? 'bg-green-500' : 'bg-red-500'
block.type === 'productive' ? 'bg-[#849978]' : 'bg-[#e69a80]'
}`}
style={{ width: `${(block.duration / totalDuration) * 100}%` }}
title={`${block.type === 'productive' ? '생산' : '소비'}: ${block.duration}분`}
Expand Down
Loading
Loading