diff --git a/apps/backend/prisma/migrations/20240805054610_add_map_image/migration.sql b/apps/backend/prisma/migrations/20240805054610_add_map_image/migration.sql new file mode 100644 index 0000000000..3d1d63b5a2 --- /dev/null +++ b/apps/backend/prisma/migrations/20240805054610_add_map_image/migration.sql @@ -0,0 +1,26 @@ +/* + Warnings: + + - You are about to drop the `Image` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "Image" DROP CONSTRAINT "Image_createdById_fkey"; + +-- DropTable +DROP TABLE "Image"; + +-- CreateTable +CREATE TABLE "image" ( + "filename" TEXT NOT NULL, + "createdById" INTEGER, + "create_time" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "image_pkey" PRIMARY KEY ("filename") +); + +-- CreateIndex +CREATE UNIQUE INDEX "image_filename_key" ON "image"("filename"); + +-- AddForeignKey +ALTER TABLE "image" ADD CONSTRAINT "image_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/backend/prisma/schema.prisma b/apps/backend/prisma/schema.prisma index c7992ff362..100f68e8f7 100644 --- a/apps/backend/prisma/schema.prisma +++ b/apps/backend/prisma/schema.prisma @@ -201,6 +201,8 @@ model Image { createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull) createdById Int? createTime DateTime @default(now()) @map("create_time") + + @@map("image") } enum Level { diff --git a/apps/frontend/app/(main)/_components/ContestCard.tsx b/apps/frontend/app/(main)/_components/ContestCard.tsx index e9887db0be..6e0a1c3c28 100644 --- a/apps/frontend/app/(main)/_components/ContestCard.tsx +++ b/apps/frontend/app/(main)/_components/ContestCard.tsx @@ -1,70 +1,91 @@ -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +'use client' + import { cn, dateFormatter } from '@/lib/utils' +import CalendarIcon from '@/public/20_calendar.svg' +import ClockIcon from '@/public/20_clock.svg' import type { Contest } from '@/types/type' -import { FaRegClock } from 'react-icons/fa' -import { FaRegCalendarAlt } from 'react-icons/fa' -import Badge from './Badge' +import Image from 'next/image' +import { CircularProgressbar } from 'react-circular-progressbar' +import 'react-circular-progressbar/dist/styles.css' +import StatusBadge from './StatusBadge' import TimeDiff from './TimeDiff' -const variants = { - ongoing: 'bg-gradient-to-br from-blue-500 to-blue-950', - upcoming: 'bg-gradient-to-br from-emerald-600 to-emerald-900', +const bgVariants = { + ongoing: 'bg-gradient-to-b from-blue-100 to-white', + upcoming: 'bg-white', finished: 'bg-gray-500', - registeredOngoing: 'bg-gradient-to-br from-blue-500 to-blue-950', - registeredUpcoming: 'bg-gradient-to-br from-emerald-600 to-emerald-900' + registeredOngoing: 'bg-gradient-to-b from-blue-100 to-white', + registeredUpcoming: 'bg-white' } +const txtVariants = { + ongoing: 'text-blue-500', + upcoming: 'text-red-400', + finished: 'text-gray-500', + registeredOngoing: 'text-blue-500', + registeredUpcoming: 'text-red-400' +} interface Props { contest: Contest } -const format = (target: Date, year: number): string => - new Date(target).getFullYear() === year - ? dateFormatter(target, 'MMM DD') - : dateFormatter(target, 'MMM DD, YYYY') - export default function ContestCard({ contest }: Props) { - const year = new Date().getFullYear() - const startTime = format(contest.startTime, year) - const endTime = format(contest.endTime, year) + const startTime = dateFormatter(contest.startTime, 'YYYY-MM-DD') + const endTime = dateFormatter(contest.endTime, 'YYYY-MM-DD') return ( - - - -

- {contest.status.startsWith('registered') - ? 'registered' - : contest.status} -

-
- +
+ +
{contest.title} - - - - {contest.status === 'finished' ? ( - <> - +
+
+
+
+
+ Calendar

- {startTime} - {endTime} + {startTime} ~ {endTime}

- - ) : ( - <> - - {contest.status === 'ongoing' ? 'Ends in' : 'Starts in'} -

- -

- +
+ +
+ {contest.status === 'finished' ? ( + <> + Calendar +

+ {startTime} - {endTime} +

+ + ) : ( + <> + Clock + {contest.status === 'ongoing' ? 'Ends in' : 'Starts in'} +

+ +

+ + )} +
+
+ {(contest.status == 'ongoing' || + contest.status == 'registeredOngoing') && ( +
+ +
)} - - +
+ ) } diff --git a/apps/frontend/app/(main)/_components/Footer.tsx b/apps/frontend/app/(main)/_components/Footer.tsx index d73966df1c..f68b430690 100644 --- a/apps/frontend/app/(main)/_components/Footer.tsx +++ b/apps/frontend/app/(main)/_components/Footer.tsx @@ -1,9 +1,11 @@ 'use client' -import { IoIosLink } from 'react-icons/io' -import { RiGithubFill } from 'react-icons/ri' +import CodedangLogo from '@/public/codedang.svg' +import Image from 'next/image' +import { AiOutlineLink } from 'react-icons/ai' +import { AiFillMail } from 'react-icons/ai' import { RiKakaoTalkFill } from 'react-icons/ri' -import { TbMail } from 'react-icons/tb' +import { TbBrandGithubFilled } from 'react-icons/tb' import { toast } from 'sonner' export default function Footer() { @@ -17,48 +19,46 @@ export default function Footer() { } } return ( -