Skip to content

Commit 237fe29

Browse files
committed
♻️ refactor of components
1 parent a3c3282 commit 237fe29

15 files changed

+132
-40
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"axios": "^0.27.2",
2525
"canvas-confetti": "^1.5.1",
2626
"chart.js": "^3.9.1",
27-
"classnames": "^2.3.1",
27+
"classnames": "^2.3.2",
2828
"flowbite": "^1.5.4",
2929
"flowbite-react": "^0.3.5",
3030
"formik": "^2.2.9",

pages/hitchhikers/index.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { UserGender } from '@/components/helpers/UserGender';
12
import { Pagination, Table } from 'flowbite-react';
23
import { GetServerSideProps, NextPage } from 'next';
34
import Head from 'next/head';
@@ -12,8 +13,7 @@ import { User } from '../../src/types';
1213
import { profilePicture } from '../../src/utils';
1314
import {
1415
countryFlag,
15-
showNumberOfRides,
16-
showUserGender,
16+
viewNumberOfRides,
1717
viewNumberOfStories,
1818
viewNumberOfTrips,
1919
} from '../../src/utils/viewHelpers';
@@ -48,7 +48,7 @@ const Index: NextPage<{ page: number }> = (props) => {
4848
query: { page: p },
4949
},
5050
undefined,
51-
{ shallow: true }
51+
{ shallow: true },
5252
);
5353
setPage(p);
5454
fetchUsers();
@@ -127,9 +127,9 @@ const Index: NextPage<{ page: number }> = (props) => {
127127
</Link>
128128
<div className="flex items-center">
129129
({user.age}
130-
{showUserGender(user.gender)})
130+
<UserGender gender={user?.gender} />)
131131
</div>
132-
{showNumberOfRides(user.number_of_rides)}
132+
{viewNumberOfRides(user.number_of_rides)}
133133
{viewNumberOfTrips(user.number_of_trips)}
134134
{user.number_of_stories > 0 &&
135135
viewNumberOfStories(user.number_of_stories)}

pnpm-lock.yaml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React, { FC } from 'react';
2+
3+
import Image from 'next/image';
4+
5+
import { User } from '@/types';
6+
import { profilePicture } from '@/utils';
7+
8+
export const ProfileImage: FC<{ user: User }> = ({ user }) => {
9+
return (
10+
<Image
11+
className="w-24 h-24 rounded-full"
12+
width={96}
13+
height={96}
14+
src={profilePicture(user.md5_email, 96)}
15+
alt={`${user?.username}'s profile picture'`}
16+
/>
17+
);
18+
};

src/components/HitchhikingTrip.tsx

+10-12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import ExperienceCircle from './helpers/ExperienceCircle';
2727
import ExperiencesForRides from './helpers/ExperiencesForRides';
2828
import LikeRide from './helpers/LikeRide';
2929
import { NumberOfLikesCount } from './helpers/NumberOfLikesCount';
30+
import { ProfileImage } from './Hitchhikers/ProfileImage';
31+
import { UserGender } from './helpers/UserGender';
3032

