Compare commits
10 Commits
v0.0.1
...
bdb3effaf0
| Author | SHA1 | Date | |
|---|---|---|---|
| bdb3effaf0 | |||
| 97879cc41b | |||
| 5288637d19 | |||
| ae73b5d256 | |||
| a2b1f761ac | |||
| a00ec135f1 | |||
| 1b1c45935b | |||
| 9d6f0ce73d | |||
| 860b628834 | |||
| af335ab4a8 |
@@ -1,9 +1,26 @@
|
||||
import { withTitle } from "@/constructors/Component";
|
||||
import { UrlsTitle } from "@/enums/urls";
|
||||
import { cn } from "@/utils/class-merge";
|
||||
import { BackwardIcon } from "@heroicons/react/24/solid";
|
||||
import { FunctionComponent, h } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
interface BackButtonProps {
|
||||
selectedDate: Date;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const BackButton: FunctionComponent<BackButtonProps> = ({ selectedDate, onClick }: BackButtonProps) => {
|
||||
const currentDate = new Date();
|
||||
|
||||
return currentDate.getMonth() !== selectedDate.getMonth() ? (
|
||||
<div
|
||||
class="fixed bottom-4 left-8 hidden aspect-square h-24 cursor-pointer flex-col items-center justify-center rounded-full bg-[rgb(251,194,199,0.53)] shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] hover:bg-[rgb(251,194,199,0.7)] md:flex"
|
||||
onClick={onClick}
|
||||
>
|
||||
<BackwardIcon class="size-8 text-sm text-white" />
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
type MarkedDateType = "event" | "holiday" | "important" | string;
|
||||
type MarkedDates = Record<string, MarkedDateType>;
|
||||
|
||||
@@ -44,7 +61,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
|
||||
const getFirstDayOfMonth = (year: number, month: number): number => {
|
||||
const day = new Date(year, month, 1).getDay();
|
||||
return day === 0 ? 6 : day - 1;
|
||||
return day === 0 ? 6 : day;
|
||||
};
|
||||
|
||||
const handlePrevMonth = (): void => {
|
||||
@@ -60,7 +77,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
setCurrentDate(new Date(date.getFullYear(), date.getMonth(), 1));
|
||||
}
|
||||
setSelectedDate(date);
|
||||
onDateSelect?.(date);
|
||||
onDateSelect(date);
|
||||
};
|
||||
|
||||
const isDateMarked = (date: Date): MarkedDateType | undefined => {
|
||||
@@ -70,7 +87,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
|
||||
const getLastDayOfMonth = (year: number, month: number): number => {
|
||||
const day = new Date(year, month + 1, 0).getDay();
|
||||
return day === 0 ? 6 : day - 1;
|
||||
return day === 0 ? 6 : day;
|
||||
};
|
||||
|
||||
const renderDays = (): h.JSX.Element[] => {
|
||||
@@ -84,12 +101,11 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
const days: h.JSX.Element[] = [];
|
||||
|
||||
// Дни предыдущего месяца
|
||||
//TODO: work on click on 31 march
|
||||
const prevMonthDays = getDaysInMonth(year, month - 1);
|
||||
const daysFromPrevMonth = firstDayOfMonth === 0 ? 6 : firstDayOfMonth;
|
||||
for (let i = daysFromPrevMonth - 1; i >= 0; i--) {
|
||||
const day = prevMonthDays - i;
|
||||
const date = new Date(year, month - 1, day + 1);
|
||||
const date = new Date(year, month - 1, day);
|
||||
const dateStr = date.toISOString().split("T")[0];
|
||||
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
||||
const markType = isDateMarked(date);
|
||||
@@ -122,7 +138,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
|
||||
// Дни текущего месяца
|
||||
for (let day = 1; day <= daysInMonth; day++) {
|
||||
const date = new Date(year, month, day + 1);
|
||||
const date = new Date(year, month, day);
|
||||
const dateStr = date.toISOString().split("T")[0];
|
||||
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
||||
const markType = isDateMarked(date);
|
||||
@@ -166,9 +182,9 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
}
|
||||
|
||||
// Дни следующего месяца
|
||||
const daysToAdd = 6 - (lastDayOfMonth === 6 ? 4 : lastDayOfMonth);
|
||||
const daysToAdd = 6 - (lastDayOfMonth === 6 ? 3 : lastDayOfMonth);
|
||||
for (let day = 1; day <= daysToAdd; day++) {
|
||||
const date = new Date(year, month + 1, day + 1);
|
||||
const date = new Date(year, month + 1, day);
|
||||
const dateStr = date.toISOString().split("T")[0];
|
||||
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
||||
const markType = isDateMarked(date);
|
||||
@@ -203,7 +219,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col ${className}`}>
|
||||
<div className={`flex w-full flex-col ${className}`}>
|
||||
<div className="mb-4 flex items-center justify-between px-2">
|
||||
<button
|
||||
onClick={handlePrevMonth}
|
||||
@@ -235,7 +251,6 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mb-2 grid grid-cols-7 gap-1 text-center text-sm font-medium text-gray-500">
|
||||
{dayNames.map((day) => (
|
||||
<div key={day} className="flex h-10 items-center justify-center">
|
||||
@@ -243,10 +258,10 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid flex-1 grid-cols-7 gap-1">{renderDays()}</div>
|
||||
<BackButton selectedDate={currentDate} onClick={() => setCurrentDate(new Date())} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTitle(UrlsTitle.CALENDAR, BigCalendar);
|
||||
export default BigCalendar;
|
||||
@@ -1,13 +1,13 @@
|
||||
@reference "../index.scss";
|
||||
|
||||
#container {
|
||||
@apply flex min-h-auto w-screen flex-col items-center gap-4 px-2 py-3 md:min-h-screen md:w-[30rem];
|
||||
@apply flex min-h-auto w-screen flex-col items-center gap-4 px-2 py-3 md:min-h-screen md:w-[20rem];
|
||||
}
|
||||
|
||||
.menu_container {
|
||||
@apply fixed right-0 bottom-0 left-0 flex h-[4rem] w-full flex-1 flex-row items-center gap-1 rounded-[44px] bg-[rgba(167,213,246,0.3)] px-1 py-5 md:sticky md:top-0 md:right-0 md:bottom-auto md:left-auto md:h-full md:flex-col md:gap-4 md:border-t-0 md:px-5 md:py-5;
|
||||
@apply fixed right-0 bottom-0 left-0 flex h-[4rem] w-full flex-1 flex-row items-center gap-1 rounded-[3rem] bg-[rgba(167,213,246,0.3)] px-1 py-5 md:sticky md:top-0 md:right-0 md:bottom-auto md:left-auto md:h-full md:flex-col md:gap-4 md:border-t-0 md:px-5 md:py-5;
|
||||
}
|
||||
|
||||
.menu_item {
|
||||
@apply flex w-full cursor-pointer flex-row items-center gap-3 rounded-full px-3 py-2 text-center hover:bg-gray-200 md:px-6;
|
||||
@apply flex w-full flex-1/3 cursor-pointer flex-row items-center justify-center gap-3 rounded-full px-3 py-2 text-center hover:bg-gray-200 md:flex-initial md:justify-start md:px-6;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ const MenuItem: FunctionComponent<MenuItemProps> = ({ title, link, icon }: MenuI
|
||||
return (
|
||||
<div class={menuItemClasses({ activity: active ? "active" : "inactive" })} onClick={() => route(link, true)}>
|
||||
{icon}
|
||||
{title}
|
||||
<div class="hidden md:block">{title}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -40,19 +40,19 @@ const Avatar: FunctionComponent = () => {
|
||||
return (
|
||||
<button
|
||||
onClick={() => route("/profile/settings")}
|
||||
class={cn("hidden h-32 w-full cursor-pointer overflow-hidden transition-[height] md:block", {
|
||||
"h-0": path === "/profile/settings",
|
||||
class={cn("hidden h-32 w-full cursor-pointer overflow-hidden opacity-100 transition-[height,opacity] md:block", {
|
||||
"h-0 opacity-0": path === "/profile/settings",
|
||||
})}
|
||||
>
|
||||
<div
|
||||
class={cn(
|
||||
"h-full flex-row items-center justify-around rounded-[44px] bg-[linear-gradient(180.00deg,rgba(249,134,143,0.5)_3.053%,rgb(228,242,252)_96.183%)] px-5 py-5 md:flex"
|
||||
"h-full flex-row items-center justify-around rounded-[3rem] bg-[linear-gradient(180.00deg,rgba(249,134,143,0.5)_3.053%,rgb(228,242,252)_96.183%)] px-5 py-5 md:flex"
|
||||
)}
|
||||
>
|
||||
<div class="my-5 aspect-square h-full rounded-full bg-white"></div>
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<p class="text-3xl font-semibold">Никнейм</p>
|
||||
<p class="text-xl font-light">Статус</p>
|
||||
<p class="text-3xl font-semibold">никнейм</p>
|
||||
<div class="rounded-[1rem] bg-white px-5 leading-5 font-light italic">статус</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@reference "../index.scss";
|
||||
|
||||
.task {
|
||||
@apply flex h-24 w-[300px] cursor-pointer flex-row items-center justify-start gap-4 rounded-[39px] bg-[rgba(251,194,199,0.53)] px-5 py-6 text-xl shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-transform hover:scale-[1.05] hover:bg-[rgba(251,194,199,0.7)] active:scale-[1.05] md:w-[500px];
|
||||
@apply flex h-24 w-full cursor-pointer flex-row items-center justify-start gap-4 rounded-[3rem] bg-[rgba(251,194,199,0.53)] px-5 py-6 text-xl shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-transform hover:scale-[1.05] hover:bg-[rgba(251,194,199,0.7)] active:scale-[1.05] md:w-[500px];
|
||||
}
|
||||
|
||||
@@ -1,16 +1,40 @@
|
||||
import { FunctionComponent } from "preact";
|
||||
import { tv } from "tailwind-variants";
|
||||
import classes from "./task.module.scss";
|
||||
|
||||
interface TaskProps {
|
||||
name: string;
|
||||
checked?: boolean;
|
||||
}
|
||||
|
||||
const Task: FunctionComponent<TaskProps> = ({ name }: TaskProps) => {
|
||||
const taskStyle = tv({
|
||||
base: "flex aspect-square h-full flex-col items-center justify-center rounded-full border",
|
||||
variants: {
|
||||
checked: {
|
||||
true: "bg-black",
|
||||
false: "bg-white",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const markStyle = tv({
|
||||
base: "text-4xl font-light text-white",
|
||||
variants: {
|
||||
checked: {
|
||||
true: "block",
|
||||
false: "hidden",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const Task: FunctionComponent<TaskProps> = ({ name, checked = false }: TaskProps) => {
|
||||
return (
|
||||
// Временное действие для тестирования
|
||||
<button onClick={() => alert(name)}>
|
||||
<button onClick={() => alert(name)} class="w-[95%]">
|
||||
<div class={classes.task}>
|
||||
<div class="aspect-square h-full rounded-full border bg-white"></div>
|
||||
<div class={taskStyle({ checked })}>
|
||||
<p class={markStyle({ checked })}>✓</p>
|
||||
</div>
|
||||
{name}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@reference '../../index.scss';
|
||||
|
||||
.button {
|
||||
@apply rounded-[23px] px-4 py-3 text-xl text-black shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-colors hover:cursor-pointer;
|
||||
@apply rounded-4xl px-4 py-3 text-xl text-black shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-colors hover:cursor-pointer;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ const button = tv({
|
||||
base: classes.button,
|
||||
variants: {
|
||||
color: {
|
||||
primary: "bg-[rgba(206,232,251,0.7)] hover:bg-[rgba(206,232,251,0.9)]",
|
||||
secondary: "bg-[rgba(255,251,197,0.68)] hover:bg-[rgba(255,251,197,0.9)]",
|
||||
primary: "bg-[rgba(206,232,251,0.7)] hover:bg-[rgba(206,232,251,0.9)] active:bg-[rgba(206,232,251,0.9)]",
|
||||
secondary: "bg-[rgba(255,251,197,0.68)] hover:bg-[rgba(255,251,197,0.9)] active:bg-[rgba(255,251,197,0.9)]",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@reference "../../index.scss";
|
||||
|
||||
.input_field {
|
||||
@apply rounded-[23px] border border-gray-300 bg-white p-2 leading-8 placeholder:transition focus:outline-0 focus:placeholder:opacity-25;
|
||||
@apply w-full rounded-[4rem] border bg-white p-2 leading-8 placeholder:transition focus:outline-0 focus:placeholder:opacity-25;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { FunctionComponent } from "preact";
|
||||
import { cn } from "@/utils/class-merge";
|
||||
import { FunctionComponent, Ref } from "preact";
|
||||
import { tv } from "tailwind-variants";
|
||||
import classes from "./Input.module.scss";
|
||||
|
||||
@@ -9,6 +10,10 @@ const input = tv({
|
||||
center: "text-center",
|
||||
left: "text-left",
|
||||
},
|
||||
"border-error": {
|
||||
true: "border-red-500 placeholder:text-red-500",
|
||||
false: "border-gray-300",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
"text-align": "left",
|
||||
@@ -19,15 +24,33 @@ interface InputProps {
|
||||
isPassword?: boolean;
|
||||
placeholder?: string;
|
||||
textAlign?: "center" | "left";
|
||||
error?: string;
|
||||
textRef?: Ref<HTMLInputElement> | null;
|
||||
}
|
||||
|
||||
const Input: FunctionComponent<InputProps> = ({ isPassword = false, placeholder = "", textAlign }: InputProps) => {
|
||||
const Input: FunctionComponent<InputProps> = ({
|
||||
isPassword = false,
|
||||
placeholder = "",
|
||||
textAlign,
|
||||
error = "",
|
||||
textRef = null,
|
||||
}: InputProps) => {
|
||||
return (
|
||||
<div class="flex w-full flex-col items-center gap-1">
|
||||
<input
|
||||
type={isPassword ? "password" : "text"}
|
||||
class={input({ "text-align": textAlign })}
|
||||
class={input({ "text-align": textAlign, "border-error": error !== "" })}
|
||||
placeholder={placeholder}
|
||||
ref={textRef}
|
||||
/>
|
||||
<p
|
||||
class={cn("invisible h-10 w-[80%] text-center text-[0.7rem] break-words text-red-500", {
|
||||
visible: error !== "",
|
||||
})}
|
||||
>
|
||||
{error}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
}
|
||||
|
||||
.login_card {
|
||||
@apply flex min-h-[50vh] w-[95%] min-w-[300px] flex-col justify-around gap-2 rounded-[103px] bg-[linear-gradient(180.00deg,_rgba(239,251,194,0.53),rgb(206,232,251)_100%)] p-7 shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] md:w-[350px];
|
||||
@apply flex h-fit w-[95%] min-w-[300px] flex-col justify-around rounded-[3rem] bg-[linear-gradient(180.00deg,_rgba(239,251,194,0.53),rgb(206,232,251)_100%)] p-7 shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] md:w-[350px];
|
||||
}
|
||||
|
||||
.login_card_name {
|
||||
@apply text-center text-2xl font-semibold;
|
||||
@apply mb-8 text-center text-2xl font-semibold;
|
||||
}
|
||||
|
||||
@@ -5,28 +5,52 @@ import { UrlsTitle } from "@/enums/urls";
|
||||
import { useAppContext } from "@/providers/AuthProvider";
|
||||
import { FunctionComponent } from "preact";
|
||||
import { useLocation } from "preact-iso";
|
||||
import "preact/debug";
|
||||
import { useRef, useState } from "preact/hooks";
|
||||
import classes from "./login.module.scss";
|
||||
|
||||
const testUser = {
|
||||
login: "test",
|
||||
password: "test",
|
||||
};
|
||||
const LoginPage: FunctionComponent = () => {
|
||||
const { isLoggedIn } = useAppContext();
|
||||
const { route } = useLocation();
|
||||
return (
|
||||
<div class={classes.login_container}>
|
||||
<div class={classes.login_card}>
|
||||
<p class={classes.login_card_name}>Антихвост</p>
|
||||
<Input placeholder="Логин" textAlign="center" />
|
||||
<Input isPassword placeholder="Пароль" textAlign="center" />
|
||||
<Button
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
const loginRef = useRef<HTMLInputElement | null>(null);
|
||||
const passwordRef = useRef<HTMLInputElement | null>(null);
|
||||
const [loginError, setLoginError] = useState("");
|
||||
const [passwordError, setPasswordError] = useState("");
|
||||
const login = async () => {
|
||||
if (!loginRef.current || !passwordRef.current) return;
|
||||
setLoginError("");
|
||||
setPasswordError("");
|
||||
if (!loginRef.current.value.length || !passwordRef.current.value.length) {
|
||||
if (!loginRef.current.value.length) setLoginError("Введите логин");
|
||||
if (!passwordRef.current.value.length) setPasswordError("Введите пароль");
|
||||
return;
|
||||
}
|
||||
if (loginRef.current.value !== testUser.login || passwordRef.current.value !== testUser.password) {
|
||||
setLoginError("Неправильный логин или пароль");
|
||||
return;
|
||||
}
|
||||
isLoggedIn.value = true;
|
||||
localStorage.setItem("loggedIn", "true");
|
||||
route("/profile/tasks", true);
|
||||
}}
|
||||
>
|
||||
};
|
||||
if (isLoggedIn.value) route("/profile/tasks", true);
|
||||
return !isLoggedIn.value ? (
|
||||
<div class={classes.login_container}>
|
||||
<div class={classes.login_card}>
|
||||
<p class={classes.login_card_name}>Антихвост</p>
|
||||
<Input placeholder="Логин" textAlign="center" textRef={loginRef} error={loginError} />
|
||||
<Input isPassword placeholder="Пароль" textAlign="center" textRef={passwordRef} error={passwordError} />
|
||||
<Button color="secondary" onClick={login}>
|
||||
Войти
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p>Redirecting...</p>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const ProfilePage: FunctionComponent = () => {
|
||||
<Router>
|
||||
<Route path="/settings" component={lazy(() => import("./profile_settings"))} />
|
||||
<Route path="/tasks" component={lazy(() => import("./profile_tasks"))} />
|
||||
<Route path="/calendar" component={lazy(() => import("./calendar"))} />
|
||||
<Route path="/calendar" component={lazy(() => import("./profile_calendar"))} />
|
||||
<Route
|
||||
default
|
||||
component={() => {
|
||||
|
||||
17
src/pages/profile_calendar.tsx
Normal file
17
src/pages/profile_calendar.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import BigCalendar from "@/components/calendar";
|
||||
import { withTitle } from "@/constructors/Component";
|
||||
import { UrlsTitle } from "@/enums/urls";
|
||||
import { FunctionComponent } from "preact";
|
||||
|
||||
const ProfileCalendar: FunctionComponent = () => {
|
||||
const onDateSelect = (date: Date) => {
|
||||
console.log(date);
|
||||
};
|
||||
return (
|
||||
<div class="flex w-full flex-col items-center">
|
||||
<BigCalendar onDateSelect={onDateSelect} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTitle(UrlsTitle.CALENDAR, ProfileCalendar);
|
||||
@@ -1,11 +1,11 @@
|
||||
@reference "../index.scss";
|
||||
|
||||
.container {
|
||||
@apply flex h-full w-full flex-col items-center px-6 pt-3 md:flex-row md:items-start;
|
||||
@apply flex h-full w-full flex-col items-center px-6 pt-8 md:items-start;
|
||||
}
|
||||
|
||||
#avatar {
|
||||
@apply flex aspect-square h-40 flex-col items-center justify-center rounded-md border;
|
||||
@apply flex aspect-square h-[7rem] flex-col items-center justify-center rounded-full bg-white;
|
||||
}
|
||||
|
||||
.profile_container {
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
|
||||
.header_block__name {
|
||||
@apply mt-5 flex h-fit w-full flex-col items-center justify-start gap-3;
|
||||
@apply flex h-fit w-full flex-1 flex-col items-center justify-start gap-3 px-10;
|
||||
}
|
||||
.settings_block {
|
||||
@apply mt-12 flex h-full w-full flex-col items-center justify-start md:mt-0 md:justify-center;
|
||||
|
||||
@@ -2,6 +2,7 @@ import Button from "@/components/ui/Button";
|
||||
import { withTitle } from "@/constructors/Component";
|
||||
import { UrlsTitle } from "@/enums/urls";
|
||||
import { useAppContext } from "@/providers/AuthProvider";
|
||||
import { cn } from "@/utils/class-merge";
|
||||
import { FunctionComponent } from "preact";
|
||||
import { useLocation } from "preact-iso";
|
||||
import classes from "./profile_settings.module.scss";
|
||||
@@ -9,15 +10,27 @@ import classes from "./profile_settings.module.scss";
|
||||
const ProfileSettings: FunctionComponent = () => {
|
||||
const { isLoggedIn } = useAppContext();
|
||||
const { route } = useLocation();
|
||||
const status = 12;
|
||||
const maxStatus = 100;
|
||||
return (
|
||||
<div class={classes.container}>
|
||||
<div class="flex w-full flex-col items-center rounded-[4rem] bg-[linear-gradient(180.00deg,rgb(251,194,199),rgba(206,232,251,0.72)_100%)] px-7 py-5 shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] md:flex-row">
|
||||
<div id={classes.avatar}>Аватар</div>
|
||||
<div class={classes.profile_container}>
|
||||
<div class={classes.header_block__name}>
|
||||
<p class="text-5xl font-semibold">Никнейм</p>
|
||||
<p class="text-4xl font-semibold">Никнейм</p>
|
||||
<p class="text-2xl font-light">Статус</p>
|
||||
<div class="h-1.5 w-full overflow-hidden rounded-2xl bg-white">
|
||||
<div
|
||||
class={cn("relative top-0 left-0 h-2 bg-black")}
|
||||
style={{ width: `${(status / maxStatus) * 100}%` }}
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div class="-mt-3 self-end text-sm font-light">
|
||||
{status}/{maxStatus}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class={classes.profile_container}>
|
||||
<div class={classes.settings_block}>
|
||||
<div class={classes.settings_block__buttons}>
|
||||
<Button>Сменить тему</Button>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
@reference "../index.scss";
|
||||
|
||||
.container {
|
||||
@apply flex h-fit w-full flex-col items-center gap-4 px-6 pt-3;
|
||||
@apply flex h-fit min-h-full w-full flex-col items-center gap-4 pt-3 md:px-6;
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply mb-12 w-full text-3xl font-semibold md:text-5xl;
|
||||
@apply mb-3 w-full text-3xl font-semibold md:mb-12 md:text-5xl;
|
||||
}
|
||||
|
||||
.tasks_container {
|
||||
@apply flex w-full flex-col items-center gap-10 md:items-start;
|
||||
@apply flex w-full flex-col items-center gap-3 md:items-start md:gap-10;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import Task from "@/components/task";
|
||||
import { withTitle } from "@/constructors/Component";
|
||||
import { UrlsTitle } from "@/enums/urls";
|
||||
import { PlusIcon } from "@heroicons/react/20/solid";
|
||||
import { FunnelIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
||||
import { FunctionComponent } from "preact";
|
||||
import { useMemo } from "preact/hooks";
|
||||
import classes from "./profile_tasks.module.scss";
|
||||
@@ -15,12 +17,38 @@ const ProfileTasks: FunctionComponent = () => {
|
||||
}, []);
|
||||
return (
|
||||
<div class={classes.container}>
|
||||
{example_tasks.length > 0 ? (
|
||||
<>
|
||||
<div class={classes.header}>Сегодня: {getDate}</div>
|
||||
<div class={classes.tasks_container}>
|
||||
{example_tasks.map((task, index) => (
|
||||
<Task name={task} key={index} />
|
||||
<Task name={task} key={index} checked={index % 2 === 0} />
|
||||
))}
|
||||
</div>
|
||||
<div class="group fixed right-[22rem] bottom-4 hidden flex-row items-center justify-start space-x-3 overflow-x-hidden py-2 md:flex">
|
||||
<div class="flex aspect-square h-20 cursor-pointer items-center justify-center rounded-full bg-[rgb(251,194,199,0.53)] text-9xl text-white shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-all duration-300 ease-out group-hover:ml-[12rem] hover:bg-[rgb(251,194,199,0.7)]">
|
||||
<PlusIcon />
|
||||
</div>
|
||||
<div class="absolute left-0 my-auto flex flex-row space-x-3 opacity-0 transition-opacity duration-100 group-hover:opacity-100">
|
||||
<div class="pointer-events-none flex aspect-square h-20 cursor-pointer flex-col items-center justify-center rounded-full bg-[rgba(206,232,251,0.7)] text-xl text-gray-600 shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] group-hover:pointer-events-auto hover:bg-[rgba(206,232,251,0.9)]">
|
||||
<MagnifyingGlassIcon class="size-12" />
|
||||
</div>
|
||||
<div class="pointer-events-none flex aspect-square h-20 cursor-pointer flex-col items-center justify-center rounded-full bg-[rgba(206,232,251,0.7)] text-xl text-gray-600 shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] group-hover:pointer-events-auto hover:bg-[rgba(206,232,251,0.9)]">
|
||||
<FunnelIcon class="size-12" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div class="flex w-full flex-1 flex-col items-center justify-center text-2xl">Начни уже сегодня!</div>
|
||||
<div class="fixed right-[22rem] bottom-4 hidden flex-row items-center justify-start overflow-x-hidden py-2 md:flex">
|
||||
<div class="flex aspect-square h-20 cursor-pointer items-center justify-center rounded-full bg-[rgb(251,194,199,0.53)] text-9xl text-white shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-all duration-300 ease-out hover:bg-[rgb(251,194,199,0.7)]">
|
||||
<PlusIcon />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user