From 1e841a5bf9e6e629d7ff19cb8f179c5d9c462ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Synowiec?= Date: Thu, 9 Mar 2023 14:26:26 +0100 Subject: [PATCH 01/19] new: tabs component --- apps/web/components/molecules/tabs/tabs.tsx | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 apps/web/components/molecules/tabs/tabs.tsx diff --git a/apps/web/components/molecules/tabs/tabs.tsx b/apps/web/components/molecules/tabs/tabs.tsx new file mode 100644 index 0000000..b3d2334 --- /dev/null +++ b/apps/web/components/molecules/tabs/tabs.tsx @@ -0,0 +1,53 @@ +import { Tab } from '@headlessui/react'; +import { Opinions } from 'molecules/opinions/opinions'; +import clsx from 'clsx'; +import type { ReactNode } from 'react'; + +type TabObject = { + label: string; + content: ReactNode; +}; + +export const Tabs = () => { + const tabs: TabObject[] = [ + { + label: 'Opinie', + content: , + }, + { + label: 'Rozwiązania', + content: 'Tab 2', + }, + { + label: 'Komentarze', + content: 'Komentarze', + }, + ]; + + return ( +
+ + + {tabs.map((tab) => ( + + clsx( + 'w-full rounded-tl-lg rounded-tr-lg py-2.5 text-sm font-medium text-blue-700', + 'ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2 hover:bg-blue-50 transition ease-in-out duration-150', + selected ? 'border-2 border-blue-500 shadow' : 'text-black', + ) + } + > + {tab.label} + + ))} + + + {tabs.map((tab) => ( + {tab.content} + ))} + + +
+ ); +}; From 14b30be91e6a9008fd270e9eca85de60f5750704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Synowiec?= Date: Thu, 9 Mar 2023 14:31:48 +0100 Subject: [PATCH 02/19] new: tabs component --- .../molecules/opinionItem/opinionItem.tsx | 56 ++++++++++++ .../molecules/opinions/opinions.tsx | 56 ++++++++++++ .../molecules/opinonStats/opinionStats.tsx | 78 +++++++++++++++++ .../newOpinionForm/newOpinionForm.tsx | 87 +++++++++++++++++++ .../newOpinionForm/useAddOpinionForm.tsx | 23 +++++ .../protectedComponent/protectedComponent.tsx | 34 ++++++++ .../challenge/single/singleChallenge.tsx | 4 + apps/web/types/types.tsx | 7 ++ apps/web/utils/plurals/PolishPlurals.tsx | 19 ++++ 9 files changed, 364 insertions(+) create mode 100644 apps/web/components/molecules/opinionItem/opinionItem.tsx create mode 100644 apps/web/components/molecules/opinions/opinions.tsx create mode 100644 apps/web/components/molecules/opinonStats/opinionStats.tsx create mode 100644 apps/web/components/organisms/newOpinionForm/newOpinionForm.tsx create mode 100644 apps/web/components/organisms/newOpinionForm/useAddOpinionForm.tsx create mode 100644 apps/web/components/organisms/protectedPage/protectedComponent/protectedComponent.tsx create mode 100644 apps/web/utils/plurals/PolishPlurals.tsx diff --git a/apps/web/components/molecules/opinionItem/opinionItem.tsx b/apps/web/components/molecules/opinionItem/opinionItem.tsx new file mode 100644 index 0000000..1afce7b --- /dev/null +++ b/apps/web/components/molecules/opinionItem/opinionItem.tsx @@ -0,0 +1,56 @@ +import { Card, Heading, Text } from 'ui'; +import Image from 'next/image'; +import clsx from 'clsx'; +import type { Opinion } from '../../../types/types'; + +type OpinionItemProps = Opinion; + +export const OpinionItem = ({ + author, + avatar, + rating, + comment, +}: OpinionItemProps) => { + return ( +
+ +
+ +
+ + {author} + +
+ {Array.from({ length: 5 }, (_, i) => { + const starClass = + i < Math.round(rating) ? 'text-yellow-400' : 'text-gray-300'; + return ( + + ); + })} +
+ + {comment} + +
+
+
+
+ ); +}; diff --git a/apps/web/components/molecules/opinions/opinions.tsx b/apps/web/components/molecules/opinions/opinions.tsx new file mode 100644 index 0000000..5017f43 --- /dev/null +++ b/apps/web/components/molecules/opinions/opinions.tsx @@ -0,0 +1,56 @@ +import { OpinionItem } from 'molecules/opinionItem/opinionItem'; +import type { Opinion } from '../../../types/types'; +import { NewOpinionForm } from 'organisms/newOpinionForm/newOpinionForm'; +import { OpinionStats } from 'molecules/opinonStats/opinionStats'; +import { ProtectedComponent } from 'organisms/protectedPage/protectedComponent/protectedComponent'; + +const opinions: Opinion[] = [ + { + author: 'Jan Kowalski', + avatar: + 'https://images.unsplash.com/photo-1633332755192-727a05c4013d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2960&q=80', + rating: 5, + comment: + 'Zadanie programistyczne, które otrzymałem, było dobrze sformułowane i precyzyjnie opisywało wymagania dotyczące tworzenia aplikacji internetowej. Zadanie miało na celu zaimplementowanie funkcjonalności wyszukiwania produktów w bazie danych i wyświetlenia wyników na stronie internetowej.', + }, + { + author: 'Jan Kowalski', + avatar: + 'https://images.unsplash.com/photo-1633332755192-727a05c4013d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2960&q=80', + rating: 5, + comment: + 'Zadanie programistyczne, które otrzymałem, było dobrze sformułowane i precyzyjnie opisywało wymagania dotyczące tworzenia aplikacji internetowej. Zadanie miało na celu zaimplementowanie funkcjonalności wyszukiwania produktów w bazie danych i wyświetlenia wyników na stronie internetowej.', + }, + { + author: 'Jan Kowalski', + avatar: + 'https://images.unsplash.com/photo-1633332755192-727a05c4013d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2960&q=80', + rating: 4, + comment: + 'Zadanie programistyczne, które otrzymałem, było dobrze sformułowane i precyzyjnie opisywało wymagania dotyczące tworzenia aplikacji internetowej. Zadanie miało na celu zaimplementowanie funkcjonalności wyszukiwania produktów w bazie danych i wyświetlenia wyników na stronie internetowej.', + }, +]; + +export const Opinions = () => { + return ( + <> +
+
+ + + +
+ +
+ {opinions.map((opinion, id) => ( + + ))} + + ); +}; diff --git a/apps/web/components/molecules/opinonStats/opinionStats.tsx b/apps/web/components/molecules/opinonStats/opinionStats.tsx new file mode 100644 index 0000000..5009b1b --- /dev/null +++ b/apps/web/components/molecules/opinonStats/opinionStats.tsx @@ -0,0 +1,78 @@ +import { Card, Heading } from 'ui'; +import type { Opinion } from '../../../types/types'; +import { PolishPlurals } from 'utils/plurals/PolishPlurals'; + +type OpinionStatsProps = { + opinions: Opinion[]; +}; + +export const OpinionStats = ({ opinions }: OpinionStatsProps) => { + return ( +
+ +
+ + Statystyki + + +
+ + + + + +

4.95 / 5

+
+

+ {PolishPlurals(opinions.length)} +

+
+
+
+ ); +}; diff --git a/apps/web/components/organisms/newOpinionForm/newOpinionForm.tsx b/apps/web/components/organisms/newOpinionForm/newOpinionForm.tsx new file mode 100644 index 0000000..a40a9de --- /dev/null +++ b/apps/web/components/organisms/newOpinionForm/newOpinionForm.tsx @@ -0,0 +1,87 @@ +import { Button, Card, Heading } from 'ui'; +import clsx from 'clsx'; +import { useAddOpinionForm } from 'organisms/newOpinionForm/useAddOpinionForm'; +import { TextArea } from 'ui/components/organisms/textArea/textArea'; + +export const NewOpinionForm = () => { + const { register, errors } = useAddOpinionForm(); + + return ( + +
+ + Dodaj opinię o zadaniu + +
+
+