3133
export function HitchhikingTrip({
3234
user,
@@ -40,7 +42,7 @@ export function HitchhikingTrip({
4042
const departure = trip.departure;
4143
const { currentUser } = useAuth();
4244
const ridesWithPhoto = rides.filter(
43-
(ride) => ride?.photo !== null && ride?.photo !== undefined
45+
(ride) => ride?.photo !== null && ride?.photo !== undefined,
4446
);
4547

4648
return (
@@ -54,21 +56,16 @@ export function HitchhikingTrip({
5456
</div>
5557
)}
5658

57-
<Image
58-
className="w-24 h-24 rounded-full"
59-
width={96}
60-
height={96}
61-
src={profilePicture(user.md5_email, 96)}
62-
alt={`${user?.username}'s profile picture'`}
63-
/>
59+
<ProfileImage user={user} />
60+
6461
<span className="flex items-center mt-2 text-sm text-gray-500 gap-1 dark:text-gray-400">
6562
<Link
6663
className="font-semibold text-gray-900 dark:text-white"
6764
href={`/hitchhikers/${user.username}`}
6865
>
6966
{capitalize(user?.username)}
7067
</Link>
71-
{showUserGender(user.gender)}
68+
<UserGender gender={user?.gender} />
7269
</span>
7370
<span className="flex items-center text-sm text-gray-500 dark:text-gray-400">
7471
Hitchhiked {moment(departure).fromNow()}
@@ -109,8 +106,9 @@ export function HitchhikingTrip({
109106
</div>
110107
<article>
111108
<div
112-
className={`h-56 sm:h-64 xl:h-76 pb-4 ${ridesWithPhoto.length === 0 && 'hidden'
113-
}`}
109+
className={`h-56 sm:h-64 xl:h-76 pb-4 ${
110+
ridesWithPhoto.length === 0 && 'hidden'
111+
}`}
114112
>
115113
<Carousel slideInterval={5000} slide={true}>
116114
{ridesWithPhoto.map(
@@ -126,7 +124,7 @@ export function HitchhikingTrip({
126124
{ride.photo_caption}
127125
</p>
128126
</div>
129-
)
127+
),
130128
)}
131129
</Carousel>
132130
</div>

src/components/ProfilePicture.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React, { FC } from 'react';
2+
3+
export const ProfilePicture: FC = () => {
4+
return (
5+
<>
6+
<Image
7+
className="w-24 h-24 rounded-full"
8+
width={96}
9+
height={96}
10+
src={profilePicture(user.md5_email, 96)}
11+
alt={`${user?.username}'s profile picture'`}
12+
/>
13+
</>
14+
);
15+
};

src/components/Trips/HitchhikingTrip/index.tsx

Whitespace-only changes.

src/components/helpers/HitchhikedBy.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import React, { FC } from 'react';
55
import { Trip } from '../../types';
66
import { profilePicture } from '../../utils';
77
import { timeAgoInWords } from '../../utils/timeAgoInWords';
8-
import { showUserGender } from '../../utils/viewHelpers';
8+
import { UserGender } from './UserGender';
99

1010
const HitchhikedBy: FC<{ trip: Trip }> = ({ trip }) => {
1111
return (
@@ -19,7 +19,7 @@ const HitchhikedBy: FC<{ trip: Trip }> = ({ trip }) => {
1919
>
2020
{trip.user.username}
2121
</Link>
22-
{showUserGender(trip.user.gender)}
22+
<UserGender gender={trip.user.gender} />
2323

2424
<Link
2525
className="flex items-center space-x-2"
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { pluralize } from '@/utils';
2+
import { Tooltip } from 'flowbite-react';
3+
import React, { FC } from 'react';
4+
import { FiThumbsUp } from 'react-icons/fi';
5+
6+
export const NumberOfRides: FC<{ ridesSize: number }> = ({ ridesSize }) => {
7+
return (
8+
<Tooltip content={`${ridesSize} ${pluralize(ridesSize, 'ride')}`}>
9+
<div className="flex items-center gap-1">
10+
<FiThumbsUp className="inline " /> {ridesSize}
11+
</div>
12+
</Tooltip>
13+
);
14+
};

src/components/helpers/Pagination.tsx

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React, { FC } from 'react';
2+
import { Pagination } from 'flowbite-react';
3+
4+
type PaginationProps = {
5+
currentPage: number;
6+
layout?: string;
7+
onPageChange: (page: number) => void;
8+
showIcons?: boolean;
9+
totalPages: number;
10+
page: number;
11+
};
12+
13+
export const Pagination: FC<PaginationProps> = ({
14+
handlePageChange,
15+
totalPages,
16+
page,
17+
}) => {
18+
return (
19+
<div className="flex justify-center my-4">
20+
<Pagination
21+
onPageChange={handlePageChange}
22+
currentPage={page}
23+
showIcons={true}
24+
layout="pagination"
25+
totalPages={totalPages}
26+
page={0}
27+
/>
28+
</div>
29+
);
30+
};

src/components/helpers/UserGender.tsx

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Tooltip } from 'flowbite-react';
2+
import React, { FC } from 'react';
3+
import { FaMars, FaMarsStrokeV, FaVenus } from 'react-icons/fa';
4+
5+
export const UserGender: FC<{ gender: string | null; size?: number }> = ({
6+
gender,
7+
size = 16,
8+
}) => {
9+
if (!gender) return null;
10+
return (
11+
<Tooltip content={gender}>
12+
{gender == 'male' ? (
13+
<FaMars className="inline" size={size} />
14+
) : gender == 'female' ? (
15+
<FaVenus className="inline" />
16+
) : gender == 'non-binary' ? (
17+
<FaMarsStrokeV className="inline" />
18+
) : (
19+
<></>
20+
)}
21+
</Tooltip>
22+
);
23+
};

src/components/users/ProfileStats.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
} from '../../utils/viewHelpers';
1919
import { useAuth } from '../contexts/AuthContext';
2020
import CountryFlagsForProfile from '../helpers/CountryFlagsForProfile';
21+
import { UserGender } from '../helpers/UserGender';
2122

2223
const ProfileStats: FC<{ profile: Profile }> = ({ profile }) => {
2324
const createdAt = moment(profile.created_at).format('MMM YYYY');
@@ -26,7 +27,7 @@ const ProfileStats: FC<{ profile: Profile }> = ({ profile }) => {
2627
<>
2728
<div className="flex justify-center image-shadow">
2829
<Image
29-
className="rounded-full shadow shadow-lg"
30+
className="rounded-full shadow"
3031
alt="Profile picture"
3132
width={128}
3233
height={128}
@@ -35,7 +36,7 @@ const ProfileStats: FC<{ profile: Profile }> = ({ profile }) => {
3536
</div>
3637
<div className="flex items-center justify-center mt-4 gap-2">
3738
{capitalize(profile.username)} {profile.age && `(${profile.age})`}
38-
{showUserGender(profile.gender, 20)}
39+
<UserGender gender={profile.gender} size={20} />
3940
{showCountryFlagForUser(profile)}
4041
</div>
4142
<div className="flex items-center justify-center text-gray-400 gap-1">

src/utils/index.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const fetchIpAddressOfClient = async () => {
3636
export const fetchLocationFromClient = async () => {
3737
const ipAddress = await fetchIpAddressOfClient();
3838
const response = await axios.get(
39-
`https://api.ipgeolocation.io/ipgeo?apiKey=${process.env.NEXT_PUBLIC_IPLOCATION}&ip=${ipAddress}`
39+
`https://api.ipgeolocation.io/ipgeo?apiKey=${process.env.NEXT_PUBLIC_IPLOCATION}&ip=${ipAddress}`,
4040
);
4141
const IpLocation = response.data;
4242
return IpLocation as IpLocation;
@@ -88,14 +88,14 @@ export const randomConfetti = () => {
8888
};
8989

9090
export const getDataFromAddressComponents = (
91-
address_components: google.maps.GeocoderAddressComponent[] | undefined
91+
address_components: google.maps.GeocoderAddressComponent[] | undefined,
9292
) => {
9393
if (!address_components) return {};
9494
const city = address_components.find((component) =>
95-
component.types.includes('locality')
95+
component.types.includes('locality'),
9696
);
9797
const country = address_components.find((component) =>
98-
component.types.includes('country')
98+
component.types.includes('country'),
9999
);
100100
return {
101101
city: city ? city.long_name : '',
@@ -126,3 +126,5 @@ export const objectToString = (obj: any) => {
126126
.map(([key, value]) => `${key}: ${value}`)
127127
.join(' ');
128128
};
129+
130+
export * from './timeAgoInWords';

src/utils/viewHelpers.tsx

-8
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,6 @@ export const showAgeAtTrip = (trip: Trip) => {
181181
);
182182
};
183183

184-
export const showNumberOfRides = (ridesLength: number) => (
185-
<Tooltip content={`${ridesLength} ${pluralize(ridesLength, 'ride')}`}>
186-
<div className="flex items-center gap-1">
187-
<FiThumbsUp className="inline " /> {ridesLength}
188-
</div>
189-
</Tooltip>
190-
);
191-
192184
export const showHitchhikedKms = (size: number) => (
193185
<Tooltip content={`${size} hitchhiked kms`}>
194186
<div className="flex items-center gap-1">

tests/login.spec.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ test('Test existence', async ({ page }) => {
44
await page.goto('http://localhost:3000/login');
55
// Expect a title "to contain" a substring.
66
await expect(page).toHaveTitle(/Hitchlog - Login/);
7-
await page.getByText('Sign up').click();
87

9-
// Expects the URL to contain intro.
10-
await expect(page).toHaveURL(/.*login/);
11-
12-
await page.locator('input[name="username"]').fill('username');
8+
// Expect to show an error when login fails
139
await page.locator('input[name="email"]').fill('[email protected]');
10+
await page.locator('input[name="password"]').fill('password');
11+
await page.locator('button[type="submit"]').click();
12+
await page.waitForSelector('.alert');
1413
});

0 commit comments

Comments
 (0)